Instrument business logic (RED)¶
Not everything worth measuring is an HTTP request or an RPC. Operations gives any
piece of business logic the same RED signals — Rate, Errors, Duration — by
wrapping a function. It's the generic instrument for "how often does this run, how
often does it fail, and how long does it take?"
ops, err := m.NewOperations()
if err != nil { return err }
err = ops.Observe(ctx, "reindex", func() error {
return search.Reindex(ctx)
})
That one call records, labelled by the operation name:
| Metric | Type |
|---|---|
operations_total{operation} |
counter |
operation_errors_total{operation} |
counter (incremented when the fn returns an error) |
operation_duration_seconds{operation} |
histogram |
operations_in_flight{operation} |
gauge |
The function's error is returned unchanged, so Observe drops cleanly into existing
code:
if err := ops.Observe(ctx, "settle_payment", func() error {
return payments.Settle(ctx, id)
}); err != nil {
return err
}
Returning a value¶
Use ObserveResult when the operation produces a value:
report, err := metrics.ObserveResult(ops, ctx, "build_report", func() (Report, error) {
return builder.Build(ctx)
})
Exemplars¶
If m has an exemplar source, the operation_duration_seconds
sample carries the current trace_id, so a slow operation on a dashboard links to
its trace — just like the HTTP and gRPC instrumentation.
Keep the operation name bounded¶
The operation label must come from a small, fixed set of names ("reindex",
"settle_payment") — a compile-time constant, not an interpolated id. See
Cardinality safety.
Options¶
NewOperations accepts the shared helper options: WithNamespace, WithBuckets,
WithConstLabels — see Instrument resources for the same
set.