API Reference
12 minute read
Complete API reference for the Tracer type and all tracing methods.
Tracer Type
type Tracer struct {
// contains filtered or unexported fields
}
The main entry point for distributed tracing. Holds OpenTelemetry tracing configuration and runtime state. All operations on Tracer are thread-safe.
Important Notes
- Immutable: Tracer is immutable after creation via
New(). All configuration must be done through functional options. - Thread-safe: All methods are safe for concurrent use.
- Global state: By default, does NOT set the global OpenTelemetry tracer provider. Use
WithGlobalTracerProvider()option if needed.
Constructor Functions
New
func New(opts ...Option) (*Tracer, error)
Creates a new Tracer with the given options. Returns an error if the tracing provider fails to initialize. When using OTLP options (WithOTLP, WithOTLPHTTP), you must call Start(ctx) before traces are exported; otherwise no traces are exported and no error is returned—only a one-time log warning when the first span is created.
Default configuration:
- Service name:
"rivaas-service". - Service version:
"1.0.0". - Sample rate:
1.0(100%). - Provider:
NoopProvider.
Example:
tracer, err := tracing.New(
tracing.WithServiceName("my-api"),
tracing.WithOTLP("localhost:4317"),
tracing.WithSampleRate(0.1),
)
if err != nil {
log.Fatal(err)
}
defer tracer.Shutdown(context.Background())
MustNew
func MustNew(opts ...Option) *Tracer
Creates a new Tracer with the given options. Panics with an error if the tracing provider fails to initialize. Callers that recover from the panic get an error they can unwrap with errors.As / errors.Is; the error message describes the failure. Use this when you want to panic on initialization errors.
Example:
tracer := tracing.MustNew(
tracing.WithServiceName("my-api"),
tracing.WithStdout(),
)
defer tracer.Shutdown(context.Background())
Middleware constructors
Middleware
func Middleware(tracer *Tracer, opts ...MiddlewareOption) (func(http.Handler) http.Handler, error)
Creates HTTP middleware for standalone request tracing. Returns the middleware function and an error if the tracer is nil or any option is invalid (e.g. nil option, invalid regex in path exclusion). Use for config-driven setup or when you need to handle errors.
Example:
handler, err := tracing.Middleware(tracer,
tracing.WithExcludePaths("/health", "/metrics"),
tracing.WithHeaders("X-Request-ID"),
)
if err != nil {
log.Fatal(err)
}
http.ListenAndServe(":8080", handler(mux))
MustMiddleware
func MustMiddleware(tracer *Tracer, opts ...MiddlewareOption) func(http.Handler) http.Handler
Same as Middleware but panics with an error on failure. Callers that recover from the panic get an error they can unwrap with errors.As / errors.Is. Use when invalid options are a programming error.
Example:
handler := tracing.MustMiddleware(tracer,
tracing.WithExcludePaths("/health", "/metrics"),
)(mux)
http.ListenAndServe(":8080", handler)
Lifecycle Methods
Start
func (t *Tracer) Start(ctx context.Context) error
Initializes OTLP providers that require network connections. When using OTLP, you must call Start(ctx) before traces are exported; forgetting it results in no traces and no error at New, and a one-time log warning when the first span is created. The context is used for the OTLP connection establishment. This method is idempotent; calling it multiple times is safe.
Required for: OTLP (gRPC and HTTP) providers
Optional for: Noop and Stdout providers (they initialize immediately in New())
Example:
tracer := tracing.MustNew(
tracing.WithOTLP("localhost:4317"),
)
if err := tracer.Start(context.Background()); err != nil {
log.Fatal(err)
}
RequiresStart
func (t *Tracer) RequiresStart() bool
Returns true if the tracer uses an OTLP provider and therefore requires Start(ctx) to be called before traces are exported. Use in tests or wiring code to assert that Start must be called.
Example:
if tracer.RequiresStart() && !tracer.IsStarted() {
log.Fatal("OTLP tracer must be started before use")
}
IsStarted
func (t *Tracer) IsStarted() bool
Returns true after Start() has been called. Use in tests or wiring code to assert that the tracer was started when required (e.g. when RequiresStart() is true).
Example:
tracer, _ := tracing.New(tracing.WithOTLP("localhost:4317"))
require.True(t, tracer.RequiresStart())
require.False(t, tracer.IsStarted())
require.NoError(t, tracer.Start(ctx))
require.True(t, tracer.IsStarted())
Shutdown
func (t *Tracer) Shutdown(ctx context.Context) error
Gracefully shuts down the tracing system, flushing any pending spans. This should be called before the application exits to ensure all spans are exported. This method is idempotent - calling it multiple times is safe and will only perform shutdown once.
Example:
defer func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := tracer.Shutdown(ctx); err != nil {
log.Printf("Error shutting down tracer: %v", err)
}
}()
Span Management Methods
StartSpan
func (t *Tracer) StartSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span)
Starts a new span with the given name and options. Returns a new context with the span attached and the span itself.
If tracing is disabled, returns the original context and a non-recording span. The returned span should always be ended, even if tracing is disabled.
Parameters:
ctx: Parent contextname: Span name (should be descriptive)opts: Optional OpenTelemetry span start options
Returns:
- New context with span attached
- The created span
Example:
ctx, span := tracer.StartSpan(ctx, "database-query")
defer tracer.FinishSpan(span)
tracer.SetSpanAttribute(span, "db.query", "SELECT * FROM users")
FinishSpan
func (t *Tracer) FinishSpan(span trace.Span)
Ends the span with status Ok. Use for child spans that complete successfully and have no HTTP status. Safe to call multiple times; subsequent calls are no-ops.
Example:
defer tracer.FinishSpan(span)
FinishSpanWithHTTPStatus
func (t *Tracer) FinishSpanWithHTTPStatus(span trace.Span, statusCode int)
Ends the span and sets status from the HTTP status code: 2xx-3xx → Ok, 4xx-5xx → Error. Use for request-level spans or when you have an HTTP status. Safe to call multiple times.
Example:
defer tracer.FinishSpanWithHTTPStatus(span, rw.Status())
FinishSpanWithError
func (t *Tracer) FinishSpanWithError(span trace.Span, err error)
Marks the span as failed with the given error, sets standard error attributes (exception.type, exception.message, error), and ends the span. Status description is err.Error(). Safe to call multiple times.
Example:
if err != nil {
tracer.FinishSpanWithError(span, err)
return err
}
tracer.FinishSpan(span)
RecordError
func (t *Tracer) RecordError(span trace.Span, err error)
Records an error on the span without ending it. Sets exception attributes and span status to Error. Use when an error occurs mid-span and you want to record it but continue (e.g. retry). Call FinishSpan or FinishSpanWithError when the span ends.
Example:
if err := step(); err != nil {
tracer.RecordError(span, err)
}
defer tracer.FinishSpan(span)
WithSpan
func (t *Tracer) WithSpan(ctx context.Context, name string, fn func(context.Context) error) error
Runs fn under a new span with the given name. The span is finished with success (FinishSpan) if fn returns nil, or with error (FinishSpanWithError) if fn returns a non-nil error. Returns the error from fn.
Example:
err := tracer.WithSpan(ctx, "process-order", func(ctx context.Context) error {
return processOrder(ctx, id)
})
SetSpanAttribute
func (t *Tracer) SetSpanAttribute(span trace.Span, key string, value any)
Adds an attribute to the span with type-safe handling.
Supported types:
string,int,int64,float64,bool: native OpenTelemetry handling- Other types: converted to string using
fmt.Sprintf
This is a no-op if tracing is disabled, span is nil, or span is not recording.
Parameters:
span: The span to add the attribute tokey: Attribute keyvalue: Attribute value
Example:
tracer.SetSpanAttribute(span, "user.id", 12345)
tracer.SetSpanAttribute(span, "user.premium", true)
tracer.SetSpanAttribute(span, "user.name", "Alice")
AddSpanEvent
func (t *Tracer) AddSpanEvent(span trace.Span, name string, attrs ...attribute.KeyValue)
Adds an event to the span with optional attributes. Events represent important moments in a span’s lifetime.
This is a no-op if tracing is disabled, span is nil, or span is not recording.
Parameters:
span: The span to add the event toname: Event nameattrs: Optional event attributes
Example:
import "go.opentelemetry.io/otel/attribute"
tracer.AddSpanEvent(span, "cache_hit",
attribute.String("key", "user:123"),
attribute.Int("ttl_seconds", 300),
)
Context Propagation Methods
ExtractTraceContext
func (t *Tracer) ExtractTraceContext(ctx context.Context, headers http.Header) context.Context
Extracts trace context from HTTP request headers. Returns a new context with the extracted trace information.
If no trace context is found in headers, returns the original context. Uses W3C Trace Context format by default.
Parameters:
ctx: Base contextheaders: HTTP headers to extract from
Returns:
- Context with extracted trace information
Example:
ctx := tracer.ExtractTraceContext(r.Context(), r.Header)
ctx, span := tracer.StartSpan(ctx, "operation")
defer tracer.FinishSpan(span)
InjectTraceContext
func (t *Tracer) InjectTraceContext(ctx context.Context, headers http.Header)
Injects trace context into HTTP headers. This allows trace context to propagate across service boundaries.
Uses W3C Trace Context format by default. This is a no-op if tracing is disabled.
Parameters:
ctx: Context containing trace informationheaders: HTTP headers to inject into
Example:
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
tracer.InjectTraceContext(ctx, req.Header)
resp, _ := http.DefaultClient.Do(req)
Request Span Methods
Use these when you integrate tracing with your own HTTP stack (for example the app package calls StartRequestSpan / FinishRequestSpan). Standalone tracing.Middleware does not use StartRequestSpan; it uses an internal helper with the same propagation, sampling, and core attributes, but sets http.route from req.URL.Path and rivaas.router.static_route to true.
StartRequestSpan
func (t *Tracer) StartRequestSpan(ctx context.Context, req *http.Request, path string, isStatic bool) (context.Context, trace.Span)
Starts a span for an HTTP request with standard attributes. The path argument becomes http.route (for example a matched route template). isStatic is stored as rivaas.router.static_route. Span start / finish hooks run when configured.
Parameters:
ctx: Request contextreq: HTTP requestpath: Route or path label forhttp.route(caller-defined)isStatic: Whether the route is static; setsrivaas.router.static_route
Returns:
- Context with span
- The created span
FinishRequestSpan
func (t *Tracer) FinishRequestSpan(span trace.Span, statusCode int)
Completes the span for an HTTP request. Sets the HTTP status code attribute and invokes the span finish hook if configured.
Parameters:
span: The span to finishstatusCode: HTTP response status code
Accessor Methods
IsEnabled
func (t *Tracer) IsEnabled() bool
Returns true if tracing is enabled.
ServiceName
func (t *Tracer) ServiceName() string
Returns the service name.
ServiceVersion
func (t *Tracer) ServiceVersion() string
Returns the service version.
GetTracer
func (t *Tracer) GetTracer() trace.Tracer
Returns the OpenTelemetry tracer.
GetPropagator
func (t *Tracer) GetPropagator() propagation.TextMapPropagator
Returns the OpenTelemetry propagator.
GetProvider
func (t *Tracer) GetProvider() Provider
Returns the current tracing provider. If tracing is disabled (IsEnabled() is false), returns an empty Provider ("").
Context Helper Functions
These are package-level functions for working with spans through context.
CopyTraceContext
func CopyTraceContext(ctx context.Context) context.Context
Returns a new context that carries the current trace (span context) from ctx but has no active span. Use when starting goroutines or background work so new spans created in that context are linked to the same trace. If ctx has no valid span context, returns context.Background().
Example:
traceCtx := tracing.CopyTraceContext(r.Context())
go func() {
_, span := tracer.StartSpan(traceCtx, "async-job")
defer tracer.FinishSpan(span)
doAsyncWork(ctx)
}()
RecordErrorFromContext
func RecordErrorFromContext(ctx context.Context, err error)
Records an error on the current span in ctx without ending it. Sets exception attributes and span status to Error. No-op if ctx has no recording span or err is nil.
Example:
if err := step(); err != nil {
tracing.RecordErrorFromContext(ctx, err)
}
TraceID
func TraceID(ctx context.Context) string
Returns the current trace ID from the active span in the context. Returns an empty string if no active span or span context is invalid.
Example:
traceID := tracing.TraceID(ctx)
log.Printf("Processing request [trace=%s]", traceID)
SpanID
func SpanID(ctx context.Context) string
Returns the current span ID from the active span in the context. Returns an empty string if no active span or span context is invalid.
Example:
spanID := tracing.SpanID(ctx)
log.Printf("Processing request [span=%s]", spanID)
SetSpanAttributeFromContext
func SetSpanAttributeFromContext(ctx context.Context, key string, value any)
Adds an attribute to the current span from context. Convenience for when you only have context (e.g. from the tracing middleware); corresponds to tracer.SetSpanAttribute(span, key, value) when you have the tracer and span. This is a no-op if tracing is not active.
Example:
func handleRequest(ctx context.Context) {
tracing.SetSpanAttributeFromContext(ctx, "user.role", "admin")
tracing.SetSpanAttributeFromContext(ctx, "user.id", 12345)
}
AddSpanEventFromContext
func AddSpanEventFromContext(ctx context.Context, name string, attrs ...attribute.KeyValue)
Adds an event to the current span from context. Convenience for when you only have context (e.g. from the tracing middleware); corresponds to tracer.AddSpanEvent(span, name, attrs...) when you have the tracer and span. This is a no-op if tracing is not active.
Example:
import "go.opentelemetry.io/otel/attribute"
tracing.AddSpanEventFromContext(ctx, "cache_miss",
attribute.String("key", "user:123"),
)
TraceContext
func TraceContext(ctx context.Context) context.Context
Returns the context as-is (it should already contain trace information). Provided for API consistency.
Internal operational events are logged at the appropriate slog level via the logger passed to [WithLogger]. See WithLogger in Options.
App Context (rivaas.dev/app)
When using the app package with tracing enabled, the request context *app.Context exposes the same semantics via:
| Method | Description |
|---|---|
FinishSpan(span) | End child span with success. Delegates to tracing.FinishSpan. |
FinishSpanWithHTTPStatus(span, statusCode) | End span with HTTP status. Delegates to tracing.FinishSpanWithHTTPStatus. |
FinishSpanWithError(span, err) | End span with error. Delegates to tracing.FinishSpanWithError. |
RecordError(err) | Record error on request span without ending it. Uses tracing.RecordErrorFromContext(c.RequestContext(), err). |
CopyTraceContext() | New context with same trace for goroutines. Delegates to tracing.CopyTraceContext(c.RequestContext()). |
WithSpan(name, fn) | Run fn under a span; finish with success or error from return. Uses c.StartSpan and FinishSpan / FinishSpanWithError. |
Example:
err := c.WithSpan("fetch-user", func(ctx context.Context) error {
user, err := fetchUser(ctx, id)
if err != nil {
return err
}
return c.JSON(http.StatusOK, user)
})
Hook Types
SpanStartHook
type SpanStartHook func(ctx context.Context, span trace.Span, req *http.Request)
Called when a request span is started. It receives the context, span, and HTTP request. This can be used for custom attribute injection, dynamic sampling, or integration with APM tools.
Example:
hook := func(ctx context.Context, span trace.Span, req *http.Request) {
if tenantID := req.Header.Get("X-Tenant-ID"); tenantID != "" {
span.SetAttributes(attribute.String("tenant.id", tenantID))
}
}
tracer := tracing.MustNew(
tracing.WithSpanStartHook(hook),
)
SpanFinishHook
type SpanFinishHook func(span trace.Span, statusCode int)
Called when a request span is finished. It receives the span and the HTTP status code. This can be used for custom metrics, logging, or post-processing.
Example:
hook := func(span trace.Span, statusCode int) {
if statusCode >= 500 {
metrics.IncrementServerErrors()
}
}
tracer := tracing.MustNew(
tracing.WithSpanFinishHook(hook),
)
ContextTracing Type
type ContextTracing struct {
// contains filtered or unexported fields
}
A helper type for router context integration that provides convenient access to tracing functionality within HTTP handlers.
NewContextTracing
func NewContextTracing(ctx context.Context, tracer *Tracer, span trace.Span) *ContextTracing
Creates a new context tracing helper. Panics if ctx, tracer, or span is nil with one of: tracing: nil context passed to NewContextTracing, tracing: tracer cannot be nil, tracing: span cannot be nil.
Parameters:
ctx: The request context (must not be nil)tracer: The Tracer instance (must not be nil)span: The current span (must not be nil)
Example:
ct := tracing.NewContextTracing(ctx, tracer, span)
ContextTracing Methods
TraceID
func (ct *ContextTracing) TraceID() string
Returns the current trace ID. Returns an empty string if no valid span.
SpanID
func (ct *ContextTracing) SpanID() string
Returns the current span ID. Returns an empty string if no valid span.
SetSpanAttribute
func (ct *ContextTracing) SetSpanAttribute(key string, value any)
Adds an attribute to the current span. No-op if span is nil or not recording.
AddSpanEvent
func (ct *ContextTracing) AddSpanEvent(name string, attrs ...attribute.KeyValue)
Adds an event to the current span. No-op if span is nil or not recording.
TraceContext
func (ct *ContextTracing) TraceContext() context.Context
Returns the trace context.
GetSpan
func (ct *ContextTracing) GetSpan() trace.Span
Returns the current span.
GetTracer
func (ct *ContextTracing) GetTracer() *Tracer
Returns the underlying Tracer.
ContextTracing Example
func handleRequest(w http.ResponseWriter, r *http.Request, tracer *tracing.Tracer) {
ctx := r.Context()
span := trace.SpanFromContext(ctx)
// Create context tracing helper
ct := tracing.NewContextTracing(ctx, tracer, span)
// Use helper methods
ct.SetSpanAttribute("user.id", "123")
ct.AddSpanEvent("processing_started")
// Get trace info for logging
log.Printf("Processing [trace=%s, span=%s]", ct.TraceID(), ct.SpanID())
}
Constants
Default Values
const (
DefaultServiceName = "rivaas-service"
DefaultServiceVersion = "1.0.0"
DefaultSampleRate = 1.0
)
Default configuration values used when not explicitly set.
Provider Types
const (
NoopProvider Provider = "noop"
StdoutProvider Provider = "stdout"
OTLPProvider Provider = "otlp"
OTLPHTTPProvider Provider = "otlp-http"
)
Available tracing providers.
Next Steps
- Review Options for all configuration options
- Check Middleware Options for HTTP middleware
- See Troubleshooting for common issues
- Explore the Tracing Guide for learning-focused content
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.