# Observability & health

Source: https://gortexa.sheng.page/en/components/observability/

The two packages a service reports itself through: `health` is the three-state dependency-check registry feeding both `/readyz` and the gRPC Health protocol, and `observability` wires up slog logging, OTLP traces and metrics.

Fetch the module first: `go get github.com/yshengliao/gortexa@v0.28.3`. Every snippet below is compile-verified against v0.28.3.

## health

A three-state registry (Healthy / Degraded / Unhealthy; Degraded still counts as serving, only Unhealthy does not) plus a bridge to the standard gRPC health protocol. Normally you use the App's own registry via `app.Health()` rather than building your own.

```go
import "github.com/yshengliao/gortexa/health"

app.Health().Register("db", func(ctx context.Context) health.State {
	return health.Healthy
})
overall := app.Health().Overall(ctx) // health.Healthy / Degraded / Unhealthy
```

Registered checks are aggregated by `/readyz`; `Names()`, `Snapshot(ctx)` and `State(ctx, name)` query them. Registering the same name twice panics: registration is boot-time and single-threaded, so a collision is a wiring mistake, and silently overwriting would leave the losing dependency unmonitored while `/readyz` kept answering 200. Use `Replace(name, check)` when substituting a check is the actual intent. `StartMetricsExport(ctx, metrics, interval)` publishes each component's state as `gortexa_health_state` (`Int64Gauge`): one series per `component`, with the state as the **value** (Healthy=0, Degraded=1, Unhealthy=2) rather than an attribute, so a recovered component stops reporting its old state — alert on the value, not on a label. Requires `observ.metrics_otlp`.

## observability

The gRPC instrumentation is a StatsHandler (not interceptors). Tracing/metrics export via OTLP when an endpoint is configured, and are no-ops otherwise. Each `Setup*` returns a `ShutdownFunc`.

```go
import "github.com/yshengliao/gortexa/observability"

log, logShutdown, err := observability.SetupLogs(ctx, cfg.Log, cfg.Observ)
traceShutdown, err := observability.SetupTracing(ctx, cfg.Observ)
metricShutdown, err := observability.SetupMetrics(ctx, cfg.Observ)
// pass observability.ServerStatsHandler() to kernel.WithStatsHandler,
// and the three ShutdownFuncs to kernel.WithShutdownHook.
```

To export to an OTLP backend that needs an auth header (Uptrace, for example), the OTel SDK reads the standard `OTEL_EXPORTER_OTLP_HEADERS` env var (e.g. `uptrace-dsn=<DSN>`), or relay through a collector.

## Related

- [Deployment](https://gortexa.sheng.page/en/deployment/): wiring readiness to real dependencies, and what the server logs by default
- [Configuration](https://gortexa.sheng.page/en/configuration/): the `observ.*` OTLP settings
