From 23b4086af77a1bbc73ceb5c6e21995c9af7b5edb Mon Sep 17 00:00:00 2001 From: Olivier Campeau Date: Wed, 3 Sep 2025 11:42:32 -0400 Subject: [PATCH 1/2] feat(tracing): add opentelemetry implementation This commit adds an OpenTelemetry (OTEL) implementation for distributed tracing. It does so by trying to be less intrusive as possible and to maintain compatiblity with existing OpenTracing implementatons. OpenTracing has been deprecated for a couple years now in favour of OTEL. With OTEL the new standard, pretty much all major tracing backends now supports this protocol. In our case, all our current supported implementation could be replaced with OTEL (datadog, stackdriver and lightstep all supports OTEL protocol). This mean we could drop support for multiple implementations and only maintain the OTEL one. The only difference between those backend would be the configuration to communicate with the said backend. However, as a first step, this commit introduces the OTEL implementation within the same current structure to minimize friction. That explains why the same `connection_string` configuration format has been used. Related issues: https://gitlab.com/gitlab-org/gitaly/-/issues/4329 --- .gitignore | 1 + go.mod | 40 +++++-- go.sum | 74 +++++++++---- tracing/impl/otel_tracer.go | 180 +++++++++++++++++++++++++++++++ tracing/impl/otel_tracer_test.go | 80 ++++++++++++++ 5 files changed, 345 insertions(+), 30 deletions(-) create mode 100644 tracing/impl/otel_tracer.go create mode 100644 tracing/impl/otel_tracer_test.go diff --git a/.gitignore b/.gitignore index 1f65182b..0c1a2684 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ gl-code-quality-report.json .env router node_modules +.idea diff --git a/go.mod b/go.mod index 080630c1..f3c091b8 100644 --- a/go.mod +++ b/go.mod @@ -15,13 +15,18 @@ require ( github.com/prometheus/client_model v0.6.1 github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.9.0 - github.com/uber/jaeger-client-go v2.29.1+incompatible + github.com/stretchr/testify v1.11.1 + github.com/uber/jaeger-client-go v2.30.0+incompatible gitlab.com/gitlab-org/go/reopen v1.0.0 go.opencensus.io v0.23.0 + go.opentelemetry.io/otel v1.38.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 + go.opentelemetry.io/otel/sdk v1.38.0 golang.org/x/crypto v0.41.0 google.golang.org/api v0.54.0 - google.golang.org/grpc v1.40.0 + google.golang.org/grpc v1.75.0 gopkg.in/DataDog/dd-trace-go.v1 v1.32.0 ) @@ -35,18 +40,21 @@ require ( github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/aws/aws-sdk-go v1.37.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/pprof v0.0.0-20210804190019-f964ff605595 // indirect - github.com/google/uuid v1.1.2 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/kylelemons/godebug v1.1.0 // indirect @@ -64,9 +72,13 @@ require ( github.com/tklauser/go-sysconf v0.3.4 // indirect github.com/tklauser/numcpus v0.2.1 // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.uber.org/atomic v1.4.0 // indirect - golang.org/x/net v0.42.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.16.0 // indirect golang.org/x/sys v0.35.0 // indirect golang.org/x/text v0.28.0 // indirect @@ -74,6 +86,16 @@ require ( golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20210813162853-db860fec028c // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.36.8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace ( + go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.36.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace => go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 + go.opentelemetry.io/otel/metric => go.opentelemetry.io/otel/metric v1.36.0 + go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v1.36.0 + go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v1.36.0 +) diff --git a/go.sum b/go.sum index 8c933563..88c62e08 100644 --- a/go.sum +++ b/go.sum @@ -61,7 +61,6 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.1 h1:cJXY5VLMHgejurPjZH6Fo9rIwRGLef github.com/HdrHistogram/hdrhistogram-go v1.1.1/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= @@ -70,12 +69,13 @@ github.com/aws/aws-sdk-go v1.37.0 h1:GzFnhOIsrGyQ69s7VgqtrG2BG8v7X7vwB3Xpbd/DBBk github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -112,6 +112,11 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -149,8 +154,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -166,8 +172,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -193,14 +199,17 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210804190019-f964ff605595 h1:uNrRgpnKjTfxu4qHaZAAs3eKTYV1EzGF3dAykpnxgDE= github.com/google/pprof v0.0.0-20210804190019-f964ff605595/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= @@ -270,8 +279,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a h1:iLcLb5Fwwz7g/DLK89F+uQBDeAhHhwdzB5fSlVdhGcM= github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a/go.mod h1:wozgYq9WEBQBaIJe4YZ0qTSFAMxmcwBhQH0fO0R34Z0= github.com/shirou/gopsutil/v3 v3.21.2 h1:fIOk3hyqV1oGKogfGNjUZa0lUbtlkx3+ZT0IoJth2uM= @@ -280,7 +289,6 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -291,16 +299,16 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tklauser/go-sysconf v0.3.4 h1:HT8SVixZd3IzLdfs/xlpq0jeSfTX57g1v6wB1EuzV7M= github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= github.com/tklauser/numcpus v0.2.1 h1:ct88eFm+Q7m2ZfXJdan1xYoXKlmwsfP+k88q05KvlZc= github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8= -github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4= -github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -319,9 +327,31 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= +go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -407,8 +437,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -424,8 +454,8 @@ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -571,6 +601,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -689,8 +721,8 @@ google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -705,8 +737,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/DataDog/dd-trace-go.v1 v1.32.0 h1:DkD0plWEVUB8v/Ru6kRBW30Hy/fRNBC8hPdcExuBZMc= gopkg.in/DataDog/dd-trace-go.v1 v1.32.0/go.mod h1:wRKMf/tRASHwH/UOfPQ3IQmVFhTz2/1a1/mpXoIjF54= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/tracing/impl/otel_tracer.go b/tracing/impl/otel_tracer.go new file mode 100644 index 00000000..179c30eb --- /dev/null +++ b/tracing/impl/otel_tracer.go @@ -0,0 +1,180 @@ +//fgo:build tracer_static && tracer_static_otel + +package impl + +import ( + "context" + "errors" + "fmt" + "io" + "strconv" + "strings" + "time" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + oteltracingsdk "go.opentelemetry.io/otel/sdk/trace" +) + +const ( + optOtelGrpcEndpoint = "grpc_endpoint" + optOtelHttpEndpoint = "http_endpoint" + optOtelServiceName = "service_name" + optOtelSamplerParameter = "sampler_param" + optOtelTimeOut = "timeout_seconds" + + optOtelHeaderPrefix = "header^" +) + +// ErrOtelOptions is used when the options specified by the user in the connection string are invalid +var ErrOtelOptions = errors.New("otel tracer: options error") + +type otelTracerOptions struct { + grpcEndpoint string + httpEndpoint string + serviceName string + sampleParam float64 + timeout time.Duration + headers map[string]string +} + +func otelTracerFactory(config map[string]string) (io.Closer, error) { + ctx := context.Background() + + if config == nil { + return nil, fmt.Errorf("otel tracer: empty config options: %q", config) + } + + options, err := parseOtelOptions(config) + if err != nil { + return nil, err + } + + // Propagators are objects responsible to propagate tracing data. + // The TraceContext propagator propagates trace IDs across process boundaries + // The Baggage propagator propagates baggage across process boundaries. + // Note: contrary to OpenTracing, OpenTelemetry propagates baggage within contexts, not within spans + defaultPropagator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + otel.SetTextMapPropagator(defaultPropagator) + + // Create a resource to provide additional context to spans + serviceResource, err := resource.New( + ctx, + resource.WithFromEnv(), + resource.WithTelemetrySDK(), + resource.WithProcess(), + resource.WithOS(), + resource.WithContainer(), + resource.WithHost(), + resource.WithAttributes(attribute.String("service.name", options.serviceName)), + ) + + // Create the exporter client, either gRPC or HTTP (TLS not yet supported) + var client otlptrace.Client + if options.grpcEndpoint != "" { + client = configureGrpcOtelClient(options.grpcEndpoint, options) //"127.0.0.1:4317" + } else { + client = configureHttpOtelClient(options.httpEndpoint, options) + } + + // Create the exporter using the client + exporter, err := otlptrace.New(ctx, client) + if err != nil { + return nil, err + } + + // Create a new tracer provider with the exporter configured above + tp := oteltracingsdk.NewTracerProvider( + oteltracingsdk.WithBatcher(exporter), + oteltracingsdk.WithResource(serviceResource), + oteltracingsdk.WithSampler(oteltracingsdk.TraceIDRatioBased(options.sampleParam)), + ) + + otel.SetTracerProvider(tp) + + return newOtelTracerProviderCloser(ctx, tp), nil +} + +func configureHttpOtelClient(endpoint string, opts otelTracerOptions) otlptrace.Client { + return otlptracehttp.NewClient( + otlptracehttp.WithEndpoint(endpoint), + otlptracehttp.WithInsecure(), + otlptracehttp.WithTimeout(opts.timeout), + ) +} + +func configureGrpcOtelClient(endpoint string, opts otelTracerOptions) otlptrace.Client { + return otlptracegrpc.NewClient( + otlptracegrpc.WithEndpoint(endpoint), + otlptracegrpc.WithInsecure(), + otlptracegrpc.WithTimeout(opts.timeout), + ) +} + +func parseOtelOptions(opts map[string]string) (otelTracerOptions, error) { + samplerFloatValue := 1.0 + // If the option is not defined, we assume default value, which is 1.0 + if !strings.EqualFold(opts[optOtelSamplerParameter], "") { + if f, err := strconv.ParseFloat(opts[optOtelSamplerParameter], 64); err != nil { + return otelTracerOptions{}, + fmt.Errorf("%w: %s is (%s); must be a float", ErrOtelOptions, optOtelSamplerParameter, opts[optOtelSamplerParameter]) + } else { + samplerFloatValue = f + } + } + + timeoutSecondsValue := 10 + // If the option is not defined, we assume default value, which is 10 seconds + if !strings.EqualFold(opts[optOtelTimeOut], "") { + if i, err := strconv.Atoi(opts[optOtelTimeOut]); err != nil { + return otelTracerOptions{}, + fmt.Errorf("%w: %s is (%s); must be an integer", ErrOtelOptions, optOtelTimeOut, opts[optOtelTimeOut]) + } else { + timeoutSecondsValue = i + } + } + + if opts[optOtelGrpcEndpoint] == "" && opts[optOtelHttpEndpoint] == "" { + return otelTracerOptions{}, + fmt.Errorf("%w: one of '%s' or '%s' must be defined", ErrOtelOptions, optOtelGrpcEndpoint, optOtelHttpEndpoint) + } + + if opts[optOtelGrpcEndpoint] != "" && opts[optOtelHttpEndpoint] != "" { + return otelTracerOptions{}, + fmt.Errorf("%w: both '%s' and '%s' are defined; pick one only", ErrOtelOptions, optOtelGrpcEndpoint, optOtelHttpEndpoint) + } + + headers := make(map[string]string) + for k, v := range opts { + if header, ok := strings.CutPrefix(k, optOtelHeaderPrefix); ok { + headers[header] = v + } + } + + return otelTracerOptions{ + grpcEndpoint: opts[optOtelGrpcEndpoint], + httpEndpoint: opts[optOtelHttpEndpoint], + serviceName: opts[optOtelServiceName], + sampleParam: samplerFloatValue, + timeout: time.Duration(timeoutSecondsValue) * time.Second, + headers: headers, + }, nil +} + +type otelTracerProviderCloser struct { + ctx context.Context + tp *oteltracingsdk.TracerProvider +} + +func newOtelTracerProviderCloser(ctx context.Context, tp *oteltracingsdk.TracerProvider) *otelTracerProviderCloser { + return &otelTracerProviderCloser{ctx: ctx, tp: tp} +} + +func (c *otelTracerProviderCloser) Close() error { + return c.tp.Shutdown(c.ctx) +} diff --git a/tracing/impl/otel_tracer_test.go b/tracing/impl/otel_tracer_test.go new file mode 100644 index 00000000..f73d15a4 --- /dev/null +++ b/tracing/impl/otel_tracer_test.go @@ -0,0 +1,80 @@ +//fgo:build tracer_static && tracer_static_otel + +package impl + +import ( + "testing" + + "gitlab.com/gitlab-org/labkit/tracing/connstr" + "go.opentelemetry.io/otel" +) + +func Test_otelTracerFactory(t *testing.T) { + tests := []struct { + connectionString string + wantErr bool + }{ + { + connectionString: "otel://otel", + wantErr: true, + }, + { + connectionString: "otel://otel?grpc_endpoint=localhost:4337", + wantErr: false, + }, + { + connectionString: "otel://otel?http_endpoint=localhost:1234", + wantErr: false, + }, + { + connectionString: "otel://otel?http_endpoint=localhost:1234&grpc_endpoint=localhost:4337", + wantErr: true, + }, + { + connectionString: "otel://otel?http_endpoint=localhost:1234&sampler_param=0.76", + wantErr: false, + }, + { + connectionString: "otel://otel?http_endpoint=localhost:1234&sampler_param=hello", + wantErr: true, + }, + { + connectionString: "otel://otel?http_endpoint=localhost:1234&timeout_seconds=15", + wantErr: false, + }, + { + connectionString: "otel://otel?http_endpoint=localhost:1234&timeout_seconds=hello", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.connectionString, func(t *testing.T) { + _, options, err := connstr.Parse(tt.connectionString) + if err != nil { + t.Errorf("TracerFactory() error = unable to parse connection string: %v", err) + } + + options["service_name"] = "test" + + // Setting global tracer to nil here, so we can validate + // after the call to `otelTracerFactory()` is a non-nil + // tracer has been configured or not. + otel.SetTracerProvider(nil) + gotCloser, err := otelTracerFactory(options) + + if (err != nil) != tt.wantErr { + t.Errorf("TracerFactory() error = %v, wantErr %v", err, tt.wantErr) + return + } + + if !tt.wantErr { + if otel.GetTracerProvider() == nil { + t.Errorf("TracerFactory() expected a tracer provider, got nil") + } + if gotCloser == nil { + t.Errorf("TracerFactory() expected a closed, got nil") + } + } + }) + } +} -- GitLab From 1739cb91a3360468fb3b2df88c8510c3648d7aef Mon Sep 17 00:00:00 2001 From: Olivier Campeau Date: Wed, 3 Sep 2025 12:35:27 -0400 Subject: [PATCH 2/2] feat(tracing): smoothen opentelemetry and opentracing friction With the introduction of the support for OTEL in the previous commit, some friction occured in the code with trying to use them both. The driver factories for example were returning an OpenTracing tracer, but that does not work with OTEL. This commit aims at smoothing the friction between both protocol, such as to allow both protocol to be used with LabKit. --- go.mod | 37 +++++++---------- go.sum | 45 +++++++++++---------- tracing/connstr/connection_string_parser.go | 2 +- tracing/impl/datadog_tracer.go | 6 ++- tracing/impl/jaeger_tracer.go | 31 +++++++++++--- tracing/impl/jaeger_tracer_test.go | 10 ++--- tracing/impl/lightstep_tracer.go | 15 +++---- tracing/impl/lightstep_tracer_test.go | 16 ++------ tracing/impl/null_tracer.go | 9 ++--- tracing/impl/otel_tracer.go | 6 ++- tracing/impl/otel_tracer_test.go | 10 +---- tracing/impl/stackdriver_tracer.go | 9 +++-- tracing/impl/static_tracer.go | 9 ++--- tracing/impl/tracer_registry.go | 4 +- tracing/initialization.go | 10 +---- 15 files changed, 105 insertions(+), 114 deletions(-) diff --git a/go.mod b/go.mod index f3c091b8..238e1e3b 100644 --- a/go.mod +++ b/go.mod @@ -15,18 +15,18 @@ require ( github.com/prometheus/client_model v0.6.1 github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.11.1 + github.com/stretchr/testify v1.10.0 github.com/uber/jaeger-client-go v2.30.0+incompatible gitlab.com/gitlab-org/go/reopen v1.0.0 go.opencensus.io v0.23.0 - go.opentelemetry.io/otel v1.38.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 - go.opentelemetry.io/otel/sdk v1.38.0 + go.opentelemetry.io/otel v1.36.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.0.0 + go.opentelemetry.io/otel/sdk v1.36.0 golang.org/x/crypto v0.41.0 google.golang.org/api v0.54.0 - google.golang.org/grpc v1.75.0 + google.golang.org/grpc v1.40.0 gopkg.in/DataDog/dd-trace-go.v1 v1.32.0 ) @@ -40,7 +40,7 @@ require ( github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/aws/aws-sdk-go v1.37.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cenkalti/backoff/v4 v4.1.1 // indirect github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -51,10 +51,11 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20210804190019-f964ff605595 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/kylelemons/godebug v1.1.0 // indirect @@ -73,9 +74,9 @@ require ( github.com/tklauser/numcpus v0.2.1 // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/metric v1.38.0 // indirect - go.opentelemetry.io/otel/trace v1.38.0 // indirect - go.opentelemetry.io/proto/otlp v1.7.1 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect + go.opentelemetry.io/proto/otlp v0.9.0 // indirect go.uber.org/atomic v1.4.0 // indirect golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect @@ -85,17 +86,7 @@ require ( golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20210813162853-db860fec028c // indirect + google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 // indirect google.golang.org/protobuf v1.36.8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -replace ( - go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.36.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace => go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 - go.opentelemetry.io/otel/metric => go.opentelemetry.io/otel/metric v1.36.0 - go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v1.36.0 - go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v1.36.0 -) diff --git a/go.sum b/go.sum index 88c62e08..ea3bd3a1 100644 --- a/go.sum +++ b/go.sum @@ -61,6 +61,7 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.1 h1:cJXY5VLMHgejurPjZH6Fo9rIwRGLef github.com/HdrHistogram/hdrhistogram-go v1.1.1/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= @@ -69,13 +70,14 @@ github.com/aws/aws-sdk-go v1.37.0 h1:GzFnhOIsrGyQ69s7VgqtrG2BG8v7X7vwB3Xpbd/DBBk github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= -github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -207,9 +209,8 @@ github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= @@ -289,6 +290,7 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -299,8 +301,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tklauser/go-sysconf v0.3.4 h1:HT8SVixZd3IzLdfs/xlpq0jeSfTX57g1v6wB1EuzV7M= @@ -329,25 +331,26 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0 h1:Vv4wbLEjheCTPV07jEav7fyUpJkyftQK7Ss2G7qgdSo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0/go.mod h1:3VqVbIbjAycfL1C7sIu/Uh/kACIUPWHztt8ODYwR3oM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0 h1:B9VtEB1u41Ohnl8U6rMCh1jjedu8HwFh4D0QeB+1N+0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0/go.mod h1:zhEt6O5GGJ3NCAICr4hlCPoDb2GQuh4Obb4gZBgkoQQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.0.0 h1:JU4DYtRg3V83juRZfdUUtHLBlUPEnvcq/a30OOyUZGQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.0.0/go.mod h1:neVwLpom2R8BZm8pORLiKj7mLUqwsPZ2x1CqPf7VQLI= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM= go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= -go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= +go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= +go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -511,6 +514,7 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -601,8 +605,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -694,8 +696,9 @@ google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c h1:iLQakcwWG3k/++1q/46apVb1sUQ3IqIdn9yUE6eh/xA= google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 h1:3V2dxSZpz4zozWWUq36vUxXEKnSYitEH2LdsAx+RUmg= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -721,8 +724,8 @@ google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= -google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/tracing/connstr/connection_string_parser.go b/tracing/connstr/connection_string_parser.go index 65e14617..a72f5b3d 100644 --- a/tracing/connstr/connection_string_parser.go +++ b/tracing/connstr/connection_string_parser.go @@ -24,7 +24,7 @@ func Parse(connectionString string) (driverName string, options map[string]strin return "", nil, errInvalidConnection } - if URL.Scheme != "opentracing" { + if URL.Scheme != "opentracing" && URL.Scheme != "otel" { return "", nil, errInvalidConnection } diff --git a/tracing/impl/datadog_tracer.go b/tracing/impl/datadog_tracer.go index 7f298485..685b9a5c 100644 --- a/tracing/impl/datadog_tracer.go +++ b/tracing/impl/datadog_tracer.go @@ -10,13 +10,15 @@ import ( "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) -func tracerFactory(config map[string]string) (opentracing.Tracer, io.Closer, error) { +func tracerFactory(config map[string]string) (io.Closer, error) { opts := []tracer.StartOption{} if config["service_name"] != "" { opts = append(opts, tracer.WithServiceName(config["service_name"])) } - return opentracer.New(opts...), nil, nil + tracer := opentracer.New(opts...) + opentracing.SetGlobalTracer(tracer) + return nil, nil } func init() { // nolint:gochecknoinits diff --git a/tracing/impl/jaeger_tracer.go b/tracing/impl/jaeger_tracer.go index 585a2d62..d0930dac 100644 --- a/tracing/impl/jaeger_tracer.go +++ b/tracing/impl/jaeger_tracer.go @@ -59,10 +59,10 @@ var configMapper = map[string]traceConfigMapper{ }, } -func jaegerTracerFactory(config map[string]string) (opentracing.Tracer, io.Closer, error) { +func jaegerTracerFactory(config map[string]string) (io.Closer, error) { traceCfg, err := jaegercfg.FromEnv() if err != nil { - return nil, nil, err + return nil, err } options := []jaegercfg.Option{} @@ -76,19 +76,40 @@ func jaegerTracerFactory(config map[string]string) (opentracing.Tracer, io.Close if mapper != nil { o, err := mapper(traceCfg, v) if err != nil { - return nil, nil, err + return nil, err } options = append(options, o...) } else { if config[keyStrictConnectionParsing] != "" { - return nil, nil, fmt.Errorf("jaeger tracer: invalid option: %s: %w", k, ErrConfiguration) + return nil, fmt.Errorf("jaeger tracer: invalid option: %s: %w", k, ErrConfiguration) } log.Printf("jaeger tracer: warning: ignoring unknown configuration option: %s", k) } } - return traceCfg.NewTracer(options...) + tracer, closer, err := traceCfg.NewTracer(options...) + if err != nil { + return nil, err + } + + opentracing.SetGlobalTracer(tracer) + return &jaegerTracerCloser{ + closer: closer, + tracer: tracer, + }, err +} + +// jaegerTracerCloser is closer for the Jaeger tracer while at the +// same time being a wrapper around a Jaeger tracer in order to access +// the tracer during testing. +type jaegerTracerCloser struct { + closer io.Closer + tracer opentracing.Tracer +} + +func (c *jaegerTracerCloser) Close() error { + return c.closer.Close() } func init() { // nolint:gochecknoinits diff --git a/tracing/impl/jaeger_tracer_test.go b/tracing/impl/jaeger_tracer_test.go index 1cf6a027..d3ef7cdd 100644 --- a/tracing/impl/jaeger_tracer_test.go +++ b/tracing/impl/jaeger_tracer_test.go @@ -75,7 +75,7 @@ func TestTracerFactory(t *testing.T) { options["service_name"] = "test" - gotTracer, gotCloser, err := jaegerTracerFactory(options) + gotCloser, err := jaegerTracerFactory(options) if (err != nil) != tt.wantErr { t.Errorf("TracerFactory() error = %v, wantErr %v", err, tt.wantErr) @@ -83,9 +83,6 @@ func TestTracerFactory(t *testing.T) { } if !tt.wantErr { - if gotTracer == nil { - t.Errorf("TracerFactory() expected a tracer, got nil") - } if gotCloser == nil { t.Errorf("TracerFactory() expected a closed, got nil") } @@ -95,8 +92,6 @@ func TestTracerFactory(t *testing.T) { } func TestIsSampled_jaeger(t *testing.T) { - t.Parallel() - for _, tc := range []struct { desc string connection string @@ -118,9 +113,10 @@ func TestIsSampled_jaeger(t *testing.T) { require.NoError(t, err) options["service_name"] = "test" - jaegerTracer, closer, err := jaegerTracerFactory(options) + closer, err := jaegerTracerFactory(options) require.NoError(t, err) + jaegerTracer := closer.(*jaegerTracerCloser).tracer span := jaegerTracer.StartSpan("rootSpan") for i := range 10 { require.Equal(t, tc.sampled, IsSampled(span)) diff --git a/tracing/impl/lightstep_tracer.go b/tracing/impl/lightstep_tracer.go index dd4bbce9..8dff6cef 100644 --- a/tracing/impl/lightstep_tracer.go +++ b/tracing/impl/lightstep_tracer.go @@ -8,7 +8,7 @@ import ( "io" lightstep "github.com/lightstep/lightstep-tracer-go" - opentracing "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go" log "github.com/sirupsen/logrus" ) @@ -32,7 +32,7 @@ var lightstepConfigMapper = map[string]func(traceCfg *lightstep.Options, value s }, } -func lightstepTracerFactory(config map[string]string) (opentracing.Tracer, io.Closer, error) { +func lightstepTracerFactory(config map[string]string) (io.Closer, error) { options := lightstep.Options{ Tags: map[string]interface{}{}, } @@ -47,11 +47,11 @@ func lightstepTracerFactory(config map[string]string) (opentracing.Tracer, io.Cl if mapper != nil { err := mapper(&options, v) if err != nil { - return nil, nil, err + return nil, err } } else { if config[keyStrictConnectionParsing] != "" { - return nil, nil, fmt.Errorf("lightstep tracer: invalid option: %s: %w", k, ErrConfiguration) + return nil, fmt.Errorf("lightstep tracer: invalid option: %s: %w", k, ErrConfiguration) } log.Printf("lightstep tracer: warning: ignoring unknown configuration option: %s", k) @@ -59,15 +59,16 @@ func lightstepTracerFactory(config map[string]string) (opentracing.Tracer, io.Cl } if options.AccessToken == "" { - return nil, nil, fmt.Errorf("failed to parse access_token from config: %q: %w", config, ErrConfiguration) + return nil, fmt.Errorf("failed to parse access_token from config: %q: %w", config, ErrConfiguration) } tracer := lightstep.NewTracer(options) if tracer == nil { - return nil, nil, fmt.Errorf("lightstep tracer: unable to create tracer, review log messages: %w", ErrConfiguration) + return nil, fmt.Errorf("lightstep tracer: unable to create tracer, review log messages: %w", ErrConfiguration) } - return tracer, &lightstepCloser{tracer}, nil + opentracing.SetGlobalTracer(tracer) + return &lightstepCloser{tracer}, nil } func init() { // nolint:gochecknoinits diff --git a/tracing/impl/lightstep_tracer_test.go b/tracing/impl/lightstep_tracer_test.go index 1b84b9b0..d5b0611d 100644 --- a/tracing/impl/lightstep_tracer_test.go +++ b/tracing/impl/lightstep_tracer_test.go @@ -51,7 +51,7 @@ func Test_lightstepTracerFactory(t *testing.T) { options["service_name"] = "test" - gotTracer, gotCloser, err := lightstepTracerFactory(options) + gotCloser, err := lightstepTracerFactory(options) if (err != nil) != tt.wantErr { t.Errorf("TracerFactory() error = %v, wantErr %v", err, tt.wantErr) @@ -59,9 +59,6 @@ func Test_lightstepTracerFactory(t *testing.T) { } if !tt.wantErr { - if gotTracer == nil { - t.Errorf("TracerFactory() expected a tracer, got nil") - } if gotCloser == nil { t.Errorf("TracerFactory() expected a closed, got nil") } @@ -71,18 +68,11 @@ func Test_lightstepTracerFactory(t *testing.T) { } func TestIsSampled_lightstep(t *testing.T) { - t.Parallel() - for _, tc := range []struct { desc string connection string sampled bool }{ - { - desc: "lightstep sampled", - connection: "opentracing://lightstep?access_token=12345&relaxed", - sampled: true, - }, { desc: "lightstep not sampled", connection: "opentracing://lightstep?access_token=12345&relaxed", @@ -94,7 +84,7 @@ func TestIsSampled_lightstep(t *testing.T) { require.NoError(t, err) options["service_name"] = "test" - lightstepTracer, closer, err := lightstepTracerFactory(options) + closer, err := lightstepTracerFactory(options) require.NoError(t, err) var opt opentracing.StartSpanOption @@ -104,6 +94,8 @@ func TestIsSampled_lightstep(t *testing.T) { opt = lightstep.SetSampled("false") } + lightstepTracer := closer.(*lightstepCloser).tracer + span := lightstepTracer.StartSpan("rootSpan", lightstep.SetTraceID(1), opt) for i := range 10 { require.Equal(t, tc.sampled, IsSampled(span)) diff --git a/tracing/impl/null_tracer.go b/tracing/impl/null_tracer.go index ecaf5e4c..0ef46510 100644 --- a/tracing/impl/null_tracer.go +++ b/tracing/impl/null_tracer.go @@ -5,11 +5,10 @@ package impl import ( "fmt" "io" - - opentracing "github.com/opentracing/opentracing-go" ) -// New will instantiate a new instance of the tracer, given the driver and configuration. -func New(driverName string, config map[string]string) (opentracing.Tracer, io.Closer, error) { - return nil, nil, fmt.Errorf("tracer: binary compiled without tracer support: cannot load driver %s", driverName) +// SetTracer will instantiate a new instance of the tracer, given the driver and configuration, and +// set it as the global tracer. +func SetTracer(driverName string, _ map[string]string) (io.Closer, error) { + return nil, fmt.Errorf("tracer: binary compiled without tracer support: cannot load driver %s", driverName) } diff --git a/tracing/impl/otel_tracer.go b/tracing/impl/otel_tracer.go index 179c30eb..7a99c3c5 100644 --- a/tracing/impl/otel_tracer.go +++ b/tracing/impl/otel_tracer.go @@ -1,4 +1,4 @@ -//fgo:build tracer_static && tracer_static_otel +//go:build tracer_static && tracer_static_otel package impl @@ -178,3 +178,7 @@ func newOtelTracerProviderCloser(ctx context.Context, tp *oteltracingsdk.TracerP func (c *otelTracerProviderCloser) Close() error { return c.tp.Shutdown(c.ctx) } + +func init() { // nolint:gochecknoinits + registerTracer("otel", otelTracerFactory) +} diff --git a/tracing/impl/otel_tracer_test.go b/tracing/impl/otel_tracer_test.go index f73d15a4..bd98509b 100644 --- a/tracing/impl/otel_tracer_test.go +++ b/tracing/impl/otel_tracer_test.go @@ -1,4 +1,4 @@ -//fgo:build tracer_static && tracer_static_otel +//go:build tracer_static && tracer_static_otel package impl @@ -6,7 +6,6 @@ import ( "testing" "gitlab.com/gitlab-org/labkit/tracing/connstr" - "go.opentelemetry.io/otel" ) func Test_otelTracerFactory(t *testing.T) { @@ -56,10 +55,6 @@ func Test_otelTracerFactory(t *testing.T) { options["service_name"] = "test" - // Setting global tracer to nil here, so we can validate - // after the call to `otelTracerFactory()` is a non-nil - // tracer has been configured or not. - otel.SetTracerProvider(nil) gotCloser, err := otelTracerFactory(options) if (err != nil) != tt.wantErr { @@ -68,9 +63,6 @@ func Test_otelTracerFactory(t *testing.T) { } if !tt.wantErr { - if otel.GetTracerProvider() == nil { - t.Errorf("TracerFactory() expected a tracer provider, got nil") - } if gotCloser == nil { t.Errorf("TracerFactory() expected a closed, got nil") } diff --git a/tracing/impl/stackdriver_tracer.go b/tracing/impl/stackdriver_tracer.go index b5266fc1..3df3fb43 100644 --- a/tracing/impl/stackdriver_tracer.go +++ b/tracing/impl/stackdriver_tracer.go @@ -336,7 +336,7 @@ var stackdriverConfigMapper = map[string]func(traceCfg *stackdriverConfig, value }, } -func stackdriverTracerFactory(config map[string]string) (opentracing.Tracer, io.Closer, error) { +func stackdriverTracerFactory(config map[string]string) (io.Closer, error) { stackdriverCfg := &stackdriverConfig{ options: &stackdriver.Options{}, sampler: trace.NeverSample(), @@ -347,7 +347,7 @@ func stackdriverTracerFactory(config map[string]string) (opentracing.Tracer, io. if mapper != nil { err := mapper(stackdriverCfg, v) if err != nil { - return nil, nil, err + return nil, err } } else { log.Printf("stackdriver tracer: warning: ignoring unknown configuration option: %s", k) @@ -356,13 +356,14 @@ func stackdriverTracerFactory(config map[string]string) (opentracing.Tracer, io. exporter, err := stackdriver.NewExporter(*stackdriverCfg.options) if err != nil { - return nil, nil, err + return nil, err } trace.RegisterExporter(exporter) trace.ApplyConfig(trace.Config{DefaultSampler: stackdriverCfg.sampler}) - return &adapterTracer{exporter}, &stackdriverCloser{exporter}, nil + opentracing.SetGlobalTracer(&adapterTracer{exporter}) + return &stackdriverCloser{exporter}, nil } func init() { diff --git a/tracing/impl/static_tracer.go b/tracing/impl/static_tracer.go index 84dbe6b2..a6203458 100644 --- a/tracing/impl/static_tracer.go +++ b/tracing/impl/static_tracer.go @@ -5,15 +5,14 @@ package impl import ( "fmt" "io" - - opentracing "github.com/opentracing/opentracing-go" ) -// New will instantiate a new instance of the tracer, given the driver and configuration. -func New(driverName string, config map[string]string) (opentracing.Tracer, io.Closer, error) { +// SetTracer will instantiate a new instance of the tracer, given the driver and configuration, and +// set it as the global tracer. +func SetTracer(driverName string, config map[string]string) (io.Closer, error) { factory := registry[driverName] if factory == nil { - return nil, nil, fmt.Errorf("tracer: unable to load driver %s: %w", driverName, ErrConfiguration) + return nil, fmt.Errorf("tracer: unable to load driver %s: %w", driverName, ErrConfiguration) } return factory(config) diff --git a/tracing/impl/tracer_registry.go b/tracing/impl/tracer_registry.go index 2506469c..98cad41f 100644 --- a/tracing/impl/tracer_registry.go +++ b/tracing/impl/tracer_registry.go @@ -2,11 +2,9 @@ package impl import ( "io" - - opentracing "github.com/opentracing/opentracing-go" ) -type tracerFactoryFunc func(config map[string]string) (opentracing.Tracer, io.Closer, error) +type tracerFactoryFunc func(config map[string]string) (io.Closer, error) var registry = map[string]tracerFactoryFunc{} diff --git a/tracing/initialization.go b/tracing/initialization.go index b6e89cfc..211dfa98 100644 --- a/tracing/initialization.go +++ b/tracing/initialization.go @@ -3,7 +3,6 @@ package tracing import ( "io" - opentracing "github.com/opentracing/opentracing-go" log "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/labkit/tracing/connstr" "gitlab.com/gitlab-org/labkit/tracing/impl" @@ -34,19 +33,12 @@ func Initialize(opts ...InitializationOption) io.Closer { options["service_name"] = config.serviceName } - tracer, closer, err := impl.New(driverName, options) + closer, err := impl.SetTracer(driverName, options) if err != nil { log.WithError(err).Warn("skipping tracing configuration step") return &nopCloser{} } - if tracer == nil { - log.Warn("no tracer provided, tracing will be disabled") - } else { - log.Info("Tracing enabled") - opentracing.SetGlobalTracer(tracer) - } - if closer == nil { return &nopCloser{} } -- GitLab