Documentation
¶
Overview ¶
Package otel provides OpenTelemetry integration for distributed tracing, metrics, and logging correlation in Tjo applications.
Usage:
provider, err := otel.New(otel.Config{
ServiceName: "my-app",
Endpoint: "localhost:4317",
})
if err != nil {
log.Fatal(err)
}
defer provider.Shutdown(context.Background())
// Use middleware
router.Use(provider.Middleware())
Package otel provides OpenTelemetry integration for Tjo applications.
Overview ¶
This package enables distributed tracing, metrics collection, and log correlation using the OpenTelemetry standard. It integrates seamlessly with Tjo's existing logging and metrics infrastructure.
Quick Start ¶
// Create provider
provider, err := otel.New(otel.Config{
ServiceName: "my-app",
Endpoint: "localhost:4317",
Insecure: true, // For local development
})
if err != nil {
log.Fatal(err)
}
defer provider.Shutdown(context.Background())
// Add middleware to your router
router.Use(provider.Middleware())
Tracing HTTP Requests ¶
The middleware automatically creates spans for all HTTP requests:
router.Use(provider.Middleware()) // All requests now have: // - Automatic span creation // - Request attributes (method, URL, status, etc.) // - Context propagation // - X-Trace-ID response header
Custom Spans ¶
Create custom spans for operations within your handlers:
func (h *Handler) ProcessOrder(w http.ResponseWriter, r *http.Request) {
ctx, span := otel.Start(r.Context(), "process_order")
defer span.End()
// Add attributes
otel.SetAttributes(ctx,
otel.String("order.id", orderID),
otel.Int("order.items", len(items)),
)
// Add events
otel.AddEvent(ctx, "validation_complete")
// Record errors
if err != nil {
otel.RecordError(ctx, err)
}
}
Database Tracing ¶
Wrap your database connection for automatic query tracing:
tracedDB := otel.WrapDB(db, "postgres", "myapp") rows, err := tracedDB.Query(ctx, "SELECT * FROM users WHERE id = ?", userID)
Log Correlation ¶
Add trace context to your logs:
logger := otel.LoggerWithTrace(ctx, g.Logging.Logger)
logger.Info("Processing request", nil)
// Logs include trace_id and span_id fields
Or add trace fields manually:
g.Logging.Logger.Info("Processing", otel.TraceFields(ctx))
Exporters ¶
The package supports three exporters:
- OTLP (recommended): Works with any OpenTelemetry Collector, Jaeger, etc.
- Zipkin: Direct export to Zipkin
- None: Disables export (useful for testing)
Example with OTLP:
provider, _ := otel.New(otel.Config{
ServiceName: "my-app",
Exporter: otel.ExporterOTLP,
Endpoint: "localhost:4317",
})
Sampling ¶
Control trace sampling to reduce overhead:
// Sample all traces (default, good for development) Sampler: otel.SamplerAlways // Sample 10% of traces (good for high-traffic production) Sampler: otel.SamplerRatio SampleRatio: 0.1 // Respect parent span's sampling decision Sampler: otel.SamplerParentBased
Environment Configuration ¶
Set these environment variables for configuration:
OTEL_ENABLED=true OTEL_SERVICE_NAME=my-app OTEL_SERVICE_VERSION=1.0.0 OTEL_EXPORTER=otlp OTEL_ENDPOINT=localhost:4317 OTEL_INSECURE=true OTEL_SAMPLER=ratio OTEL_SAMPLE_RATIO=0.1
Local Development with Jaeger ¶
Run Jaeger locally with Docker:
docker run -d --name jaeger \ -p 16686:16686 \ -p 4317:4317 \ jaegertracing/all-in-one:latest
Then view traces at http://localhost:16686
Index ¶
- Variables
- func AddCallerInfo(ctx context.Context)
- func AddEvent(ctx context.Context, name string, attrs ...attribute.KeyValue)
- func CallerInfo(skip int) (file string, line int, function string)
- func DBAttributes(system, name, statement string) []attribute.KeyValue
- func ErrorEvent(err error) (string, []attribute.KeyValue)
- func HTTPClientAttributes(method, url string, statusCode int) []attribute.KeyValue
- func LoggerWithTrace(ctx context.Context, logger *logging.Logger) *logging.Logger
- func MergeFields(ctx context.Context, additional map[string]interface{}) map[string]interface{}
- func MessagingAttributes(system, destination, operation string) []attribute.KeyValue
- func MetricsMiddleware(metrics *logging.ApplicationMetrics) func(http.Handler) http.Handler
- func Middleware(serviceName string) func(http.Handler) http.Handler
- func RecordDuration(histogram *logging.Histogram, start time.Time)
- func RecordError(ctx context.Context, err error, opts ...trace.EventOption)
- func SetAttributes(ctx context.Context, attrs ...attribute.KeyValue)
- func SetStatus(ctx context.Context, code codes.Code, description string)
- func SpanFromContext(ctx context.Context) trace.Span
- func SpanIDFromContext(ctx context.Context) string
- func Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span)
- func StartWithTracer(ctx context.Context, tracer trace.Tracer, name string, ...) (context.Context, trace.Span)
- func TraceFields(ctx context.Context) map[string]interface{}
- func TraceIDFromContext(ctx context.Context) string
- func WithSpan(ctx context.Context, name string, fn func(context.Context) error, ...) error
- func WithSpanResult[T any](ctx context.Context, name string, fn func(context.Context) (T, error), ...) (T, error)
- type Config
- type ExporterType
- type HTTPRequestMetrics
- type LogContext
- func (l *LogContext) Debug(message string, fields ...map[string]interface{})
- func (l *LogContext) Error(message string, fields ...map[string]interface{})
- func (l *LogContext) Info(message string, fields ...map[string]interface{})
- func (l *LogContext) Trace(message string, fields ...map[string]interface{})
- func (l *LogContext) Warn(message string, fields ...map[string]interface{})
- func (l *LogContext) WithField(key string, value interface{}) *LogContext
- func (l *LogContext) WithFields(fields map[string]interface{}) *LogContext
- type MetricsRecorder
- func (r *MetricsRecorder) Add(name string, delta int64)
- func (r *MetricsRecorder) Counter(name string) *logging.Counter
- func (r *MetricsRecorder) Gauge(name string) *logging.Gauge
- func (r *MetricsRecorder) Histogram(name string) *logging.Histogram
- func (r *MetricsRecorder) Inc(name string)
- func (r *MetricsRecorder) Observe(name string, value float64)
- func (r *MetricsRecorder) Set(name string, value int64)
- func (r *MetricsRecorder) TimeSince(name string, start time.Time)
- type Module
- type ModuleOption
- func WithAlwaysSample() ModuleOption
- func WithConfig(cfg Config) ModuleOption
- func WithEnvironment(env string) ModuleOption
- func WithOTLPExporter(endpoint string, insecure bool) ModuleOption
- func WithRatioSample(ratio float64) ModuleOption
- func WithServiceName(name string) ModuleOption
- func WithServiceVersion(version string) ModuleOption
- func WithZipkinExporter(endpoint string) ModuleOption
- type Provider
- func (p *Provider) Config() Config
- func (p *Provider) ForceFlush(ctx context.Context) error
- func (p *Provider) IsEnabled() bool
- func (p *Provider) Middleware() func(http.Handler) http.Handler
- func (p *Provider) Propagator() propagation.TextMapPropagator
- func (p *Provider) Shutdown(ctx context.Context) error
- func (p *Provider) Tracer() trace.Tracer
- func (p *Provider) TracerProvider() *sdktrace.TracerProvider
- type SamplerType
- type SpanMetrics
- type SpanOptions
- type TraceInfo
- type TracedDB
- func (t *TracedDB) Begin(ctx context.Context) (*TracedTx, error)
- func (t *TracedDB) Close() error
- func (t *TracedDB) DB() *sql.DB
- func (t *TracedDB) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
- func (t *TracedDB) Ping(ctx context.Context) error
- func (t *TracedDB) Prepare(ctx context.Context, query string) (*TracedStmt, error)
- func (t *TracedDB) Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
- func (t *TracedDB) QueryRow(ctx context.Context, query string, args ...interface{}) *sql.Row
- type TracedStmt
- type TracedTx
Constants ¶
This section is empty.
Variables ¶
var ( String = attribute.String Int = attribute.Int Int64 = attribute.Int64 Float64 = attribute.Float64 Bool = attribute.Bool )
Attr is a convenience function to create attributes.
Functions ¶
func AddCallerInfo ¶
AddCallerInfo adds source location as span attributes.
func CallerInfo ¶
CallerInfo returns file and line information for the caller. Useful for adding source location to spans.
func DBAttributes ¶
DBAttributes returns common database span attributes.
func ErrorEvent ¶
ErrorEvent creates a standard error event.
func HTTPClientAttributes ¶
HTTPClientAttributes returns common HTTP client span attributes.
func LoggerWithTrace ¶
LoggerWithTrace returns a logger with trace context fields added. This enables log correlation with traces.
Usage:
logger := otel.LoggerWithTrace(ctx, g.Logging.Logger)
logger.Info("Processing request", nil)
// Logs will include trace_id and span_id fields
func MergeFields ¶
MergeFields merges trace fields with additional fields.
func MessagingAttributes ¶
MessagingAttributes returns common messaging span attributes.
func MetricsMiddleware ¶
MetricsMiddleware returns a middleware that records HTTP metrics. It integrates with Tjo's existing metrics system.
func Middleware ¶
MiddlewareFunc is a convenience type for middleware without a provider. Use this when you want to use the global tracer.
func RecordDuration ¶
RecordDuration is a helper to record operation duration.
func RecordError ¶
func RecordError(ctx context.Context, err error, opts ...trace.EventOption)
RecordError records an error on the current span. The error is recorded as an event and the span status is set to Error.
func SetAttributes ¶
SetAttributes sets attributes on the current span.
func SpanFromContext ¶
SpanFromContext returns the current span from the context. Returns a no-op span if no span is present.
func SpanIDFromContext ¶
SpanIDFromContext extracts the span ID from the context. Returns an empty string if no span is active.
func Start ¶
func Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span)
Start creates a new span with the given name. It returns the updated context and the span. Remember to call span.End() when the operation is complete.
Usage:
ctx, span := otel.Start(ctx, "operation_name") defer span.End()
func StartWithTracer ¶
func StartWithTracer(ctx context.Context, tracer trace.Tracer, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span)
StartWithTracer creates a new span using the specified tracer.
func TraceFields ¶
TraceFields returns log fields with trace context. Use this when you want to add trace context to a log call.
Usage:
logger.Info("Processing", otel.TraceFields(ctx))
func TraceIDFromContext ¶
TraceIDFromContext extracts the trace ID from the context. Returns an empty string if no trace is active.
func WithSpan ¶
func WithSpan(ctx context.Context, name string, fn func(context.Context) error, opts ...trace.SpanStartOption) error
WithSpan executes a function within a new span. The span is automatically ended when the function returns. If the function returns an error, it is recorded on the span.
Usage:
err := otel.WithSpan(ctx, "process_data", func(ctx context.Context) error {
// Your code here
return nil
})
func WithSpanResult ¶
func WithSpanResult[T any](ctx context.Context, name string, fn func(context.Context) (T, error), opts ...trace.SpanStartOption) (T, error)
WithSpanResult executes a function within a new span and returns both result and error. Useful when you need to return a value from the traced operation.
Types ¶
type Config ¶
type Config struct {
// ServiceName identifies this service in traces. Required.
ServiceName string
// ServiceVersion is the version of this service (optional).
ServiceVersion string
// Environment identifies the deployment environment (e.g., "production", "staging").
Environment string
// Endpoint is the collector endpoint (e.g., "localhost:4317" for OTLP).
// Required unless Exporter is ExporterNone.
Endpoint string
// Exporter selects the telemetry exporter. Defaults to OTLP.
Exporter ExporterType
// Insecure disables TLS for the exporter connection.
// Set to true for local development.
Insecure bool
// Sampler selects the sampling strategy. Defaults to SamplerAlways.
Sampler SamplerType
// SampleRatio is the sampling ratio when Sampler is SamplerRatio.
// Value between 0.0 and 1.0. Defaults to 1.0.
SampleRatio float64
// EnableMetrics enables OpenTelemetry metrics collection.
// Metrics are exported alongside traces.
EnableMetrics bool
// EnableTracing enables distributed tracing. Defaults to true.
EnableTracing bool
// Headers are additional headers to send with exports (e.g., authentication).
Headers map[string]string
// ResourceAttributes are additional attributes to add to all spans.
ResourceAttributes map[string]string
// PropagateB3 enables B3 propagation format (used by Zipkin).
// By default, W3C TraceContext is used.
PropagateB3 bool
}
Config holds OpenTelemetry configuration.
type ExporterType ¶
type ExporterType string
ExporterType defines the telemetry exporter to use.
const ( // ExporterOTLP exports to an OTLP-compatible collector (recommended). ExporterOTLP ExporterType = "otlp" // ExporterJaeger exports directly to Jaeger. ExporterJaeger ExporterType = "jaeger" // ExporterZipkin exports directly to Zipkin. ExporterZipkin ExporterType = "zipkin" // ExporterNone disables exporting (useful for testing). ExporterNone ExporterType = "none" )
type HTTPRequestMetrics ¶
type HTTPRequestMetrics struct {
// contains filtered or unexported fields
}
HTTPRequestMetrics records metrics for an HTTP request. Use this when you need manual control over metric recording.
func StartRequest ¶
func StartRequest(metrics *logging.ApplicationMetrics, method, path string) *HTTPRequestMetrics
StartRequest begins tracking metrics for an HTTP request.
func (*HTTPRequestMetrics) End ¶
func (m *HTTPRequestMetrics) End(statusCode int)
End completes the metric recording for the request.
type LogContext ¶
type LogContext struct {
// contains filtered or unexported fields
}
LogContext provides logging methods that automatically include trace context.
func NewLogContext ¶
func NewLogContext(ctx context.Context, logger *logging.Logger) *LogContext
NewLogContext creates a new LogContext.
func (*LogContext) Debug ¶
func (l *LogContext) Debug(message string, fields ...map[string]interface{})
Debug logs a debug message with trace context.
func (*LogContext) Error ¶
func (l *LogContext) Error(message string, fields ...map[string]interface{})
Error logs an error message with trace context.
func (*LogContext) Info ¶
func (l *LogContext) Info(message string, fields ...map[string]interface{})
Info logs an info message with trace context.
func (*LogContext) Trace ¶
func (l *LogContext) Trace(message string, fields ...map[string]interface{})
Trace logs a trace message with trace context.
func (*LogContext) Warn ¶
func (l *LogContext) Warn(message string, fields ...map[string]interface{})
Warn logs a warning message with trace context.
func (*LogContext) WithField ¶
func (l *LogContext) WithField(key string, value interface{}) *LogContext
WithField adds a field and returns a new LogContext.
func (*LogContext) WithFields ¶
func (l *LogContext) WithFields(fields map[string]interface{}) *LogContext
WithFields adds fields and returns a new LogContext.
type MetricsRecorder ¶
type MetricsRecorder struct {
// contains filtered or unexported fields
}
MetricsRecorder provides a simple interface for recording custom metrics.
func NewMetricsRecorder ¶
func NewMetricsRecorder(registry *logging.MetricRegistry) *MetricsRecorder
NewMetricsRecorder creates a new metrics recorder.
func (*MetricsRecorder) Add ¶
func (r *MetricsRecorder) Add(name string, delta int64)
Add adds to a counter by name.
func (*MetricsRecorder) Counter ¶
func (r *MetricsRecorder) Counter(name string) *logging.Counter
Counter gets or creates a counter by name.
func (*MetricsRecorder) Gauge ¶
func (r *MetricsRecorder) Gauge(name string) *logging.Gauge
Gauge gets or creates a gauge by name.
func (*MetricsRecorder) Histogram ¶
func (r *MetricsRecorder) Histogram(name string) *logging.Histogram
Histogram gets or creates a histogram by name.
func (*MetricsRecorder) Inc ¶
func (r *MetricsRecorder) Inc(name string)
Inc increments a counter by name.
func (*MetricsRecorder) Observe ¶
func (r *MetricsRecorder) Observe(name string, value float64)
Observe records a histogram observation by name.
func (*MetricsRecorder) Set ¶
func (r *MetricsRecorder) Set(name string, value int64)
Set sets a gauge by name.
type Module ¶
type Module struct {
Provider *Provider
// contains filtered or unexported fields
}
Module implements the tjo.Module interface for OpenTelemetry functionality. Use this to opt-in to distributed tracing in your application.
Example:
app := tjo.Tjo{}
app.New(rootPath, otel.NewModule(
otel.WithServiceName("my-app"),
otel.WithOTLPExporter("localhost:4317"),
))
// Later, use the provider:
if otelModule := app.Modules.Get("otel"); otelModule != nil {
provider := otelModule.(*otel.Module).Provider
ctx, span := provider.Tracer().Start(ctx, "my-operation")
defer span.End()
}
func NewModule ¶
func NewModule(opts ...ModuleOption) *Module
NewModule creates a new OpenTelemetry module with default configuration from environment.
func (*Module) Initialize ¶
Initialize creates the OpenTelemetry provider. This is called automatically during app.New().
type ModuleOption ¶
type ModuleOption func(*Module)
ModuleOption is a function that configures the OTel module
func WithAlwaysSample ¶
func WithAlwaysSample() ModuleOption
WithAlwaysSample configures the always-sample strategy
func WithEnvironment ¶
func WithEnvironment(env string) ModuleOption
WithEnvironment sets the deployment environment
func WithOTLPExporter ¶
func WithOTLPExporter(endpoint string, insecure bool) ModuleOption
WithOTLPExporter configures OTLP export to the given endpoint
func WithRatioSample ¶
func WithRatioSample(ratio float64) ModuleOption
WithRatioSample configures ratio-based sampling
func WithServiceName ¶
func WithServiceName(name string) ModuleOption
WithServiceName sets the service name for traces
func WithServiceVersion ¶
func WithServiceVersion(version string) ModuleOption
WithServiceVersion sets the service version for traces
func WithZipkinExporter ¶
func WithZipkinExporter(endpoint string) ModuleOption
WithZipkinExporter configures Zipkin export to the given endpoint
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider manages OpenTelemetry tracing and metrics.
func (*Provider) ForceFlush ¶
ForceFlush immediately exports all pending spans.
func (*Provider) IsEnabled ¶
IsEnabled returns true if tracing is enabled and the provider is active.
func (*Provider) Middleware ¶
Middleware returns an HTTP middleware that traces requests. It extracts trace context from incoming requests and creates spans.
func (*Provider) Propagator ¶
func (p *Provider) Propagator() propagation.TextMapPropagator
Propagator returns the text map propagator for context injection/extraction.
func (*Provider) Shutdown ¶
Shutdown gracefully shuts down the provider, flushing any pending spans. It should be called when the application exits.
func (*Provider) TracerProvider ¶
func (p *Provider) TracerProvider() *sdktrace.TracerProvider
TracerProvider returns the underlying tracer provider.
type SamplerType ¶
type SamplerType string
SamplerType defines the sampling strategy.
const ( // SamplerAlways samples all traces. SamplerAlways SamplerType = "always" // SamplerNever samples no traces. SamplerNever SamplerType = "never" // SamplerRatio samples a percentage of traces. SamplerRatio SamplerType = "ratio" // SamplerParentBased respects the parent span's sampling decision. SamplerParentBased SamplerType = "parent" )
type SpanMetrics ¶
type SpanMetrics struct {
// contains filtered or unexported fields
}
SpanMetrics bridges OpenTelemetry spans with Tjo metrics. It automatically records span duration as a histogram observation.
func NewSpanMetrics ¶
func NewSpanMetrics(ctx context.Context, histogram *logging.Histogram, counter *logging.Counter) *SpanMetrics
NewSpanMetrics creates a span metrics tracker.
func (*SpanMetrics) EndWithError ¶
func (s *SpanMetrics) EndWithError(err error, errorCounter *logging.Counter)
EndWithError records the duration and optionally increments an error counter.
func (*SpanMetrics) WithAttributes ¶
func (s *SpanMetrics) WithAttributes(attrs ...attribute.KeyValue) *SpanMetrics
WithAttributes adds attributes to track.
type SpanOptions ¶
type SpanOptions struct {
// contains filtered or unexported fields
}
SpanOptions provides a fluent interface for building span options.
func NewSpanOptions ¶
func NewSpanOptions() *SpanOptions
NewSpanOptions creates a new SpanOptions builder.
func (*SpanOptions) Build ¶
func (s *SpanOptions) Build() []trace.SpanStartOption
Build returns the accumulated span options.
func (*SpanOptions) WithAttribute ¶
func (s *SpanOptions) WithAttribute(key, value string) *SpanOptions
WithAttribute adds a string attribute.
func (*SpanOptions) WithAttributes ¶
func (s *SpanOptions) WithAttributes(attrs ...attribute.KeyValue) *SpanOptions
WithAttributes adds multiple attributes.
func (*SpanOptions) WithKind ¶
func (s *SpanOptions) WithKind(kind trace.SpanKind) *SpanOptions
WithKind sets the span kind.
type TraceInfo ¶
TraceInfo returns both trace ID and span ID from context.
func GetTraceInfo ¶
GetTraceInfo extracts trace information from context.
type TracedDB ¶
type TracedDB struct {
// contains filtered or unexported fields
}
TracedDB wraps a sql.DB to add tracing to all database operations.
func WrapDBWithTracer ¶
WrapDBWithTracer wraps a sql.DB with a specific tracer.
type TracedStmt ¶
type TracedStmt struct {
// contains filtered or unexported fields
}
TracedStmt is a traced prepared statement.