Skip to content
Trilha
Chapters

Reference

Observability

Config.Observability, health endpoints, metrics registry, environment variables and the contract of each response.

Config.Observability#

FieldDefaultWhat it does
Health string/_trilha/healthbase path of the probes; trilha.Off removes them
Metrics string"" (off)scrape path; empty registers no endpoint and does not instrument requests
Token stringTRILHA_OBS_TOKENauthorizes details and metrics; at least 32 bytes, compared in constant time
Trusted []stringCIDRs (or IPs) that do not need the token
Details stringautomatictrilha.Off never reveals details, not even to a token holder; empty = open in dev, authorized in prod
Timeout time.Duration2 sdeadline of each check; trilha.NoTimeout disables it
CacheFor time.Duration1 svalidity of the readiness result; trilha.NoTimeout disables the cache

Variables read by ConfigFromEnv: TRILHA_OBS_TOKEN, TRILHA_METRICS, TRILHA_OBS_TRUSTED (comma-separated list).

Endpoints#

Method and pathResponseStatus
GET /_trilha/health/liveapplication/health+jsonalways 200
GET /_trilha/health/readysame, runs the checks200 or 503 + Retry-After: 5
GET /_trilha/healthsame as ready200 or 503
GET <Metrics>text/plain; version=0.0.4200, or 401 without authorization

All of them carry Cache-Control: no-store, X-Robots-Tag: noindex and X-Content-Type-Options: nosniff. Any other method returns 405 with Allow: GET, HEAD.

The probes run outside the middleware chain: no CSRF, no layout, no rate limit (a liveness probe that got a 429 would kill a healthy process) and logged at Debug level, so they do not drown the audit log.

Readiness checks#

func (a *App) Check(name string, fn func(context.Context) error)
func (a *App) HealthReport(ctx context.Context) HealthReport
type HealthReport struct {
	Status        string        // "pass" | "fail"
	Checks        []CheckResult
	UptimeSeconds float64
}

type CheckResult struct {
	Name       string
	Status     string
	DurationMS float64
	Error      string
}

HealthReport always returns everything: it is for your code (an internal status page, a startup gate). The endpoint decides what to reveal.

Metrics registry#

func (a *App) Metrics() *Metrics

func (m *Metrics) Counter(name, help string, labels ...string) *Counter
func (m *Metrics) Gauge(name, help string, labels ...string) *Gauge
func (m *Metrics) Histogram(name, help string, buckets []float64, labels ...string) *Histogram

MaxSeries (a thousand by default) caps the label combinations per metric; the overflow falls into one series with every label set to other and a single warning in the log.

TypeMethods
*CounterInc(), Add(v), With(values...)
*GaugeSet(v), Add(v), Inc(), Dec(), With(values...)
*HistogramObserve(v), With(values...)

An invalid name (outside [a-zA-Z_:][a-zA-Z0-9_:]*) or the wrong number of label values causes a panic: it is a programming error, shows up on the first run and does not corrupt the output. Calling Counter twice with the same name returns the same series.

Histogram with nil buckets uses the defaults, in seconds: 0.001 0.005 0.01 0.025 0.05 0.1 0.25 0.5 1 2.5 5 10.

Framework metrics#

MetricTypeLabels
trilha_requests_totalcountermethod, route, status
trilha_request_duration_secondshistogrammethod, route
trilha_requests_in_flightgauge
trilha_security_events_totalcounterkind (csrf, auth, body, rate, panic)
trilha_panics_totalcounter
go_goroutines, go_memstats_alloc_bytes, go_memstats_sys_bytesgauges
go_gc_cycles_totalcounter
trilha_uptime_secondsgauge
trilha_build_infogauge (always 1)version, go_version

route is the registered pattern (/blog/{slug}). Static files, 404 and anything outside the router come in as other.

Correlation#

func (c *Ctx) RequestID() string  // the client's X-Request-ID, or generated
func (c *Ctx) TraceID() string    // W3C traceparent; "" when absent or malformed
func (c *Ctx) Log() *slog.Logger  // logger with request_id and trace_id

A malformed traceparent is silently dropped: a value chosen by a third party does not enter the log as if it were a legitimate trace.

What the audit checks#

trilha audit adds these items: token too short (critical), metrics configured without a token or a trusted network (critical), 0.0.0.0/0 in Trusted (warning) and no a.Check( anywhere in the project (warning).