or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

embedded.mdindex.mdnoop.mdspan-context.mdspan-options.mdspan.mdtracer-provider-tracer.md
tile.json

tracer-provider-tracer.mddocs/

TracerProvider and Tracer

TracerProvider and Tracer are the factory interfaces for creating and managing spans. TracerProvider represents the telemetry collection pipeline, while Tracer creates spans for a specific instrumentation scope.

TracerProvider Interface

TracerProvider provides Tracers for instrumentation code. It represents the collection destination of all spans from the tracers it creates.

type TracerProvider interface {
    // Users of the interface can ignore this. This embedded type is only used
    // by implementations of this interface.
    embedded.TracerProvider

    // Tracer returns a unique Tracer scoped to be used by instrumentation code
    // to trace computational workflows. The scope and identity of that
    // instrumentation code is uniquely defined by the name and options passed.
    //
    // The passed name needs to uniquely identify instrumentation code.
    // Therefore, it is recommended that name is the Go package name of the
    // library providing instrumentation (note: not the code being instrumented).
    // Instrumentation libraries can have multiple versions, therefore, the
    // WithInstrumentationVersion option should be used to distinguish these
    // different codebases.
    //
    // If the same name and options are passed multiple times, the same Tracer
    // will be returned (it is up to the implementation if this will be the
    // same underlying instance of that Tracer or not). It is not necessary to
    // call this multiple times with the same name and options to get an
    // up-to-date Tracer. All implementations will ensure any TracerProvider
    // configuration changes are propagated to all provided Tracers.
    //
    // If name is empty, then an implementation defined default name will be
    // used instead.
    //
    // This method is safe to call concurrently.
    Tracer(name string, options ...TracerOption) Tracer
}

Usage Example

package mylib

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/trace"
)

const (
    instrumentationName    = "github.com/example/mylib"
    instrumentationVersion = "v1.2.3"
)

type Library struct {
    tracer trace.Tracer
}

// NewLibrary creates a new instance accepting a TracerProvider.
// If tp is nil, uses the global TracerProvider.
func NewLibrary(tp trace.TracerProvider) *Library {
    if tp == nil {
        tp = otel.TracerProvider()
    }

    return &Library{
        tracer: tp.Tracer(
            instrumentationName,
            trace.WithInstrumentationVersion(instrumentationVersion),
        ),
    }
}

func (l *Library) DoWork(ctx context.Context) {
    ctx, span := l.tracer.Start(ctx, "DoWork")
    defer span.End()
    // ... work happens here
}

Tracer Interface

Tracer is the creator of Spans. It is unique to the instrumentation scope.

type Tracer interface {
    // Users of the interface can ignore this. This embedded type is only used
    // by implementations of this interface.
    embedded.Tracer

    // Start creates a span and a context.Context containing the newly-created span.
    //
    // If the context.Context provided in `ctx` contains a Span then the newly-created
    // Span will be a child of that span, otherwise it will be a root span. This behavior
    // can be overridden by providing `WithNewRoot()` as a SpanOption, causing the
    // newly-created Span to be a root span even if `ctx` contains a Span.
    //
    // When creating a Span it is recommended to provide all known span attributes using
    // the `WithAttributes()` SpanOption as samplers will only have access to the
    // attributes provided when a Span is created.
    //
    // Any Span that is created MUST also be ended. This is the responsibility of the user.
    // Implementations of this API may leak memory or other resources if Spans are not ended.
    Start(ctx context.Context, spanName string, opts ...SpanStartOption) (context.Context, Span)
}

Start Method Details

The Start method creates a new span and returns a context containing that span. Key behaviors:

  1. Parent-child relationships: If ctx contains a span, the new span becomes its child
  2. Root spans: Use WithNewRoot() option to create a root span regardless of parent
  3. Attribute timing: Samplers only see attributes provided at creation time
  4. Resource management: Every span MUST be ended to prevent leaks

Usage Example

import (
    "context"
    "go.opentelemetry.io/otel/trace"
    "go.opentelemetry.io/otel/attribute"
)

