observability

package
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2025 License: Apache-2.0 Imports: 25 Imported by: 0

Documentation

Overview

Package observability provides utilities for adding observability capabilities to the Midaz SDK, including metrics, logging, and distributed tracing.

Index

Examples

Constants

View Source
const (
	// General attributes
	KeySDKVersion     = "midaz.sdk.version"
	KeySDKLanguage    = "midaz.sdk.language"
	KeyOperationName  = "midaz.operation.name"
	KeyOperationType  = "midaz.operation.type"
	KeyResourceType   = "midaz.resource.type"
	KeyResourceID     = "midaz.resource.id"
	KeyOrganizationID = "midaz.organization_id"
	KeyLedgerID       = "midaz.ledger_id"
	KeyAccountID      = "midaz.account_id"

	// HTTP request attributes
	KeyHTTPMethod   = "http.method"
	KeyHTTPPath     = "http.path"
	KeyHTTPStatus   = "http.status_code"
	KeyHTTPHost     = "http.host"
	KeyErrorCode    = "error.code"
	KeyErrorMessage = "error.message"

	// Metric names
	MetricRequestTotal        = "midaz.sdk.request.total"
	MetricRequestDuration     = "midaz.sdk.request.duration"
	MetricRequestErrorTotal   = "midaz.sdk.request.error.total"
	MetricRequestSuccess      = "midaz.sdk.request.success"
	MetricRequestRetryTotal   = "midaz.sdk.request.retry.total"
	MetricRequestBatchSize    = "midaz.sdk.request.batch.size"
	MetricRequestBatchLatency = "midaz.sdk.request.batch.latency"
)

Constants for attribute keys used in spans and metrics

Variables

This section is empty.

Functions

func AddAttribute

func AddAttribute(ctx context.Context, key string, value interface{})

AddAttribute adds an attribute to the current span in the context

func AddEvent

func AddEvent(ctx context.Context, name string, attrs map[string]string)

AddEvent adds an event to the current span

func AddSpanAttributes

func AddSpanAttributes(ctx context.Context, attrs ...attribute.KeyValue)

AddSpanAttributes adds attributes to the current span

func AddSpanEvent

func AddSpanEvent(ctx context.Context, name string, attrs ...attribute.KeyValue)

AddSpanEvent adds an event to the current span

func ExtractContext

func ExtractContext(ctx context.Context, headers map[string]string) context.Context

ExtractContext extracts context from HTTP headers for distributed tracing

func GetBaggageItem

func GetBaggageItem(ctx context.Context, key string) string

GetBaggageItem returns a baggage item from the context

func InjectContext

func InjectContext(ctx context.Context, headers map[string]string)

InjectContext injects context into HTTP headers for distributed tracing

func NewHTTPMiddleware

func NewHTTPMiddleware(provider Provider, opts ...HTTPOption) func(http.RoundTripper) http.RoundTripper

NewHTTPMiddleware creates a new HTTP middleware for tracing and metrics

Example
// Create a provider with options
provider, err := New(context.Background(),
	WithServiceName("example-service"),
	WithEnvironment("development"),
	WithHighTracingSampling(),
)
if err != nil {
	fmt.Printf("Failed to create provider: %v\n", err)
	return
}
defer provider.Shutdown(context.Background())

// Create an HTTP client with the middleware and security defaults
client := &http.Client{
	Transport: NewHTTPMiddleware(
		provider,
		WithSecurityDefaults(),     // Apply security defaults
		WithIgnorePaths("/health"), // Don't trace health checks
		WithHideRequestBody(true),  // Don't include request bodies
	)(http.DefaultTransport),
}

// Now any requests made with this client will be traced
resp, err := client.Get("https://example.com")
if err != nil {
	fmt.Printf("Request failed: %v\n", err)
	return
}
defer resp.Body.Close()

fmt.Printf("Response status: %s\n", resp.Status)

func RecordDuration

func RecordDuration(ctx context.Context, provider Provider, name string, start time.Time, attrs ...attribute.KeyValue)

RecordDuration records a duration metric using the provided meter

func RecordError

func RecordError(ctx context.Context, err error, eventName string, attrs ...map[string]string)

RecordError records an error on the current span

func RecordMetric

func RecordMetric(ctx context.Context, provider Provider, name string, value float64, attrs ...attribute.KeyValue)

RecordMetric records a metric using the provided meter

func RecordSpanMetric

func RecordSpanMetric(ctx context.Context, name string, value float64)

