Packages
Key management service with embedded OTP runtime, optional HTTP API, SQLite/PostgreSQL storage, and external RMK providers
Current section
Files
Jump to
Current section
Files
docs/observability.md
# KMS observability
KMS core observability is vendor-neutral. The application emits `:telemetry` events and exposes `KMS.Telemetry.metrics/0`; operators choose the reporter/exporter.
## Built in
### Telemetry events
KMS emits these events with low-cardinality, redacted metadata:
| Event | Measurements | Metadata |
| --- | --- | --- |
| `[:kms, :operation, :stop]` | `duration` native time | `operation`, `status`, optional safe `error` |
| `[:kms, :rmk, :operation, :stop]` | `duration` native time | `operation`, `provider`, `status`, optional safe `error` |
| `[:kms, :cache, :lookup]` | `count` | `namespace`, `result` |
| `[:kms, :signing, :operation, :stop]` | `duration` native time | `operation`, `status`, optional safe `error` |
| `[:kms, :factor, :attempt]` | `count` | `result` |
| `[:kms, :remote_client, :request, :stop]` | `duration` native time | `method`, `endpoint`, `status`, optional `http_status` |
| `[:kms, :api, :request, :stop]` | `duration` native time | `method`, `route`, `status` |
Security rule: event metadata must never include plaintext, ciphertext, bearer tokens, passwords, factor codes, private keys, or RMK material.
### Metrics definitions
Use `KMS.Telemetry.metrics/0` with any `Telemetry.Metrics` reporter:
```elixir
children = [
{TelemetryMetricsPrometheus, metrics: KMS.Telemetry.metrics()}
]
```
### Health endpoints
`KMS.API` exposes:
- `GET /health` cheap compatibility check
- `GET /health/live` liveness check
- `GET /health/ready` readiness check for dependencies
Readiness checks database access and API token presence from `config :kms, :api`.
## Optional recommendations
### Prometheus / PromEx
PromEx is a good optional choice for Prometheus and Grafana dashboards. Keep it in the host application, not as a hard KMS dependency.
Recommended shape:
- keep PromEx in the host app supervision tree
- enable BEAM, Ecto, and HTTP server plugins
- add `KMS.Telemetry.metrics()` through a custom PromEx plugin or manual metrics hook
- add Grafana panels for KMS operation latency, RMK latency, cache hit/miss, factor failures, and readiness
Protect `/metrics`; do not expose it publicly without auth or network controls.
### OpenTelemetry tracing
For tracing, use OpenTelemetry packages in the host release:
- `opentelemetry_bandit` or Plug/Phoenix instrumentation for HTTP server spans
- `opentelemetry_ecto` for database spans
- `opentelemetry_finch` for Req/Finch outbound HTTP spans
Keep custom spans around operation boundaries only. Do not put sensitive payloads in attributes.
### Structured JSON logs
Use normal Elixir `Logger` in KMS and configure structured logging in the host app, for example `logger_json`.
Recommended metadata allowlist:
- `request_id`
- `method`
- `route`
- `status`
- `operation`
- `error_kind`
Never log request/response bodies or secret material.
### Error reporting
Sentry or similar tools should be configured by deployers, not required by KMS.
Recommended setup:
- configure DSN through environment
- attach Logger handler in host app
- scrub headers and metadata
- drop request bodies for KMS routes
### VM metrics
Add `telemetry_poller` in the host release for BEAM metrics:
- memory
- run queue
- process count
- port count
- atom count
These complement KMS metrics but should not be required by the library.