fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

1package tracer 2 3import ( 4 "context" 5 "fmt" 6 "regexp" 7 8 "github.com/opentracing/opentracing-go" 9 "github.com/pkg/errors" 10 sglog "github.com/sourcegraph/log" 11 jaegerpropagator "go.opentelemetry.io/contrib/propagators/jaeger" 12 otpropagator "go.opentelemetry.io/contrib/propagators/ot" 13 "go.opentelemetry.io/otel" 14 otelbridge "go.opentelemetry.io/otel/bridge/opentracing" 15 "go.opentelemetry.io/otel/exporters/otlp/otlptrace" 16 "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" 17 "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" 18 w3cpropagator "go.opentelemetry.io/otel/propagation" 19 otelresource "go.opentelemetry.io/otel/sdk/resource" 20 oteltracesdk "go.opentelemetry.io/otel/sdk/trace" 21 semconv "go.opentelemetry.io/otel/semconv/v1.4.0" 22 23 "github.com/sourcegraph/zoekt/internal/otlpenv" 24) 25 26// configureOpenTelemetry creates an opentracing.Tracer that exports all OpenTracing traces 27// as OpenTelemetry traces to an OpenTelemetry collector (effectively "bridging" the two 28// APIs). This enables us to continue leveraging the OpenTracing API (which is a predecessor 29// to OpenTelemetry tracing) without making changes to existing tracing code. 30// 31// All configuration is sourced directly from the environment using the specification 32// laid out in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md 33// 34// This setup is based on the one done in sourcegraph/sourcegraph - when making changes, 35// be wary of divergences from the source: https://github.com/sourcegraph/sourcegraph/blob/main/internal/tracer/otel.go 36func configureOpenTelemetry(resource sglog.Resource) (opentracing.Tracer, error) { 37 // Ensure propagation between services continues to work. This is also done by another 38 // project that uses the OpenTracing bridge: 39 // https://sourcegraph.com/github.com/thanos-io/thanos/-/blob/pkg/tracing/migration/bridge.go?L62 40 compositePropagator := w3cpropagator.NewCompositeTextMapPropagator( 41 jaegerpropagator.Jaeger{}, 42 otpropagator.OT{}, 43 w3cpropagator.TraceContext{}, 44 w3cpropagator.Baggage{}, 45 ) 46 otel.SetTextMapPropagator(compositePropagator) 47 48 // Initialize OpenTelemetry processor and tracer provider 49 processor, err := newOTelCollectorExporter(context.Background(), otlpenv.GetEndpoint()) 50 if err != nil { 51 return nil, fmt.Errorf("new exporter: %w", err) 52 } 53 provider := oteltracesdk.NewTracerProvider( 54 oteltracesdk.WithResource(otelresource.NewWithAttributes( 55 semconv.SchemaURL, 56 semconv.ServiceNameKey.String(resource.Name), 57 semconv.ServiceInstanceIDKey.String(resource.InstanceID), 58 semconv.ServiceVersionKey.String(resource.Version))), 59 oteltracesdk.WithSampler(oteltracesdk.ParentBased(oteltracesdk.NeverSample())), 60 oteltracesdk.WithSpanProcessor(processor), 61 ) 62 63 // Set up bridge for converting opentracing API calls to OpenTelemetry. 64 bridge, otelTracerProvider := otelbridge.NewTracerPair(provider.Tracer("tracer.global")) 65 bridge.SetTextMapPropagator(compositePropagator) 66 otel.SetTracerProvider(otelTracerProvider) 67 otelLogger := sglog.Scoped("otel") 68 otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) { 69 otelLogger.Debug("error encountered", sglog.Error(err)) 70 })) 71 72 // Done 73 return bridge, nil 74} 75 76// newOTelCollectorExporter creates a processor that exports spans to an OpenTelemetry 77// collector. 78func newOTelCollectorExporter(ctx context.Context, endpoint string) (oteltracesdk.SpanProcessor, error) { 79 // Set up client to otel-collector - we replicate some of the logic used internally in 80 // https://github.com/open-telemetry/opentelemetry-go/blob/21c1641831ca19e3acf341cc11459c87b9791f2f/exporters/otlp/internal/otlpconfig/envconfig.go 81 // based on our own inferred endpoint. 82 var ( 83 client otlptrace.Client 84 protocol = otlpenv.GetProtocol() 85 trimmedEndpoint = trimSchema(endpoint) 86 insecure = otlpenv.IsInsecure(endpoint) 87 ) 88 89 // Work with different protocols 90 switch protocol { 91 case otlpenv.ProtocolGRPC: 92 opts := []otlptracegrpc.Option{ 93 otlptracegrpc.WithEndpoint(trimmedEndpoint), 94 } 95 if insecure { 96 opts = append(opts, otlptracegrpc.WithInsecure()) 97 } 98 client = otlptracegrpc.NewClient(opts...) 99 100 case otlpenv.ProtocolHTTPJSON: 101 opts := []otlptracehttp.Option{ 102 otlptracehttp.WithEndpoint(trimmedEndpoint), 103 } 104 if insecure { 105 opts = append(opts, otlptracehttp.WithInsecure()) 106 } 107 client = otlptracehttp.NewClient(opts...) 108 } 109 110 // Initialize the exporter 111 traceExporter, err := otlptrace.New(ctx, client) 112 if err != nil { 113 return nil, errors.Wrap(err, "failed to create trace exporter") 114 } 115 116 return oteltracesdk.NewBatchSpanProcessor(traceExporter), nil 117} 118 119var httpSchemeRegexp = regexp.MustCompile(`(?i)^http://|https://`) 120 121func trimSchema(endpoint string) string { 122 return httpSchemeRegexp.ReplaceAllString(endpoint, "") 123}