RecordSpanMetric records a metric with the given name and value

func SpanID

func SpanID(ctx context.Context) string

SpanID returns the span ID from the context, if available

func Start

func Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span)

Start starts a new span from a context

func StartSpan

func StartSpan(ctx context.Context, name string) (context.Context, trace.Span)

StartSpan starts a new span with the given name

func TraceID

func TraceID(ctx context.Context) string

TraceID returns the trace ID from the context, if available

func WithBaggageItem

func WithBaggageItem(ctx context.Context, key, value string) (context.Context, error)

WithBaggageItem returns a new context with a baggage item added

func WithProvider

func WithProvider(ctx context.Context, provider Provider) context.Context

WithProvider returns a new context with the provider added

func WithSpan

func WithSpan(ctx context.Context, provider Provider, name string, fn func(context.Context) error, opts ...trace.SpanStartOption) error

WithSpan creates a new span and executes the function within the context of that span. It automatically ends the span when the function returns.

Example
// Create a provider with options
provider, err := New(context.Background(),
	WithServiceName("example-service"),
	WithEnvironment("development"),
	WithFullTracingSampling(), // Use 100% sampling for better examples
)
if err != nil {
	fmt.Printf("Failed to create provider: %v\n", err)
	return
}
defer provider.Shutdown(context.Background())

// Use WithSpan to automatically create, end, and handle errors for a span
err = WithSpan(context.Background(), provider, "example-operation", func(ctx context.Context) error {
	// Do something with the context that has the span
	span := trace.SpanFromContext(ctx)
	span.SetAttributes(attribute.String("example", "attribute"))

	// Simulate work
	time.Sleep(10 * time.Millisecond)

	// Simulate success
	return nil
})

if err != nil {
	fmt.Printf("Operation failed: %v\n", err)
} else {
	fmt.Println("Operation succeeded")
}
Output:

Operation succeeded

func WithSpanAttributes

func WithSpanAttributes(ctx context.Context, attrs ...attribute.KeyValue) context.Context

WithSpanAttributes returns a new context with attributes added to the current span

func WithTraceID

func WithTraceID(ctx context.Context, traceID string) context.Context

WithTraceID adds a trace ID to the context for correlation

Types

type Config

type Config struct {
	// ServiceName is the name of the service using the SDK
	ServiceName string

	// ServiceVersion is the version of the service using the SDK
	ServiceVersion string

	// SDKVersion is the version of the Midaz Go SDK
	SDKVersion string

	// Environment is the environment where the service is running
	Environment string

	// CollectorEndpoint is the endpoint for the OpenTelemetry collector
	CollectorEndpoint string

	// LogLevel is the minimum log level to record
	LogLevel LogLevel

	// LogOutput is where to write logs (defaults to os.Stderr)
	LogOutput io.Writer

	// TraceSampleRate is the sampling rate for traces (0.0 to 1.0)
	TraceSampleRate float64

	// EnabledComponents controls which observability components are enabled
	EnabledComponents EnabledComponents

	// Attributes are additional attributes to add to all telemetry
	Attributes []attribute.KeyValue

	// Propagators for context propagation
	Propagators []propagation.TextMapPropagator

	// Headers to extract for trace context propagation
	PropagationHeaders []string
}

Config holds the configuration for the observability provider

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a default configuration for the observability provider

type ContextKey

type ContextKey string

ContextKey is the type for context keys

const (
	// ProviderKey is the context key for the observability provider
	ProviderKey ContextKey = "midaz-observability-provider"
)

type EnabledComponents

type EnabledComponents struct {
	Tracing bool
	Metrics bool
	Logging bool
}

EnabledComponents controls which observability components are enabled

type HTTPOption

type HTTPOption func(*httpMiddleware) error

HTTPOption is a function type for configuring the HTTP middleware

func WithDefaultSensitiveHeaders

func WithDefaultSensitiveHeaders() HTTPOption

WithDefaultSensitiveHeaders sets the default list of headers to ignore for security

func WithDefaultSensitiveParams

func WithDefaultSensitiveParams() HTTPOption

WithDefaultSensitiveParams sets the default list of parameters to mask for security

func WithHideRequestBody

func WithHideRequestBody(hide bool) HTTPOption

WithHideRequestBody specifies whether to hide request bodies from logs

func WithIgnoreHeaders

func WithIgnoreHeaders(headers ...string) HTTPOption

