Observability
Native OpenTelemetry tracing support with zero overhead when disabled, plus diagnostic events.
2 minute read
The router includes native OpenTelemetry tracing support and optional diagnostic events.
OpenTelemetry Tracing
Enable Tracing
r := router.New(router.WithTracing())
Configuration Options
r := router.New(
router.WithTracing(),
router.WithTracingServiceName("my-api"),
router.WithTracingServiceVersion("v1.2.3"),
router.WithTracingSampleRate(0.1), // 10% sampling
router.WithTracingExcludePaths("/health", "/metrics"),
)
Context Tracing Methods
func handler(c *router.Context) {
// Get trace/span IDs
traceID := c.TraceID()
spanID := c.SpanID()
// Add custom attributes
c.SetSpanAttribute("user.id", "123")
c.SetSpanAttribute("operation.type", "database_query")
// Add events
c.AddSpanEvent("processing_started")
c.AddSpanEvent("cache_miss",
attribute.String("cache.key", "user:123"),
)
}
Complete Tracing Example
package main
import (
"context"
"log"
"net/http"
"rivaas.dev/router"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/trace"
)
func main() {
// Initialize Jaeger exporter
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(
jaeger.WithEndpoint("http://localhost:14268/api/traces"),
))
if err != nil {
log.Fatal(err)
}
tp := trace.NewTracerProvider(
trace.WithBatcher(exp),
trace.WithSampler(trace.TraceIDRatioBased(0.1)),
)
otel.SetTracerProvider(tp)
// Create router with tracing
r := router.New(
router.WithTracing(),
router.WithTracingServiceName("my-service"),
)
r.GET("/", func(c *router.Context) {
c.SetSpanAttribute("handler", "home")
c.JSON(200, map[string]string{"message": "Hello"})
})
defer tp.Shutdown(context.Background())
log.Fatal(http.ListenAndServe(":8080", r))
}
Diagnostics
Enable diagnostic events for security concerns and configuration issues:
import "log/slog"
handler := router.DiagnosticHandlerFunc(func(e router.DiagnosticEvent) {
slog.Warn(e.Message, "kind", e.Kind, "fields", e.Fields)
})
r := router.New(router.WithDiagnostics(handler))
Diagnostic Event Types
DiagXFFSuspicious- Suspicious X-Forwarded-For chain detectedDiagHeaderInjection- Header injection attempt blockedDiagInvalidProto- Invalid X-Forwarded-Proto valueDiagHighParamCount- Route has >8 parameters (uses map storage)DiagH2CEnabled- H2C enabled (development warning)
Example with Metrics
handler := router.DiagnosticHandlerFunc(func(e router.DiagnosticEvent) {
metrics.Increment("router.diagnostics", "kind", string(e.Kind))
})
r := router.New(router.WithDiagnostics(handler))
Best Practices
Use path exclusion for high-frequency endpoints:
router.WithTracingExcludePaths("/health", "/metrics", "/ping")Set appropriate sampling rates in production:
router.WithTracingSampleRate(0.01) // 1% samplingAdd meaningful attributes in handlers:
c.SetSpanAttribute("user.id", userID) c.SetSpanAttribute("operation.type", "database_query")Disable parameter recording for sensitive data:
router.WithTracingDisableParams()
Next Steps
- Static Files: Learn about static file serving
- Testing: See testing patterns
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.