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 "log" 7 "regexp" 8 9 "github.com/opentracing/opentracing-go" 10 "github.com/pkg/errors" 11 sglog "github.com/sourcegraph/log" 12 jaegerpropagator "go.opentelemetry.io/contrib/propagators/jaeger" 13 otpropagator "go.opentelemetry.io/contrib/propagators/ot" 14 "go.opentelemetry.io/otel" 15 otelbridge "go.opentelemetry.io/otel/bridge/opentracing" 16 "go.opentelemetry.io/otel/exporters/otlp/otlptrace" 17 "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" 18 "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" 19 w3cpropagator "go.opentelemetry.io/otel/propagation" 20 otelresource "go.opentelemetry.io/otel/sdk/resource" 21 oteltracesdk "go.opentelemetry.io/otel/sdk/trace" 22 semconv "go.opentelemetry.io/otel/semconv/v1.4.0" 23 24 "github.com/sourcegraph/zoekt/internal/otlpenv" 25) 26 27// configureOpenTelemetry creates an opentracing.Tracer that exports all OpenTracing traces 28// as OpenTelemetry traces to an OpenTelemetry collector (effectively "bridging" the two 29// APIs). This enables us to continue leveraging the OpenTracing API (which is a predecessor 30// to OpenTelemetry tracing) without making changes to existing tracing code. 31// 32// All configuration is sourced directly from the environment using the specification 33// laid out in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md 34// 35// This setup is based on the one done in sourcegraph/sourcegraph - when making changes, 36// be wary of divergences from the source: https://github.com/sourcegraph/sourcegraph/blob/main/internal/tracer/otel.go 37func configureOpenTelemetry(resource sglog.Resource) (opentracing.Tracer, error) { 38 // Ensure propagation between services continues to work. This is also done by another 39 // project that uses the OpenTracing bridge: 40 // https://sourcegraph.com/github.com/thanos-io/thanos/-/blob/pkg/tracing/migration/bridge.go?L62 41 compositePropagator := w3cpropagator.NewCompositeTextMapPropagator( 42 jaegerpropagator.Jaeger{}, 43 otpropagator.OT{}, 44 w3cpropagator.TraceContext{}, 45 w3cpropagator.Baggage{}, 46 ) 47 otel.SetTextMapPropagator(compositePropagator) 48 49 // Initialize OpenTelemetry processor and tracer provider 50 processor, err := newOTelCollectorExporter(context.Background(), otlpenv.GetEndpoint()) 51 if err != nil { 52 return nil, fmt.Errorf("new exporter: %w", err) 53 } 54 provider := oteltracesdk.NewTracerProvider( 55 oteltracesdk.WithResource(otelresource.NewWithAttributes( 56 semconv.SchemaURL, 57 semconv.ServiceNameKey.String(resource.Name), 58 semconv.ServiceInstanceIDKey.String(resource.InstanceID), 59 semconv.ServiceVersionKey.String(resource.Version))), 60 oteltracesdk.WithSampler(oteltracesdk.ParentBased(oteltracesdk.NeverSample())), 61 oteltracesdk.WithSpanProcessor(processor), 62 ) 63 64 // Set up bridge for converting opentracing API calls to OpenTelemetry. 65 bridge, otelTracerProvider := otelbridge.NewTracerPair(provider.Tracer("tracer.global")) 66 bridge.SetTextMapPropagator(compositePropagator) 67 otel.SetTracerProvider(otelTracerProvider) 68 otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) { 69 log.Println("opentelemetry: ", err.Error()) 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}