WithIgnoreHeaders specifies HTTP header names that should not be logged

func WithIgnorePaths

func WithIgnorePaths(paths ...string) HTTPOption

WithIgnorePaths specifies URL paths that should not be traced

func WithMaskedParams

func WithMaskedParams(params ...string) HTTPOption

WithMaskedParams specifies query parameters that should have their values masked

func WithSecurityDefaults

func WithSecurityDefaults() HTTPOption

WithSecurityDefaults sets all default security options

type LogLevel

type LogLevel int

LogLevel represents the logging level

const (
	// DebugLevel is the most verbose logging level, used for debugging information
	DebugLevel LogLevel = iota
	// InfoLevel is for general information about normal operation
	InfoLevel
	// WarnLevel is for potentially problematic situations that don't cause errors
	WarnLevel
	// ErrorLevel is for errors that may still allow the application to continue
	ErrorLevel
	// FatalLevel is for severe errors that will likely cause the application to terminate
	FatalLevel
)

func (LogLevel) String

func (l LogLevel) String() string

String returns the string representation of the log level

type Logger

type Logger interface {
	// Debug logs a message at debug level
	Debug(args ...interface{})
	// Debugf logs a formatted message at debug level
	Debugf(format string, args ...interface{})
	// Info logs a message at info level
	Info(args ...interface{})
	// Infof logs a formatted message at info level
	Infof(format string, args ...interface{})
	// Warn logs a message at warn level
	Warn(args ...interface{})
	// Warnf logs a formatted message at warn level
	Warnf(format string, args ...interface{})
	// Error logs a message at error level
	Error(args ...interface{})
	// Errorf logs a formatted message at error level
	Errorf(format string, args ...interface{})
	// Fatal logs a message at fatal level
	Fatal(args ...interface{})
	// Fatalf logs a formatted message at fatal level
	Fatalf(format string, args ...interface{})
	// With returns a logger with added structured fields
	With(fields map[string]interface{}) Logger
	// WithContext returns a logger with context information (trace ID, etc.)
	WithContext(ctx trace.SpanContext) Logger
	// WithSpan returns a logger with span information (span ID, trace ID, etc.)
	WithSpan(span trace.Span) Logger
}

Logger is the interface for all logging operations

func Log

func Log(ctx context.Context) Logger

Log returns a logger from the context

func NewLogger

func NewLogger(level LogLevel, output io.Writer, resource *sdkresource.Resource) Logger

NewLogger creates a new logger with the specified level and output

func NewNoopLogger

func NewNoopLogger() Logger

NewNoopLogger creates a new no-op logger

type LoggerImpl

type LoggerImpl struct {
	// contains filtered or unexported fields
}

LoggerImpl is the standard implementation of the Logger interface

func (*LoggerImpl) Debug

func (l *LoggerImpl) Debug(args ...interface{})

Debug logs a message at debug level

func (*LoggerImpl) Debugf

func (l *LoggerImpl) Debugf(format string, args ...interface{})

Debugf logs a formatted message at debug level

func (*LoggerImpl) Error

func (l *LoggerImpl) Error(args ...interface{})

Error logs a message at error level

func (*LoggerImpl) Errorf

func (l *LoggerImpl) Errorf(format string, args ...interface{})

Errorf logs a formatted message at error level

func (*LoggerImpl) Fatal

func (l *LoggerImpl) Fatal(args ...interface{})

Fatal logs a message at fatal level

func (*LoggerImpl) Fatalf

func (l *LoggerImpl) Fatalf(format string, args ...interface{})

Fatalf logs a formatted message at fatal level

func (*LoggerImpl) Info

func (l *LoggerImpl) Info(args ...interface{})

Info logs a message at info level

func (*LoggerImpl) Infof

func (l *LoggerImpl) Infof(format string, args ...interface{})

Infof logs a formatted message at info level

func (*LoggerImpl) Warn

func (l *LoggerImpl) Warn(args ...interface{})

Warn logs a message at warn level

func (*LoggerImpl) Warnf

func (l *LoggerImpl) Warnf(format string, args ...interface{})

Warnf logs a formatted message at warn level

func (*LoggerImpl) With

func (l *LoggerImpl) With(fields map[string]interface{}) Logger

With returns a logger with added structured fields

func (*LoggerImpl) WithContext

func (l *LoggerImpl) WithContext(ctx trace.SpanContext) Logger

WithContext returns a logger with context information (trace ID, etc.)

func (*LoggerImpl) WithSpan