func processRequest(ctx context.Context, tracer trace.Tracer, requestID string) error {
    // Create span with initial attributes for sampling decisions
    ctx, span := tracer.Start(ctx, "processRequest",
        trace.WithAttributes(
            attribute.String("request.id", requestID),
            attribute.String("operation.type", "process"),
        ),
        trace.WithSpanKind(trace.SpanKindServer),
    )
    defer span.End()

    // Child spans automatically link to parent through context
    if err := fetchData(ctx, tracer); err != nil {
        return err
    }

    return saveResults(ctx, tracer)
}

func fetchData(ctx context.Context, tracer trace.Tracer) error {
    // This span's parent is the processRequest span
    ctx, span := tracer.Start(ctx, "fetchData")
    defer span.End()

    // ... fetch data
    return nil
}

func saveResults(ctx context.Context, tracer trace.Tracer) error {
    // This span is also a child of processRequest (sibling to fetchData)
    ctx, span := tracer.Start(ctx, "saveResults")
    defer span.End()

    // ... save results
    return nil
}

TracerOption

TracerOption applies configuration to a Tracer when it's created.

type TracerOption interface {
    // contains unexported methods
}

Available TracerOptions

// WithInstrumentationVersion sets the instrumentation version.
func WithInstrumentationVersion(version string) TracerOption

// WithInstrumentationAttributes sets the instrumentation attributes.
// The passed attributes will be de-duplicated.
func WithInstrumentationAttributes(attr ...attribute.KeyValue) TracerOption

// WithSchemaURL sets the schema URL for the Tracer.
func WithSchemaURL(schemaURL string) TracerOption

Usage Example

import (
    "go.opentelemetry.io/otel/trace"
    "go.opentelemetry.io/otel/attribute"
)

tracer := tp.Tracer(
    "github.com/example/mylib",
    trace.WithInstrumentationVersion("v1.2.3"),
    trace.WithInstrumentationAttributes(
        attribute.String("library.language", "go"),
        attribute.String("library.platform", "linux"),
    ),
    trace.WithSchemaURL("https://opentelemetry.io/schemas/1.21.0"),
)

TracerConfig

TracerConfig holds the configuration for a Tracer. It's typically used by SDK implementations.

type TracerConfig struct {
    // contains unexported fields
}

// NewTracerConfig applies all the options to a returned TracerConfig.
func NewTracerConfig(options ...TracerOption) TracerConfig

TracerConfig Methods

// InstrumentationVersion returns the version of the library providing instrumentation.
func (t *TracerConfig) InstrumentationVersion() string

// InstrumentationAttributes returns the attributes associated with the library
// providing instrumentation.
func (t *TracerConfig) InstrumentationAttributes() attribute.Set

// SchemaURL returns the Schema URL of the telemetry emitted by the Tracer.
func (t *TracerConfig) SchemaURL() string

No-Op TracerProvider

A no-op TracerProvider is available for testing or disabling telemetry:

// NewNoopTracerProvider returns an implementation of TracerProvider that
// performs no operations. The Tracer and Spans created from the returned
// TracerProvider also perform no operations.
//
// Deprecated: Use go.opentelemetry.io/otel/trace/noop.NewTracerProvider instead.
func NewNoopTracerProvider() TracerProvider

For production use, prefer the noop package:

import "go.opentelemetry.io/otel/trace/noop"

tp := noop.NewTracerProvider()

Creating Root Spans

To create a root span (ignoring any parent in context):

ctx, span := tracer.Start(ctx, "rootOperation",
    trace.WithNewRoot(),
)
defer span.End()

This is useful when:

  • Starting a new trace from a public endpoint
  • Untrusted parent context should be ignored for security
  • Creating independent traces in batch processing

Global vs Injected TracerProvider

Using Global TracerProvider

import "go.opentelemetry.io/otel"

func init() {
    tracer = otel.Tracer("my-service")
}

Using Injected TracerProvider (Recommended)

type Service struct {
    tracer trace.Tracer
}

func NewService(tp trace.TracerProvider) *Service {
    if tp == nil {
        tp = otel.TracerProvider()
    }
    return &Service{
        tracer: tp.Tracer("my-service"),
    }
}

Injecting the TracerProvider provides:

  • Better testability (can inject mock or no-op provider)
  • Explicit dependencies
  • Easier to configure different providers per component