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

Configure Feed

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

tracer: add OpenTelemetry tracing with OPENTELEMETRY_DISABLED=false (#413)

Adds the ability for Zoekt to export OpenTelemetry, configured with OPENTELEMETRY_DISABLED=false (analogous to JAEGER_DISABLED=false). It updates internal/trace with mostly the same OpenTelemetry setup as internal/trace in sourcegraph/sourcegraph - it turns out most of the same workarounds are required for this to work correctly out of the box.

Instructions for enabling in dev are currently in https://github.com/sourcegraph/sourcegraph/pull/40629/files, and I tested this by following the instructions in https://docs.sourcegraph.com/dev/how-to/zoekt_local_dev and running a search with tracing enabled. Inspecting the trace in Honeycomb confirms it went through the OpenTelemetry collector.

Co-authored-by: Jean-Hadrien Chabran <jh@chabran.fr>
Co-authored-by: Keegan Carruthers-Smith <keegan.csmith@gmail.com>

+335 -67
+9 -10
cmd/zoekt-webserver/main.go
··· 48 48 "github.com/prometheus/client_golang/prometheus/promauto" 49 49 sglog "github.com/sourcegraph/log" 50 50 "github.com/uber/jaeger-client-go" 51 + oteltrace "go.opentelemetry.io/otel/trace" 51 52 "go.uber.org/automaxprocs/maxprocs" 52 53 ) 53 54 ··· 466 467 467 468 // traceID returns a trace ID, if any, found in the given context. 468 469 func traceID(ctx context.Context) string { 469 - span := opentracing.SpanFromContext(ctx) 470 - if span == nil { 471 - return "" 470 + otSpan := opentracing.SpanFromContext(ctx) 471 + if otSpan != nil { 472 + if jaegerSpan, ok := otSpan.Context().(jaeger.SpanContext); ok { 473 + return jaegerSpan.TraceID().String() 474 + } 472 475 } 473 - return traceIDFromSpan(span) 474 - } 475 476 476 - // traceIDFromSpan returns a trace ID, if any, found in the given span. 477 - func traceIDFromSpan(span opentracing.Span) string { 478 - switch v := span.Context().(type) { 479 - case jaeger.SpanContext: 480 - return v.TraceID().String() 477 + if otelSpan := oteltrace.SpanFromContext(ctx).SpanContext(); otelSpan.IsValid() { 478 + return otelSpan.TraceID().String() 481 479 } 480 + 482 481 return "" 483 482 } 484 483
+18 -3
go.mod
··· 21 21 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f 22 22 github.com/opentracing/opentracing-go v1.2.0 23 23 github.com/peterbourgon/ff/v3 v3.1.2 24 + github.com/pkg/errors v0.9.1 24 25 github.com/prometheus/client_golang v1.12.1 25 26 github.com/rs/xid v1.4.0 26 27 github.com/sourcegraph/go-ctags v0.0.0-20220611154803-db463692f037 ··· 28 29 github.com/uber/jaeger-client-go v2.30.0+incompatible 29 30 github.com/uber/jaeger-lib v2.4.1+incompatible 30 31 github.com/xanzy/go-gitlab v0.64.0 32 + go.opentelemetry.io/contrib/propagators/jaeger v1.9.0 33 + go.opentelemetry.io/contrib/propagators/ot v1.9.0 34 + go.opentelemetry.io/otel v1.9.0 35 + go.opentelemetry.io/otel/bridge/opentracing v1.9.0 36 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.9.0 37 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.9.0 38 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.9.0 39 + go.opentelemetry.io/otel/sdk v1.9.0 40 + go.opentelemetry.io/otel/trace v1.9.0 31 41 go.uber.org/atomic v1.9.0 32 42 go.uber.org/automaxprocs v1.5.1 33 43 golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 ··· 45 55 github.com/acomagu/bufpipe v1.0.3 // indirect 46 56 github.com/beorn7/perks v1.0.1 // indirect 47 57 github.com/bits-and-blooms/bitset v1.2.2 // indirect 58 + github.com/cenkalti/backoff/v4 v4.1.3 // indirect 48 59 github.com/cespare/xxhash/v2 v2.1.2 // indirect 49 60 github.com/cockroachdb/errors v1.9.0 // indirect 50 61 github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f // indirect ··· 55 66 github.com/go-enry/go-oniguruma v1.2.1 // indirect 56 67 github.com/go-git/gcfg v1.5.0 // indirect 57 68 github.com/go-git/go-billy/v5 v5.3.1 // indirect 69 + github.com/go-logr/logr v1.2.3 // indirect 70 + github.com/go-logr/stdr v1.2.2 // indirect 58 71 github.com/gogo/protobuf v1.3.2 // indirect 59 72 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 60 73 github.com/golang/protobuf v1.5.2 // indirect ··· 62 75 github.com/google/pprof v0.0.0-20220412212628-83db2b799d1f // indirect 63 76 github.com/google/uuid v1.3.0 // indirect 64 77 github.com/googleapis/gax-go/v2 v2.3.0 // indirect 78 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect 65 79 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 66 80 github.com/hashicorp/go-hclog v0.16.2 // indirect 67 81 github.com/imdario/mergo v0.3.12 // indirect ··· 75 89 github.com/mitchellh/go-homedir v1.1.0 // indirect 76 90 github.com/mitchellh/mapstructure v1.5.0 // indirect 77 91 github.com/mschoch/smat v0.2.0 // indirect 78 - github.com/pkg/errors v0.9.1 // indirect 79 92 github.com/prometheus/client_model v0.2.0 // indirect 80 93 github.com/prometheus/common v0.32.1 // indirect 81 94 github.com/prometheus/procfs v0.7.3 // indirect ··· 84 97 github.com/stretchr/objx v0.2.0 // indirect 85 98 github.com/xanzy/ssh-agent v0.3.1 // indirect 86 99 go.opencensus.io v0.23.0 // indirect 87 - go.uber.org/multierr v1.6.0 // indirect 100 + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.9.0 // indirect 101 + go.opentelemetry.io/proto/otlp v0.18.0 // indirect 102 + go.uber.org/multierr v1.8.0 // indirect 88 103 go.uber.org/zap v1.21.0 // indirect 89 104 golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect 90 105 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect ··· 93 108 google.golang.org/api v0.77.0 // indirect 94 109 google.golang.org/appengine v1.6.7 // indirect 95 110 google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect 96 - google.golang.org/grpc v1.46.0 // indirect 111 + google.golang.org/grpc v1.46.2 // indirect 97 112 google.golang.org/protobuf v1.28.0 // indirect 98 113 gopkg.in/warnings.v0 v0.1.2 // indirect 99 114 )
+40 -4
go.sum
··· 115 115 github.com/bits-and-blooms/bitset v1.2.2/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= 116 116 github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= 117 117 github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= 118 + github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= 119 + github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= 118 120 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 119 121 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 120 122 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= ··· 221 223 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 222 224 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 223 225 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 226 + github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 227 + github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= 228 + github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 229 + github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 230 + github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 224 231 github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= 225 232 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 226 233 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= ··· 239 246 github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 240 247 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= 241 248 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 249 + github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= 250 + github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= 242 251 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 243 252 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 244 253 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= ··· 340 349 github.com/grafana/regexp v0.0.0-20220304100321-149c8afcd6cb h1:wwzNkyaQwcXCzQuKoWz3lwngetmcyg+EhW0fF5lz73M= 341 350 github.com/grafana/regexp v0.0.0-20220304100321-149c8afcd6cb/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= 342 351 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 352 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= 353 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= 343 354 github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 344 355 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 345 356 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= ··· 563 574 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 564 575 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 565 576 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 566 - github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= 577 + github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= 567 578 github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= 568 579 github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= 569 580 github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= ··· 604 615 go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= 605 616 go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= 606 617 go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 618 + go.opentelemetry.io/contrib/propagators/jaeger v1.9.0 h1:edJTgwezAtLKUINAXfjxllJ1vlsphNPV7RkuKNd/HkQ= 619 + go.opentelemetry.io/contrib/propagators/jaeger v1.9.0/go.mod h1:Q/AXutvrBTfEDSeRLwOmKhyviX5adJvTesg6JFTybYg= 620 + go.opentelemetry.io/contrib/propagators/ot v1.9.0 h1:+pYoqyFoA3H6EZ7Wie2ZQdqS4ZfG42PAGvj3eLUukHE= 621 + go.opentelemetry.io/contrib/propagators/ot v1.9.0/go.mod h1:D2GfaecHHX67fXT93/5iKl2DArjt8+H0XWtFD8b4Z+k= 622 + go.opentelemetry.io/otel v1.9.0 h1:8WZNQFIB2a71LnANS9JeyidJKKGOOremcUtb/OtHISw= 623 + go.opentelemetry.io/otel v1.9.0/go.mod h1:np4EoPGzoPs3O67xUVNoPPcmSvsfOxNlNA4F4AC+0Eo= 624 + go.opentelemetry.io/otel/bridge/opentracing v1.9.0 h1:jlrWaQ/BRcf7C1+LldCcTcqwANsfc1E5HmOv4kE7EZc= 625 + go.opentelemetry.io/otel/bridge/opentracing v1.9.0/go.mod h1:QYKRAmt+MWDoudzsVKYSutcVs9scYhc2K6YspGV/LLw= 626 + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.9.0 h1:ggqApEjDKczicksfvZUCxuvoyDmR6Sbm56LwiK8DVR0= 627 + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.9.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= 628 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.9.0 h1:NN90Cuna0CnBg8YNu1Q0V35i2E8LDByFOwHRCq/ZP9I= 629 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.9.0/go.mod h1:0EsCXjZAiiZGnLdEUXM9YjCKuuLZMYyglh2QDXcYKVA= 630 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.9.0 h1:M0/hqGuJBLeIEu20f89H74RGtqV2dn+SFWEz9ATAAwY= 631 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.9.0/go.mod h1:K5G92gbtCrYJ0mn6zj9Pst7YFsDFuvSYEhYKRMcufnM= 632 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.9.0 h1:FAF9l8Wjxi9Ad2k/vLTfHZyzXYX72C62wBGpV3G6AIo= 633 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.9.0/go.mod h1:smUdtylgc0YQiUr2PuifS4hBXhAS5xtR6WQhxP1wiNA= 634 + go.opentelemetry.io/otel/sdk v1.9.0 h1:LNXp1vrr83fNXTHgU8eO89mhzxb/bbWAsHG6fNf3qWo= 635 + go.opentelemetry.io/otel/sdk v1.9.0/go.mod h1:AEZc8nt5bd2F7BC24J5R0mrjYnpEgYHyTcM/vrSple4= 636 + go.opentelemetry.io/otel/trace v1.9.0 h1:oZaCNJUjWcg60VXWee8lJKlqhPbXAPB51URuR47pQYc= 637 + go.opentelemetry.io/otel/trace v1.9.0/go.mod h1:2737Q0MuG8q1uILYm2YYVkAyLtOofiTNGg6VODnOiPo= 607 638 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 639 + go.opentelemetry.io/proto/otlp v0.18.0 h1:W5hyXNComRa23tGpKwG+FRAc4rfF6ZUg1JReK+QHS80= 640 + go.opentelemetry.io/proto/otlp v0.18.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= 608 641 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 609 642 go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= 610 643 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 611 644 go.uber.org/automaxprocs v1.5.1 h1:e1YG66Lrk73dn4qhg8WFSvhF0JuFQF0ERIp4rpuV8Qk= 612 645 go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU= 613 - go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= 614 646 go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 615 - go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= 647 + go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= 616 648 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 649 + go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= 650 + go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= 617 651 go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= 618 652 go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= 619 653 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= ··· 1084 1118 google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= 1085 1119 google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 1086 1120 google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 1121 + google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 1087 1122 google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 1088 1123 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= 1089 - google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8= 1090 1124 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= 1125 + google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ= 1126 + google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= 1091 1127 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 1092 1128 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 1093 1129 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+56
internal/otlpenv/otlpenv.go
··· 1 + // Package otlpenv exports getters to read OpenTelemetry protocol configuration options 2 + // based on the official spec: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options 3 + package otlpenv 4 + 5 + import ( 6 + "os" 7 + "strings" 8 + ) 9 + 10 + // getWithDefault returns the default value if no env in keys is set, or the first env from keys that is 11 + // set. 12 + func getWithDefault(def string, keys ...string) string { 13 + for _, k := range keys { 14 + if v, set := os.LookupEnv(k); set { 15 + return v 16 + } 17 + } 18 + return def 19 + } 20 + 21 + // This is a custom default that's also not quite compliant but hopefully close enough (we 22 + // use 127.0.0.1 instead of localhost, since there's a linter rule banning localhost). 23 + const defaultGRPCCollectorEndpoint = "http://127.0.0.1:4317" 24 + 25 + // GetEndpoint returns the root collector endpoint, NOT per-signal endpoints. We do not 26 + // yet support per-signal endpoints. 27 + // 28 + // See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options 29 + func GetEndpoint() string { 30 + return getWithDefault(defaultGRPCCollectorEndpoint, 31 + "OTEL_EXPORTER_OTLP_ENDPOINT") 32 + } 33 + 34 + type Protocol string 35 + 36 + const ( 37 + // ProtocolGRPC is protobuf-encoded data using gRPC wire format over HTTP/2 connection 38 + ProtocolGRPC Protocol = "grpc" 39 + // ProtocolHTTPProto is protobuf-encoded data over HTTP connection 40 + ProtocolHTTPProto Protocol = "http/proto" 41 + // ProtocolHTTPJSON is JSON-encoded data over HTTP connection 42 + ProtocolHTTPJSON Protocol = "http/json" 43 + ) 44 + 45 + // GetProtocol returns the configured protocol for the root collector endpoint, NOT 46 + // per-signal endpoints. We do not yet support per-signal endpoints. 47 + // 48 + // See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#specify-protocol 49 + func GetProtocol() Protocol { 50 + return Protocol(getWithDefault(string(ProtocolGRPC), 51 + "OTEL_EXPORTER_OTLP_PROTOCOL")) 52 + } 53 + 54 + func IsInsecure(endpoint string) bool { 55 + return strings.HasPrefix(strings.ToLower(endpoint), "http://") 56 + }
+46
internal/tracer/jaeger.go
··· 1 + package tracer 2 + 3 + import ( 4 + "log" 5 + "reflect" 6 + 7 + "github.com/opentracing/opentracing-go" 8 + "github.com/uber/jaeger-client-go" 9 + jaegercfg "github.com/uber/jaeger-client-go/config" 10 + jaegermetrics "github.com/uber/jaeger-lib/metrics" 11 + ) 12 + 13 + func configureJaeger(svcName string, version string) (opentracing.Tracer, error) { 14 + cfg, err := jaegercfg.FromEnv() 15 + cfg.ServiceName = svcName 16 + if err != nil { 17 + return nil, err 18 + } 19 + cfg.Tags = append(cfg.Tags, opentracing.Tag{Key: "service.version", Value: version}) 20 + if reflect.DeepEqual(cfg.Sampler, &jaegercfg.SamplerConfig{}) { 21 + // Default sampler configuration for when it is not specified via 22 + // JAEGER_SAMPLER_* env vars. In most cases, this is sufficient 23 + // enough to connect to Jaeger without any env vars. 24 + cfg.Sampler.Type = jaeger.SamplerTypeConst 25 + cfg.Sampler.Param = 1 // 1 => enabled 26 + } 27 + tracer, _, err := cfg.NewTracer( 28 + jaegercfg.Logger(&jaegerLogger{}), 29 + jaegercfg.Metrics(jaegermetrics.NullFactory), 30 + ) 31 + if err != nil { 32 + return nil, err 33 + } 34 + return tracer, nil 35 + } 36 + 37 + type jaegerLogger struct{} 38 + 39 + func (l *jaegerLogger) Error(msg string) { 40 + log.Printf("ERROR: %s", msg) 41 + } 42 + 43 + // Infof logs a message at info priority 44 + func (l *jaegerLogger) Infof(msg string, args ...interface{}) { 45 + log.Printf(msg, args...) 46 + }
+121
internal/tracer/opentelemetry.go
··· 1 + package tracer 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + "log" 7 + "regexp" 8 + 9 + "github.com/opentracing/opentracing-go" 10 + "github.com/pkg/errors" 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 + "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 36 + func configureOpenTelemetry(svcName string, version string) (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(resource.NewWithAttributes( 55 + semconv.SchemaURL, 56 + semconv.ServiceNameKey.String(svcName), 57 + semconv.ServiceVersionKey.String(version))), 58 + oteltracesdk.WithSampler(oteltracesdk.AlwaysSample()), 59 + oteltracesdk.WithSpanProcessor(processor), 60 + ) 61 + 62 + // Set up bridge for converting opentracing API calls to OpenTelemetry. 63 + bridge, otelTracerProvider := otelbridge.NewTracerPair(provider.Tracer("tracer.global")) 64 + bridge.SetTextMapPropagator(compositePropagator) 65 + otel.SetTracerProvider(otelTracerProvider) 66 + otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) { 67 + log.Println("opentelemetry: ", err.Error()) 68 + })) 69 + 70 + // Done 71 + return bridge, nil 72 + } 73 + 74 + // newOTelCollectorExporter creates a processor that exports spans to an OpenTelemetry 75 + // collector. 76 + func newOTelCollectorExporter(ctx context.Context, endpoint string) (oteltracesdk.SpanProcessor, error) { 77 + // Set up client to otel-collector - we replicate some of the logic used internally in 78 + // https://github.com/open-telemetry/opentelemetry-go/blob/21c1641831ca19e3acf341cc11459c87b9791f2f/exporters/otlp/internal/otlpconfig/envconfig.go 79 + // based on our own inferred endpoint. 80 + var ( 81 + client otlptrace.Client 82 + protocol = otlpenv.GetProtocol() 83 + trimmedEndpoint = trimSchema(endpoint) 84 + insecure = otlpenv.IsInsecure(endpoint) 85 + ) 86 + 87 + // Work with different protocols 88 + switch protocol { 89 + case otlpenv.ProtocolGRPC: 90 + opts := []otlptracegrpc.Option{ 91 + otlptracegrpc.WithEndpoint(trimmedEndpoint), 92 + } 93 + if insecure { 94 + opts = append(opts, otlptracegrpc.WithInsecure()) 95 + } 96 + client = otlptracegrpc.NewClient(opts...) 97 + 98 + case otlpenv.ProtocolHTTPJSON: 99 + opts := []otlptracehttp.Option{ 100 + otlptracehttp.WithEndpoint(trimmedEndpoint), 101 + } 102 + if insecure { 103 + opts = append(opts, otlptracehttp.WithInsecure()) 104 + } 105 + client = otlptracehttp.NewClient(opts...) 106 + } 107 + 108 + // Initialize the exporter 109 + traceExporter, err := otlptrace.New(ctx, client) 110 + if err != nil { 111 + return nil, errors.Wrap(err, "failed to create trace exporter") 112 + } 113 + 114 + return oteltracesdk.NewBatchSpanProcessor(traceExporter), nil 115 + } 116 + 117 + var httpSchemeRegexp = regexp.MustCompile(`(?i)^http://|https://`) 118 + 119 + func trimSchema(endpoint string) string { 120 + return httpSchemeRegexp.ReplaceAllString(endpoint, "") 121 + }
+45 -50
internal/tracer/tracer.go
··· 3 3 import ( 4 4 "log" 5 5 "os" 6 - "reflect" 7 6 "strconv" 8 7 9 8 "github.com/opentracing/opentracing-go" 10 - "github.com/uber/jaeger-client-go" 11 - jaegercfg "github.com/uber/jaeger-client-go/config" 12 - jaegermetrics "github.com/uber/jaeger-lib/metrics" 13 9 ) 14 10 15 - // Init should only be called from main and only once 16 - // It will initialize the configured tracer, and register it as the global tracer 17 - // This MUST be the same tracer as the one used by Sourcegraph 18 - func Init(svcName, version string) { 11 + type tracerType string 12 + 13 + const ( 14 + tracerTypeNone tracerType = "none" 15 + tracerTypeJaeger tracerType = "jaeger" 16 + tracerTypeOpenTelemetry tracerType = "opentelemetry" 17 + ) 18 + 19 + func inferTracerType() tracerType { 20 + // default to disabled 19 21 isJaegerDisabled, err := strconv.ParseBool(os.Getenv("JAEGER_DISABLED")) 20 - if err != nil { 21 - log.Printf("failed to parse JAEGER_DISABLED: %v", err) 22 - return 23 - } 24 - if isJaegerDisabled { 25 - return 22 + if err == nil && !isJaegerDisabled { 23 + return tracerTypeJaeger 26 24 } 27 25 28 - tracer, err := configureJaeger(svcName, version) 29 - if err != nil { 30 - log.Printf("failed to configure Jaeger tracer: %v", err) 31 - return 26 + // defaults to disabled 27 + isOpenTelemetryDisabled, err := strconv.ParseBool(os.Getenv("OPENTELEMETRY_DISABLED")) 28 + if err == nil && !isOpenTelemetryDisabled { 29 + return tracerTypeOpenTelemetry 32 30 } 33 - log.Printf("INFO: using Jaeger tracer") 34 - opentracing.SetGlobalTracer(tracer) 31 + 32 + return tracerTypeNone 35 33 } 36 34 37 - func configureJaeger(svcName string, version string) (opentracing.Tracer, error) { 38 - cfg, err := jaegercfg.FromEnv() 39 - cfg.ServiceName = svcName 40 - if err != nil { 41 - return nil, err 42 - } 43 - cfg.Tags = append(cfg.Tags, opentracing.Tag{Key: "service.version", Value: version}) 44 - if reflect.DeepEqual(cfg.Sampler, &jaegercfg.SamplerConfig{}) { 45 - // Default sampler configuration for when it is not specified via 46 - // JAEGER_SAMPLER_* env vars. In most cases, this is sufficient 47 - // enough to connect to Jaeger without any env vars. 48 - cfg.Sampler.Type = jaeger.SamplerTypeConst 49 - cfg.Sampler.Param = 1 50 - } 51 - tracer, _, err := cfg.NewTracer( 52 - jaegercfg.Logger(&jaegerLogger{}), 53 - jaegercfg.Metrics(jaegermetrics.NullFactory), 35 + // Init should only be called from main and only once 36 + // It will initialize the configured tracer, and register it as the global tracer 37 + // This MUST be the same tracer as the one used by Sourcegraph 38 + func Init(svcName, version string) { 39 + var ( 40 + tt = inferTracerType() 41 + tracer opentracing.Tracer 42 + err error 54 43 ) 55 - if err != nil { 56 - return nil, err 44 + switch tt { 45 + case tracerTypeJaeger: 46 + tracer, err = configureJaeger(svcName, version) 47 + if err != nil { 48 + log.Printf("failed to configure Jaeger tracer: %v", err) 49 + return 50 + } 51 + log.Printf("INFO: using Jaeger tracer") 52 + 53 + case tracerTypeOpenTelemetry: 54 + tracer, err = configureOpenTelemetry(svcName, version) 55 + if err != nil { 56 + log.Printf("failed to configure OpenTelemetry tracer: %v", err) 57 + return 58 + } 59 + log.Printf("INFO: using OpenTelemetry tracer") 57 60 } 58 - return tracer, nil 59 - } 60 61 61 - type jaegerLogger struct{} 62 - 63 - func (l *jaegerLogger) Error(msg string) { 64 - log.Printf("ERROR: %s", msg) 65 - } 66 - 67 - // Infof logs a message at info priority 68 - func (l *jaegerLogger) Infof(msg string, args ...interface{}) { 69 - log.Printf(msg, args...) 62 + if tracer != nil { 63 + opentracing.SetGlobalTracer(tracer) 64 + } 70 65 }