func (l *LoggerImpl) WithSpan(span trace.Span) Logger

WithSpan returns a logger with span information (span ID, trace ID, etc.)

type MetricsCollector

type MetricsCollector struct {
	// contains filtered or unexported fields
}

MetricsCollector provides convenient methods for recording common metrics related to the SDK operations.

func NewMetricsCollector

func NewMetricsCollector(provider Provider) (*MetricsCollector, error)

NewMetricsCollector creates a new MetricsCollector for recording SDK metrics

func (*MetricsCollector) NewTimer

func (m *MetricsCollector) NewTimer(ctx context.Context, operation, resourceType string, attrs ...attribute.KeyValue) *Timer

NewTimer creates a new timer for recording the duration of an operation

func (*MetricsCollector) RecordBatchRequest

func (m *MetricsCollector) RecordBatchRequest(ctx context.Context, operation, resourceType string, batchSize int, duration time.Duration, attrs ...attribute.KeyValue)

RecordBatchRequest records a batch request with its size and latency

func (*MetricsCollector) RecordRequest

func (m *MetricsCollector) RecordRequest(ctx context.Context, operation, resourceType string, statusCode int, duration time.Duration, attrs ...attribute.KeyValue)

RecordRequest records a request with its result and duration

func (*MetricsCollector) RecordRetry

func (m *MetricsCollector) RecordRetry(ctx context.Context, operation, resourceType string, attempt int, attrs ...attribute.KeyValue)

RecordRetry records a retry attempt

type MidazProvider

type MidazProvider struct {
	// contains filtered or unexported fields
}

MidazProvider is the main implementation of the Provider interface It provides access to OpenTelemetry tracing, metrics, and logging

func (*MidazProvider) IsEnabled

func (p *MidazProvider) IsEnabled() bool

IsEnabled returns true if observability is enabled

func (*MidazProvider) Logger

func (p *MidazProvider) Logger() Logger

Logger returns a logger

Example
// Create a provider with options
provider, err := New(context.Background(),
	WithServiceName("example-service"),
	WithEnvironment("development"),
	WithLogLevel(InfoLevel),
	WithDevelopmentDefaults(),
)
if err != nil {
	fmt.Printf("Failed to create provider: %v\n", err)
	return
}
defer provider.Shutdown(context.Background())

// Get a logger
logger := provider.Logger()

// Log at different levels
logger.Debug("This is a debug message (won't be shown with InfoLevel)")
logger.Info("This is an info message")

// Add structured fields
structuredLogger := logger.With(map[string]interface{}{
	"user_id": "123",
	"action":  "login",
})
structuredLogger.Info("User logged in")

// Add context information (tracing)
_, span := provider.Tracer().Start(context.Background(), "example-span")
defer span.End()

tracingLogger := logger.WithSpan(span)
tracingLogger.Info("This log includes trace and span IDs")

// Add error information
span.SetStatus(codes.Error, "Something went wrong")
span.RecordError(errors.New("example error"))

tracingLogger.Error("An error occurred")

func (*MidazProvider) Meter

func (p *MidazProvider) Meter() metric.Meter

Meter returns a meter for creating metrics

func (*MidazProvider) Shutdown

func (p *MidazProvider) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the provider and all its components

func (*MidazProvider) Tracer

func (p *MidazProvider) Tracer() trace.Tracer

Tracer returns a tracer for creating spans

type NoopLogger

type NoopLogger struct{}

NoopLogger is a no-op implementation of the Logger interface

func (*NoopLogger) Debug

func (l *NoopLogger) Debug(args ...interface{})

Debug is a no-op

func (*NoopLogger) Debugf

func (l *NoopLogger) Debugf(format string, args ...interface{})

Debugf is a no-op

func (*NoopLogger) Error

func (l *NoopLogger) Error(args ...interface{})

Error is a no-op

func (*NoopLogger) Errorf

func (l *NoopLogger) Errorf(format string, args ...interface{})

Errorf is a no-op

func (*NoopLogger) Fatal

func (l *NoopLogger) Fatal(args ...interface{})

Fatal is a no-op

func (*NoopLogger) Fatalf

func (l *NoopLogger) Fatalf(format string, args ...interface{})

Fatalf is a no-op

func (*NoopLogger) Info

func (l *NoopLogger) Info(args ...interface{})

Info is a no-op

func (*NoopLogger) Infof

func (l *NoopLogger) Infof(format string, args ...interface{})

