From 16d31342ae47ce93da33f22403d14f638d4ef79f Mon Sep 17 00:00:00 2001 From: Aditi Ahuja Date: Sun, 12 Jun 2022 15:47:22 +0530 Subject: [PATCH] added jaeger exporter Signed-off-by: Aditi Ahuja --- pkg/tracing/client/factory.go | 13 +++-- pkg/tracing/jaeger/jaeger.go | 103 +++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 8 deletions(-) diff --git a/pkg/tracing/client/factory.go b/pkg/tracing/client/factory.go index 55753724f93..1a418a51ad6 100644 --- a/pkg/tracing/client/factory.go +++ b/pkg/tracing/client/factory.go @@ -47,6 +47,7 @@ type TracingConfig struct { Config interface{} `yaml:"config"` } +// NewOTELTracer returns an OTLP exporter based tracer. func NewOTELTracer(ctx context.Context, logger log.Logger) trace.Tracer { client := otlptracehttp.NewClient() exporter, err := otlptrace.New(ctx, client) @@ -65,15 +66,11 @@ func NewOTELTracer(ctx context.Context, logger log.Logger) trace.Tracer { tracer := otel.GetTracerProvider().Tracer( name, - trace.WithInstrumentationVersion("v0.1"), trace.WithSchemaURL(semconv.SchemaURL), ) return tracer } -// exporter will export data in OTLP format -// need to add a collector which will export data in multiple formats eg. Jaeger - func NewTracer(ctx context.Context, logger log.Logger, metrics *prometheus.Registry, confContentYaml []byte) (opentracing.Tracer, io.Closer, error) { level.Info(logger).Log("msg", "loading tracing configuration") tracingConf := &TracingConfig{} @@ -100,8 +97,12 @@ func NewTracer(ctx context.Context, logger log.Logger, metrics *prometheus.Regis tracer, closerFunc := migration.Bridge(tracerProvider, logger) return tracer, closerFunc, nil case string(Jaeger): - // next step - create newTracerProvider like google_cloud - return jaeger.NewTracer(ctx, logger, metrics, config) + tracerProvider, err := jaeger.NewTracerProvider(ctx, logger, config) + if err != nil { + return nil, nil, errors.Wrap(err, "new tracer provider err") + } + tracer, closerFunc := migration.Bridge(tracerProvider, logger) + return tracer, closerFunc, nil case string(ElasticAPM): return elasticapm.NewTracer(config) case string(Lightstep): diff --git a/pkg/tracing/jaeger/jaeger.go b/pkg/tracing/jaeger/jaeger.go index 872976e5f73..a7d8973534d 100644 --- a/pkg/tracing/jaeger/jaeger.go +++ b/pkg/tracing/jaeger/jaeger.go @@ -7,18 +7,27 @@ import ( "context" "fmt" "io" + "os" + "strconv" "strings" "github.com/thanos-io/thanos/pkg/tracing" + "github.com/thanos-io/thanos/pkg/tracing/migration" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/opentracing/opentracing-go" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/version" "github.com/uber/jaeger-client-go" "github.com/uber/jaeger-client-go/config" jaeger_prometheus "github.com/uber/jaeger-lib/metrics/prometheus" + "go.opentelemetry.io/otel/attribute" otel_jaeger "go.opentelemetry.io/otel/exporters/jaeger" + "go.opentelemetry.io/otel/sdk/resource" + tracesdk "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + "gopkg.in/yaml.v2" ) // Tracer extends opentracing.Tracer. @@ -34,6 +43,94 @@ func (t *Tracer) GetTraceIDFromSpanContext(ctx opentracing.SpanContext) (string, return "", false } +// NewTracerProvider returns a new instance of an OpenTelemetry tracer provider. +func NewTracerProvider(ctx context.Context, logger log.Logger, conf []byte) (*tracesdk.TracerProvider, error) { + config := Config{} + if err := yaml.Unmarshal(conf, &config); err != nil { + return nil, err + } + + var exporter *otel_jaeger.Exporter + var err error + + if config.Endpoint != "" { + var jaegerCollectorEndpointOptions []otel_jaeger.CollectorEndpointOption + if config.User != "" { + jaegerCollectorEndpointOptions = append(jaegerCollectorEndpointOptions, otel_jaeger.WithUsername(config.User)) + } + if config.Password != "" { + jaegerCollectorEndpointOptions = append(jaegerCollectorEndpointOptions, otel_jaeger.WithPassword(config.Password)) + } + jaegerCollectorEndpointOptions = append(jaegerCollectorEndpointOptions, otel_jaeger.WithEndpoint(config.Endpoint)) + + exporter, err = otel_jaeger.New(otel_jaeger.WithCollectorEndpoint(jaegerCollectorEndpointOptions...)) + if err != nil { + return nil, err + } + } else if config.AgentHost != "" && config.AgentPort != 0 { + var jaegerAgentEndpointOptions []otel_jaeger.AgentEndpointOption + jaegerAgentEndpointOptions = append(jaegerAgentEndpointOptions, otel_jaeger.WithAgentHost(config.AgentHost)) + jaegerAgentEndpointOptions = append(jaegerAgentEndpointOptions, otel_jaeger.WithAgentPort(strconv.Itoa(config.AgentPort))) + + exporter, err = otel_jaeger.New(otel_jaeger.WithAgentEndpoint(jaegerAgentEndpointOptions...)) + if err != nil { + return nil, err + } + } else { + exporter, err = otel_jaeger.New(nil) + if err != nil { + return nil, err + } + } + + processor := tracesdk.NewBatchSpanProcessor(exporter) + tp := newTraceProvider(ctx, logger, processor, config.SamplerParam, config.ServiceName) + + return tp, nil +} + +func newTraceProvider(ctx context.Context, logger log.Logger, processor tracesdk.SpanProcessor, + samplingFactor float64, serviceName string) *tracesdk.TracerProvider { + + var fraction float64 + if samplingFactor == 0 { + fraction = 0 + } else { + fraction = 1 / float64(samplingFactor) + } + + resource, err := resource.New(ctx, resource.WithAttributes(collectAttributes(serviceName)...)) + if err != nil { + level.Warn(logger).Log("msg", "jaeger: detecting resources for tracing provider failed", "err", err) + } + + tp := tracesdk.NewTracerProvider( + tracesdk.WithSpanProcessor(processor), + tracesdk.WithSampler( + migration.SamplerWithOverride( + tracesdk.ParentBased(tracesdk.TraceIDRatioBased(fraction)), + migration.ForceTracingAttributeKey, + ), + ), + tracesdk.WithResource(resource), + ) + + return tp +} + +func collectAttributes(serviceName string) []attribute.KeyValue { + attr := []attribute.KeyValue{ + semconv.ServiceNameKey.String(serviceName), + attribute.String("binary_revision", version.Revision), + } + + if len(os.Args) > 1 { + attr = append(attr, attribute.String("binary_cmd", os.Args[1])) + } + + return attr +} + // NewTracer create tracer from YAML. func NewTracer(ctx context.Context, logger log.Logger, metrics *prometheus.Registry, conf []byte) (opentracing.Tracer, io.Closer, error) { var ( @@ -64,8 +161,10 @@ func NewTracer(ctx context.Context, logger log.Logger, metrics *prometheus.Regis logger: logger, }), ) - // return OTEL Jaeger exporter here instead - // exp, err := otel_jaeger.New(otel_jaeger.WithCollectorEndpoint(otel_jaeger.WithEndpoint(url))) + if err != nil { + return nil, nil, err + } + exp, err := otel_jaeger.New(otel_jaeger.WithCollectorEndpoint()) if err != nil { return nil, nil, err