From 4e8d0f83e5166c9f69ce6c928d4908b027e0e4a0 Mon Sep 17 00:00:00 2001 From: viveksing Date: Thu, 9 Jan 2025 15:57:59 +0100 Subject: [PATCH 1/4] Add opentelemetry bridge Signed-off-by: viveksing --- go.mod | 44 ++++--- go.sum | 90 ++++++------- tracing/tracers/otel/otel.go | 247 +++++++++++++++++++++++++++++++++++ tracing/tracing.go | 3 + 4 files changed, 319 insertions(+), 65 deletions(-) create mode 100644 tracing/tracers/otel/otel.go diff --git a/go.mod b/go.mod index 728ccb10c8..e985778eea 100644 --- a/go.mod +++ b/go.mod @@ -47,15 +47,21 @@ require ( github.com/uber/jaeger-lib v2.4.1+incompatible github.com/yookoala/gofast v0.8.0 github.com/yuin/gopher-lua v1.1.1 + go.opentelemetry.io/otel v1.32.0 + go.opentelemetry.io/otel/bridge/opentracing v1.32.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 + go.opentelemetry.io/otel/sdk v1.32.0 go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 - golang.org/x/net v0.29.0 + golang.org/x/net v0.30.0 golang.org/x/oauth2 v0.23.0 - golang.org/x/sync v0.8.0 - golang.org/x/term v0.24.0 + golang.org/x/sync v0.9.0 + golang.org/x/term v0.25.0 golang.org/x/time v0.6.0 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.35.1 gopkg.in/go-jose/go-jose.v2 v2.6.3 gopkg.in/yaml.v2 v2.4.0 layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf @@ -63,7 +69,7 @@ require ( ) require ( - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect @@ -77,7 +83,7 @@ require ( github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect + github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 // indirect github.com/containerd/containerd v1.7.21 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect @@ -91,7 +97,7 @@ require ( github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect + github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-ini/ini v1.67.0 // indirect @@ -101,14 +107,14 @@ require ( github.com/go-ole/go-ole v1.2.6 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.0.0 // indirect github.com/google/flatbuffers v1.12.1 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect @@ -161,23 +167,19 @@ require ( github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/sdk v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/automaxprocs v1.5.3 // indirect golang.org/x/mod v0.20.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect golang.org/x/tools v0.24.0 // indirect gonum.org/v1/gonum v0.8.2 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/grpc v1.66.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect oras.land/oras-go/v2 v2.3.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index 5836018b9f..d8ad219f2d 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -72,8 +72,8 @@ github.com/cjoudrey/gluaurl v0.0.0-20161028222611-31cbb9bef199 h1:cJ1E8ZwZLfercT github.com/cjoudrey/gluaurl v0.0.0-20161028222611-31cbb9bef199/go.mod h1:jC+zrjHA5CaxJzn+tojIoIOzSp/6BlkRWXnMlxNkB+g= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= +github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= @@ -138,8 +138,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -183,8 +183,8 @@ github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQg github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -229,8 +229,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -406,8 +406,8 @@ github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0 github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/sarslanhan/cronmask v0.0.0-20230801193303-54e29300a091 h1:L644WnBAUw4546Wrt52yzuSPoV24t0ArlMwc5iRr8U0= github.com/sarslanhan/cronmask v0.0.0-20230801193303-54e29300a091/go.mod h1:qZKxttzn8iyVLtc7edFrmQper3FUBJsc/rHCONN2wIQ= @@ -502,20 +502,22 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/bridge/opentracing v1.32.0 h1:eZ3h8PniTg1rZ5pgBCodc8zvLees+FOKI6KLtlSIZCE= +go.opentelemetry.io/otel/bridge/opentracing v1.32.0/go.mod h1:WnzpYWji96dHm4ol0DYYU7wOcwcoj0ySPLw6wBjAMgk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -532,8 +534,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -571,8 +573,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -584,8 +586,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -613,15 +615,15 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -660,10 +662,10 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= 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= @@ -671,8 +673,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= -google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -682,8 +684,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -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.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/tracing/tracers/otel/otel.go b/tracing/tracers/otel/otel.go new file mode 100644 index 0000000000..9808d48c39 --- /dev/null +++ b/tracing/tracers/otel/otel.go @@ -0,0 +1,247 @@ +package otel + +import ( + "context" + "errors" + "github.com/opentracing/opentracing-go" + log "github.com/sirupsen/logrus" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + otelBridge "go.opentelemetry.io/otel/bridge/opentracing" + "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" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" + "os" + "strings" +) + +const ( + defComponentName = "skipper" + defaultGRPMaxMsgSize = 16 * 1024 * 1000 +) + +type Options struct { + Collector string + AccessToken string + Environment string + UseHttp bool + UseGrpc bool + PlainText bool + ComponentName string + ServiceName string + ServiceVersion string +} + +func parseOptions(opts []string) (Options, error) { + var ( + collector, accessToken, environment, componentName, serviceName, serviceVersion string + useHttp, useGrpc, usePlainText bool + ) + + for _, o := range opts { + key, val, _ := strings.Cut(o, "=") + switch key { + case "collector": + collector = val + case "access-token": + accessToken = val + case "environment": + environment = val + case "use-http": + useHttp = true + case "use-grpc": + useGrpc = true + case "plaintext": + usePlainText = true + case "component-name": + componentName = val + case "service-name": + serviceName = val + case "service-version": + serviceVersion = val + } + } + + return Options{ + Collector: collector, + AccessToken: accessToken, + Environment: environment, + UseHttp: useHttp, + UseGrpc: useGrpc, + PlainText: usePlainText, + ComponentName: componentName, + ServiceName: serviceName, + ServiceVersion: serviceVersion, + }, nil +} + +var ( + serviceName = os.Getenv("LS_SERVICE_NAME") + urlPath = "traces/otlp/v0.9" + serviceVersion = os.Getenv("LS_SERVICE_VERSION") + endpoint = os.Getenv("LS_SATELLITE_URL") + lsToken = os.Getenv("LS_ACCESS_TOKEN") + lsEnvironment = os.Getenv("LS_ENVIRONMENT") +) + +// setupOTelSDK bootstraps the OpenTelemetry pipeline. +// If it does not return an error, make sure to call shutdown for proper cleanup. +func setupOTelSDK(ctx context.Context, opts Options) (shutdown func(context.Context) error, err error) { + var shutdownFuncs []func(context.Context) error + + // shutdown calls cleanup functions registered via shutdownFuncs. + // The errors from the calls are joined. + // Each registered cleanup will be invoked once. + shutdown = func(ctx context.Context) error { + var err error + for _, fn := range shutdownFuncs { + err = errors.Join(err, fn(ctx)) + } + shutdownFuncs = nil + return err + } + + // handleErr calls shutdown for cleanup and makes sure that all errors are returned. + handleErr := func(inErr error) { + err = errors.Join(inErr, shutdown(ctx)) + } + + // Set up propagator. + otel.SetTextMapPropagator( + propagation.NewCompositeTextMapPropagator( + propagation.TraceContext{}, + propagation.Baggage{}, + ), + ) + + // Set up trace provider. + exp, err := newExporter(ctx, opts) + if err != nil { + handleErr(err) + return + } + + tracerProvider := newTraceProvider(exp, opts) + if err != nil { + handleErr(err) + return + } + shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) + otel.SetTracerProvider(tracerProvider) + + return +} + +func newExporter(ctx context.Context, o Options) (*otlptrace.Exporter, error) { + + if len(o.Collector) > 0 { + endpoint = o.Collector + log.Infof("Using custom LS endpoint %s/%s", endpoint, urlPath) + } else if len(endpoint) == 0 { + endpoint = "ingest.lightstep.com:443" + log.Infof("Using default LS endpoint %s/%s", endpoint, urlPath) + } + + if len(o.AccessToken) > 0 { + lsToken = o.AccessToken + log.Infof("Using custom LS token") + } + + var headers = map[string]string{ + "lightstep-access-token": lsToken, + } + + var client otlptrace.Client + + if o.UseGrpc { + var tOpt []otlptracegrpc.Option + tOpt = append(tOpt, otlptracegrpc.WithHeaders(headers)) + tOpt = append(tOpt, otlptracegrpc.WithEndpoint(endpoint)) + if o.PlainText { + tOpt = append(tOpt, otlptracegrpc.WithInsecure()) + } + client = otlptracegrpc.NewClient(tOpt...) + } else { + var tOpt []otlptracehttp.Option + tOpt = append(tOpt, otlptracehttp.WithHeaders(headers)) + tOpt = append(tOpt, otlptracehttp.WithEndpoint(endpoint)) + tOpt = append(tOpt, otlptracehttp.WithURLPath(urlPath)) + if o.PlainText { + tOpt = append(tOpt, otlptracehttp.WithInsecure()) + } + client = otlptracehttp.NewClient(tOpt...) + } + + return otlptrace.New(ctx, client) +} + +func newTraceProvider(exp *otlptrace.Exporter, opt Options) *sdktrace.TracerProvider { + + if len(opt.ServiceName) > 0 { + serviceName = opt.ServiceName + log.Infof("Using custom service name %s", serviceName) + } else if len(serviceName) == 0 { + serviceName = "skipper" + log.Infof("Using default service name %s", serviceName) + } + + if len(opt.ServiceVersion) > 0 { + serviceVersion = opt.ServiceVersion + log.Infof("Using custom service version %s", serviceVersion) + } else if len(serviceVersion) == 0 { + serviceVersion = "0.1.0" + log.Infof("Using default service version %s", serviceVersion) + } + + if len(opt.Environment) > 0 { + lsEnvironment = opt.Environment + log.Infof("Using custom environment %s", lsEnvironment) + } else if len(lsEnvironment) == 0 { + lsEnvironment = "dev" + log.Infof("Using default environment %s", lsEnvironment) + } + + r, rErr := + resource.Merge( + resource.Default(), + resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceNameKey.String(serviceName), + semconv.ServiceVersionKey.String(serviceVersion), + attribute.String("environment", lsEnvironment), + ), + ) + + if rErr != nil { + panic(rErr) + } + + return sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exp), + sdktrace.WithResource(r), + ) +} + +func InitTracer(opts []string) opentracing.Tracer { + + options, err := parseOptions(opts) + + _, err = setupOTelSDK(context.Background(), options) + if err != nil { + log.WithError(err).Error("failed to set up OpenTelemetry SDK") + return nil + } + + provider := otel.GetTracerProvider() + otelTracer := provider.Tracer("otel-ls-brigde") + bridgeTracer, wrapperTracerProvider := otelBridge.NewTracerPair(otelTracer) + otel.SetTracerProvider(wrapperTracerProvider) + + log.Infof("OpenTelemetry bridge tracer initialized") + + return bridgeTracer +} diff --git a/tracing/tracing.go b/tracing/tracing.go index be66d20963..23b7655188 100644 --- a/tracing/tracing.go +++ b/tracing/tracing.go @@ -53,6 +53,7 @@ import ( "context" "errors" "fmt" + "github.com/zalando/skipper/tracing/tracers/otel" "path/filepath" "plugin" @@ -86,6 +87,8 @@ func InitTracer(opts []string) (tracer ot.Tracer, err error) { return instana.InitTracer(opts) case "jaeger": return jaeger.InitTracer(opts) + case "otel": + return otel.InitTracer(opts), nil case "lightstep": return lightstep.InitTracer(opts) default: From 5818dfa230dae14097593fa178d0c279a68eb7c1 Mon Sep 17 00:00:00 2001 From: viveksing Date: Thu, 9 Jan 2025 15:57:59 +0100 Subject: [PATCH 2/4] Add opentelemetry bridge - add options Signed-off-by: viveksing --- go.mod | 3 + go.sum | 6 ++ tracing/tracers/otel/otel.go | 140 +++++++++++++++++++++++++---------- 3 files changed, 111 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index e985778eea..b6e00695e0 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,8 @@ require ( github.com/uber/jaeger-lib v2.4.1+incompatible github.com/yookoala/gofast v0.8.0 github.com/yuin/gopher-lua v1.1.1 + go.opentelemetry.io/contrib/propagators/b3 v1.28.0 + go.opentelemetry.io/contrib/propagators/ot v1.32.0 go.opentelemetry.io/otel v1.32.0 go.opentelemetry.io/otel/bridge/opentracing v1.32.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 @@ -172,6 +174,7 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/automaxprocs v1.5.3 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.20.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect diff --git a/go.sum b/go.sum index d8ad219f2d..8c7e821c63 100644 --- a/go.sum +++ b/go.sum @@ -502,6 +502,10 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/contrib/propagators/b3 v1.28.0 h1:XR6CFQrQ/ttAYmTBX2loUEFGdk1h17pxYI8828dk/1Y= +go.opentelemetry.io/contrib/propagators/b3 v1.28.0/go.mod h1:DWRkzJONLquRz7OJPh2rRbZ7MugQj62rk7g6HRnEqh0= +go.opentelemetry.io/contrib/propagators/ot v1.32.0 h1:Poy02A4wOZubHyd2hpHPDgZW+rn6EIq0vCwTZJ6Lmu8= +go.opentelemetry.io/contrib/propagators/ot v1.32.0/go.mod h1:cbhaURV+VR3NIMarzDYZU1RDEkXG1fNd1WMP1XCcGkY= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/bridge/opentracing v1.32.0 h1:eZ3h8PniTg1rZ5pgBCodc8zvLees+FOKI6KLtlSIZCE= @@ -526,6 +530,8 @@ go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= 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.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab h1:+yW1yrZ09EYNu1spCUOHBBNRbrLnfmutwyhbhCv3b6Q= go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/tracing/tracers/otel/otel.go b/tracing/tracers/otel/otel.go index 9808d48c39..44b1374991 100644 --- a/tracing/tracers/otel/otel.go +++ b/tracing/tracers/otel/otel.go @@ -5,6 +5,8 @@ import ( "errors" "github.com/opentracing/opentracing-go" log "github.com/sirupsen/logrus" + "go.opentelemetry.io/contrib/propagators/b3" + ottrace "go.opentelemetry.io/contrib/propagators/ot" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" otelBridge "go.opentelemetry.io/otel/bridge/opentracing" @@ -16,12 +18,36 @@ import ( sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" "os" + "strconv" "strings" + "time" ) const ( - defComponentName = "skipper" - defaultGRPMaxMsgSize = 16 * 1024 * 1000 + HostNameKey = "hostname" + LSHostNameKey = "lightstep.hostname" + LSEnvironmentKey = "environment" + LSComponentNameKey = "lightstep.component_name" + DefaultEndpoint = "ingest.lightstep.com:443" + DefaultServiceName = "skipper" + DefaultServiceVersion = "0.1.0" + DefaultEnvironment = "dev" + DefaultTracerName = "otel-lightstep-bridge" + DefaultComponentName = "skipper" +) + +var ( + serviceName = os.Getenv("LS_SERVICE_NAME") + urlPath = "traces/otlp/v0.9" + serviceVersion = os.Getenv("LS_SERVICE_VERSION") + endpoint = os.Getenv("LS_SATELLITE_URL") + lsToken = os.Getenv("LS_ACCESS_TOKEN") + lsEnvironment = os.Getenv("LS_ENVIRONMENT") + hostname, _ = os.Hostname() + batchTimeout = 2500 * time.Millisecond + processorQueueSize = 10000 + batchSize = 512 + exportTimeout = 5000 * time.Millisecond ) type Options struct { @@ -30,7 +56,7 @@ type Options struct { Environment string UseHttp bool UseGrpc bool - PlainText bool + UsePlainText bool ComponentName string ServiceName string ServiceVersion string @@ -55,7 +81,7 @@ func parseOptions(opts []string) (Options, error) { useHttp = true case "use-grpc": useGrpc = true - case "plaintext": + case "use-plain-text": usePlainText = true case "component-name": componentName = val @@ -63,6 +89,30 @@ func parseOptions(opts []string) (Options, error) { serviceName = val case "service-version": serviceVersion = val + case "batch-timeout": + intVal, err := strconv.Atoi(val) + if err != nil { + return Options{}, errors.New("failed to parse batch-timeout as int") + } + batchTimeout = time.Duration(intVal) * time.Millisecond + case "processor-queue-size": + intVal, err := strconv.Atoi(val) + if err != nil { + return Options{}, errors.New("failed to parse processor-queue-size as int") + } + processorQueueSize = intVal + case "batch-size": + intVal, err := strconv.Atoi(val) + if err != nil { + return Options{}, errors.New("failed to parse batch-size as int") + } + batchSize = intVal + case "export-timeout": + intVal, err := strconv.Atoi(val) + if err != nil { + return Options{}, errors.New("failed to parse export-timeout as int") + } + exportTimeout = time.Duration(intVal) * time.Millisecond } } @@ -72,22 +122,13 @@ func parseOptions(opts []string) (Options, error) { Environment: environment, UseHttp: useHttp, UseGrpc: useGrpc, - PlainText: usePlainText, + UsePlainText: usePlainText, ComponentName: componentName, ServiceName: serviceName, ServiceVersion: serviceVersion, }, nil } -var ( - serviceName = os.Getenv("LS_SERVICE_NAME") - urlPath = "traces/otlp/v0.9" - serviceVersion = os.Getenv("LS_SERVICE_VERSION") - endpoint = os.Getenv("LS_SATELLITE_URL") - lsToken = os.Getenv("LS_ACCESS_TOKEN") - lsEnvironment = os.Getenv("LS_ENVIRONMENT") -) - // setupOTelSDK bootstraps the OpenTelemetry pipeline. // If it does not return an error, make sure to call shutdown for proper cleanup. func setupOTelSDK(ctx context.Context, opts Options) (shutdown func(context.Context) error, err error) { @@ -113,8 +154,10 @@ func setupOTelSDK(ctx context.Context, opts Options) (shutdown func(context.Cont // Set up propagator. otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( - propagation.TraceContext{}, - propagation.Baggage{}, + //propagation.TraceContext{}, + //propagation.Baggage{}, + ottrace.OT{}, + b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader|b3.B3SingleHeader)), ), ) @@ -125,43 +168,48 @@ func setupOTelSDK(ctx context.Context, opts Options) (shutdown func(context.Cont return } - tracerProvider := newTraceProvider(exp, opts) + tracerProvider, err := newTraceProvider(exp, opts) if err != nil { handleErr(err) return } + shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) otel.SetTracerProvider(tracerProvider) return } -func newExporter(ctx context.Context, o Options) (*otlptrace.Exporter, error) { +func newExporter(ctx context.Context, opt Options) (*otlptrace.Exporter, error) { - if len(o.Collector) > 0 { - endpoint = o.Collector + if len(opt.Collector) > 0 { + endpoint = opt.Collector log.Infof("Using custom LS endpoint %s/%s", endpoint, urlPath) } else if len(endpoint) == 0 { - endpoint = "ingest.lightstep.com:443" + endpoint = DefaultEndpoint log.Infof("Using default LS endpoint %s/%s", endpoint, urlPath) } - if len(o.AccessToken) > 0 { - lsToken = o.AccessToken + if len(opt.AccessToken) > 0 { + lsToken = opt.AccessToken log.Infof("Using custom LS token") } + if len(lsToken) == 0 { + return nil, errors.New("missing Lightstep access token") + } + var headers = map[string]string{ "lightstep-access-token": lsToken, } var client otlptrace.Client - if o.UseGrpc { + if opt.UseGrpc { var tOpt []otlptracegrpc.Option tOpt = append(tOpt, otlptracegrpc.WithHeaders(headers)) tOpt = append(tOpt, otlptracegrpc.WithEndpoint(endpoint)) - if o.PlainText { + if opt.UsePlainText { tOpt = append(tOpt, otlptracegrpc.WithInsecure()) } client = otlptracegrpc.NewClient(tOpt...) @@ -170,7 +218,7 @@ func newExporter(ctx context.Context, o Options) (*otlptrace.Exporter, error) { tOpt = append(tOpt, otlptracehttp.WithHeaders(headers)) tOpt = append(tOpt, otlptracehttp.WithEndpoint(endpoint)) tOpt = append(tOpt, otlptracehttp.WithURLPath(urlPath)) - if o.PlainText { + if opt.UsePlainText { tOpt = append(tOpt, otlptracehttp.WithInsecure()) } client = otlptracehttp.NewClient(tOpt...) @@ -179,13 +227,19 @@ func newExporter(ctx context.Context, o Options) (*otlptrace.Exporter, error) { return otlptrace.New(ctx, client) } -func newTraceProvider(exp *otlptrace.Exporter, opt Options) *sdktrace.TracerProvider { +func newTraceProvider(exp *otlptrace.Exporter, opt Options) (*sdktrace.TracerProvider, error) { + + var componentName = DefaultComponentName + if len(opt.ComponentName) > 0 { + componentName = opt.ComponentName + log.Infof("Using custom component name %s", componentName) + } if len(opt.ServiceName) > 0 { serviceName = opt.ServiceName log.Infof("Using custom service name %s", serviceName) } else if len(serviceName) == 0 { - serviceName = "skipper" + serviceName = DefaultServiceName log.Infof("Using default service name %s", serviceName) } @@ -193,7 +247,7 @@ func newTraceProvider(exp *otlptrace.Exporter, opt Options) *sdktrace.TracerProv serviceVersion = opt.ServiceVersion log.Infof("Using custom service version %s", serviceVersion) } else if len(serviceVersion) == 0 { - serviceVersion = "0.1.0" + serviceVersion = DefaultServiceVersion log.Infof("Using default service version %s", serviceVersion) } @@ -201,29 +255,39 @@ func newTraceProvider(exp *otlptrace.Exporter, opt Options) *sdktrace.TracerProv lsEnvironment = opt.Environment log.Infof("Using custom environment %s", lsEnvironment) } else if len(lsEnvironment) == 0 { - lsEnvironment = "dev" + lsEnvironment = DefaultEnvironment log.Infof("Using default environment %s", lsEnvironment) } - r, rErr := + r, err := resource.Merge( resource.Default(), resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String(serviceName), semconv.ServiceVersionKey.String(serviceVersion), - attribute.String("environment", lsEnvironment), + attribute.String(LSEnvironmentKey, lsEnvironment), + attribute.String(LSComponentNameKey, componentName), + // TODO does not work + attribute.String(LSHostNameKey, hostname), + attribute.String(HostNameKey, hostname), ), ) - if rErr != nil { - panic(rErr) + if err != nil { + return nil, err } return sdktrace.NewTracerProvider( - sdktrace.WithBatcher(exp), + sdktrace.WithBatcher( + exp, + sdktrace.WithBatchTimeout(batchTimeout), + sdktrace.WithMaxExportBatchSize(batchSize), + sdktrace.WithMaxQueueSize(processorQueueSize), + sdktrace.WithExportTimeout(exportTimeout), + ), sdktrace.WithResource(r), - ) + ), nil } func InitTracer(opts []string) opentracing.Tracer { @@ -237,11 +301,11 @@ func InitTracer(opts []string) opentracing.Tracer { } provider := otel.GetTracerProvider() - otelTracer := provider.Tracer("otel-ls-brigde") + otelTracer := provider.Tracer(DefaultTracerName) bridgeTracer, wrapperTracerProvider := otelBridge.NewTracerPair(otelTracer) otel.SetTracerProvider(wrapperTracerProvider) - log.Infof("OpenTelemetry bridge tracer initialized") + log.Infof("OpenTelemetry Lightstep bridge tracer initialized") return bridgeTracer } From dc33e96fef8ab2edfbb49fb005bafeb886c95f68 Mon Sep 17 00:00:00 2001 From: viveksing Date: Thu, 9 Jan 2025 15:57:59 +0100 Subject: [PATCH 3/4] Add opentelemetry bridge - add tests Signed-off-by: viveksing --- tracing/tracers/lightstepotelbridge/README.md | 28 + tracing/tracers/lightstepotelbridge/bridge.go | 385 +++++++++ .../lightstepotelbridge/bridge_test.go | 818 ++++++++++++++++++ tracing/tracers/otel/otel.go | 311 ------- tracing/tracing.go | 6 +- 5 files changed, 1234 insertions(+), 314 deletions(-) create mode 100644 tracing/tracers/lightstepotelbridge/README.md create mode 100644 tracing/tracers/lightstepotelbridge/bridge.go create mode 100644 tracing/tracers/lightstepotelbridge/bridge_test.go delete mode 100644 tracing/tracers/otel/otel.go diff --git a/tracing/tracers/lightstepotelbridge/README.md b/tracing/tracers/lightstepotelbridge/README.md new file mode 100644 index 0000000000..95fe7bf75b --- /dev/null +++ b/tracing/tracers/lightstepotelbridge/README.md @@ -0,0 +1,28 @@ +# lightstep-otel-bridge tracer + +As with [other tracers](https://pkg.go.dev/github.com/zalando/skipper/tracing), the lightstep-otel-bridge tracer is configured by setting +`-opentracing="lightstep-otel-bridge OPTIONS"`. Valid options are: + +* `component-name` - set component name instead of `skipper` +* `access-token` - Access token for the lightstep satellites (REQUIRED) +* `protocol` - sets `UseGRPC` option to true if set to `"grpc"`, defaults to `"grpc"`, but can be set to `"http"` +* `tag` - key-value pairs (`key=value`) separated by commas (`,`) to set as tags + in every span +* `environment` - set the environment tag, defaults to `dev` +* `service-name` - set the service name tag, defaults to `skipper` +* `service-version` - set the service version tag, defaults to `unknown` +* `batch-size` - maximum number of spans to send in a batch +* `batch-timeout` - maximum time ms to wait before sending spans to the satellites +* `processor-queue-size` - maximum number of spans to queue before sending to the satellites +* `export-timeout` - maximum time to wait in ms for a batch to be sent +* `collector` - hostname (+port) - (e.g. `lightstep-satellites.example.org:4443`) to send the + spans to, i.e. your lightstep satellites +* `insecure-connection` (boolean) - force plaintext communication with satellites +* `propagators` - set propagators to use (i.e. format of http headers used for tracing). This can be used + to pick up traces from / to applications which only understand the B3 format (e.g. grafana where the + jaeger instrumentation can be switched to use the B3 format). This can be combined, e.g. `ottrace,b3` + should be used to pick up both formats (attempted in that order). + * `ottrace` - use the standard lightstep headers (default) + * `b3` - use the B3 propagation format + * `baggage` - use the baggage propagation format + * `tracecontext` - use the tracecontext propagation format diff --git a/tracing/tracers/lightstepotelbridge/bridge.go b/tracing/tracers/lightstepotelbridge/bridge.go new file mode 100644 index 0000000000..2d62b50ea3 --- /dev/null +++ b/tracing/tracers/lightstepotelbridge/bridge.go @@ -0,0 +1,385 @@ +package lightstepotelbridge + +import ( + "context" + "errors" + "fmt" + "github.com/opentracing/opentracing-go" + log "github.com/sirupsen/logrus" + "go.opentelemetry.io/contrib/propagators/b3" + ottrace "go.opentelemetry.io/contrib/propagators/ot" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + otelBridge "go.opentelemetry.io/otel/bridge/opentracing" + "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" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" + "net" + "os" + "strconv" + "strings" + "time" +) + +const ( + defaultEndpoint = "ingest.lightstep.com:443" + defaultServiceName = "skipper" + defaultServiceVersion = "0.1.0" + defaultEnvironment = "dev" + defaultTracerName = "lightstep-otel-bridge" + defaultComponentName = "skipper" + urlPath = "traces/otlp/v0.9" + defaultPropagators = "ottrace,b3" + hostNameKey = "hostname" + lsEnvironmentKey = "environment" + defaultBatchTimeout = 2500 * time.Millisecond + defaultProcessorQueueSize = 10000 + defaultBatchSize = 512 + defaultExportTimeout = 5000 * time.Millisecond +) + +type Options struct { + Collector string + AccessToken string + Environment string + UseHttp bool + UseGrpc bool + UsePlainText bool + ComponentName string + ServiceName string + ServiceVersion string + BatchTimeout time.Duration + ProcessorQueueSize int + BatchSize int + ExportTimeout time.Duration + Hostname string + Propagators []propagation.TextMapPropagator + GlobalAttributes []attribute.KeyValue +} + +func parseOptions(opts []string) (Options, error) { + + var ( + serviceName string + serviceVersion string + endpoint string + lsToken string + lsEnvironment string + componentName string + propagators string + useHttp, useGrpc, usePlainText bool + err error + globalTags []attribute.KeyValue + hostname, _ = os.Hostname() + batchTimeout = defaultBatchTimeout + processorQueueSize = defaultProcessorQueueSize + batchSize = defaultBatchSize + exportTimeout = defaultExportTimeout + ) + + for _, o := range opts { + key, val, _ := strings.Cut(o, "=") + switch key { + case "collector": + var sport string + + _, sport, err = net.SplitHostPort(val) + if err != nil { + return Options{}, err + } + + _, err = strconv.Atoi(sport) + if err != nil { + return Options{}, fmt.Errorf("failed to parse %s as int: %w", sport, err) + } + endpoint = val + + case "access-token": + lsToken = val + case "environment": + lsEnvironment = val + case "protocol": + if strings.ToLower(val) == "http" { + useHttp = true + } else if strings.ToLower(val) == "grpc" { + useGrpc = true + } else { + return Options{}, fmt.Errorf("unsupported protocol %s", val) + } + case "insecure-connection": + usePlainText, err = strconv.ParseBool(val) + if err != nil { + return Options{}, fmt.Errorf("failed to parse %s as bool: %w", val, err) + } + case "component-name": + componentName = val + case "service-name": + serviceName = val + case "service-version": + serviceVersion = val + case "batch-timeout": + intVal, err := strconv.Atoi(val) + if err != nil { + return Options{}, errors.New("failed to parse batch-timeout as int") + } + batchTimeout = time.Duration(intVal) * time.Millisecond + case "processor-queue-size": + intVal, err := strconv.Atoi(val) + if err != nil { + return Options{}, errors.New("failed to parse processor-queue-size as int") + } + processorQueueSize = intVal + case "batch-size": + intVal, err := strconv.Atoi(val) + if err != nil { + return Options{}, errors.New("failed to parse batch-size as int") + } + batchSize = intVal + case "export-timeout": + intVal, err := strconv.Atoi(val) + if err != nil { + return Options{}, errors.New("failed to parse export-timeout as int") + } + exportTimeout = time.Duration(intVal) * time.Millisecond + case "propagators": + for _, p := range strings.Split(val, ",") { + switch strings.ToLower(p) { + case "tracecontext": + // no-op + case "baggage": + // no-op + case "ottrace": + // no-op + case "b3": + // no-op + default: + return Options{}, fmt.Errorf("unsupported propagator %s", p) + } + } + propagators = val + case "tag": + if val != "" { + tag, tagVal, found := strings.Cut(val, "=") + if !found { + return Options{}, fmt.Errorf("missing value for tag %s", val) + } + globalTags = append(globalTags, attribute.String(tag, tagVal)) + } + } + } + + if endpoint == "" { + endpoint = defaultEndpoint + } + + if lsToken == "" { + return Options{}, errors.New("missing Lightstep access token") + } + + if lsEnvironment == "" { + lsEnvironment = defaultEnvironment + } + + if !useHttp { + useGrpc = true + } + + if componentName == "" { + componentName = defaultComponentName + } + + if serviceName == "" { + serviceName = defaultServiceName + } + + if serviceVersion == "" { + serviceVersion = defaultServiceVersion + } + + if propagators == "" { + propagators = defaultPropagators + } + + var textMapPropagator []propagation.TextMapPropagator + + for _, prop := range strings.Split(propagators, ",") { + switch strings.ToLower(prop) { + case "tracecontext": + textMapPropagator = append(textMapPropagator, propagation.TraceContext{}) + case "baggage": + textMapPropagator = append(textMapPropagator, propagation.Baggage{}) + case "ottrace": + textMapPropagator = append(textMapPropagator, ottrace.OT{}) + case "b3": + textMapPropagator = append(textMapPropagator, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader|b3.B3SingleHeader))) + default: + return Options{}, fmt.Errorf("unsupported propagator %s", prop) + } + } + log.Infof("serviceName: %s, serviceVersion: %s, endpoint: %s, lsEnvironment: %s, componentName: %s, useHttp: %t, useGrpc: %t, usePlainText: %t, batchTimeout: %s, processorQueueSize: %d, batchSize: %d, exportTimeout: %s, hostname: %s, propagators: %s, globalTags: %v", serviceName, serviceVersion, endpoint, lsEnvironment, componentName, useHttp, useGrpc, usePlainText, batchTimeout, processorQueueSize, batchSize, exportTimeout, hostname, propagators, globalTags) + return Options{ + Collector: endpoint, + AccessToken: lsToken, + Environment: lsEnvironment, + UseHttp: useHttp, + UseGrpc: useGrpc, + UsePlainText: usePlainText, + ComponentName: componentName, + ServiceName: serviceName, + ServiceVersion: serviceVersion, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + Propagators: textMapPropagator, + GlobalAttributes: globalTags, + }, nil +} + +// setupOTelSDK bootstraps the OpenTelemetry pipeline. +// If it does not return an error, make sure to call shutdown for proper cleanup. +func setupOTelSDK(ctx context.Context, schemaUrl string, opts Options) (shutdown func(context.Context) error, err error) { + var shutdownFuncs []func(context.Context) error + + // shutdown calls cleanup functions registered via shutdownFuncs. + // The errors from the calls are joined. + // Each registered cleanup will be invoked once. + shutdown = func(ctx context.Context) error { + var err error + for _, fn := range shutdownFuncs { + err = errors.Join(err, fn(ctx)) + } + shutdownFuncs = nil + return err + } + + // handleErr calls shutdown for cleanup and makes sure that all errors are returned. + handleErr := func(inErr error) { + err = errors.Join(inErr, shutdown(ctx)) + } + + // Set up propagator. + otel.SetTextMapPropagator( + propagation.NewCompositeTextMapPropagator( + opts.Propagators..., + ), + ) + + // Set up trace provider. + exp, _, err := newExporter(ctx, opts) + if err != nil { + handleErr(err) + return + } + + tracerProvider, err := newTraceProvider(exp, schemaUrl, resource.Default(), opts) + if err != nil { + handleErr(err) + return + } + + shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) + otel.SetTracerProvider(tracerProvider) + + return +} + +func newExporter(ctx context.Context, opt Options) (*otlptrace.Exporter, bool, error) { + + var headers = map[string]string{ + "lightstep-access-token": opt.AccessToken, + } + + var client otlptrace.Client + var isSecure = false + + if opt.UseHttp { + var tOpt []otlptracehttp.Option + tOpt = append(tOpt, otlptracehttp.WithHeaders(headers)) + tOpt = append(tOpt, otlptracehttp.WithEndpoint(opt.Collector)) + tOpt = append(tOpt, otlptracehttp.WithURLPath(urlPath)) + if opt.UsePlainText { + tOpt = append(tOpt, otlptracehttp.WithInsecure()) + isSecure = true + } + client = otlptracehttp.NewClient(tOpt...) + } else { + var tOpt []otlptracegrpc.Option + tOpt = append(tOpt, otlptracegrpc.WithHeaders(headers)) + tOpt = append(tOpt, otlptracegrpc.WithEndpoint(opt.Collector)) + if opt.UsePlainText { + tOpt = append(tOpt, otlptracegrpc.WithInsecure()) + isSecure = true + } + client = otlptracegrpc.NewClient(tOpt...) + } + + exp, err := otlptrace.New(ctx, client) + return exp, isSecure, err +} + +func newTraceProvider(exp *otlptrace.Exporter, schemaUrl string, r *resource.Resource, opt Options) (*sdktrace.TracerProvider, error) { + + opts := opt.GlobalAttributes + + opts = append( + opts, + semconv.ServiceName(opt.ServiceName), + semconv.HostName(opt.Hostname), + semconv.ServiceVersionKey.String(opt.ServiceVersion), + attribute.String(lsEnvironmentKey, opt.Environment), + attribute.String(hostNameKey, opt.Hostname), + ) + + r, err := resource.Merge( + r, + resource.NewWithAttributes( + schemaUrl, + opts..., + ), + ) + + if err != nil { + return nil, err + } + + return sdktrace.NewTracerProvider( + sdktrace.WithBatcher( + exp, + sdktrace.WithBatchTimeout(opt.BatchTimeout), + sdktrace.WithMaxExportBatchSize(opt.BatchSize), + sdktrace.WithMaxQueueSize(opt.ProcessorQueueSize), + sdktrace.WithExportTimeout(opt.ExportTimeout), + ), + sdktrace.WithResource(r), + ), nil +} + +func InitTracer(opts []string) opentracing.Tracer { + + options, err := parseOptions(opts) + if err != nil { + log.WithError(err).Error("failed to parse options") + return &opentracing.NoopTracer{} + } + + _, err = setupOTelSDK(context.Background(), semconv.SchemaURL, options) + if err != nil { + log.WithError(err).Error("failed to set up OpenTelemetry SDK") + return &opentracing.NoopTracer{} + } + + provider := otel.GetTracerProvider() + otelTracer := provider.Tracer(defaultTracerName) + bridgeTracer, wrapperTracerProvider := otelBridge.NewTracerPair(otelTracer) + otel.SetTracerProvider(wrapperTracerProvider) + + log.Infof("OpenTelemetry Lightstep bridge tracer initialized") + + return bridgeTracer +} diff --git a/tracing/tracers/lightstepotelbridge/bridge_test.go b/tracing/tracers/lightstepotelbridge/bridge_test.go new file mode 100644 index 0000000000..61e1a04321 --- /dev/null +++ b/tracing/tracers/lightstepotelbridge/bridge_test.go @@ -0,0 +1,818 @@ +package lightstepotelbridge + +import ( + "context" + "github.com/google/go-cmp/cmp" + "github.com/opentracing/opentracing-go" + "go.opentelemetry.io/contrib/propagators/b3" + "go.opentelemetry.io/contrib/propagators/ot" + "go.opentelemetry.io/otel/attribute" + opentracing2 "go.opentelemetry.io/otel/bridge/opentracing" + "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" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" + "os" + "reflect" + "testing" + "time" + "unsafe" +) + +func Test_parseOptions(t *testing.T) { + + var ( + batchTimeout = defaultBatchTimeout + processorQueueSize = defaultProcessorQueueSize + batchSize = defaultBatchSize + exportTimeout = defaultExportTimeout + hostname, _ = os.Hostname() + ) + + token := "mytoken" + + tests := []struct { + name string + opts []string + want Options + wantErr bool + }{ + { + name: "test without token should fail", + opts: []string{}, + want: Options{}, + wantErr: true, + }, + { + name: "test with token works", + opts: []string{"access-token=" + token}, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + wantErr: false, + }, + { + name: "test with token works and environment set", + opts: []string{"access-token=" + token, "environment=production"}, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: "production", + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + wantErr: false, + }, + { + name: "test with token works and set service name", + opts: []string{"access-token=" + token, "service-name=myservice"}, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: "myservice", + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + wantErr: false, + }, + { + name: "test with token works and set service version", + opts: []string{"access-token=" + token, "service-version=1.3.4"}, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: "1.3.4", + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + wantErr: false, + }, + { + name: "test with token works and component set", + opts: []string{"access-token=" + token, "component-name=mycomponent"}, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: "mycomponent", + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + wantErr: false, + }, + { + name: "test with token set collector", + opts: []string{ + "access-token=" + token, + "collector=collector.example.com:8888", + }, + want: Options{ + AccessToken: token, + Collector: "collector.example.com:8888", + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + wantErr: false, + }, + { + name: "test with token set collector wrong format", + opts: []string{ + "access-token=" + token, + "collector=collector.example.com=8888", + }, + want: Options{}, + wantErr: true, + }, + { + name: "test with token set collector wrong port", + opts: []string{ + "access-token=" + token, + "collector=collector.example.com:abc", + }, + want: Options{}, + wantErr: true, + }, + { + name: "test with token set component name", + opts: []string{ + "access-token=" + token, + "component-name=skipper-ingress", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: "skipper-ingress", + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + wantErr: false, + }, + { + name: "test with token set protocol to use grpc", + opts: []string{ + "access-token=" + token, + "protocol=grpc", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + }, + { + name: "test with token set protocol to use http", + opts: []string{ + "access-token=" + token, + "protocol=http", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseHttp: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + }, + { + name: "test with token set and wrong protocol", + opts: []string{ + "access-token=" + token, + "protocol=wrong", + }, + wantErr: true, + want: Options{}, + }, + { + name: "test with token set protocol to use grpc and insecure", + opts: []string{ + "access-token=" + token, + "protocol=grpc", + "insecure-connection=true", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + UsePlainText: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + }, + { + name: "test with token set protocol to use grpc and insecure incorrect value", + opts: []string{ + "access-token=" + token, + "protocol=grpc", + "insecure-connection=wrong", + }, + wantErr: true, + want: Options{}, + }, + { + name: "test with token set protocol to use http and insecure", + opts: []string{ + "access-token=" + token, + "protocol=http", + "insecure-connection=true", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseHttp: true, + UsePlainText: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + }, + { + name: "test with token set and max queue size set", + opts: []string{ + "access-token=" + token, + "processor-queue-size=100", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + ProcessorQueueSize: 100, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + }, + { + name: "test with token set and max queue size set to non numeric", + opts: []string{ + "access-token=" + token, + "processor-queue-size=wrong", + }, + wantErr: true, + want: Options{}, + }, + { + name: "test with token set and batch size set", + opts: []string{ + "access-token=" + token, + "batch-size=100", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + BatchSize: 100, + ExportTimeout: exportTimeout, + Hostname: hostname, + ProcessorQueueSize: processorQueueSize, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + }, + { + name: "test with token set and batch size set to non numeric", + opts: []string{ + "access-token=" + token, + "batch-size=wrong", + }, + wantErr: true, + want: Options{}, + }, + { + name: "test with token set and export timeout set", + opts: []string{ + "access-token=" + token, + "export-timeout=100", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + BatchSize: batchSize, + ExportTimeout: 100 * time.Millisecond, + Hostname: hostname, + ProcessorQueueSize: processorQueueSize, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + }, + { + name: "test with token set and export timeout set to non numeric", + opts: []string{ + "access-token=" + token, + "export-timeout=wrong", + }, + wantErr: true, + want: Options{}, + }, + { + name: "test with token set and batch timeout set", + opts: []string{ + "access-token=" + token, + "batch-timeout=100", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: 100 * time.Millisecond, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + ProcessorQueueSize: processorQueueSize, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + }, + }, + { + name: "test with token set and batch timeout set to non numeric", + opts: []string{ + "access-token=" + token, + "batch-timeout=wrong", + }, + wantErr: true, + want: Options{}, + }, + { + name: "test with token set and propagators set", + opts: []string{ + "access-token=" + token, + "propagators=ottrace,baggage,b3,tracecontext", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + ProcessorQueueSize: processorQueueSize, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, propagation.Baggage{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader)), propagation.TraceContext{}}, + }, + }, + { + name: "test with token set and propagators set and b3 removed", + opts: []string{ + "access-token=" + token, + "propagators=ottrace,baggage,tracecontext", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + ProcessorQueueSize: processorQueueSize, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, propagation.Baggage{}, propagation.TraceContext{}}, + }, + }, + { + name: "test with token set and propagators set and b3 removed", + opts: []string{ + "access-token=" + token, + "propagators=wro,ng", + }, + wantErr: true, + want: Options{}, + }, + { + name: "test with token works with global tag", + opts: []string{ + "access-token=" + token, + "tag=foo=bar", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + GlobalAttributes: []attribute.KeyValue{attribute.String("foo", "bar")}, + }, + wantErr: false, + }, + { + name: "test with token works with multiple global tag", + opts: []string{ + "access-token=" + token, + "tag=foo=bar", + "tag=bar=foo", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + GlobalAttributes: []attribute.KeyValue{attribute.String("foo", "bar"), attribute.String("bar", "foo")}, + }, + wantErr: false, + }, + { + name: "test with token works with global tag empty", + opts: []string{ + "access-token=" + token, + "tag=", + }, + want: Options{ + AccessToken: token, + Collector: defaultEndpoint, + Environment: defaultEnvironment, + ServiceName: defaultServiceName, + ServiceVersion: defaultServiceVersion, + ComponentName: defaultComponentName, + BatchTimeout: batchTimeout, + ProcessorQueueSize: processorQueueSize, + BatchSize: batchSize, + ExportTimeout: exportTimeout, + Hostname: hostname, + UseGrpc: true, + Propagators: []propagation.TextMapPropagator{ot.OT{}, b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader))}, + //GlobalAttributes: []attribute.KeyValue{attribute.String("foo", "bar")}, + }, + wantErr: false, + }, + { + name: "test with token works with global tag wrong format", + opts: []string{ + "access-token=" + token, + "tag=wrong", + }, + wantErr: true, + want: Options{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseOptions(tt.opts) + if (err != nil) != tt.wantErr { + t.Errorf("parseOptions() error = %v, wantErr %v", err, tt.wantErr) + return + } + //if !reflect.DeepEqual(got.Propagators, tt.propagators) { + // t.Logf("diff: %v", cmp.Diff(tt.propagators, got.Propagators)) + // t.Errorf("propagators = %v, want %v", got.Propagators, tt.propagators) + //} + //got.Propagators = nil + + if !reflect.DeepEqual(got, tt.want) { + t.Logf("diff: %v", cmp.Diff(tt.want, got)) + t.Errorf("parseOptions() = %v, want %v", got, tt.want) + } + }) + } + +} + +func Test_newExporter(t *testing.T) { + type args struct { + ctx context.Context + opt Options + } + tests := []struct { + name string + args args + wantErr bool + want interface{} + wantPlainText bool + }{ + { + name: "test with grpc", + args: args{ + ctx: context.Background(), + opt: Options{}, + }, + wantErr: false, + want: otlptracegrpc.NewClient(), + }, + { + name: "test with grpc and plain text", + args: args{ + ctx: context.Background(), + opt: Options{ + UsePlainText: true, + }, + }, + wantErr: false, + want: otlptracegrpc.NewClient(), + wantPlainText: true, + }, + { + name: "test with http", + args: args{ + ctx: context.Background(), + opt: Options{ + UseHttp: true, + }, + }, + wantErr: false, + want: otlptracehttp.NewClient(), + }, + { + name: "test with http and plain text", + args: args{ + ctx: context.Background(), + opt: Options{ + UseHttp: true, + UsePlainText: true, + }, + }, + wantErr: false, + want: otlptracehttp.NewClient(), + wantPlainText: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, plainText, err := newExporter(tt.args.ctx, tt.args.opt) + if (err != nil) != tt.wantErr { + t.Errorf("newExporter() error = %v, wantErr %v", err, tt.wantErr) + return + } + + gotClient := reflect.ValueOf(got).Elem().FieldByName("client") + // Use unsafe to get the underlying value of the unexported field + ptr := unsafe.Pointer(gotClient.UnsafeAddr()) + concreteValue := reflect.NewAt(gotClient.Type(), ptr).Elem().Interface() + concreteType := reflect.TypeOf(concreteValue) + + if plainText != tt.wantPlainText { + t.Errorf("newExporter() = %v, want %v", plainText, tt.wantPlainText) + } + + if !reflect.DeepEqual(concreteType, reflect.TypeOf(tt.want)) { + t.Errorf("newExporter() = %v, want %v", concreteType, reflect.TypeOf(tt.want)) + } + }) + } +} + +func Test_newTraceProvider(t *testing.T) { + + exp := &otlptrace.Exporter{} + opts := Options{} + r := resource.Default() + tp := sdktrace.NewTracerProvider() + + type args struct { + exp *otlptrace.Exporter + schemaUrl string + r *resource.Resource + opt Options + } + tests := []struct { + name string + args args + want interface{} + wantErr bool + }{ + { + name: "test newTraceProvider fail resource.Merge", + args: args{ + exp: exp, + schemaUrl: "wrongschema", + opt: opts, + r: r, + }, + wantErr: true, + }, + { + name: "test newTraceProvider success", + args: args{ + exp: exp, + schemaUrl: semconv.SchemaURL, + opt: opts, + r: r, + }, + wantErr: false, + want: tp, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := newTraceProvider(tt.args.exp, tt.args.schemaUrl, tt.args.r, tt.args.opt) + if err != nil { + if (err != nil) != tt.wantErr { + t.Errorf("newTraceProvider() error = %v, wantErr %v", err, tt.wantErr) + } + return + } + + if reflect.TypeOf(got) != reflect.TypeOf(tt.want) { + t.Errorf("newTraceProvider() got = %v, want %v", reflect.TypeOf(got), reflect.TypeOf(tt.want)) + } + }) + } +} + +func Test_setupOTelSDK(t *testing.T) { + type args struct { + ctx context.Context + schemaUrl string + opts Options + } + tests := []struct { + name string + args args + wantShutdown func(context.Context) error + wantErr bool + }{ + { + name: "test setupOTelSDK success", + }, + { + name: "test setupOTelSDK fail", + args: args{ + ctx: context.Background(), + opts: Options{}, + schemaUrl: "wrong", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotShutdown, err := setupOTelSDK(tt.args.ctx, tt.args.schemaUrl, tt.args.opts) + if (err != nil) != tt.wantErr { + t.Errorf("setupOTelSDK() error = %v, wantErr %v", err, tt.wantErr) + return + } + + if reflect.TypeOf(gotShutdown) != reflect.TypeOf(tt.wantShutdown) { + t.Errorf("setupOTelSDK() gotShutdown = %v, want %v", reflect.TypeOf(gotShutdown), reflect.TypeOf(tt.wantShutdown)) + } + }) + } +} + +func TestInitTracer(t *testing.T) { + + type args struct { + opts []string + } + tests := []struct { + name string + args args + want interface{} + }{ + { + name: "test InitTracer successful", + want: &opentracing2.BridgeTracer{}, + args: args{ + opts: []string{"access-token=mytoken", "collector=example.com:8443"}, + }, + }, + { + name: "test InitTracer fail parse options and return no op tracer", + want: &opentracing.NoopTracer{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := InitTracer(tt.args.opts) + if reflect.TypeOf(got) != reflect.TypeOf(tt.want) { + t.Errorf("InitTracer() got = %v, want %v", reflect.TypeOf(got), reflect.TypeOf(tt.want)) + } + }) + } +} diff --git a/tracing/tracers/otel/otel.go b/tracing/tracers/otel/otel.go deleted file mode 100644 index 44b1374991..0000000000 --- a/tracing/tracers/otel/otel.go +++ /dev/null @@ -1,311 +0,0 @@ -package otel - -import ( - "context" - "errors" - "github.com/opentracing/opentracing-go" - log "github.com/sirupsen/logrus" - "go.opentelemetry.io/contrib/propagators/b3" - ottrace "go.opentelemetry.io/contrib/propagators/ot" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - otelBridge "go.opentelemetry.io/otel/bridge/opentracing" - "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" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.26.0" - "os" - "strconv" - "strings" - "time" -) - -const ( - HostNameKey = "hostname" - LSHostNameKey = "lightstep.hostname" - LSEnvironmentKey = "environment" - LSComponentNameKey = "lightstep.component_name" - DefaultEndpoint = "ingest.lightstep.com:443" - DefaultServiceName = "skipper" - DefaultServiceVersion = "0.1.0" - DefaultEnvironment = "dev" - DefaultTracerName = "otel-lightstep-bridge" - DefaultComponentName = "skipper" -) - -var ( - serviceName = os.Getenv("LS_SERVICE_NAME") - urlPath = "traces/otlp/v0.9" - serviceVersion = os.Getenv("LS_SERVICE_VERSION") - endpoint = os.Getenv("LS_SATELLITE_URL") - lsToken = os.Getenv("LS_ACCESS_TOKEN") - lsEnvironment = os.Getenv("LS_ENVIRONMENT") - hostname, _ = os.Hostname() - batchTimeout = 2500 * time.Millisecond - processorQueueSize = 10000 - batchSize = 512 - exportTimeout = 5000 * time.Millisecond -) - -type Options struct { - Collector string - AccessToken string - Environment string - UseHttp bool - UseGrpc bool - UsePlainText bool - ComponentName string - ServiceName string - ServiceVersion string -} - -func parseOptions(opts []string) (Options, error) { - var ( - collector, accessToken, environment, componentName, serviceName, serviceVersion string - useHttp, useGrpc, usePlainText bool - ) - - for _, o := range opts { - key, val, _ := strings.Cut(o, "=") - switch key { - case "collector": - collector = val - case "access-token": - accessToken = val - case "environment": - environment = val - case "use-http": - useHttp = true - case "use-grpc": - useGrpc = true - case "use-plain-text": - usePlainText = true - case "component-name": - componentName = val - case "service-name": - serviceName = val - case "service-version": - serviceVersion = val - case "batch-timeout": - intVal, err := strconv.Atoi(val) - if err != nil { - return Options{}, errors.New("failed to parse batch-timeout as int") - } - batchTimeout = time.Duration(intVal) * time.Millisecond - case "processor-queue-size": - intVal, err := strconv.Atoi(val) - if err != nil { - return Options{}, errors.New("failed to parse processor-queue-size as int") - } - processorQueueSize = intVal - case "batch-size": - intVal, err := strconv.Atoi(val) - if err != nil { - return Options{}, errors.New("failed to parse batch-size as int") - } - batchSize = intVal - case "export-timeout": - intVal, err := strconv.Atoi(val) - if err != nil { - return Options{}, errors.New("failed to parse export-timeout as int") - } - exportTimeout = time.Duration(intVal) * time.Millisecond - } - } - - return Options{ - Collector: collector, - AccessToken: accessToken, - Environment: environment, - UseHttp: useHttp, - UseGrpc: useGrpc, - UsePlainText: usePlainText, - ComponentName: componentName, - ServiceName: serviceName, - ServiceVersion: serviceVersion, - }, nil -} - -// setupOTelSDK bootstraps the OpenTelemetry pipeline. -// If it does not return an error, make sure to call shutdown for proper cleanup. -func setupOTelSDK(ctx context.Context, opts Options) (shutdown func(context.Context) error, err error) { - var shutdownFuncs []func(context.Context) error - - // shutdown calls cleanup functions registered via shutdownFuncs. - // The errors from the calls are joined. - // Each registered cleanup will be invoked once. - shutdown = func(ctx context.Context) error { - var err error - for _, fn := range shutdownFuncs { - err = errors.Join(err, fn(ctx)) - } - shutdownFuncs = nil - return err - } - - // handleErr calls shutdown for cleanup and makes sure that all errors are returned. - handleErr := func(inErr error) { - err = errors.Join(inErr, shutdown(ctx)) - } - - // Set up propagator. - otel.SetTextMapPropagator( - propagation.NewCompositeTextMapPropagator( - //propagation.TraceContext{}, - //propagation.Baggage{}, - ottrace.OT{}, - b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader|b3.B3SingleHeader)), - ), - ) - - // Set up trace provider. - exp, err := newExporter(ctx, opts) - if err != nil { - handleErr(err) - return - } - - tracerProvider, err := newTraceProvider(exp, opts) - if err != nil { - handleErr(err) - return - } - - shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) - otel.SetTracerProvider(tracerProvider) - - return -} - -func newExporter(ctx context.Context, opt Options) (*otlptrace.Exporter, error) { - - if len(opt.Collector) > 0 { - endpoint = opt.Collector - log.Infof("Using custom LS endpoint %s/%s", endpoint, urlPath) - } else if len(endpoint) == 0 { - endpoint = DefaultEndpoint - log.Infof("Using default LS endpoint %s/%s", endpoint, urlPath) - } - - if len(opt.AccessToken) > 0 { - lsToken = opt.AccessToken - log.Infof("Using custom LS token") - } - - if len(lsToken) == 0 { - return nil, errors.New("missing Lightstep access token") - } - - var headers = map[string]string{ - "lightstep-access-token": lsToken, - } - - var client otlptrace.Client - - if opt.UseGrpc { - var tOpt []otlptracegrpc.Option - tOpt = append(tOpt, otlptracegrpc.WithHeaders(headers)) - tOpt = append(tOpt, otlptracegrpc.WithEndpoint(endpoint)) - if opt.UsePlainText { - tOpt = append(tOpt, otlptracegrpc.WithInsecure()) - } - client = otlptracegrpc.NewClient(tOpt...) - } else { - var tOpt []otlptracehttp.Option - tOpt = append(tOpt, otlptracehttp.WithHeaders(headers)) - tOpt = append(tOpt, otlptracehttp.WithEndpoint(endpoint)) - tOpt = append(tOpt, otlptracehttp.WithURLPath(urlPath)) - if opt.UsePlainText { - tOpt = append(tOpt, otlptracehttp.WithInsecure()) - } - client = otlptracehttp.NewClient(tOpt...) - } - - return otlptrace.New(ctx, client) -} - -func newTraceProvider(exp *otlptrace.Exporter, opt Options) (*sdktrace.TracerProvider, error) { - - var componentName = DefaultComponentName - if len(opt.ComponentName) > 0 { - componentName = opt.ComponentName - log.Infof("Using custom component name %s", componentName) - } - - if len(opt.ServiceName) > 0 { - serviceName = opt.ServiceName - log.Infof("Using custom service name %s", serviceName) - } else if len(serviceName) == 0 { - serviceName = DefaultServiceName - log.Infof("Using default service name %s", serviceName) - } - - if len(opt.ServiceVersion) > 0 { - serviceVersion = opt.ServiceVersion - log.Infof("Using custom service version %s", serviceVersion) - } else if len(serviceVersion) == 0 { - serviceVersion = DefaultServiceVersion - log.Infof("Using default service version %s", serviceVersion) - } - - if len(opt.Environment) > 0 { - lsEnvironment = opt.Environment - log.Infof("Using custom environment %s", lsEnvironment) - } else if len(lsEnvironment) == 0 { - lsEnvironment = DefaultEnvironment - log.Infof("Using default environment %s", lsEnvironment) - } - - r, err := - resource.Merge( - resource.Default(), - resource.NewWithAttributes( - semconv.SchemaURL, - semconv.ServiceNameKey.String(serviceName), - semconv.ServiceVersionKey.String(serviceVersion), - attribute.String(LSEnvironmentKey, lsEnvironment), - attribute.String(LSComponentNameKey, componentName), - // TODO does not work - attribute.String(LSHostNameKey, hostname), - attribute.String(HostNameKey, hostname), - ), - ) - - if err != nil { - return nil, err - } - - return sdktrace.NewTracerProvider( - sdktrace.WithBatcher( - exp, - sdktrace.WithBatchTimeout(batchTimeout), - sdktrace.WithMaxExportBatchSize(batchSize), - sdktrace.WithMaxQueueSize(processorQueueSize), - sdktrace.WithExportTimeout(exportTimeout), - ), - sdktrace.WithResource(r), - ), nil -} - -func InitTracer(opts []string) opentracing.Tracer { - - options, err := parseOptions(opts) - - _, err = setupOTelSDK(context.Background(), options) - if err != nil { - log.WithError(err).Error("failed to set up OpenTelemetry SDK") - return nil - } - - provider := otel.GetTracerProvider() - otelTracer := provider.Tracer(DefaultTracerName) - bridgeTracer, wrapperTracerProvider := otelBridge.NewTracerPair(otelTracer) - otel.SetTracerProvider(wrapperTracerProvider) - - log.Infof("OpenTelemetry Lightstep bridge tracer initialized") - - return bridgeTracer -} diff --git a/tracing/tracing.go b/tracing/tracing.go index 23b7655188..4c13628c94 100644 --- a/tracing/tracing.go +++ b/tracing/tracing.go @@ -53,7 +53,7 @@ import ( "context" "errors" "fmt" - "github.com/zalando/skipper/tracing/tracers/otel" + "github.com/zalando/skipper/tracing/tracers/lightstepotelbridge" "path/filepath" "plugin" @@ -87,8 +87,8 @@ func InitTracer(opts []string) (tracer ot.Tracer, err error) { return instana.InitTracer(opts) case "jaeger": return jaeger.InitTracer(opts) - case "otel": - return otel.InitTracer(opts), nil + case "lightstep-otel-bridge": + return lightstepotelbridge.InitTracer(opts), nil case "lightstep": return lightstep.InitTracer(opts) default: From c9b52dc8b8eeb9caa28fcf852c22348171460548 Mon Sep 17 00:00:00 2001 From: viveksing Date: Thu, 9 Jan 2025 16:23:58 +0100 Subject: [PATCH 4/4] update deps Signed-off-by: viveksing --- go.mod | 22 +++++++++++++++------- go.sum | 26 ++++++++++++++++++-------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index dca2cfeb24..5a9d182967 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,14 @@ require ( github.com/uber/jaeger-lib v2.4.1+incompatible github.com/yookoala/gofast v0.8.0 github.com/yuin/gopher-lua v1.1.1 + go.opentelemetry.io/contrib/propagators/b3 v1.28.0 + go.opentelemetry.io/contrib/propagators/ot v1.33.0 + go.opentelemetry.io/otel v1.33.0 + go.opentelemetry.io/otel/bridge/opentracing v1.33.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 + go.opentelemetry.io/otel/sdk v1.28.0 go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab golang.org/x/crypto v0.31.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 @@ -160,16 +168,14 @@ require ( github.com/yashtewari/glob-intersection v0.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/sdk v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.33.0 // indirect + go.opentelemetry.io/otel/trace v1.33.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/automaxprocs v1.5.3 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.20.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect @@ -183,4 +189,6 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -go 1.22 +go 1.22.0 + +toolchain go1.22.4 diff --git a/go.sum b/go.sum index 64968e8bbb..c79ce833f2 100644 --- a/go.sum +++ b/go.sum @@ -406,8 +406,8 @@ github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/sarslanhan/cronmask v0.0.0-20230801193303-54e29300a091 h1:L644WnBAUw4546Wrt52yzuSPoV24t0ArlMwc5iRr8U0= github.com/sarslanhan/cronmask v0.0.0-20230801193303-54e29300a091/go.mod h1:qZKxttzn8iyVLtc7edFrmQper3FUBJsc/rHCONN2wIQ= @@ -502,22 +502,30 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +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/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/contrib/propagators/b3 v1.28.0 h1:XR6CFQrQ/ttAYmTBX2loUEFGdk1h17pxYI8828dk/1Y= +go.opentelemetry.io/contrib/propagators/b3 v1.28.0/go.mod h1:DWRkzJONLquRz7OJPh2rRbZ7MugQj62rk7g6HRnEqh0= +go.opentelemetry.io/contrib/propagators/ot v1.33.0 h1:xj/pQFKo4ROsx0v129KpLgFwaYMgFTu3dAMEEih97cY= +go.opentelemetry.io/contrib/propagators/ot v1.33.0/go.mod h1:/xxHCLhTmaypEFwMViRGROj2qgrGiFrkxIlATt0rddc= +go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= +go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/otel/bridge/opentracing v1.33.0 h1:eH88qvKdY7ns7Xu6WlJBQNOzZ3MVvBR6tEl2euaYS9w= +go.opentelemetry.io/otel/bridge/opentracing v1.33.0/go.mod h1:FNai/nhRSn/kHyv+V1zaf/30BU8hO/DXo0MvV0PaUS8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= +go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= +go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -526,6 +534,8 @@ go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= 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.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab h1:+yW1yrZ09EYNu1spCUOHBBNRbrLnfmutwyhbhCv3b6Q= go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=