Skip to main content

Overview

Sentry Options is a multi-language configuration system with JSON schemas as the source of truth. It provides validated, hot-reloadable options without database overhead, replacing database-stored configuration with git-managed, schema-validated config files. Key benefits:
  • Fast reads - Options loaded in memory, file reads only on init and updates
  • Schema validation - Type-safe options with defaults
  • Hot-reload - Values update without pod restart (~1-2 min propagation)
  • Audit trail - All changes tracked in git

Component flow

┌─────────────────────────────────────────────────────────────────┐
│                         Build Time                              │
│  service repo (e.g., seer)                                      │
│    └── sentry-options/schemas/seer/schema.json  ──→  Docker image│
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                         CI Pipeline                             │
│  sentry-options-automator repo                                  │
│    └── option-values/seer/default/values.yaml                   │
│              ↓                                                  │
│    sentry-options-cli (validates against schema)                │
│              ↓                                                  │
│    ConfigMap applied to cluster                                 │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                         Runtime                                 │
│  Kubernetes Pod                                                 │
│    ├── /etc/sentry-options/schemas/seer/schema.json (image)     │
│    └── /etc/sentry-options/values/seer/values.json (ConfigMap)  │
│              ↓                                                  │
│    sentry_options client library                                │
│    - Validates values against schema                            │
│    - Polls for file changes (5s interval)                       │
│    - Returns defaults when values missing                       │
└─────────────────────────────────────────────────────────────────┘

Components

ComponentLocationPurpose
SchemasService repo (e.g., seer/sentry-options/schemas/)Define options with types and defaults
Valuessentry-options-automator/option-values/Runtime configuration values
CLIsentry-options-cliFetches schemas, validates YAML, generates ConfigMaps
Client (Python)sentry_options (Python)Reads options at runtime with hot-reload
Client (Rust)sentry-options (Rust)Reads options at runtime with hot-reload
Validation librarysentry-options-validationShared validation logic for CLI and clients

Repository structure

The main sentry-options repository is organized as follows:
sentry-options/
├── Cargo.toml                       # Root Cargo workspace
├── schemas/                         # Example JSON schemas
│   ├── getsentry/
│   │   └── schema.json
│   ├── relay/
│   │   └── schema.json
│   └── sentry/
│       └── schema.json

├── clients/                         # Language-specific clients
│   ├── rust/                        # Rust client library
│   │   └── src/lib.rs
│   │
│   └── python/                      # Python client (PyO3 bindings)
│       ├── src/lib.rs
│       └── pyproject.toml

├── sentry-options-cli/              # CLI tool
│   ├── Cargo.toml
│   └── src/
│       ├── main.rs
│       ├── loader.rs
│       └── output.rs

├── sentry-options-validation/       # Shared validation library
│   ├── Cargo.toml
│   └── src/lib.rs

└── .github/
    ├── workflows/                   # CI/CD
    └── actions/
        └── validate-schema/         # Composite action for schema validation

Client library architecture

Rust client

The Rust client (clients/rust/src/lib.rs) provides:
  • Global initialization: init() function sets up a global Options instance
  • Namespace-based access: options(namespace) returns a NamespaceOptions handle
  • Thread-safe reads: Uses Arc<RwLock<>> for shared state
  • Automatic hot-reload: Background watcher thread integrated
Key types:
  • Options - Main options store with schema registry and values
  • NamespaceOptions - Handle for accessing options in a specific namespace
  • OptionsError - Error types for unknown namespaces/options

Python client

The Python client (clients/python/src/lib.rs) is implemented as PyO3 bindings to the Rust client:
  • Thin wrapper: Delegates to Rust implementation
  • Python-native types: Converts JSON values to Python bool, int, float, str, list
  • Exception hierarchy: Custom exceptions for different error types
  • Same API: Mirrors Rust client interface
Exceptions:
  • OptionsError - Base exception
  • SchemaError - Schema loading/validation failures
  • UnknownNamespaceError - Unknown namespace access
  • UnknownOptionError - Unknown option access
  • InitializationError - Already initialized error

Validation library

The shared validation library (sentry-options-validation/src/lib.rs) provides:
  • SchemaRegistry: Loads and stores namespace schemas from disk (lib.rs:218-467)
  • NamespaceSchema: Individual schema with validator and option metadata (lib.rs:175-216)
  • ValuesWatcher: Background thread for file watching and hot-reload (lib.rs:483-672)
  • Path resolution: Fallback chain for locating options directory (lib.rs:88-99)

Design decisions

Runtime validation (no codegen)

Schemas are loaded at runtime and values are validated against them. Rationale:
  • No build-time dependencies
  • Can update schemas without rebuilding clients
  • Simple to understand and debug

File watching strategy

Background thread with interval polling (not inotify/FSEvents) every 5 seconds. Rationale:
  • Works reliably with Kubernetes ConfigMaps, NFS, virtual filesystems
  • Simple to implement and debug
  • ConfigMap propagation is ~1-2 minutes, so 5s polling is acceptable overhead
Implementation details:
  • Polls modification time of all values.json files (lib.rs:548-583)
  • Reloads all namespaces if any file changed (lib.rs:586-610)
  • Emits Sentry transaction per namespace with metrics (lib.rs:612-644)
  • Old values persist if validation fails (lib.rs:1389-1415)

Strict validation

Reject unknown options, fail fast on type mismatches. Behavior:
  • Unknown keys in values file → Error (catches typos)
  • Type mismatch → Error
  • null values → Error (use defaults instead)
  • additionalProperties: false auto-injected (lib.rs:368-371)

JSON number handling

  • Schema says integer → Reject 5.5, accept 5
  • Schema says number → Accept both 5 and 5.5
Validated using jsonschema crate.

Configuration paths

The client libraries use a fallback chain to locate the options directory:
  1. SENTRY_OPTIONS_DIR environment variable (if set)
  2. /etc/sentry-options (if exists) - production path
  3. sentry-options/ (local fallback) - development
Implementation: resolve_options_dir() in lib.rs:88-99 Within the options directory, the expected structure is:
/etc/sentry-options/
├── schemas/                    # Baked into Docker image
│   └── {namespace}/
│       └── schema.json
└── values/                     # Mounted via ConfigMap
    └── {namespace}/
        └── values.json

Environment variables

VariablePurposeDefault
SENTRY_OPTIONS_DIROverride options directory path(uses fallback chain)
SENTRY_OPTIONS_SUPPRESS_MISSING_DIRSuppress missing directory errorsfalse

Observability

The validation library includes a dedicated Sentry integration for tracking hot-reload operations:
  • Dedicated DSN: Uses separate Sentry project (lib.rs:35-36)
  • Transaction per namespace: Emitted on each reload (lib.rs:612-644)
  • Metrics included:
    • reload_duration_ms - Time to reload and validate values
    • generated_at - When ConfigMap was generated (from values.json)
    • applied_at - When application loaded values
    • propagation_delay_secs - Time from generation to application
The dedicated Sentry Hub is isolated from the host application’s Sentry setup (lib.rs:42-63), ensuring observability metrics don’t interfere with application telemetry.

Build docs developers (and LLMs) love