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 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
}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 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)
}The Start method creates a new span and returns a context containing that span. Key behaviors:
ctx contains a span, the new span becomes its childWithNewRoot() option to create a root span regardless of parentimport (
"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 applies configuration to a Tracer when it's created.
type TracerOption interface {
// contains unexported methods
}// 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) TracerOptionimport (
"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 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// 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() stringA 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() TracerProviderFor production use, prefer the noop package:
import "go.opentelemetry.io/otel/trace/noop"
tp := noop.NewTracerProvider()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:
import "go.opentelemetry.io/otel"
func init() {
tracer = otel.Tracer("my-service")
}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: