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, as the HTTP and gRPC instrumentation does.
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.