When changing or adding metrics/traces, make signals stable, accurate, and alert-friendly.
Apply these rules before submitting:
1) Preserve metric semantics and document scope
2) Use the right labeling approach (avoid redundant series)
status/result label when the values are the same logical event (e.g., complete vs incomplete vs error), rather than adding many separate counters.3) Suppress expected/noisy error increments
4) Design duration histograms from meaningful timestamps
5) For tracing: always propagate the provided context
ctx as the parent (don’t start from context.Background()), so nested spans are correctly correlated.Example pattern (metrics + context propagation):
func (h *handler) Sync(ctx context.Context, req *Request) {
// Tracing: use ctx as parent
ctx, span := h.tracer.Start(ctx, "syncRequest")
defer span.End()
// Metrics: measure from a meaningful point
start := time.Now() // or a controller-observed timestamp
result := doWork(req)
// Error metrics: gate expected backoff/retry cases
if result.Err != nil && !isExpectedBackoff(result.Err) {
metrics.SyncErrorsTotal.WithLabelValues("sync").Inc()
}
// Duration: buckets should match the resolution/intent
metrics.RequestProcessingDurationSeconds.Observe(time.Since(start).Seconds())
}
Following these rules keeps dashboards stable, prevents alert fatigue, and ensures traces and metrics can be trusted together.