Infof is a no-op

func (*NoopLogger) Warn

func (l *NoopLogger) Warn(args ...interface{})

Warn is a no-op

func (*NoopLogger) Warnf

func (l *NoopLogger) Warnf(format string, args ...interface{})

Warnf is a no-op

func (*NoopLogger) With

func (l *NoopLogger) With(fields map[string]interface{}) Logger

With returns the same no-op logger

func (*NoopLogger) WithContext

func (l *NoopLogger) WithContext(ctx trace.SpanContext) Logger

WithContext returns the same no-op logger

func (*NoopLogger) WithSpan

func (l *NoopLogger) WithSpan(span trace.Span) Logger

WithSpan returns the same no-op logger

type Option

type Option func(*Config) error

Option defines a function that configures the observability Config

func WithAttributes

func WithAttributes(attrs ...attribute.KeyValue) Option

WithAttributes adds additional attributes to all telemetry

func WithCollectorEndpoint

func WithCollectorEndpoint(endpoint string) Option

WithCollectorEndpoint sets the endpoint for the OpenTelemetry collector

func WithComponentEnabled

func WithComponentEnabled(tracing, metrics, logging bool) Option

WithComponentEnabled enables or disables specific observability components

func WithDevelopmentDefaults

func WithDevelopmentDefaults() Option

WithDevelopmentDefaults sets reasonable defaults for development environments - High trace sampling rate (0.5) - Debug log level - Development environment

func WithEnvironment

func WithEnvironment(env string) Option

WithEnvironment sets the environment for observability (e.g., "production", "staging", "development")

func WithFullTracingSampling

func WithFullTracingSampling() Option

WithFullTracingSampling sets a full trace sampling rate (1.0) for testing environments

func WithHighTracingSampling

func WithHighTracingSampling() Option

WithHighTracingSampling sets a high trace sampling rate (0.5) for development environments

func WithLogLevel

func WithLogLevel(level LogLevel) Option

WithLogLevel sets the minimum log level to record

func WithLogOutput

func WithLogOutput(output io.Writer) Option

WithLogOutput sets the writer for logs

func WithProductionDefaults

func WithProductionDefaults() Option

WithProductionDefaults sets reasonable defaults for production environments - Low trace sampling rate (0.1) - Info log level - Production environment

func WithPropagationHeaders

func WithPropagationHeaders(headers ...string) Option

WithPropagationHeaders sets the headers to extract for trace context propagation

func WithPropagators

func WithPropagators(propagators ...propagation.TextMapPropagator) Option

WithPropagators sets the propagators for context propagation

func WithSDKVersion

func WithSDKVersion(version string) Option

WithSDKVersion sets the SDK version for observability

func WithServiceName

func WithServiceName(name string) Option

WithServiceName sets the service name for observability

func WithServiceVersion

func WithServiceVersion(version string) Option

WithServiceVersion sets the service version for observability

func WithTraceSampleRate

func WithTraceSampleRate(rate float64) Option

WithTraceSampleRate sets the sampling rate for traces (0.0 to 1.0)

type Provider

type Provider interface {
	// Tracer returns a tracer for creating spans
	Tracer() trace.Tracer

	// Meter returns a meter for creating metrics
	Meter() metric.Meter

	// Logger returns a logger
	Logger() Logger

	// Shutdown gracefully shuts down the provider
	Shutdown(ctx context.Context) error

	// IsEnabled returns true if observability is enabled
	IsEnabled() bool
}

Provider is the interface for observability providers. It allows for consistent access to tracing, metrics, and logging capabilities.

func GetProvider

func GetProvider(ctx context.Context) Provider

GetProvider returns the provider from the context, if any

func New

func New(ctx context.Context, opts ...Option) (Provider, error)

New creates a new observability provider with the given options

func NewWithConfig

func NewWithConfig(ctx context.Context, config *Config) (Provider, error)

NewWithConfig creates a new observability provider with the given configuration This is provided for backward compatibility with existing code

type Timer

type Timer struct {
	// contains filtered or unexported fields
}

Timer provides a convenient way to record the duration of an operation

func (*Timer) Stop

func (t *Timer) Stop(statusCode int, additionalAttrs ...attribute.KeyValue)

Stop records the duration of the operation with the result

func (*Timer) StopBatch

func (t *Timer) StopBatch(batchSize int, additionalAttrs ...attribute.KeyValue)

StopBatch records the duration of a batch operation

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL