pomerium/config/trace.go
Caleb Doxsey d2c14cd6d2
logging: remove ctx from global log methods (#5337)
* log: remove warn

* log: update debug

* log: update info

* remove level, log

* remove contextLogger function
2024-10-23 14:18:52 -06:00

125 lines
3.4 KiB
Go

package config
import (
"context"
"fmt"
"reflect"
"sync"
"github.com/rs/zerolog"
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/telemetry"
"github.com/pomerium/pomerium/internal/telemetry/trace"
"github.com/pomerium/pomerium/internal/urlutil"
)
// TracingOptions are the options for tracing.
type TracingOptions = trace.TracingOptions
// NewTracingOptions builds a new TracingOptions from core Options
func NewTracingOptions(o *Options) (*TracingOptions, error) {
tracingOpts := TracingOptions{
Provider: o.TracingProvider,
Service: telemetry.ServiceName(o.Services),
JaegerAgentEndpoint: o.TracingJaegerAgentEndpoint,
SampleRate: o.TracingSampleRate,
}
switch o.TracingProvider {
case trace.DatadogTracingProviderName:
tracingOpts.DatadogAddress = o.TracingDatadogAddress
case trace.JaegerTracingProviderName:
if o.TracingJaegerCollectorEndpoint != "" {
jaegerCollectorEndpoint, err := urlutil.ParseAndValidateURL(o.TracingJaegerCollectorEndpoint)
if err != nil {
return nil, fmt.Errorf("config: invalid jaeger endpoint url: %w", err)
}
tracingOpts.JaegerCollectorEndpoint = jaegerCollectorEndpoint
tracingOpts.JaegerAgentEndpoint = o.TracingJaegerAgentEndpoint
}
case trace.ZipkinTracingProviderName:
zipkinEndpoint, err := urlutil.ParseAndValidateURL(o.ZipkinEndpoint)
if err != nil {
return nil, fmt.Errorf("config: invalid zipkin endpoint url: %w", err)
}
tracingOpts.ZipkinEndpoint = zipkinEndpoint
case "":
return &TracingOptions{}, nil
default:
return nil, fmt.Errorf("config: provider %s unknown", o.TracingProvider)
}
return &tracingOpts, nil
}
// A TraceManager manages setting up a trace exporter based on configuration options.
type TraceManager struct {
mu sync.Mutex
traceOpts *TracingOptions
provider trace.Provider
}
// NewTraceManager creates a new TraceManager.
func NewTraceManager(ctx context.Context, src Source) *TraceManager {
ctx = log.WithContext(ctx, func(c zerolog.Context) zerolog.Context {
return c.Str("service", "trace_manager")
})
mgr := &TraceManager{}
src.OnConfigChange(ctx, mgr.OnConfigChange)
mgr.OnConfigChange(ctx, src.GetConfig())
return mgr
}
// Close closes any underlying trace exporter.
func (mgr *TraceManager) Close() error {
mgr.mu.Lock()
defer mgr.mu.Unlock()
var err error
if mgr.provider != nil {
err = mgr.provider.Unregister()
}
return err
}
// OnConfigChange updates the manager whenever the configuration is changed.
func (mgr *TraceManager) OnConfigChange(ctx context.Context, cfg *Config) {
mgr.mu.Lock()
defer mgr.mu.Unlock()
traceOpts, err := NewTracingOptions(cfg.Options)
if err != nil {
log.Ctx(ctx).Error().Err(err).Msg("trace: failed to build tracing options")
return
}
if reflect.DeepEqual(traceOpts, mgr.traceOpts) {
log.Ctx(ctx).Debug().Msg("no change detected in trace options")
return
}
mgr.traceOpts = traceOpts
if mgr.provider != nil {
_ = mgr.provider.Unregister()
mgr.provider = nil
}
if !traceOpts.Enabled() {
return
}
log.Ctx(ctx).Info().Interface("options", traceOpts).Msg("trace: starting exporter")
mgr.provider, err = trace.GetProvider(traceOpts)
if err != nil {
log.Ctx(ctx).Error().Err(err).Msg("trace: failed to register exporter")
return
}
err = mgr.provider.Register(traceOpts)
if err != nil {
log.Ctx(ctx).Error().Err(err).Msg("trace: failed to register exporter")
return
}
}