log/slog. No fmt.Println in
library code; main configures the handler once, at startup.DEBUG for local development, INFO as the production default, WARN
for recoverable anomalies, ERROR for failures a human should look at.KROOT_LOG_LEVEL (debug|info|warn|error).Required keys on every record where they apply:
| Key | Meaning |
|---|---|
component |
emitting subsystem, stable identifier |
err |
the error value, wrapped, never a stringified stack |
request_id |
correlation ID for the originating request |
duration_ms |
elapsed time for a timed operation |
slog.InfoContext(ctx, "config loaded",
"component", "config",
"request_id", reqID,
"duration_ms", ms,
)
Never logged, at any level: credentials, tokens, authorization headers, full request bodies, or personal data.
A single X-Request-ID is accepted from the ingress proxy or generated at the
boundary if absent. It is attached to the context.Context, propagated to every
downstream call, and included on every log record for that request.
Liveness and readiness answer different questions and must not be conflated:
| Endpoint | Question | Semantics |
|---|---|---|
GET /healthz |
is the process alive? | constant 200, no dependency checks, safe to poll frequently |
GET /readyz |
can it serve traffic now? | 200 when every dependency is reachable, 503 otherwise with a reason per dependency |
/readyz must not be used as a liveness probe: a brief dependency outage would
otherwise cause the orchestrator to restart a healthy process.
Exposed at GET /metrics in Prometheus text format once the HTTP layer exists.
The first metrics worth adding, in order of usefulness:
| Metric | Type | Why |
|---|---|---|
kroot_http_requests_total{method,route,status} |
counter | error rate and traffic shape |
kroot_http_request_duration_seconds{route} |
histogram | latency percentiles |
kroot_build_info{version,commit} |
gauge (always 1) |
correlate behaviour with a release |
Alert on symptoms, not causes: a rising 5xx rate and a saturated p99 latency are actionable; a single elevated CPU reading is not.
Targets, to be calibrated against real traffic rather than guessed:
| Objective | Target | Window |
|---|---|---|
| Availability | 99.5% of successful responses | 30 days rolling |
| Latency | p99 request latency under an agreed budget | 30 days rolling |
| Error rate | below 1% of requests | 30 days rolling |
An SLO without an error budget is decoration. When the budget is exhausted, feature work pauses in favour of reliability work.
Distributed tracing is introduced when there is more than one service to
correlate. Until then, X-Request-ID plus structured logs provide the same
narrative at a fraction of the operational cost.