# 可觀測性與健康

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

`health` 與 `observability` 是服務對外回報自身狀態的兩個 package：health 是三態的依賴檢查登記處，同時餵給 `/readyz` 與 gRPC Health protocol；observability 負責 slog 日誌、OTLP traces 與 metrics 的初始化。

先取得模組：`go get github.com/yshengliao/gortexa@v0.28.3`。以下片段皆對 v0.28.3 編譯驗證過。

## health

三態 registry（Healthy／Degraded／Unhealthy；Degraded 仍視為 serving，只有 Unhealthy 不是）＋ 標準 gRPC health 橋接。一般用 App 自帶的 registry（`app.Health()`），不必自建。

```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
```

`Register` 的 check 會被 `/readyz` 聚合；`Names()`、`Snapshot(ctx)`、`State(ctx, name)` 供查詢。同名重複 `Register` 會 panic：註冊發生在開機期的單執行緒階段，撞名是接線錯誤，默默覆蓋會讓輸掉的那個依賴從此無人監控、而 `/readyz` 照樣回 200；真的要替換請用 `Replace(name, check)`。`StartMetricsExport(ctx, metrics, interval)` 把各元件狀態輸出為 `gortexa_health_state`（`Int64Gauge`）：每個 `component` 一條序列，狀態是**值**（Healthy=0、Degraded=1、Unhealthy=2）而不是屬性，所以元件恢復後不會繼續回報舊狀態——告警請看值、不要看 label。需要 `observ.metrics_otlp`。

## observability

gRPC 儀表是 StatsHandler（非 interceptor）。tracing／metrics 在有設 OTLP endpoint 時匯出，否則為 no-op。三個 `Setup*` 各回一個 `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)
// observability.ServerStatsHandler() 傳給 kernel.WithStatsHandler
// 三個 ShutdownFunc 各傳給 kernel.WithShutdownHook
```

要對 uptrace 等需要認證 header 的 OTLP 後端匯出，OTel SDK 會讀標準環境變數 `OTEL_EXPORTER_OTLP_HEADERS`（例如 `uptrace-dsn=<DSN>`），或改由 collector 中繼。

## 延伸閱讀

- [部署](https://gortexa.sheng.page/deployment/)：readiness 接真實依賴，以及預設會記哪些 log
- [設定](https://gortexa.sheng.page/configuration/)：`observ.*` 的 OTLP 設定鍵
