Merge pull request #10445 from containerd/dependabot/go_modules/otel-c1db8401eb

build(deps): bump the otel group across 1 directory with 8 updates
This commit is contained in:
Kazuyoshi Kato 2024-07-23 18:18:00 +00:00 committed by GitHub
commit 87833dccdc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
90 changed files with 11770 additions and 459 deletions

26
go.mod
View File

@ -61,14 +61,14 @@ require (
github.com/urfave/cli/v2 v2.27.2 github.com/urfave/cli/v2 v2.27.2
github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netlink v1.2.1-beta.2
go.etcd.io/bbolt v1.3.10 go.etcd.io/bbolt v1.3.10
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0
go.opentelemetry.io/otel v1.26.0 go.opentelemetry.io/otel v1.28.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0
go.opentelemetry.io/otel/sdk v1.26.0 go.opentelemetry.io/otel/sdk v1.28.0
go.opentelemetry.io/otel/trace v1.26.0 go.opentelemetry.io/otel/trace v1.28.0
golang.org/x/mod v0.19.0 golang.org/x/mod v0.19.0
golang.org/x/sync v0.7.0 golang.org/x/sync v0.7.0
golang.org/x/sys v0.22.0 golang.org/x/sys v0.22.0
@ -95,7 +95,7 @@ require (
github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect
github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
@ -104,7 +104,7 @@ require (
github.com/google/gofuzz v1.2.0 // indirect github.com/google/gofuzz v1.2.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect
@ -126,8 +126,8 @@ require (
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel/metric v1.26.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/proto/otlp v1.2.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect
golang.org/x/crypto v0.24.0 // indirect golang.org/x/crypto v0.24.0 // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
golang.org/x/net v0.26.0 // indirect golang.org/x/net v0.26.0 // indirect
@ -135,7 +135,7 @@ require (
golang.org/x/term v0.21.0 // indirect golang.org/x/term v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

52
go.sum
View File

@ -103,8 +103,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@ -167,8 +167,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpS
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 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 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -333,26 +333,26 @@ go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwf
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= 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.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk=
go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 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/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -438,8 +438,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 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 v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0=
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= 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 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=

View File

@ -1,6 +1,7 @@
# A minimal logging API for Go # A minimal logging API for Go
[![Go Reference](https://pkg.go.dev/badge/github.com/go-logr/logr.svg)](https://pkg.go.dev/github.com/go-logr/logr) [![Go Reference](https://pkg.go.dev/badge/github.com/go-logr/logr.svg)](https://pkg.go.dev/github.com/go-logr/logr)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-logr/logr)](https://goreportcard.com/report/github.com/go-logr/logr)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-logr/logr/badge)](https://securityscorecards.dev/viewer/?platform=github.com&org=go-logr&repo=logr) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-logr/logr/badge)](https://securityscorecards.dev/viewer/?platform=github.com&org=go-logr&repo=logr)
logr offers an(other) opinion on how Go programs and libraries can do logging logr offers an(other) opinion on how Go programs and libraries can do logging

View File

@ -236,15 +236,14 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter {
// implementation. It should be constructed with NewFormatter. Some of // implementation. It should be constructed with NewFormatter. Some of
// its methods directly implement logr.LogSink. // its methods directly implement logr.LogSink.
type Formatter struct { type Formatter struct {
outputFormat outputFormat outputFormat outputFormat
prefix string prefix string
values []any values []any
valuesStr string valuesStr string
parentValuesStr string depth int
depth int opts *Options
opts *Options groupName string // for slog groups
group string // for slog groups groups []groupDef
groupDepth int
} }
// outputFormat indicates which outputFormat to use. // outputFormat indicates which outputFormat to use.
@ -257,6 +256,13 @@ const (
outputJSON outputJSON
) )
// groupDef represents a saved group. The values may be empty, but we don't
// know if we need to render the group until the final record is rendered.
type groupDef struct {
name string
values string
}
// PseudoStruct is a list of key-value pairs that gets logged as a struct. // PseudoStruct is a list of key-value pairs that gets logged as a struct.
type PseudoStruct []any type PseudoStruct []any
@ -264,76 +270,102 @@ type PseudoStruct []any
func (f Formatter) render(builtins, args []any) string { func (f Formatter) render(builtins, args []any) string {
// Empirically bytes.Buffer is faster than strings.Builder for this. // Empirically bytes.Buffer is faster than strings.Builder for this.
buf := bytes.NewBuffer(make([]byte, 0, 1024)) buf := bytes.NewBuffer(make([]byte, 0, 1024))
if f.outputFormat == outputJSON { if f.outputFormat == outputJSON {
buf.WriteByte('{') // for the whole line buf.WriteByte('{') // for the whole record
} }
// Render builtins
vals := builtins vals := builtins
if hook := f.opts.RenderBuiltinsHook; hook != nil { if hook := f.opts.RenderBuiltinsHook; hook != nil {
vals = hook(f.sanitize(vals)) vals = hook(f.sanitize(vals))
} }
f.flatten(buf, vals, false, false) // keys are ours, no need to escape f.flatten(buf, vals, false) // keys are ours, no need to escape
continuing := len(builtins) > 0 continuing := len(builtins) > 0
if f.parentValuesStr != "" { // Turn the inner-most group into a string
argsStr := func() string {
buf := bytes.NewBuffer(make([]byte, 0, 1024))
vals = args
if hook := f.opts.RenderArgsHook; hook != nil {
vals = hook(f.sanitize(vals))
}
f.flatten(buf, vals, true) // escape user-provided keys
return buf.String()
}()
// Render the stack of groups from the inside out.
bodyStr := f.renderGroup(f.groupName, f.valuesStr, argsStr)
for i := len(f.groups) - 1; i >= 0; i-- {
grp := &f.groups[i]
if grp.values == "" && bodyStr == "" {
// no contents, so we must elide the whole group
continue
}
bodyStr = f.renderGroup(grp.name, grp.values, bodyStr)
}
if bodyStr != "" {
if continuing { if continuing {
buf.WriteByte(f.comma()) buf.WriteByte(f.comma())
} }
buf.WriteString(f.parentValuesStr) buf.WriteString(bodyStr)
continuing = true
}
groupDepth := f.groupDepth
if f.group != "" {
if f.valuesStr != "" || len(args) != 0 {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(f.quoted(f.group, true)) // escape user-provided keys
buf.WriteByte(f.colon())
buf.WriteByte('{') // for the group
continuing = false
} else {
// The group was empty
groupDepth--
}
}
if f.valuesStr != "" {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(f.valuesStr)
continuing = true
}
vals = args
if hook := f.opts.RenderArgsHook; hook != nil {
vals = hook(f.sanitize(vals))
}
f.flatten(buf, vals, continuing, true) // escape user-provided keys
for i := 0; i < groupDepth; i++ {
buf.WriteByte('}') // for the groups
} }
if f.outputFormat == outputJSON { if f.outputFormat == outputJSON {
buf.WriteByte('}') // for the whole line buf.WriteByte('}') // for the whole record
} }
return buf.String() return buf.String()
} }
// flatten renders a list of key-value pairs into a buffer. If continuing is // renderGroup returns a string representation of the named group with rendered
// true, it assumes that the buffer has previous values and will emit a // values and args. If the name is empty, this will return the values and args,
// separator (which depends on the output format) before the first pair it // joined. If the name is not empty, this will return a single key-value pair,
// writes. If escapeKeys is true, the keys are assumed to have // where the value is a grouping of the values and args. If the values and
// non-JSON-compatible characters in them and must be evaluated for escapes. // args are both empty, this will return an empty string, even if the name was
// specified.
func (f Formatter) renderGroup(name string, values string, args string) string {
buf := bytes.NewBuffer(make([]byte, 0, 1024))
needClosingBrace := false
if name != "" && (values != "" || args != "") {
buf.WriteString(f.quoted(name, true)) // escape user-provided keys
buf.WriteByte(f.colon())
buf.WriteByte('{')
needClosingBrace = true
}
continuing := false
if values != "" {
buf.WriteString(values)
continuing = true
}
if args != "" {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(args)
}
if needClosingBrace {
buf.WriteByte('}')
}
return buf.String()
}
// flatten renders a list of key-value pairs into a buffer. If escapeKeys is
// true, the keys are assumed to have non-JSON-compatible characters in them
// and must be evaluated for escapes.
// //
// This function returns a potentially modified version of kvList, which // This function returns a potentially modified version of kvList, which
// ensures that there is a value for every key (adding a value if needed) and // ensures that there is a value for every key (adding a value if needed) and
// that each key is a string (substituting a key if needed). // that each key is a string (substituting a key if needed).
func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, escapeKeys bool) []any { func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, escapeKeys bool) []any {
// This logic overlaps with sanitize() but saves one type-cast per key, // This logic overlaps with sanitize() but saves one type-cast per key,
// which can be measurable. // which can be measurable.
if len(kvList)%2 != 0 { if len(kvList)%2 != 0 {
@ -354,7 +386,7 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, esc
} }
v := kvList[i+1] v := kvList[i+1]
if i > 0 || continuing { if i > 0 {
if f.outputFormat == outputJSON { if f.outputFormat == outputJSON {
buf.WriteByte(f.comma()) buf.WriteByte(f.comma())
} else { } else {
@ -766,46 +798,17 @@ func (f Formatter) sanitize(kvList []any) []any {
// startGroup opens a new group scope (basically a sub-struct), which locks all // startGroup opens a new group scope (basically a sub-struct), which locks all
// the current saved values and starts them anew. This is needed to satisfy // the current saved values and starts them anew. This is needed to satisfy
// slog. // slog.
func (f *Formatter) startGroup(group string) { func (f *Formatter) startGroup(name string) {
// Unnamed groups are just inlined. // Unnamed groups are just inlined.
if group == "" { if name == "" {
return return
} }
// Any saved values can no longer be changed. n := len(f.groups)
buf := bytes.NewBuffer(make([]byte, 0, 1024)) f.groups = append(f.groups[:n:n], groupDef{f.groupName, f.valuesStr})
continuing := false
if f.parentValuesStr != "" {
buf.WriteString(f.parentValuesStr)
continuing = true
}
if f.group != "" && f.valuesStr != "" {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(f.quoted(f.group, true)) // escape user-provided keys
buf.WriteByte(f.colon())
buf.WriteByte('{') // for the group
continuing = false
}
if f.valuesStr != "" {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(f.valuesStr)
}
// NOTE: We don't close the scope here - that's done later, when a log line
// is actually rendered (because we have N scopes to close).
f.parentValuesStr = buf.String()
// Start collecting new values. // Start collecting new values.
f.group = group f.groupName = name
f.groupDepth++
f.valuesStr = "" f.valuesStr = ""
f.values = nil f.values = nil
} }
@ -900,7 +903,7 @@ func (f *Formatter) AddValues(kvList []any) {
// Pre-render values, so we don't have to do it on each Info/Error call. // Pre-render values, so we don't have to do it on each Info/Error call.
buf := bytes.NewBuffer(make([]byte, 0, 1024)) buf := bytes.NewBuffer(make([]byte, 0, 1024))
f.flatten(buf, vals, false, true) // escape user-provided keys f.flatten(buf, vals, true) // escape user-provided keys
f.valuesStr = buf.String() f.valuesStr = buf.String()
} }

View File

@ -148,6 +148,12 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM
var pairs []string var pairs []string
for key, vals := range req.Header { for key, vals := range req.Header {
key = textproto.CanonicalMIMEHeaderKey(key) key = textproto.CanonicalMIMEHeaderKey(key)
switch key {
case xForwardedFor, xForwardedHost:
// Handled separately below
continue
}
for _, val := range vals { for _, val := range vals {
// For backwards-compatibility, pass through 'authorization' header with no prefix. // For backwards-compatibility, pass through 'authorization' header with no prefix.
if key == "Authorization" { if key == "Authorization" {
@ -181,18 +187,17 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM
pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host) pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host)
} }
xff := req.Header.Values(xForwardedFor)
if addr := req.RemoteAddr; addr != "" { if addr := req.RemoteAddr; addr != "" {
if remoteIP, _, err := net.SplitHostPort(addr); err == nil { if remoteIP, _, err := net.SplitHostPort(addr); err == nil {
if fwd := req.Header.Get(xForwardedFor); fwd == "" { xff = append(xff, remoteIP)
pairs = append(pairs, strings.ToLower(xForwardedFor), remoteIP)
} else {
pairs = append(pairs, strings.ToLower(xForwardedFor), fmt.Sprintf("%s, %s", fwd, remoteIP))
}
} }
} }
if len(xff) > 0 {
pairs = append(pairs, strings.ToLower(xForwardedFor), strings.Join(xff, ", "))
}
if timeout != 0 { if timeout != 0 {
//nolint:govet // The context outlives this function
ctx, _ = context.WithTimeout(ctx, timeout) ctx, _ = context.WithTimeout(ctx, timeout)
} }
if len(pairs) == 0 { if len(pairs) == 0 {

View File

@ -71,7 +71,7 @@ func HTTPStatusFromCode(code codes.Code) int {
case codes.DataLoss: case codes.DataLoss:
return http.StatusInternalServerError return http.StatusInternalServerError
default: default:
grpclog.Infof("Unknown gRPC error code: %v", code) grpclog.Warningf("Unknown gRPC error code: %v", code)
return http.StatusInternalServerError return http.StatusInternalServerError
} }
} }
@ -114,17 +114,17 @@ func DefaultHTTPErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marsh
buf, merr := marshaler.Marshal(pb) buf, merr := marshaler.Marshal(pb)
if merr != nil { if merr != nil {
grpclog.Infof("Failed to marshal error message %q: %v", s, merr) grpclog.Errorf("Failed to marshal error message %q: %v", s, merr)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
if _, err := io.WriteString(w, fallback); err != nil { if _, err := io.WriteString(w, fallback); err != nil {
grpclog.Infof("Failed to write response: %v", err) grpclog.Errorf("Failed to write response: %v", err)
} }
return return
} }
md, ok := ServerMetadataFromContext(ctx) md, ok := ServerMetadataFromContext(ctx)
if !ok { if !ok {
grpclog.Infof("Failed to extract ServerMetadata from context") grpclog.Error("Failed to extract ServerMetadata from context")
} }
handleForwardResponseServerMetadata(w, mux, md) handleForwardResponseServerMetadata(w, mux, md)
@ -148,7 +148,7 @@ func DefaultHTTPErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marsh
w.WriteHeader(st) w.WriteHeader(st)
if _, err := w.Write(buf); err != nil { if _, err := w.Write(buf); err != nil {
grpclog.Infof("Failed to write response: %v", err) grpclog.Errorf("Failed to write response: %v", err)
} }
if doForwardTrailers { if doForwardTrailers {

View File

@ -6,6 +6,7 @@ import (
"io" "io"
"net/http" "net/http"
"net/textproto" "net/textproto"
"strconv"
"strings" "strings"
"google.golang.org/genproto/googleapis/api/httpbody" "google.golang.org/genproto/googleapis/api/httpbody"
@ -17,16 +18,10 @@ import (
// ForwardResponseStream forwards the stream from gRPC server to REST client. // ForwardResponseStream forwards the stream from gRPC server to REST client.
func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, recv func() (proto.Message, error), opts ...func(context.Context, http.ResponseWriter, proto.Message) error) { func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, recv func() (proto.Message, error), opts ...func(context.Context, http.ResponseWriter, proto.Message) error) {
f, ok := w.(http.Flusher) rc := http.NewResponseController(w)
if !ok {
grpclog.Infof("Flush not supported in %T", w)
http.Error(w, "unexpected type of web server", http.StatusInternalServerError)
return
}
md, ok := ServerMetadataFromContext(ctx) md, ok := ServerMetadataFromContext(ctx)
if !ok { if !ok {
grpclog.Infof("Failed to extract ServerMetadata from context") grpclog.Error("Failed to extract ServerMetadata from context")
http.Error(w, "unexpected error", http.StatusInternalServerError) http.Error(w, "unexpected error", http.StatusInternalServerError)
return return
} }
@ -81,20 +76,29 @@ func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshal
} }
if err != nil { if err != nil {
grpclog.Infof("Failed to marshal response chunk: %v", err) grpclog.Errorf("Failed to marshal response chunk: %v", err)
handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err, delimiter) handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err, delimiter)
return return
} }
if _, err := w.Write(buf); err != nil { if _, err := w.Write(buf); err != nil {
grpclog.Infof("Failed to send response chunk: %v", err) grpclog.Errorf("Failed to send response chunk: %v", err)
return return
} }
wroteHeader = true wroteHeader = true
if _, err := w.Write(delimiter); err != nil { if _, err := w.Write(delimiter); err != nil {
grpclog.Infof("Failed to send delimiter chunk: %v", err) grpclog.Errorf("Failed to send delimiter chunk: %v", err)
return
}
err = rc.Flush()
if err != nil {
if errors.Is(err, http.ErrNotSupported) {
grpclog.Errorf("Flush not supported in %T", w)
http.Error(w, "unexpected type of web server", http.StatusInternalServerError)
return
}
grpclog.Errorf("Failed to flush response to client: %v", err)
return return
} }
f.Flush()
} }
} }
@ -136,7 +140,7 @@ type responseBody interface {
func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) { func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) {
md, ok := ServerMetadataFromContext(ctx) md, ok := ServerMetadataFromContext(ctx)
if !ok { if !ok {
grpclog.Infof("Failed to extract ServerMetadata from context") grpclog.Error("Failed to extract ServerMetadata from context")
} }
handleForwardResponseServerMetadata(w, mux, md) handleForwardResponseServerMetadata(w, mux, md)
@ -168,13 +172,17 @@ func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marsha
buf, err = marshaler.Marshal(resp) buf, err = marshaler.Marshal(resp)
} }
if err != nil { if err != nil {
grpclog.Infof("Marshal error: %v", err) grpclog.Errorf("Marshal error: %v", err)
HTTPError(ctx, mux, marshaler, w, req, err) HTTPError(ctx, mux, marshaler, w, req, err)
return return
} }
if !doForwardTrailers {
w.Header().Set("Content-Length", strconv.Itoa(len(buf)))
}
if _, err = w.Write(buf); err != nil { if _, err = w.Write(buf); err != nil {
grpclog.Infof("Failed to write response: %v", err) grpclog.Errorf("Failed to write response: %v", err)
} }
if doForwardTrailers { if doForwardTrailers {
@ -193,7 +201,7 @@ func handleForwardResponseOptions(ctx context.Context, w http.ResponseWriter, re
} }
for _, opt := range opts { for _, opt := range opts {
if err := opt(ctx, w, resp); err != nil { if err := opt(ctx, w, resp); err != nil {
grpclog.Infof("Error handling ForwardResponseOptions: %v", err) grpclog.Errorf("Error handling ForwardResponseOptions: %v", err)
return err return err
} }
} }
@ -209,15 +217,15 @@ func handleForwardResponseStreamError(ctx context.Context, wroteHeader bool, mar
} }
buf, err := marshaler.Marshal(msg) buf, err := marshaler.Marshal(msg)
if err != nil { if err != nil {
grpclog.Infof("Failed to marshal an error: %v", err) grpclog.Errorf("Failed to marshal an error: %v", err)
return return
} }
if _, err := w.Write(buf); err != nil { if _, err := w.Write(buf); err != nil {
grpclog.Infof("Failed to notify error to client: %v", err) grpclog.Errorf("Failed to notify error to client: %v", err)
return return
} }
if _, err := w.Write(delimiter); err != nil { if _, err := w.Write(delimiter); err != nil {
grpclog.Infof("Failed to send delimiter chunk: %v", err) grpclog.Errorf("Failed to send delimiter chunk: %v", err)
return return
} }
} }

View File

@ -24,6 +24,11 @@ func (j *JSONBuiltin) Marshal(v interface{}) ([]byte, error) {
return json.Marshal(v) return json.Marshal(v)
} }
// MarshalIndent is like Marshal but applies Indent to format the output
func (j *JSONBuiltin) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
return json.MarshalIndent(v, prefix, indent)
}
// Unmarshal unmarshals JSON data into "v". // Unmarshal unmarshals JSON data into "v".
func (j *JSONBuiltin) Unmarshal(data []byte, v interface{}) error { func (j *JSONBuiltin) Unmarshal(data []byte, v interface{}) error {
return json.Unmarshal(data, v) return json.Unmarshal(data, v)

View File

@ -30,10 +30,6 @@ func (*JSONPb) ContentType(_ interface{}) string {
// Marshal marshals "v" into JSON. // Marshal marshals "v" into JSON.
func (j *JSONPb) Marshal(v interface{}) ([]byte, error) { func (j *JSONPb) Marshal(v interface{}) ([]byte, error) {
if _, ok := v.(proto.Message); !ok {
return j.marshalNonProtoField(v)
}
var buf bytes.Buffer var buf bytes.Buffer
if err := j.marshalTo(&buf, v); err != nil { if err := j.marshalTo(&buf, v); err != nil {
return nil, err return nil, err
@ -48,9 +44,17 @@ func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error {
if err != nil { if err != nil {
return err return err
} }
if j.Indent != "" {
b := &bytes.Buffer{}
if err := json.Indent(b, buf, "", j.Indent); err != nil {
return err
}
buf = b.Bytes()
}
_, err = w.Write(buf) _, err = w.Write(buf)
return err return err
} }
b, err := j.MarshalOptions.Marshal(p) b, err := j.MarshalOptions.Marshal(p)
if err != nil { if err != nil {
return err return err
@ -150,9 +154,6 @@ func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) {
} }
m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf) m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf)
} }
if j.Indent != "" {
return json.MarshalIndent(m, "", j.Indent)
}
return json.Marshal(m) return json.Marshal(m)
} }
if enum, ok := rv.Interface().(protoEnum); ok && !j.UseEnumNumbers { if enum, ok := rv.Interface().(protoEnum); ok && !j.UseEnumNumbers {

View File

@ -46,7 +46,7 @@ func MarshalerForRequest(mux *ServeMux, r *http.Request) (inbound Marshaler, out
for _, contentTypeVal := range r.Header[contentTypeHeader] { for _, contentTypeVal := range r.Header[contentTypeHeader] {
contentType, _, err := mime.ParseMediaType(contentTypeVal) contentType, _, err := mime.ParseMediaType(contentTypeVal)
if err != nil { if err != nil {
grpclog.Infof("Failed to parse Content-Type %s: %v", contentTypeVal, err) grpclog.Errorf("Failed to parse Content-Type %s: %v", contentTypeVal, err)
continue continue
} }
if m, ok := mux.marshalers.mimeMap[contentType]; ok { if m, ok := mux.marshalers.mimeMap[contentType]; ok {

View File

@ -52,13 +52,13 @@ type Pattern struct {
// It returns an error if the given definition is invalid. // It returns an error if the given definition is invalid.
func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, error) { func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, error) {
if version != 1 { if version != 1 {
grpclog.Infof("unsupported version: %d", version) grpclog.Errorf("unsupported version: %d", version)
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }
l := len(ops) l := len(ops)
if l%2 != 0 { if l%2 != 0 {
grpclog.Infof("odd number of ops codes: %d", l) grpclog.Errorf("odd number of ops codes: %d", l)
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }
@ -81,14 +81,14 @@ func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, er
stack++ stack++
case utilities.OpPushM: case utilities.OpPushM:
if pushMSeen { if pushMSeen {
grpclog.Infof("pushM appears twice") grpclog.Error("pushM appears twice")
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }
pushMSeen = true pushMSeen = true
stack++ stack++
case utilities.OpLitPush: case utilities.OpLitPush:
if op.operand < 0 || len(pool) <= op.operand { if op.operand < 0 || len(pool) <= op.operand {
grpclog.Infof("negative literal index: %d", op.operand) grpclog.Errorf("negative literal index: %d", op.operand)
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }
if pushMSeen { if pushMSeen {
@ -97,18 +97,18 @@ func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, er
stack++ stack++
case utilities.OpConcatN: case utilities.OpConcatN:
if op.operand <= 0 { if op.operand <= 0 {
grpclog.Infof("negative concat size: %d", op.operand) grpclog.Errorf("negative concat size: %d", op.operand)
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }
stack -= op.operand stack -= op.operand
if stack < 0 { if stack < 0 {
grpclog.Info("stack underflow") grpclog.Error("stack underflow")
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }
stack++ stack++
case utilities.OpCapture: case utilities.OpCapture:
if op.operand < 0 || len(pool) <= op.operand { if op.operand < 0 || len(pool) <= op.operand {
grpclog.Infof("variable name index out of bound: %d", op.operand) grpclog.Errorf("variable name index out of bound: %d", op.operand)
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }
v := pool[op.operand] v := pool[op.operand]
@ -116,11 +116,11 @@ func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, er
vars = append(vars, v) vars = append(vars, v)
stack-- stack--
if stack < 0 { if stack < 0 {
grpclog.Infof("stack underflow") grpclog.Error("stack underflow")
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }
default: default:
grpclog.Infof("invalid opcode: %d", op.code) grpclog.Errorf("invalid opcode: %d", op.code)
return Pattern{}, ErrInvalidPattern return Pattern{}, ErrInvalidPattern
} }

View File

@ -4,6 +4,8 @@
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
import ( import (
"google.golang.org/grpc/stats"
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric"
@ -20,18 +22,26 @@ const (
GRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code") GRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code")
) )
// Filter is a predicate used to determine whether a given request in // InterceptorFilter is a predicate used to determine whether a given request in
// interceptor info should be traced. A Filter must return true if // interceptor info should be instrumented. A InterceptorFilter must return true if
// the request should be traced. // the request should be traced.
type Filter func(*InterceptorInfo) bool //
// Deprecated: Use stats handlers instead.
type InterceptorFilter func(*InterceptorInfo) bool
// Filter is a predicate used to determine whether a given request in
// should be instrumented by the attached RPC tag info.
// A Filter must return true if the request should be instrumented.
type Filter func(*stats.RPCTagInfo) bool
// config is a group of options for this instrumentation. // config is a group of options for this instrumentation.
type config struct { type config struct {
Filter Filter Filter Filter
Propagators propagation.TextMapPropagator InterceptorFilter InterceptorFilter
TracerProvider trace.TracerProvider Propagators propagation.TextMapPropagator
MeterProvider metric.MeterProvider TracerProvider trace.TracerProvider
SpanStartOptions []trace.SpanStartOption MeterProvider metric.MeterProvider
SpanStartOptions []trace.SpanStartOption
ReceivedEvent bool ReceivedEvent bool
SentEvent bool SentEvent bool
@ -152,15 +162,30 @@ func (o tracerProviderOption) apply(c *config) {
// WithInterceptorFilter returns an Option to use the request filter. // WithInterceptorFilter returns an Option to use the request filter.
// //
// Deprecated: Use stats handlers instead. // Deprecated: Use stats handlers instead.
func WithInterceptorFilter(f Filter) Option { func WithInterceptorFilter(f InterceptorFilter) Option {
return interceptorFilterOption{f: f} return interceptorFilterOption{f: f}
} }
type interceptorFilterOption struct { type interceptorFilterOption struct {
f Filter f InterceptorFilter
} }
func (o interceptorFilterOption) apply(c *config) { func (o interceptorFilterOption) apply(c *config) {
if o.f != nil {
c.InterceptorFilter = o.f
}
}
// WithFilter returns an Option to use the request filter.
func WithFilter(f Filter) Option {
return filterOption{f: f}
}
type filterOption struct {
f Filter
}
func (o filterOption) apply(c *config) {
if o.f != nil { if o.f != nil {
c.Filter = o.f c.Filter = o.f
} }

View File

@ -7,6 +7,7 @@ package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.g
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md
import ( import (
"context" "context"
"errors"
"io" "io"
"net" "net"
"strconv" "strconv"
@ -70,7 +71,7 @@ func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor {
Method: method, Method: method,
Type: UnaryClient, Type: UnaryClient,
} }
if cfg.Filter != nil && !cfg.Filter(i) { if cfg.InterceptorFilter != nil && !cfg.InterceptorFilter(i) {
return invoker(ctx, method, req, reply, cc, callOpts...) return invoker(ctx, method, req, reply, cc, callOpts...)
} }
@ -136,7 +137,7 @@ func (w *clientStream) RecvMsg(m interface{}) error {
if err == nil && !w.desc.ServerStreams { if err == nil && !w.desc.ServerStreams {
w.endSpan(nil) w.endSpan(nil)
} else if err == io.EOF { } else if errors.Is(err, io.EOF) {
w.endSpan(nil) w.endSpan(nil)
} else if err != nil { } else if err != nil {
w.endSpan(err) w.endSpan(err)
@ -230,7 +231,7 @@ func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
Method: method, Method: method,
Type: StreamClient, Type: StreamClient,
} }
if cfg.Filter != nil && !cfg.Filter(i) { if cfg.InterceptorFilter != nil && !cfg.InterceptorFilter(i) {
return streamer(ctx, desc, cc, method, callOpts...) return streamer(ctx, desc, cc, method, callOpts...)
} }
@ -285,7 +286,7 @@ func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
UnaryServerInfo: info, UnaryServerInfo: info,
Type: UnaryServer, Type: UnaryServer,
} }
if cfg.Filter != nil && !cfg.Filter(i) { if cfg.InterceptorFilter != nil && !cfg.InterceptorFilter(i) {
return handler(ctx, req) return handler(ctx, req)
} }
@ -333,7 +334,7 @@ func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
elapsedTime := float64(time.Since(before)) / float64(time.Millisecond) elapsedTime := float64(time.Since(before)) / float64(time.Millisecond)
metricAttrs = append(metricAttrs, grpcStatusCodeAttr) metricAttrs = append(metricAttrs, grpcStatusCodeAttr)
cfg.rpcDuration.Record(ctx, elapsedTime, metric.WithAttributes(metricAttrs...)) cfg.rpcDuration.Record(ctx, elapsedTime, metric.WithAttributeSet(attribute.NewSet(metricAttrs...)))
return resp, err return resp, err
} }
@ -411,7 +412,7 @@ func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
StreamServerInfo: info, StreamServerInfo: info,
Type: StreamServer, Type: StreamServer,
} }
if cfg.Filter != nil && !cfg.Filter(i) { if cfg.InterceptorFilter != nil && !cfg.InterceptorFilter(i) {
return handler(srv, wrapServerStream(ctx, ss, cfg)) return handler(srv, wrapServerStream(ctx, ss, cfg))
} }

View File

@ -27,6 +27,7 @@ type gRPCContext struct {
messagesReceived int64 messagesReceived int64
messagesSent int64 messagesSent int64
metricAttrs []attribute.KeyValue metricAttrs []attribute.KeyValue
record bool
} }
type serverHandler struct { type serverHandler struct {
@ -66,6 +67,10 @@ func (h *serverHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) cont
gctx := gRPCContext{ gctx := gRPCContext{
metricAttrs: attrs, metricAttrs: attrs,
record: true,
}
if h.config.Filter != nil {
gctx.record = h.config.Filter(info)
} }
return context.WithValue(ctx, gRPCContextKey{}, &gctx) return context.WithValue(ctx, gRPCContextKey{}, &gctx)
} }
@ -102,6 +107,10 @@ func (h *clientHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) cont
gctx := gRPCContext{ gctx := gRPCContext{
metricAttrs: attrs, metricAttrs: attrs,
record: true,
}
if h.config.Filter != nil {
gctx.record = h.config.Filter(info)
} }
return inject(context.WithValue(ctx, gRPCContextKey{}, &gctx), h.config.Propagators) return inject(context.WithValue(ctx, gRPCContextKey{}, &gctx), h.config.Propagators)
@ -130,6 +139,9 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats, isServer bool
gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext) gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext)
if gctx != nil { if gctx != nil {
if !gctx.record {
return
}
metricAttrs = make([]attribute.KeyValue, 0, len(gctx.metricAttrs)+1) metricAttrs = make([]attribute.KeyValue, 0, len(gctx.metricAttrs)+1)
metricAttrs = append(metricAttrs, gctx.metricAttrs...) metricAttrs = append(metricAttrs, gctx.metricAttrs...)
} }
@ -139,7 +151,7 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats, isServer bool
case *stats.InPayload: case *stats.InPayload:
if gctx != nil { if gctx != nil {
messageId = atomic.AddInt64(&gctx.messagesReceived, 1) messageId = atomic.AddInt64(&gctx.messagesReceived, 1)
c.rpcRequestSize.Record(ctx, int64(rs.Length), metric.WithAttributes(metricAttrs...)) c.rpcRequestSize.Record(ctx, int64(rs.Length), metric.WithAttributeSet(attribute.NewSet(metricAttrs...)))
} }
if c.ReceivedEvent { if c.ReceivedEvent {
@ -155,7 +167,7 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats, isServer bool
case *stats.OutPayload: case *stats.OutPayload:
if gctx != nil { if gctx != nil {
messageId = atomic.AddInt64(&gctx.messagesSent, 1) messageId = atomic.AddInt64(&gctx.messagesSent, 1)
c.rpcResponseSize.Record(ctx, int64(rs.Length), metric.WithAttributes(metricAttrs...)) c.rpcResponseSize.Record(ctx, int64(rs.Length), metric.WithAttributeSet(attribute.NewSet(metricAttrs...)))
} }
if c.SentEvent { if c.SentEvent {
@ -192,14 +204,17 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats, isServer bool
span.End() span.End()
metricAttrs = append(metricAttrs, rpcStatusAttr) metricAttrs = append(metricAttrs, rpcStatusAttr)
// Allocate vararg slice once.
recordOpts := []metric.RecordOption{metric.WithAttributeSet(attribute.NewSet(metricAttrs...))}
// Use floating point division here for higher precision (instead of Millisecond method). // Use floating point division here for higher precision (instead of Millisecond method).
// Measure right before calling Record() to capture as much elapsed time as possible.
elapsedTime := float64(rs.EndTime.Sub(rs.BeginTime)) / float64(time.Millisecond) elapsedTime := float64(rs.EndTime.Sub(rs.BeginTime)) / float64(time.Millisecond)
c.rpcDuration.Record(ctx, elapsedTime, metric.WithAttributes(metricAttrs...)) c.rpcDuration.Record(ctx, elapsedTime, recordOpts...)
if gctx != nil { if gctx != nil {
c.rpcRequestsPerRPC.Record(ctx, atomic.LoadInt64(&gctx.messagesReceived), metric.WithAttributes(metricAttrs...)) c.rpcRequestsPerRPC.Record(ctx, atomic.LoadInt64(&gctx.messagesReceived), recordOpts...)
c.rpcResponsesPerRPC.Record(ctx, atomic.LoadInt64(&gctx.messagesSent), metric.WithAttributes(metricAttrs...)) c.rpcResponsesPerRPC.Record(ctx, atomic.LoadInt64(&gctx.messagesSent), recordOpts...)
} }
default: default:
return return

View File

@ -5,7 +5,7 @@ package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.g
// Version is the current release version of the gRPC instrumentation. // Version is the current release version of the gRPC instrumentation.
func Version() string { func Version() string {
return "0.51.0" return "0.53.0"
// This string is updated by the pre_release.sh script during release // This string is updated by the pre_release.sh script during release
} }

View File

@ -12,7 +12,7 @@ import (
) )
// DefaultClient is the default Client and is used by Get, Head, Post and PostForm. // DefaultClient is the default Client and is used by Get, Head, Post and PostForm.
// Please be careful of intitialization order - for example, if you change // Please be careful of initialization order - for example, if you change
// the global propagator, the DefaultClient might still be using the old one. // the global propagator, the DefaultClient might still be using the old one.
var DefaultClient = &http.Client{Transport: NewTransport(http.DefaultTransport)} var DefaultClient = &http.Client{Transport: NewTransport(http.DefaultTransport)}

View File

@ -100,7 +100,7 @@ func WithPublicEndpoint() Option {
}) })
} }
// WithPublicEndpointFn runs with every request, and allows conditionnally // WithPublicEndpointFn runs with every request, and allows conditionally
// configuring the Handler to link the span with an incoming span context. If // configuring the Handler to link the span with an incoming span context. If
// this option is not provided or returns false, then the association is a // this option is not provided or returns false, then the association is a
// child association instead of a link. // child association instead of a link.

View File

@ -12,6 +12,7 @@ import (
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil"
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
@ -204,10 +205,15 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
WriteHeader: func(httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc { WriteHeader: func(httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
return rww.WriteHeader return rww.WriteHeader
}, },
Flush: func(httpsnoop.FlushFunc) httpsnoop.FlushFunc {
return rww.Flush
},
}) })
labeler := &Labeler{} labeler, found := LabelerFromContext(ctx)
ctx = injectLabeler(ctx, labeler) if !found {
ctx = ContextWithLabeler(ctx, labeler)
}
next.ServeHTTP(w, r.WithContext(ctx)) next.ServeHTTP(w, r.WithContext(ctx))
@ -225,9 +231,10 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
if rww.statusCode > 0 { if rww.statusCode > 0 {
attributes = append(attributes, semconv.HTTPStatusCode(rww.statusCode)) attributes = append(attributes, semconv.HTTPStatusCode(rww.statusCode))
} }
o := metric.WithAttributes(attributes...) o := metric.WithAttributeSet(attribute.NewSet(attributes...))
h.requestBytesCounter.Add(ctx, bw.read.Load(), o) addOpts := []metric.AddOption{o} // Allocate vararg slice once.
h.responseBytesCounter.Add(ctx, rww.written, o) h.requestBytesCounter.Add(ctx, bw.read.Load(), addOpts...)
h.responseBytesCounter.Add(ctx, rww.written, addOpts...)
// Use floating point division here for higher precision (instead of Millisecond method). // Use floating point division here for higher precision (instead of Millisecond method).
elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond) elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond)

View File

@ -6,6 +6,8 @@ package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"os"
"strings"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/codes"
@ -19,40 +21,51 @@ type ResponseTelemetry struct {
WriteError error WriteError error
} }
type HTTPServer interface { type HTTPServer struct {
// RequestTraceAttrs returns trace attributes for an HTTP request received by a duplicate bool
// server.
//
// The server must be the primary server name if it is known. For example this
// would be the ServerName directive
// (https://httpd.apache.org/docs/2.4/mod/core.html#servername) for an Apache
// server, and the server_name directive
// (http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name) for an
// nginx server. More generically, the primary server name would be the host
// header value that matches the default virtual host of an HTTP server. It
// should include the host identifier and if a port is used to route to the
// server that port identifier should be included as an appropriate port
// suffix.
//
// If the primary server name is not known, server should be an empty string.
// The req Host will be used to determine the server instead.
RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue
// ResponseTraceAttrs returns trace attributes for telemetry from an HTTP response.
//
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
ResponseTraceAttrs(ResponseTelemetry) []attribute.KeyValue
// Route returns the attribute for the route.
Route(string) attribute.KeyValue
} }
// var warnOnce = sync.Once{} // RequestTraceAttrs returns trace attributes for an HTTP request received by a
// server.
//
// The server must be the primary server name if it is known. For example this
// would be the ServerName directive
// (https://httpd.apache.org/docs/2.4/mod/core.html#servername) for an Apache
// server, and the server_name directive
// (http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name) for an
// nginx server. More generically, the primary server name would be the host
// header value that matches the default virtual host of an HTTP server. It
// should include the host identifier and if a port is used to route to the
// server that port identifier should be included as an appropriate port
// suffix.
//
// If the primary server name is not known, server should be an empty string.
// The req Host will be used to determine the server instead.
func (s HTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
if s.duplicate {
return append(oldHTTPServer{}.RequestTraceAttrs(server, req), newHTTPServer{}.RequestTraceAttrs(server, req)...)
}
return oldHTTPServer{}.RequestTraceAttrs(server, req)
}
// ResponseTraceAttrs returns trace attributes for telemetry from an HTTP response.
//
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
func (s HTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
if s.duplicate {
return append(oldHTTPServer{}.ResponseTraceAttrs(resp), newHTTPServer{}.ResponseTraceAttrs(resp)...)
}
return oldHTTPServer{}.ResponseTraceAttrs(resp)
}
// Route returns the attribute for the route.
func (s HTTPServer) Route(route string) attribute.KeyValue {
return oldHTTPServer{}.Route(route)
}
func NewHTTPServer() HTTPServer { func NewHTTPServer() HTTPServer {
// TODO (#5331): Detect version based on environment variable OTEL_HTTP_CLIENT_COMPATIBILITY_MODE. env := strings.ToLower(os.Getenv("OTEL_HTTP_CLIENT_COMPATIBILITY_MODE"))
// TODO (#5331): Add warning of use of a deprecated version of Semantic Versions. return HTTPServer{duplicate: env == "http/dup"}
return oldHTTPServer{}
} }
// ServerStatus returns a span status code and message for an HTTP status code // ServerStatus returns a span status code and message for an HTTP status code

View File

@ -5,8 +5,12 @@ package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/
import ( import (
"net" "net"
"net/http"
"strconv" "strconv"
"strings" "strings"
"go.opentelemetry.io/otel/attribute"
semconvNew "go.opentelemetry.io/otel/semconv/v1.24.0"
) )
// splitHostPort splits a network address hostport of the form "host", // splitHostPort splits a network address hostport of the form "host",
@ -47,3 +51,41 @@ func splitHostPort(hostport string) (host string, port int) {
} }
return host, int(p) return host, int(p)
} }
func requiredHTTPPort(https bool, port int) int { // nolint:revive
if https {
if port > 0 && port != 443 {
return port
}
} else {
if port > 0 && port != 80 {
return port
}
}
return -1
}
func serverClientIP(xForwardedFor string) string {
if idx := strings.Index(xForwardedFor, ","); idx >= 0 {
xForwardedFor = xForwardedFor[:idx]
}
return xForwardedFor
}
func netProtocol(proto string) (name string, version string) {
name, version, _ = strings.Cut(proto, "/")
name = strings.ToLower(name)
return name, version
}
var methodLookup = map[string]attribute.KeyValue{
http.MethodConnect: semconvNew.HTTPRequestMethodConnect,
http.MethodDelete: semconvNew.HTTPRequestMethodDelete,
http.MethodGet: semconvNew.HTTPRequestMethodGet,
http.MethodHead: semconvNew.HTTPRequestMethodHead,
http.MethodOptions: semconvNew.HTTPRequestMethodOptions,
http.MethodPatch: semconvNew.HTTPRequestMethodPatch,
http.MethodPost: semconvNew.HTTPRequestMethodPost,
http.MethodPut: semconvNew.HTTPRequestMethodPut,
http.MethodTrace: semconvNew.HTTPRequestMethodTrace,
}

View File

@ -4,6 +4,7 @@
package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv" package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
import ( import (
"errors"
"io" "io"
"net/http" "net/http"
@ -14,8 +15,6 @@ import (
type oldHTTPServer struct{} type oldHTTPServer struct{}
var _ HTTPServer = oldHTTPServer{}
// RequestTraceAttrs returns trace attributes for an HTTP request received by a // RequestTraceAttrs returns trace attributes for an HTTP request received by a
// server. // server.
// //
@ -45,7 +44,7 @@ func (o oldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.Ke
if resp.ReadBytes > 0 { if resp.ReadBytes > 0 {
attributes = append(attributes, semconv.HTTPRequestContentLength(int(resp.ReadBytes))) attributes = append(attributes, semconv.HTTPRequestContentLength(int(resp.ReadBytes)))
} }
if resp.ReadError != nil && resp.ReadError != io.EOF { if resp.ReadError != nil && !errors.Is(resp.ReadError, io.EOF) {
// This is not in the semantic conventions, but is historically provided // This is not in the semantic conventions, but is historically provided
attributes = append(attributes, attribute.String("http.read_error", resp.ReadError.Error())) attributes = append(attributes, attribute.String("http.read_error", resp.ReadError.Error()))
} }
@ -55,7 +54,7 @@ func (o oldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.Ke
if resp.StatusCode > 0 { if resp.StatusCode > 0 {
attributes = append(attributes, semconv.HTTPStatusCode(resp.StatusCode)) attributes = append(attributes, semconv.HTTPStatusCode(resp.StatusCode))
} }
if resp.WriteError != nil && resp.WriteError != io.EOF { if resp.WriteError != nil && !errors.Is(resp.WriteError, io.EOF) {
// This is not in the semantic conventions, but is historically provided // This is not in the semantic conventions, but is historically provided
attributes = append(attributes, attribute.String("http.write_error", resp.WriteError.Error())) attributes = append(attributes, attribute.String("http.write_error", resp.WriteError.Error()))
} }

View File

@ -0,0 +1,197 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
import (
"net/http"
"strings"
"go.opentelemetry.io/otel/attribute"
semconvNew "go.opentelemetry.io/otel/semconv/v1.24.0"
)
type newHTTPServer struct{}
// TraceRequest returns trace attributes for an HTTP request received by a
// server.
//
// The server must be the primary server name if it is known. For example this
// would be the ServerName directive
// (https://httpd.apache.org/docs/2.4/mod/core.html#servername) for an Apache
// server, and the server_name directive
// (http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name) for an
// nginx server. More generically, the primary server name would be the host
// header value that matches the default virtual host of an HTTP server. It
// should include the host identifier and if a port is used to route to the
// server that port identifier should be included as an appropriate port
// suffix.
//
// If the primary server name is not known, server should be an empty string.
// The req Host will be used to determine the server instead.
func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
count := 3 // ServerAddress, Method, Scheme
var host string
var p int
if server == "" {
host, p = splitHostPort(req.Host)
} else {
// Prioritize the primary server name.
host, p = splitHostPort(server)
if p < 0 {
_, p = splitHostPort(req.Host)
}
}
hostPort := requiredHTTPPort(req.TLS != nil, p)
if hostPort > 0 {
count++
}
method, methodOriginal := n.method(req.Method)
if methodOriginal != (attribute.KeyValue{}) {
count++
}
scheme := n.scheme(req.TLS != nil)
if peer, peerPort := splitHostPort(req.RemoteAddr); peer != "" {
// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
// file-path that would be interpreted with a sock family.
count++
if peerPort > 0 {
count++
}
}
useragent := req.UserAgent()
if useragent != "" {
count++
}
clientIP := serverClientIP(req.Header.Get("X-Forwarded-For"))
if clientIP != "" {
count++
}
if req.URL != nil && req.URL.Path != "" {
count++
}
protoName, protoVersion := netProtocol(req.Proto)
if protoName != "" && protoName != "http" {
count++
}
if protoVersion != "" {
count++
}
attrs := make([]attribute.KeyValue, 0, count)
attrs = append(attrs,
semconvNew.ServerAddress(host),
method,
scheme,
)
if hostPort > 0 {
attrs = append(attrs, semconvNew.ServerPort(hostPort))
}
if methodOriginal != (attribute.KeyValue{}) {
attrs = append(attrs, methodOriginal)
}
if peer, peerPort := splitHostPort(req.RemoteAddr); peer != "" {
// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
// file-path that would be interpreted with a sock family.
attrs = append(attrs, semconvNew.NetworkPeerAddress(peer))
if peerPort > 0 {
attrs = append(attrs, semconvNew.NetworkPeerPort(peerPort))
}
}
if useragent := req.UserAgent(); useragent != "" {
attrs = append(attrs, semconvNew.UserAgentOriginal(useragent))
}
if clientIP != "" {
attrs = append(attrs, semconvNew.ClientAddress(clientIP))
}
if req.URL != nil && req.URL.Path != "" {
attrs = append(attrs, semconvNew.URLPath(req.URL.Path))
}
if protoName != "" && protoName != "http" {
attrs = append(attrs, semconvNew.NetworkProtocolName(protoName))
}
if protoVersion != "" {
attrs = append(attrs, semconvNew.NetworkProtocolVersion(protoVersion))
}
return attrs
}
func (n newHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) {
if method == "" {
return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{}
}
if attr, ok := methodLookup[method]; ok {
return attr, attribute.KeyValue{}
}
orig := semconvNew.HTTPRequestMethodOriginal(method)
if attr, ok := methodLookup[strings.ToUpper(method)]; ok {
return attr, orig
}
return semconvNew.HTTPRequestMethodGet, orig
}
func (n newHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
if https {
return semconvNew.URLScheme("https")
}
return semconvNew.URLScheme("http")
}
// TraceResponse returns trace attributes for telemetry from an HTTP response.
//
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
func (n newHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
var count int
if resp.ReadBytes > 0 {
count++
}
if resp.WriteBytes > 0 {
count++
}
if resp.StatusCode > 0 {
count++
}
attributes := make([]attribute.KeyValue, 0, count)
if resp.ReadBytes > 0 {
attributes = append(attributes,
semconvNew.HTTPRequestBodySize(int(resp.ReadBytes)),
)
}
if resp.WriteBytes > 0 {
attributes = append(attributes,
semconvNew.HTTPResponseBodySize(int(resp.WriteBytes)),
)
}
if resp.StatusCode > 0 {
attributes = append(attributes,
semconvNew.HTTPResponseStatusCode(resp.StatusCode),
)
}
return attributes
}
// Route returns the attribute for the route.
func (n newHTTPServer) Route(route string) attribute.KeyValue {
return semconvNew.HTTPRoute(route)
}

View File

@ -92,7 +92,7 @@ func (c *netConv) Host(address string) []attribute.KeyValue {
attrs := make([]attribute.KeyValue, 0, n) attrs := make([]attribute.KeyValue, 0, n)
attrs = append(attrs, c.HostName(h)) attrs = append(attrs, c.HostName(h))
if p > 0 { if p > 0 {
attrs = append(attrs, c.HostPort(int(p))) attrs = append(attrs, c.HostPort(p))
} }
return attrs return attrs
} }
@ -138,7 +138,7 @@ func (c *netConv) Peer(address string) []attribute.KeyValue {
attrs := make([]attribute.KeyValue, 0, n) attrs := make([]attribute.KeyValue, 0, n)
attrs = append(attrs, c.PeerName(h)) attrs = append(attrs, c.PeerName(h))
if p > 0 { if p > 0 {
attrs = append(attrs, c.PeerPort(int(p))) attrs = append(attrs, c.PeerPort(p))
} }
return attrs return attrs
} }

View File

@ -37,8 +37,12 @@ type labelerContextKeyType int
const lablelerContextKey labelerContextKeyType = 0 const lablelerContextKey labelerContextKeyType = 0
func injectLabeler(ctx context.Context, l *Labeler) context.Context { // ContextWithLabeler returns a new context with the provided Labeler instance.
return context.WithValue(ctx, lablelerContextKey, l) // Attributes added to the specified labeler will be injected into metrics
// emitted by the instrumentation. Only one labeller can be injected into the
// context. Injecting it multiple times will override the previous calls.
func ContextWithLabeler(parent context.Context, l *Labeler) context.Context {
return context.WithValue(parent, lablelerContextKey, l)
} }
// LabelerFromContext retrieves a Labeler instance from the provided context if // LabelerFromContext retrieves a Labeler instance from the provided context if

View File

@ -11,15 +11,14 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil"
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.20.0" semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
"go.opentelemetry.io/otel/trace"
) )
// Transport implements the http.RoundTripper interface and wraps // Transport implements the http.RoundTripper interface and wraps
@ -137,8 +136,10 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
ctx = httptrace.WithClientTrace(ctx, t.clientTrace(ctx)) ctx = httptrace.WithClientTrace(ctx, t.clientTrace(ctx))
} }
labeler := &Labeler{} labeler, found := LabelerFromContext(ctx)
ctx = injectLabeler(ctx, labeler) if !found {
ctx = ContextWithLabeler(ctx, labeler)
}
r = r.Clone(ctx) // According to RoundTripper spec, we shouldn't modify the origin request. r = r.Clone(ctx) // According to RoundTripper spec, we shouldn't modify the origin request.
@ -170,11 +171,12 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
if res.StatusCode > 0 { if res.StatusCode > 0 {
metricAttrs = append(metricAttrs, semconv.HTTPStatusCode(res.StatusCode)) metricAttrs = append(metricAttrs, semconv.HTTPStatusCode(res.StatusCode))
} }
o := metric.WithAttributes(metricAttrs...) o := metric.WithAttributeSet(attribute.NewSet(metricAttrs...))
t.requestBytesCounter.Add(ctx, bw.read.Load(), o) addOpts := []metric.AddOption{o} // Allocate vararg slice once.
t.requestBytesCounter.Add(ctx, bw.read.Load(), addOpts...)
// For handling response bytes we leverage a callback when the client reads the http response // For handling response bytes we leverage a callback when the client reads the http response
readRecordFunc := func(n int64) { readRecordFunc := func(n int64) {
t.responseBytesCounter.Add(ctx, n, o) t.responseBytesCounter.Add(ctx, n, addOpts...)
} }
// traces // traces

View File

@ -5,7 +5,7 @@ package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http
// Version is the current release version of the otelhttp instrumentation. // Version is the current release version of the otelhttp instrumentation.
func Version() string { func Version() string {
return "0.51.0" return "0.53.0"
// This string is updated by the pre_release.sh script during release // This string is updated by the pre_release.sh script during release
} }

View File

@ -87,3 +87,13 @@ func (w *respWriterWrapper) WriteHeader(statusCode int) {
} }
w.ResponseWriter.WriteHeader(statusCode) w.ResponseWriter.WriteHeader(statusCode)
} }
func (w *respWriterWrapper) Flush() {
if !w.wroteHeader {
w.WriteHeader(http.StatusOK)
}
if f, ok := w.ResponseWriter.(http.Flusher); ok {
f.Flush()
}
}

View File

@ -5,3 +5,5 @@ collison
consequentially consequentially
ans ans
nam nam
valu
thirdparty

View File

@ -5,6 +5,6 @@ check-filenames =
check-hidden = check-hidden =
ignore-words = .codespellignore ignore-words = .codespellignore
interactive = 1 interactive = 1
skip = .git,go.mod,go.sum,semconv,venv,.tools skip = .git,go.mod,go.sum,go.work,go.work.sum,semconv,venv,.tools
uri-ignore-words-list = * uri-ignore-words-list = *
write = write =

View File

@ -1,3 +0,0 @@
[submodule "opentelemetry-proto"]
path = exporters/otlp/internal/opentelemetry-proto
url = https://github.com/open-telemetry/opentelemetry-proto

View File

@ -11,6 +11,7 @@ linters:
enable: enable:
- depguard - depguard
- errcheck - errcheck
- errorlint
- godot - godot
- gofumpt - gofumpt
- goimports - goimports
@ -21,8 +22,11 @@ linters:
- misspell - misspell
- revive - revive
- staticcheck - staticcheck
- tenv
- typecheck - typecheck
- unconvert
- unused - unused
- unparam
issues: issues:
# Maximum issues count per one linter. # Maximum issues count per one linter.
@ -124,6 +128,8 @@ linters-settings:
- "**/example/**/*.go" - "**/example/**/*.go"
- "**/trace/*.go" - "**/trace/*.go"
- "**/trace/**/*.go" - "**/trace/**/*.go"
- "**/log/*.go"
- "**/log/**/*.go"
deny: deny:
- pkg: "go.opentelemetry.io/otel/internal$" - pkg: "go.opentelemetry.io/otel/internal$"
desc: Do not use cross-module internal packages. desc: Do not use cross-module internal packages.

View File

@ -8,6 +8,83 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased] ## [Unreleased]
## [1.28.0/0.50.0/0.4.0] 2024-07-02
### Added
- The `IsEmpty` method is added to the `Instrument` type in `go.opentelemetry.io/otel/sdk/metric`.
This method is used to check if an `Instrument` instance is a zero-value. (#5431)
- Store and provide the emitted `context.Context` in `ScopeRecords` of `go.opentelemetry.io/otel/sdk/log/logtest`. (#5468)
- The `go.opentelemetry.io/otel/semconv/v1.26.0` package.
The package contains semantic conventions from the `v1.26.0` version of the OpenTelemetry Semantic Conventions. (#5476)
- The `AssertRecordEqual` method to `go.opentelemetry.io/otel/log/logtest` to allow comparison of two log records in tests. (#5499)
- The `WithHeaders` option to `go.opentelemetry.io/otel/exporters/zipkin` to allow configuring custom http headers while exporting spans. (#5530)
### Changed
- `Tracer.Start` in `go.opentelemetry.io/otel/trace/noop` no longer allocates a span for empty span context. (#5457)
- Upgrade `go.opentelemetry.io/otel/semconv/v1.25.0` to `go.opentelemetry.io/otel/semconv/v1.26.0` in `go.opentelemetry.io/otel/example/otel-collector`. (#5490)
- Upgrade `go.opentelemetry.io/otel/semconv/v1.25.0` to `go.opentelemetry.io/otel/semconv/v1.26.0` in `go.opentelemetry.io/otel/example/zipkin`. (#5490)
- Upgrade `go.opentelemetry.io/otel/semconv/v1.25.0` to `go.opentelemetry.io/otel/semconv/v1.26.0` in `go.opentelemetry.io/otel/exporters/zipkin`. (#5490)
- The exporter no longer exports the deprecated "otel.library.name" or "otel.library.version" attributes.
- Upgrade `go.opentelemetry.io/otel/semconv/v1.25.0` to `go.opentelemetry.io/otel/semconv/v1.26.0` in `go.opentelemetry.io/otel/sdk/resource`. (#5490)
- Upgrade `go.opentelemetry.io/otel/semconv/v1.25.0` to `go.opentelemetry.io/otel/semconv/v1.26.0` in `go.opentelemetry.io/otel/sdk/trace`. (#5490)
- `SimpleProcessor.OnEmit` in `go.opentelemetry.io/otel/sdk/log` no longer allocates a slice which makes it possible to have a zero-allocation log processing using `SimpleProcessor`. (#5493)
- Use non-generic functions in the `Start` method of `"go.opentelemetry.io/otel/sdk/trace".Trace` to reduce memory allocation. (#5497)
- `service.instance.id` is populated for a `Resource` created with `"go.opentelemetry.io/otel/sdk/resource".Default` with a default value when `OTEL_GO_X_RESOURCE` is set. (#5520)
- Improve performance of metric instruments in `go.opentelemetry.io/otel/sdk/metric` by removing unnecessary calls to `time.Now`. (#5545)
### Fixed
- Log a warning to the OpenTelemetry internal logger when a `Record` in `go.opentelemetry.io/otel/sdk/log` drops an attribute due to a limit being reached. (#5376)
- Identify the `Tracer` returned from the global `TracerProvider` in `go.opentelemetry.io/otel/global` with its schema URL. (#5426)
- Identify the `Meter` returned from the global `MeterProvider` in `go.opentelemetry.io/otel/global` with its schema URL. (#5426)
- Log a warning to the OpenTelemetry internal logger when a `Span` in `go.opentelemetry.io/otel/sdk/trace` drops an attribute, event, or link due to a limit being reached. (#5434)
- Document instrument name requirements in `go.opentelemetry.io/otel/metric`. (#5435)
- Prevent random number generation data-race for experimental rand exemplars in `go.opentelemetry.io/otel/sdk/metric`. (#5456)
- Fix counting number of dropped attributes of `Record` in `go.opentelemetry.io/otel/sdk/log`. (#5464)
- Fix panic in baggage creation when a member contains `0x80` char in key or value. (#5494)
- Correct comments for the priority of the `WithEndpoint` and `WithEndpointURL` options and their corresponding environment variables in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#5508)
- Retry trace and span ID generation if it generated an invalid one in `go.opentelemetry.io/otel/sdk/trace`. (#5514)
- Fix stale timestamps reported by the last-value aggregation. (#5517)
- Indicate the `Exporter` in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` must be created by the `New` method. (#5521)
- Improved performance in all `{Bool,Int64,Float64,String}SliceValue` functions of `go.opentelemetry.io/attributes` by reducing the number of allocations. (#5549)
## [1.27.0/0.49.0/0.3.0] 2024-05-21
### Added
- Add example for `go.opentelemetry.io/otel/exporters/stdout/stdoutlog`. (#5242)
- Add `RecordFactory` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing exporter and processor implementations. (#5258)
- Add `RecordFactory` in `go.opentelemetry.io/otel/log/logtest` to facilitate testing bridge implementations. (#5263)
- The count of dropped records from the `BatchProcessor` in `go.opentelemetry.io/otel/sdk/log` is logged. (#5276)
- Add metrics in the `otel-collector` example. (#5283)
- Add the synchronous gauge instrument to `go.opentelemetry.io/otel/metric`. (#5304)
- An `int64` or `float64` synchronous gauge instrument can now be created from a `Meter`.
- All implementations of the API (`go.opentelemetry.io/otel/metric/noop`, `go.opentelemetry.io/otel/sdk/metric`) are updated to support this instrument.
- Add logs to `go.opentelemetry.io/otel/example/dice`. (#5349)
### Changed
- The `Shutdown` method of `Exporter` in `go.opentelemetry.io/otel/exporters/stdout/stdouttrace` ignores the context cancellation and always returns `nil`. (#5189)
- The `ForceFlush` and `Shutdown` methods of the exporter returned by `New` in `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` ignore the context cancellation and always return `nil`. (#5189)
- Apply the value length limits to `Record` attributes in `go.opentelemetry.io/otel/sdk/log`. (#5230)
- De-duplicate map attributes added to a `Record` in `go.opentelemetry.io/otel/sdk/log`. (#5230)
- `go.opentelemetry.io/otel/exporters/stdout/stdoutlog` won't print timestamps when `WithoutTimestamps` option is set. (#5241)
- The `go.opentelemetry.io/otel/exporters/stdout/stdoutlog` exporter won't print `AttributeValueLengthLimit` and `AttributeCountLimit` fields now, instead it prints the `DroppedAttributes` field. (#5272)
- Improved performance in the `Stringer` implementation of `go.opentelemetry.io/otel/baggage.Member` by reducing the number of allocations. (#5286)
- Set the start time for last-value aggregates in `go.opentelemetry.io/otel/sdk/metric`. (#5305)
- The `Span` in `go.opentelemetry.io/otel/sdk/trace` will record links without span context if either non-empty `TraceState` or attributes are provided. (#5315)
- Upgrade all dependencies of `go.opentelemetry.io/otel/semconv/v1.24.0` to `go.opentelemetry.io/otel/semconv/v1.25.0`. (#5374)
### Fixed
- Comparison of unordered maps for `go.opentelemetry.io/otel/log.KeyValue` and `go.opentelemetry.io/otel/log.Value`. (#5306)
- Fix the empty output of `go.opentelemetry.io/otel/log.Value` in `go.opentelemetry.io/otel/exporters/stdout/stdoutlog`. (#5311)
- Split the behavior of `Recorder` in `go.opentelemetry.io/otel/log/logtest` so it behaves as a `LoggerProvider` only. (#5365)
- Fix wrong package name of the error message when parsing endpoint URL in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#5371)
- Identify the `Logger` returned from the global `LoggerProvider` in `go.opentelemetry.io/otel/log/global` with its schema URL. (#5375)
## [1.26.0/0.48.0/0.2.0-alpha] 2024-04-24 ## [1.26.0/0.48.0/0.2.0-alpha] 2024-04-24
### Added ### Added
@ -33,6 +110,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Update `go.opentelemetry.io/proto/otlp` from v1.1.0 to v1.2.0. (#5177) - Update `go.opentelemetry.io/proto/otlp` from v1.1.0 to v1.2.0. (#5177)
- Improve performance of baggage member character validation in `go.opentelemetry.io/otel/baggage`. (#5214) - Improve performance of baggage member character validation in `go.opentelemetry.io/otel/baggage`. (#5214)
- The `otel-collector` example now uses docker compose to bring up services instead of kubernetes. (#5244)
### Fixed
- Slice attribute values in `go.opentelemetry.io/otel/attribute` are now emitted as their JSON representation. (#5159)
## [1.25.0/0.47.0/0.0.8/0.1.0-alpha] 2024-04-05 ## [1.25.0/0.47.0/0.0.8/0.1.0-alpha] 2024-04-05
@ -210,7 +292,7 @@ See our [versioning policy](VERSIONING.md) for more information about these stab
## [1.20.0/0.43.0] 2023-11-10 ## [1.20.0/0.43.0] 2023-11-10
This release brings a breaking change for custom trace API implementations. Some interfaces (`TracerProvider`, `Tracer`, `Span`) now embed the `go.opentelemetry.io/otel/trace/embedded` types. Implementors need to update their implementations based on what they want the default behavior to be. See the "API Implementations" section of the [trace API] package documentation for more information about how to accomplish this. This release brings a breaking change for custom trace API implementations. Some interfaces (`TracerProvider`, `Tracer`, `Span`) now embed the `go.opentelemetry.io/otel/trace/embedded` types. Implementers need to update their implementations based on what they want the default behavior to be. See the "API Implementations" section of the [trace API] package documentation for more information about how to accomplish this.
### Added ### Added
@ -242,15 +324,15 @@ This release brings a breaking change for custom trace API implementations. Some
- `go.opentelemetry.io/otel/bridge/opencensus.NewMetricProducer` returns a `*MetricProducer` struct instead of the metric.Producer interface. (#4583) - `go.opentelemetry.io/otel/bridge/opencensus.NewMetricProducer` returns a `*MetricProducer` struct instead of the metric.Producer interface. (#4583)
- The `TracerProvider` in `go.opentelemetry.io/otel/trace` now embeds the `go.opentelemetry.io/otel/trace/embedded.TracerProvider` type. - The `TracerProvider` in `go.opentelemetry.io/otel/trace` now embeds the `go.opentelemetry.io/otel/trace/embedded.TracerProvider` type.
This extends the `TracerProvider` interface and is is a breaking change for any existing implementation. This extends the `TracerProvider` interface and is is a breaking change for any existing implementation.
Implementors need to update their implementations based on what they want the default behavior of the interface to be. Implementers need to update their implementations based on what they want the default behavior of the interface to be.
See the "API Implementations" section of the `go.opentelemetry.io/otel/trace` package documentation for more information about how to accomplish this. (#4620) See the "API Implementations" section of the `go.opentelemetry.io/otel/trace` package documentation for more information about how to accomplish this. (#4620)
- The `Tracer` in `go.opentelemetry.io/otel/trace` now embeds the `go.opentelemetry.io/otel/trace/embedded.Tracer` type. - The `Tracer` in `go.opentelemetry.io/otel/trace` now embeds the `go.opentelemetry.io/otel/trace/embedded.Tracer` type.
This extends the `Tracer` interface and is is a breaking change for any existing implementation. This extends the `Tracer` interface and is is a breaking change for any existing implementation.
Implementors need to update their implementations based on what they want the default behavior of the interface to be. Implementers need to update their implementations based on what they want the default behavior of the interface to be.
See the "API Implementations" section of the `go.opentelemetry.io/otel/trace` package documentation for more information about how to accomplish this. (#4620) See the "API Implementations" section of the `go.opentelemetry.io/otel/trace` package documentation for more information about how to accomplish this. (#4620)
- The `Span` in `go.opentelemetry.io/otel/trace` now embeds the `go.opentelemetry.io/otel/trace/embedded.Span` type. - The `Span` in `go.opentelemetry.io/otel/trace` now embeds the `go.opentelemetry.io/otel/trace/embedded.Span` type.
This extends the `Span` interface and is is a breaking change for any existing implementation. This extends the `Span` interface and is is a breaking change for any existing implementation.
Implementors need to update their implementations based on what they want the default behavior of the interface to be. Implementers need to update their implementations based on what they want the default behavior of the interface to be.
See the "API Implementations" section of the `go.opentelemetry.io/otel/trace` package documentation for more information about how to accomplish this. (#4620) See the "API Implementations" section of the `go.opentelemetry.io/otel/trace` package documentation for more information about how to accomplish this. (#4620)
- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` does no longer depend on `go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#4660) - `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` does no longer depend on `go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#4660)
- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` does no longer depend on `go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#4660) - `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` does no longer depend on `go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#4660)
@ -886,7 +968,7 @@ The next release will require at least [Go 1.19].
- Exported `Status` codes in the `go.opentelemetry.io/otel/exporters/zipkin` exporter are now exported as all upper case values. (#3340) - Exported `Status` codes in the `go.opentelemetry.io/otel/exporters/zipkin` exporter are now exported as all upper case values. (#3340)
- `Aggregation`s from `go.opentelemetry.io/otel/sdk/metric` with no data are not exported. (#3394, #3436) - `Aggregation`s from `go.opentelemetry.io/otel/sdk/metric` with no data are not exported. (#3394, #3436)
- Re-enabled Attribute Filters in the Metric SDK. (#3396) - Re-enabled Attribute Filters in the Metric SDK. (#3396)
- Asynchronous callbacks are only called if they are registered with at least one instrument that does not use drop aggragation. (#3408) - Asynchronous callbacks are only called if they are registered with at least one instrument that does not use drop aggregation. (#3408)
- Do not report empty partial-success responses in the `go.opentelemetry.io/otel/exporters/otlp` exporters. (#3438, #3432) - Do not report empty partial-success responses in the `go.opentelemetry.io/otel/exporters/otlp` exporters. (#3438, #3432)
- Handle partial success responses in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric` exporters. (#3162, #3440) - Handle partial success responses in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric` exporters. (#3162, #3440)
- Prevent duplicate Prometheus description, unit, and type. (#3469) - Prevent duplicate Prometheus description, unit, and type. (#3469)
@ -1931,7 +2013,7 @@ with major version 0.
- `NewExporter` from `exporters/otlp` now takes a `ProtocolDriver` as a parameter. (#1369) - `NewExporter` from `exporters/otlp` now takes a `ProtocolDriver` as a parameter. (#1369)
- Many OTLP Exporter options became gRPC ProtocolDriver options. (#1369) - Many OTLP Exporter options became gRPC ProtocolDriver options. (#1369)
- Unify endpoint API that related to OTel exporter. (#1401) - Unify endpoint API that related to OTel exporter. (#1401)
- Optimize metric histogram aggregator to re-use its slice of buckets. (#1435) - Optimize metric histogram aggregator to reuse its slice of buckets. (#1435)
- Metric aggregator Count() and histogram Bucket.Counts are consistently `uint64`. (1430) - Metric aggregator Count() and histogram Bucket.Counts are consistently `uint64`. (1430)
- Histogram aggregator accepts functional options, uses default boundaries if none given. (#1434) - Histogram aggregator accepts functional options, uses default boundaries if none given. (#1434)
- `SamplingResult` now passed a `Tracestate` from the parent `SpanContext` (#1432) - `SamplingResult` now passed a `Tracestate` from the parent `SpanContext` (#1432)
@ -2921,7 +3003,9 @@ It contains api and sdk for trace and meter.
- CircleCI build CI manifest files. - CircleCI build CI manifest files.
- CODEOWNERS file to track owners of this project. - CODEOWNERS file to track owners of this project.
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.26.0...HEAD [Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.28.0...HEAD
[1.28.0/0.50.0/0.4.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.28.0
[1.27.0/0.49.0/0.3.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.27.0
[1.26.0/0.48.0/0.2.0-alpha]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.26.0 [1.26.0/0.48.0/0.2.0-alpha]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.26.0
[1.25.0/0.47.0/0.0.8/0.1.0-alpha]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.25.0 [1.25.0/0.47.0/0.0.8/0.1.0-alpha]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.25.0
[1.24.0/0.46.0/0.0.1-alpha]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.24.0 [1.24.0/0.46.0/0.0.1-alpha]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.24.0

View File

@ -12,6 +12,6 @@
# https://help.github.com/en/articles/about-code-owners # https://help.github.com/en/articles/about-code-owners
# #
* @MrAlias @Aneurysm9 @evantorrie @XSAM @dashpole @MadVikingGod @pellared @hanyuancheung @dmathieu * @MrAlias @XSAM @dashpole @MadVikingGod @pellared @hanyuancheung @dmathieu
CODEOWNERS @MrAlias @MadVikingGod @pellared @dashpole CODEOWNERS @MrAlias @MadVikingGod @pellared @dashpole @XSAM @dmathieu

View File

@ -570,6 +570,9 @@ functionality should be added, each one will need their own super-set
interfaces and will duplicate the pattern. For this reason, the simple targeted interfaces and will duplicate the pattern. For this reason, the simple targeted
interface that defines the specific functionality should be preferred. interface that defines the specific functionality should be preferred.
See also:
[Keeping Your Modules Compatible: Working with interfaces](https://go.dev/blog/module-compatibility#working-with-interfaces).
### Testing ### Testing
The tests should never leak goroutines. The tests should never leak goroutines.
@ -625,17 +628,15 @@ should be canceled.
### Approvers ### Approvers
- [Evan Torrie](https://github.com/evantorrie), Verizon Media
- [Sam Xie](https://github.com/XSAM), Cisco/AppDynamics
- [Chester Cheung](https://github.com/hanyuancheung), Tencent - [Chester Cheung](https://github.com/hanyuancheung), Tencent
- [Damien Mathieu](https://github.com/dmathieu), Elastic
- [Anthony Mirabella](https://github.com/Aneurysm9), AWS
### Maintainers ### Maintainers
- [David Ashpole](https://github.com/dashpole), Google
- [Aaron Clawson](https://github.com/MadVikingGod), LightStep - [Aaron Clawson](https://github.com/MadVikingGod), LightStep
- [Damien Mathieu](https://github.com/dmathieu), Elastic
- [David Ashpole](https://github.com/dashpole), Google
- [Robert Pająk](https://github.com/pellared), Splunk - [Robert Pająk](https://github.com/pellared), Splunk
- [Sam Xie](https://github.com/XSAM), Cisco/AppDynamics
- [Tyler Yahn](https://github.com/MrAlias), Splunk - [Tyler Yahn](https://github.com/MrAlias), Splunk
### Emeritus ### Emeritus
@ -643,6 +644,8 @@ should be canceled.
- [Liz Fong-Jones](https://github.com/lizthegrey), Honeycomb - [Liz Fong-Jones](https://github.com/lizthegrey), Honeycomb
- [Gustavo Silva Paiva](https://github.com/paivagustavo), LightStep - [Gustavo Silva Paiva](https://github.com/paivagustavo), LightStep
- [Josh MacDonald](https://github.com/jmacd), LightStep - [Josh MacDonald](https://github.com/jmacd), LightStep
- [Anthony Mirabella](https://github.com/Aneurysm9), AWS
- [Evan Torrie](https://github.com/evantorrie), Yahoo
### Become an Approver or a Maintainer ### Become an Approver or a Maintainer

View File

@ -14,8 +14,8 @@ TIMEOUT = 60
.DEFAULT_GOAL := precommit .DEFAULT_GOAL := precommit
.PHONY: precommit ci .PHONY: precommit ci
precommit: generate dependabot-generate license-check misspell go-mod-tidy golangci-lint-fix verify-readmes test-default precommit: generate license-check misspell go-mod-tidy golangci-lint-fix verify-readmes verify-mods test-default
ci: generate dependabot-check license-check lint vanity-import-check verify-readmes build test-default check-clean-work-tree test-coverage ci: generate license-check lint vanity-import-check verify-readmes verify-mods build test-default check-clean-work-tree test-coverage
# Tools # Tools
@ -39,9 +39,6 @@ $(TOOLS)/crosslink: PACKAGE=go.opentelemetry.io/build-tools/crosslink
SEMCONVKIT = $(TOOLS)/semconvkit SEMCONVKIT = $(TOOLS)/semconvkit
$(TOOLS)/semconvkit: PACKAGE=go.opentelemetry.io/otel/$(TOOLS_MOD_DIR)/semconvkit $(TOOLS)/semconvkit: PACKAGE=go.opentelemetry.io/otel/$(TOOLS_MOD_DIR)/semconvkit
DBOTCONF = $(TOOLS)/dbotconf
$(TOOLS)/dbotconf: PACKAGE=go.opentelemetry.io/build-tools/dbotconf
GOLANGCI_LINT = $(TOOLS)/golangci-lint GOLANGCI_LINT = $(TOOLS)/golangci-lint
$(TOOLS)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/cmd/golangci-lint $(TOOLS)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/cmd/golangci-lint
@ -70,7 +67,7 @@ GOVULNCHECK = $(TOOLS)/govulncheck
$(TOOLS)/govulncheck: PACKAGE=golang.org/x/vuln/cmd/govulncheck $(TOOLS)/govulncheck: PACKAGE=golang.org/x/vuln/cmd/govulncheck
.PHONY: tools .PHONY: tools
tools: $(CROSSLINK) $(DBOTCONF) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(GOJQ) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE) tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(GOJQ) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE)
# Virtualized python tools via docker # Virtualized python tools via docker
@ -252,15 +249,6 @@ license-check:
exit 1; \ exit 1; \
fi fi
DEPENDABOT_CONFIG = .github/dependabot.yml
.PHONY: dependabot-check
dependabot-check: $(DBOTCONF)
@$(DBOTCONF) verify $(DEPENDABOT_CONFIG) || ( echo "(run: make dependabot-generate)"; exit 1 )
.PHONY: dependabot-generate
dependabot-generate: $(DBOTCONF)
@$(DBOTCONF) generate > $(DEPENDABOT_CONFIG)
.PHONY: check-clean-work-tree .PHONY: check-clean-work-tree
check-clean-work-tree: check-clean-work-tree:
@if ! git diff --quiet; then \ @if ! git diff --quiet; then \
@ -276,10 +264,7 @@ SEMCONVPKG ?= "semconv/"
semconv-generate: $(SEMCONVGEN) $(SEMCONVKIT) semconv-generate: $(SEMCONVGEN) $(SEMCONVKIT)
[ "$(TAG)" ] || ( echo "TAG unset: missing opentelemetry semantic-conventions tag"; exit 1 ) [ "$(TAG)" ] || ( echo "TAG unset: missing opentelemetry semantic-conventions tag"; exit 1 )
[ "$(OTEL_SEMCONV_REPO)" ] || ( echo "OTEL_SEMCONV_REPO unset: missing path to opentelemetry semantic-conventions repo"; exit 1 ) [ "$(OTEL_SEMCONV_REPO)" ] || ( echo "OTEL_SEMCONV_REPO unset: missing path to opentelemetry semantic-conventions repo"; exit 1 )
$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=span -p conventionType=trace -f trace.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)"
$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=attribute_group -p conventionType=trace -f attribute_group.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" $(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=attribute_group -p conventionType=trace -f attribute_group.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)"
$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=event -p conventionType=event -f event.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)"
$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=resource -p conventionType=resource -f resource.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)"
$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=metric -f metric.go -t "$(SEMCONVPKG)/metric_template.j2" -s "$(TAG)" $(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=metric -f metric.go -t "$(SEMCONVPKG)/metric_template.j2" -s "$(TAG)"
$(SEMCONVKIT) -output "$(SEMCONVPKG)/$(TAG)" -tag "$(TAG)" $(SEMCONVKIT) -output "$(SEMCONVPKG)/$(TAG)" -tag "$(TAG)"
@ -292,16 +277,20 @@ gorelease/%:| $(GORELEASE)
&& $(GORELEASE) \ && $(GORELEASE) \
|| echo "" || echo ""
.PHONY: verify-mods
verify-mods: $(MULTIMOD)
$(MULTIMOD) verify
.PHONY: prerelease .PHONY: prerelease
prerelease: $(MULTIMOD) prerelease: verify-mods
@[ "${MODSET}" ] || ( echo ">> env var MODSET is not set"; exit 1 ) @[ "${MODSET}" ] || ( echo ">> env var MODSET is not set"; exit 1 )
$(MULTIMOD) verify && $(MULTIMOD) prerelease -m ${MODSET} $(MULTIMOD) prerelease -m ${MODSET}
COMMIT ?= "HEAD" COMMIT ?= "HEAD"
.PHONY: add-tags .PHONY: add-tags
add-tags: $(MULTIMOD) add-tags: verify-mods
@[ "${MODSET}" ] || ( echo ">> env var MODSET is not set"; exit 1 ) @[ "${MODSET}" ] || ( echo ">> env var MODSET is not set"; exit 1 )
$(MULTIMOD) verify && $(MULTIMOD) tag -m ${MODSET} -c ${COMMIT} $(MULTIMOD) tag -m ${MODSET} -c ${COMMIT}
.PHONY: lint-markdown .PHONY: lint-markdown
lint-markdown: lint-markdown:

View File

@ -15,7 +15,7 @@ It provides a set of APIs to directly measure performance and behavior of your s
|---------|--------------------| |---------|--------------------|
| Traces | Stable | | Traces | Stable |
| Metrics | Stable | | Metrics | Stable |
| Logs | In development[^1] | | Logs | Beta[^1] |
Progress and status specific to this repository is tracked in our Progress and status specific to this repository is tracked in our
[project boards](https://github.com/open-telemetry/opentelemetry-go/projects) [project boards](https://github.com/open-telemetry/opentelemetry-go/projects)
@ -97,12 +97,12 @@ export pipeline to send that telemetry to an observability platform.
All officially supported exporters for the OpenTelemetry project are contained in the [exporters directory](./exporters). All officially supported exporters for the OpenTelemetry project are contained in the [exporters directory](./exporters).
| Exporter | Metrics | Traces | | Exporter | Logs | Metrics | Traces |
|---------------------------------------|:-------:|:------:| |---------------------------------------|:----:|:-------:|:------:|
| [OTLP](./exporters/otlp/) | ✓ | ✓ | | [OTLP](./exporters/otlp/) | ✓ | ✓ | ✓ |
| [Prometheus](./exporters/prometheus/) | ✓ | | | [Prometheus](./exporters/prometheus/) | | ✓ | |
| [stdout](./exporters/stdout/) | ✓ | ✓ | | [stdout](./exporters/stdout/) | ✓ | ✓ | ✓ |
| [Zipkin](./exporters/zipkin/) | | ✓ | | [Zipkin](./exporters/zipkin/) | | | ✓ |
## Contributing ## Contributing

View File

@ -27,6 +27,12 @@ You can run `make gorelease` that runs [gorelease](https://pkg.go.dev/golang.org
You can check/report problems with `gorelease` [here](https://golang.org/issues/26420). You can check/report problems with `gorelease` [here](https://golang.org/issues/26420).
## Verify changes for contrib repository
If the changes in the main repository are going to affect the contrib repository, it is important to verify that the changes are compatible with the contrib repository.
Follow [the steps](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/RELEASING.md#verify-otel-changes) in the contrib repository to verify OTel changes.
## Pre-Release ## Pre-Release
First, decide which module sets will be released and update their versions First, decide which module sets will be released and update their versions

View File

@ -231,15 +231,27 @@ func (v Value) Emit() string {
case BOOL: case BOOL:
return strconv.FormatBool(v.AsBool()) return strconv.FormatBool(v.AsBool())
case INT64SLICE: case INT64SLICE:
return fmt.Sprint(v.asInt64Slice()) j, err := json.Marshal(v.asInt64Slice())
if err != nil {
return fmt.Sprintf("invalid: %v", v.asInt64Slice())
}
return string(j)
case INT64: case INT64:
return strconv.FormatInt(v.AsInt64(), 10) return strconv.FormatInt(v.AsInt64(), 10)
case FLOAT64SLICE: case FLOAT64SLICE:
return fmt.Sprint(v.asFloat64Slice()) j, err := json.Marshal(v.asFloat64Slice())
if err != nil {
return fmt.Sprintf("invalid: %v", v.asFloat64Slice())
}
return string(j)
case FLOAT64: case FLOAT64:
return fmt.Sprint(v.AsFloat64()) return fmt.Sprint(v.AsFloat64())
case STRINGSLICE: case STRINGSLICE:
return fmt.Sprint(v.asStringSlice()) j, err := json.Marshal(v.asStringSlice())
if err != nil {
return fmt.Sprintf("invalid: %v", v.asStringSlice())
}
return string(j)
case STRING: case STRING:
return v.stringly return v.stringly
default: default:

View File

@ -302,7 +302,7 @@ func parseMember(member string) (Member, error) {
// Decode a percent-encoded value. // Decode a percent-encoded value.
value, err := url.PathUnescape(val) value, err := url.PathUnescape(val)
if err != nil { if err != nil {
return newInvalidMember(), fmt.Errorf("%w: %v", errInvalidValue, err) return newInvalidMember(), fmt.Errorf("%w: %w", errInvalidValue, err)
} }
return Member{key: key, value: value, properties: props, hasData: true}, nil return Member{key: key, value: value, properties: props, hasData: true}, nil
} }
@ -335,9 +335,9 @@ func (m Member) String() string {
// A key is just an ASCII string. A value is restricted to be // A key is just an ASCII string. A value is restricted to be
// US-ASCII characters excluding CTLs, whitespace, // US-ASCII characters excluding CTLs, whitespace,
// DQUOTE, comma, semicolon, and backslash. // DQUOTE, comma, semicolon, and backslash.
s := fmt.Sprintf("%s%s%s", m.key, keyValueDelimiter, valueEscape(m.value)) s := m.key + keyValueDelimiter + valueEscape(m.value)
if len(m.properties) > 0 { if len(m.properties) > 0 {
s = fmt.Sprintf("%s%s%s", s, propertyDelimiter, m.properties.String()) s += propertyDelimiter + m.properties.String()
} }
return s return s
} }
@ -735,7 +735,7 @@ func validateKey(s string) bool {
} }
func validateKeyChar(c int32) bool { func validateKeyChar(c int32) bool {
return c >= 0 && c <= int32(utf8.RuneSelf) && safeKeyCharset[c] return c >= 0 && c < int32(utf8.RuneSelf) && safeKeyCharset[c]
} }
func validateValue(s string) bool { func validateValue(s string) bool {
@ -850,7 +850,7 @@ var safeValueCharset = [utf8.RuneSelf]bool{
} }
func validateValueChar(c int32) bool { func validateValueChar(c int32) bool {
return c >= 0 && c <= int32(utf8.RuneSelf) && safeValueCharset[c] return c >= 0 && c < int32(utf8.RuneSelf) && safeValueCharset[c]
} }
// valueEscape escapes the string so it can be safely placed inside a baggage value, // valueEscape escapes the string so it can be safely placed inside a baggage value,

View File

@ -256,6 +256,9 @@ func NewGRPCOption(fn func(cfg Config) Config) GRPCOption {
// Generic Options // Generic Options
// WithEndpoint configures the trace host and port only; endpoint should
// resemble "example.com" or "localhost:4317". To configure the scheme and path,
// use WithEndpointURL.
func WithEndpoint(endpoint string) GenericOption { func WithEndpoint(endpoint string) GenericOption {
return newGenericOption(func(cfg Config) Config { return newGenericOption(func(cfg Config) Config {
cfg.Traces.Endpoint = endpoint cfg.Traces.Endpoint = endpoint
@ -263,6 +266,8 @@ func WithEndpoint(endpoint string) GenericOption {
}) })
} }
// WithEndpointURL configures the trace scheme, host, port, and path; the
// provided value should resemble "https://example.com:4318/v1/traces".
func WithEndpointURL(v string) GenericOption { func WithEndpointURL(v string) GenericOption {
return newGenericOption(func(cfg Config) Config { return newGenericOption(func(cfg Config) Config {
u, err := url.Parse(v) u, err := url.Parse(v)

View File

@ -112,7 +112,7 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
} }
if ctxErr := waitFunc(ctx, delay); ctxErr != nil { if ctxErr := waitFunc(ctx, delay); ctxErr != nil {
return fmt.Errorf("%w: %s", ctxErr, err) return fmt.Errorf("%w: %w", ctxErr, err)
} }
} }
} }

View File

@ -53,12 +53,15 @@ func WithInsecure() Option {
return wrappedOption{otlpconfig.WithInsecure()} return wrappedOption{otlpconfig.WithInsecure()}
} }
// WithEndpoint sets the target endpoint the Exporter will connect to. // WithEndpoint sets the target endpoint (host and port) the Exporter will
// connect to. The provided endpoint should resemble "example.com:4317" (no
// scheme or path).
// //
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT // If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
// environment variable is set, and this option is not passed, that variable // environment variable is set, and this option is not passed, that variable
// value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT // value will be used. If both environment variables are set,
// will take precedence. // OTEL_EXPORTER_OTLP_TRACES_ENDPOINT will take precedence. If an environment
// variable is set, and this option is passed, this option will take precedence.
// //
// If both this option and WithEndpointURL are used, the last used option will // If both this option and WithEndpointURL are used, the last used option will
// take precedence. // take precedence.
@ -71,12 +74,15 @@ func WithEndpoint(endpoint string) Option {
return wrappedOption{otlpconfig.WithEndpoint(endpoint)} return wrappedOption{otlpconfig.WithEndpoint(endpoint)}
} }
// WithEndpointURL sets the target endpoint URL the Exporter will connect to. // WithEndpointURL sets the target endpoint URL (scheme, host, port, path)
// the Exporter will connect to. The provided endpoint URL should resemble
// "https://example.com:4318/v1/traces".
// //
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT // If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
// environment variable is set, and this option is not passed, that variable // environment variable is set, and this option is not passed, that variable
// value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT // value will be used. If both environment variables are set,
// will take precedence. // OTEL_EXPORTER_OTLP_TRACES_ENDPOINT will take precedence. If an environment
// variable is set, and this option is passed, this option will take precedence.
// //
// If both this option and WithEndpoint are used, the last used option will // If both this option and WithEndpoint are used, the last used option will
// take precedence. // take precedence.
@ -84,7 +90,7 @@ func WithEndpoint(endpoint string) Option {
// If an invalid URL is provided, the default value will be kept. // If an invalid URL is provided, the default value will be kept.
// //
// By default, if an environment variable is not set, and this option is not // By default, if an environment variable is not set, and this option is not
// passed, "localhost:4317" will be used. // passed, "https://localhost:4317/v1/traces" will be used.
// //
// This option has no effect if WithGRPCConn is used. // This option has no effect if WithGRPCConn is used.
func WithEndpointURL(u string) Option { func WithEndpointURL(u string) Option {

View File

@ -316,7 +316,10 @@ func evaluate(err error) (bool, time.Duration) {
return false, 0 return false, 0
} }
rErr, ok := err.(retryableError) // Do not use errors.As here, this should only be flattened one layer. If
// there are several chained errors, all the errors above it will be
// discarded if errors.As is used instead.
rErr, ok := err.(retryableError) //nolint:errorlint
if !ok { if !ok {
return false, 0 return false, 0
} }

View File

@ -256,6 +256,9 @@ func NewGRPCOption(fn func(cfg Config) Config) GRPCOption {
// Generic Options // Generic Options
// WithEndpoint configures the trace host and port only; endpoint should
// resemble "example.com" or "localhost:4317". To configure the scheme and path,
// use WithEndpointURL.
func WithEndpoint(endpoint string) GenericOption { func WithEndpoint(endpoint string) GenericOption {
return newGenericOption(func(cfg Config) Config { return newGenericOption(func(cfg Config) Config {
cfg.Traces.Endpoint = endpoint cfg.Traces.Endpoint = endpoint
@ -263,6 +266,8 @@ func WithEndpoint(endpoint string) GenericOption {
}) })
} }
// WithEndpointURL configures the trace scheme, host, port, and path; the
// provided value should resemble "https://example.com:4318/v1/traces".
func WithEndpointURL(v string) GenericOption { func WithEndpointURL(v string) GenericOption {
return newGenericOption(func(cfg Config) Config { return newGenericOption(func(cfg Config) Config {
u, err := url.Parse(v) u, err := url.Parse(v)

View File

@ -112,7 +112,7 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
} }
if ctxErr := waitFunc(ctx, delay); ctxErr != nil { if ctxErr := waitFunc(ctx, delay); ctxErr != nil {
return fmt.Errorf("%w: %s", ctxErr, err) return fmt.Errorf("%w: %w", ctxErr, err)
} }
} }
} }

View File

@ -56,12 +56,15 @@ func (w wrappedOption) applyHTTPOption(cfg otlpconfig.Config) otlpconfig.Config
return w.ApplyHTTPOption(cfg) return w.ApplyHTTPOption(cfg)
} }
// WithEndpoint sets the target endpoint the Exporter will connect to. // WithEndpoint sets the target endpoint (host and port) the Exporter will
// connect to. The provided endpoint should resemble "example.com:4318" (no
// scheme or path).
// //
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT // If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
// environment variable is set, and this option is not passed, that variable // environment variable is set, and this option is not passed, that variable
// value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT // value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
// will take precedence. // will take precedence. Note, both environment variables include the full
// scheme and path, while WithEndpoint sets only the host and port.
// //
// If both this option and WithEndpointURL are used, the last used option will // If both this option and WithEndpointURL are used, the last used option will
// take precedence. // take precedence.
@ -74,9 +77,10 @@ func WithEndpoint(endpoint string) Option {
return wrappedOption{otlpconfig.WithEndpoint(endpoint)} return wrappedOption{otlpconfig.WithEndpoint(endpoint)}
} }
// WithEndpointURL sets the target endpoint URL the Exporter will connect to. // WithEndpointURL sets the target endpoint URL (scheme, host, port, path) the
// Exporter will connect to.
// //
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT // If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
// environment variable is set, and this option is not passed, that variable // environment variable is set, and this option is not passed, that variable
// value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT // value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
// will take precedence. // will take precedence.

View File

@ -5,5 +5,5 @@ package otlptrace // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
// Version is the current release version of the OpenTelemetry OTLP trace exporter in use. // Version is the current release version of the OpenTelemetry OTLP trace exporter in use.
func Version() string { func Version() string {
return "1.26.0" return "1.28.0"
} }

View File

@ -14,33 +14,33 @@ import (
// BoolSliceValue converts a bool slice into an array with same elements as slice. // BoolSliceValue converts a bool slice into an array with same elements as slice.
func BoolSliceValue(v []bool) interface{} { func BoolSliceValue(v []bool) interface{} {
var zero bool var zero bool
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero))) cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero))).Elem()
copy(cp.Elem().Slice(0, len(v)).Interface().([]bool), v) reflect.Copy(cp, reflect.ValueOf(v))
return cp.Elem().Interface() return cp.Interface()
} }
// Int64SliceValue converts an int64 slice into an array with same elements as slice. // Int64SliceValue converts an int64 slice into an array with same elements as slice.
func Int64SliceValue(v []int64) interface{} { func Int64SliceValue(v []int64) interface{} {
var zero int64 var zero int64
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero))) cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero))).Elem()
copy(cp.Elem().Slice(0, len(v)).Interface().([]int64), v) reflect.Copy(cp, reflect.ValueOf(v))
return cp.Elem().Interface() return cp.Interface()
} }
// Float64SliceValue converts a float64 slice into an array with same elements as slice. // Float64SliceValue converts a float64 slice into an array with same elements as slice.
func Float64SliceValue(v []float64) interface{} { func Float64SliceValue(v []float64) interface{} {
var zero float64 var zero float64
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero))) cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero))).Elem()
copy(cp.Elem().Slice(0, len(v)).Interface().([]float64), v) reflect.Copy(cp, reflect.ValueOf(v))
return cp.Elem().Interface() return cp.Interface()
} }
// StringSliceValue converts a string slice into an array with same elements as slice. // StringSliceValue converts a string slice into an array with same elements as slice.
func StringSliceValue(v []string) interface{} { func StringSliceValue(v []string) interface{} {
var zero string var zero string
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero))) cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero))).Elem()
copy(cp.Elem().Slice(0, len(v)).Interface().([]string), v) reflect.Copy(cp, reflect.ValueOf(v))
return cp.Elem().Interface() return cp.Interface()
} }
// AsBoolSlice converts a bool array into a slice into with same elements as array. // AsBoolSlice converts a bool array into a slice into with same elements as array.

View File

@ -281,6 +281,32 @@ func (i *sfHistogram) Record(ctx context.Context, x float64, opts ...metric.Reco
} }
} }
type sfGauge struct {
embedded.Float64Gauge
name string
opts []metric.Float64GaugeOption
delegate atomic.Value // metric.Float64Gauge
}
var _ metric.Float64Gauge = (*sfGauge)(nil)
func (i *sfGauge) setDelegate(m metric.Meter) {
ctr, err := m.Float64Gauge(i.name, i.opts...)
if err != nil {
GetErrorHandler().Handle(err)
return
}
i.delegate.Store(ctr)
}
func (i *sfGauge) Record(ctx context.Context, x float64, opts ...metric.RecordOption) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(metric.Float64Gauge).Record(ctx, x, opts...)
}
}
type siCounter struct { type siCounter struct {
embedded.Int64Counter embedded.Int64Counter
@ -358,3 +384,29 @@ func (i *siHistogram) Record(ctx context.Context, x int64, opts ...metric.Record
ctr.(metric.Int64Histogram).Record(ctx, x, opts...) ctr.(metric.Int64Histogram).Record(ctx, x, opts...)
} }
} }
type siGauge struct {
embedded.Int64Gauge
name string
opts []metric.Int64GaugeOption
delegate atomic.Value // metric.Int64Gauge
}
var _ metric.Int64Gauge = (*siGauge)(nil)
func (i *siGauge) setDelegate(m metric.Meter) {
ctr, err := m.Int64Gauge(i.name, i.opts...)
if err != nil {
GetErrorHandler().Handle(err)
return
}
i.delegate.Store(ctr)
}
func (i *siGauge) Record(ctx context.Context, x int64, opts ...metric.RecordOption) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(metric.Int64Gauge).Record(ctx, x, opts...)
}
}

View File

@ -65,6 +65,7 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me
key := il{ key := il{
name: name, name: name,
version: c.InstrumentationVersion(), version: c.InstrumentationVersion(),
schema: c.SchemaURL(),
} }
if p.meters == nil { if p.meters == nil {
@ -164,6 +165,17 @@ func (m *meter) Int64Histogram(name string, options ...metric.Int64HistogramOpti
return i, nil return i, nil
} }
func (m *meter) Int64Gauge(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
if del, ok := m.delegate.Load().(metric.Meter); ok {
return del.Int64Gauge(name, options...)
}
m.mtx.Lock()
defer m.mtx.Unlock()
i := &siGauge{name: name, opts: options}
m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) { func (m *meter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) {
if del, ok := m.delegate.Load().(metric.Meter); ok { if del, ok := m.delegate.Load().(metric.Meter); ok {
return del.Int64ObservableCounter(name, options...) return del.Int64ObservableCounter(name, options...)
@ -230,6 +242,17 @@ func (m *meter) Float64Histogram(name string, options ...metric.Float64Histogram
return i, nil return i, nil
} }
func (m *meter) Float64Gauge(name string, options ...metric.Float64GaugeOption) (metric.Float64Gauge, error) {
if del, ok := m.delegate.Load().(metric.Meter); ok {
return del.Float64Gauge(name, options...)
}
m.mtx.Lock()
defer m.mtx.Unlock()
i := &sfGauge{name: name, opts: options}
m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) { func (m *meter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) {
if del, ok := m.delegate.Load().(metric.Meter); ok { if del, ok := m.delegate.Load().(metric.Meter); ok {
return del.Float64ObservableCounter(name, options...) return del.Float64ObservableCounter(name, options...)

View File

@ -86,6 +86,7 @@ func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T
key := il{ key := il{
name: name, name: name,
version: c.InstrumentationVersion(), version: c.InstrumentationVersion(),
schema: c.SchemaURL(),
} }
if p.tracers == nil { if p.tracers == nil {
@ -101,10 +102,7 @@ func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T
return t return t
} }
type il struct { type il struct{ name, version, schema string }
name string
version string
}
// tracer is a placeholder for a trace.Tracer. // tracer is a placeholder for a trace.Tracer.
// //

View File

@ -39,7 +39,7 @@ type Float64ObservableCounter interface {
} }
// Float64ObservableCounterConfig contains options for asynchronous counter // Float64ObservableCounterConfig contains options for asynchronous counter
// instruments that record int64 values. // instruments that record float64 values.
type Float64ObservableCounterConfig struct { type Float64ObservableCounterConfig struct {
description string description string
unit string unit string
@ -97,7 +97,7 @@ type Float64ObservableUpDownCounter interface {
} }
// Float64ObservableUpDownCounterConfig contains options for asynchronous // Float64ObservableUpDownCounterConfig contains options for asynchronous
// counter instruments that record int64 values. // counter instruments that record float64 values.
type Float64ObservableUpDownCounterConfig struct { type Float64ObservableUpDownCounterConfig struct {
description string description string
unit string unit string
@ -154,7 +154,7 @@ type Float64ObservableGauge interface {
} }
// Float64ObservableGaugeConfig contains options for asynchronous counter // Float64ObservableGaugeConfig contains options for asynchronous counter
// instruments that record int64 values. // instruments that record float64 values.
type Float64ObservableGaugeConfig struct { type Float64ObservableGaugeConfig struct {
description string description string
unit string unit string

View File

@ -57,6 +57,23 @@ asynchronous measurement, a Gauge ([Int64ObservableGauge] and
See the [OpenTelemetry documentation] for more information about instruments See the [OpenTelemetry documentation] for more information about instruments
and their intended use. and their intended use.
# Instrument Name
OpenTelemetry defines an [instrument name syntax] that restricts what
instrument names are allowed.
Instrument names should ...
- Not be empty.
- Have an alphabetic character as their first letter.
- Have any letter after the first be an alphanumeric character, _, .,
-, or /.
- Have a maximum length of 255 letters.
To ensure compatibility with observability platforms, all instruments created
need to conform to this syntax. Not all implementations of the API will validate
these names, it is the callers responsibility to ensure compliance.
# Measurements # Measurements
Measurements are made by recording values and information about the values with Measurements are made by recording values and information about the values with
@ -153,6 +170,7 @@ It is strongly recommended that authors only embed
That implementation is the only one OpenTelemetry authors can guarantee will That implementation is the only one OpenTelemetry authors can guarantee will
fully implement all the API interfaces when a user updates their API. fully implement all the API interfaces when a user updates their API.
[instrument name syntax]: https://opentelemetry.io/docs/specs/otel/metrics/api/#instrument-name-syntax
[OpenTelemetry documentation]: https://opentelemetry.io/docs/concepts/signals/metrics/ [OpenTelemetry documentation]: https://opentelemetry.io/docs/concepts/signals/metrics/
[GetMeterProvider]: https://pkg.go.dev/go.opentelemetry.io/otel#GetMeterProvider [GetMeterProvider]: https://pkg.go.dev/go.opentelemetry.io/otel#GetMeterProvider
*/ */

View File

@ -102,6 +102,16 @@ type Float64Counter interface{ float64Counter() }
// the API package). // the API package).
type Float64Histogram interface{ float64Histogram() } type Float64Histogram interface{ float64Histogram() }
// Float64Gauge is embedded in [go.opentelemetry.io/otel/metric.Float64Gauge].
//
// Embed this interface in your implementation of the
// [go.opentelemetry.io/otel/metric.Float64Gauge] if you want users to
// experience a compilation error, signaling they need to update to your latest
// implementation, when the [go.opentelemetry.io/otel/metric.Float64Gauge]
// interface is extended (which is something that can happen without a major
// version bump of the API package).
type Float64Gauge interface{ float64Gauge() }
// Float64ObservableCounter is embedded in // Float64ObservableCounter is embedded in
// [go.opentelemetry.io/otel/metric.Float64ObservableCounter]. // [go.opentelemetry.io/otel/metric.Float64ObservableCounter].
// //
@ -174,6 +184,16 @@ type Int64Counter interface{ int64Counter() }
// the API package). // the API package).
type Int64Histogram interface{ int64Histogram() } type Int64Histogram interface{ int64Histogram() }
// Int64Gauge is embedded in [go.opentelemetry.io/otel/metric.Int64Gauge].
//
// Embed this interface in your implementation of the
// [go.opentelemetry.io/otel/metric.Int64Gauge] if you want users to experience
// a compilation error, signaling they need to update to your latest
// implementation, when the [go.opentelemetry.io/otel/metric.Int64Gauge]
// interface is extended (which is something that can happen without a major
// version bump of the API package).
type Int64Gauge interface{ int64Gauge() }
// Int64ObservableCounter is embedded in // Int64ObservableCounter is embedded in
// [go.opentelemetry.io/otel/metric.Int64ObservableCounter]. // [go.opentelemetry.io/otel/metric.Int64ObservableCounter].
// //

View File

@ -16,6 +16,7 @@ type InstrumentOption interface {
Int64CounterOption Int64CounterOption
Int64UpDownCounterOption Int64UpDownCounterOption
Int64HistogramOption Int64HistogramOption
Int64GaugeOption
Int64ObservableCounterOption Int64ObservableCounterOption
Int64ObservableUpDownCounterOption Int64ObservableUpDownCounterOption
Int64ObservableGaugeOption Int64ObservableGaugeOption
@ -23,6 +24,7 @@ type InstrumentOption interface {
Float64CounterOption Float64CounterOption
Float64UpDownCounterOption Float64UpDownCounterOption
Float64HistogramOption Float64HistogramOption
Float64GaugeOption
Float64ObservableCounterOption Float64ObservableCounterOption
Float64ObservableUpDownCounterOption Float64ObservableUpDownCounterOption
Float64ObservableGaugeOption Float64ObservableGaugeOption
@ -51,6 +53,11 @@ func (o descOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64Histogra
return c return c
} }
func (o descOpt) applyFloat64Gauge(c Float64GaugeConfig) Float64GaugeConfig {
c.description = string(o)
return c
}
func (o descOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig { func (o descOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
c.description = string(o) c.description = string(o)
return c return c
@ -81,6 +88,11 @@ func (o descOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfi
return c return c
} }
func (o descOpt) applyInt64Gauge(c Int64GaugeConfig) Int64GaugeConfig {
c.description = string(o)
return c
}
func (o descOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig { func (o descOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
c.description = string(o) c.description = string(o)
return c return c
@ -116,6 +128,11 @@ func (o unitOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64Histogra
return c return c
} }
func (o unitOpt) applyFloat64Gauge(c Float64GaugeConfig) Float64GaugeConfig {
c.unit = string(o)
return c
}
func (o unitOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig { func (o unitOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
c.unit = string(o) c.unit = string(o)
return c return c
@ -146,6 +163,11 @@ func (o unitOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfi
return c return c
} }
func (o unitOpt) applyInt64Gauge(c Int64GaugeConfig) Int64GaugeConfig {
c.unit = string(o)
return c
}
func (o unitOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig { func (o unitOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
c.unit = string(o) c.unit = string(o)
return c return c

View File

@ -47,17 +47,37 @@ type Meter interface {
// Int64Counter returns a new Int64Counter instrument identified by name // Int64Counter returns a new Int64Counter instrument identified by name
// and configured with options. The instrument is used to synchronously // and configured with options. The instrument is used to synchronously
// record increasing int64 measurements during a computational operation. // record increasing int64 measurements during a computational operation.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Int64Counter(name string, options ...Int64CounterOption) (Int64Counter, error) Int64Counter(name string, options ...Int64CounterOption) (Int64Counter, error)
// Int64UpDownCounter returns a new Int64UpDownCounter instrument // Int64UpDownCounter returns a new Int64UpDownCounter instrument
// identified by name and configured with options. The instrument is used // identified by name and configured with options. The instrument is used
// to synchronously record int64 measurements during a computational // to synchronously record int64 measurements during a computational
// operation. // operation.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Int64UpDownCounter(name string, options ...Int64UpDownCounterOption) (Int64UpDownCounter, error) Int64UpDownCounter(name string, options ...Int64UpDownCounterOption) (Int64UpDownCounter, error)
// Int64Histogram returns a new Int64Histogram instrument identified by // Int64Histogram returns a new Int64Histogram instrument identified by
// name and configured with options. The instrument is used to // name and configured with options. The instrument is used to
// synchronously record the distribution of int64 measurements during a // synchronously record the distribution of int64 measurements during a
// computational operation. // computational operation.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Int64Histogram(name string, options ...Int64HistogramOption) (Int64Histogram, error) Int64Histogram(name string, options ...Int64HistogramOption) (Int64Histogram, error)
// Int64Gauge returns a new Int64Gauge instrument identified by name and
// configured with options. The instrument is used to synchronously record
// instantaneous int64 measurements during a computational operation.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Int64Gauge(name string, options ...Int64GaugeOption) (Int64Gauge, error)
// Int64ObservableCounter returns a new Int64ObservableCounter identified // Int64ObservableCounter returns a new Int64ObservableCounter identified
// by name and configured with options. The instrument is used to // by name and configured with options. The instrument is used to
// asynchronously record increasing int64 measurements once per a // asynchronously record increasing int64 measurements once per a
@ -67,6 +87,10 @@ type Meter interface {
// the WithInt64Callback option to register the callback here, or use the // the WithInt64Callback option to register the callback here, or use the
// RegisterCallback method of this Meter to register one later. See the // RegisterCallback method of this Meter to register one later. See the
// Measurements section of the package documentation for more information. // Measurements section of the package documentation for more information.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Int64ObservableCounter(name string, options ...Int64ObservableCounterOption) (Int64ObservableCounter, error) Int64ObservableCounter(name string, options ...Int64ObservableCounterOption) (Int64ObservableCounter, error)
// Int64ObservableUpDownCounter returns a new Int64ObservableUpDownCounter // Int64ObservableUpDownCounter returns a new Int64ObservableUpDownCounter
// instrument identified by name and configured with options. The // instrument identified by name and configured with options. The
@ -77,6 +101,10 @@ type Meter interface {
// the WithInt64Callback option to register the callback here, or use the // the WithInt64Callback option to register the callback here, or use the
// RegisterCallback method of this Meter to register one later. See the // RegisterCallback method of this Meter to register one later. See the
// Measurements section of the package documentation for more information. // Measurements section of the package documentation for more information.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Int64ObservableUpDownCounter(name string, options ...Int64ObservableUpDownCounterOption) (Int64ObservableUpDownCounter, error) Int64ObservableUpDownCounter(name string, options ...Int64ObservableUpDownCounterOption) (Int64ObservableUpDownCounter, error)
// Int64ObservableGauge returns a new Int64ObservableGauge instrument // Int64ObservableGauge returns a new Int64ObservableGauge instrument
// identified by name and configured with options. The instrument is used // identified by name and configured with options. The instrument is used
@ -87,23 +115,47 @@ type Meter interface {
// the WithInt64Callback option to register the callback here, or use the // the WithInt64Callback option to register the callback here, or use the
// RegisterCallback method of this Meter to register one later. See the // RegisterCallback method of this Meter to register one later. See the
// Measurements section of the package documentation for more information. // Measurements section of the package documentation for more information.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Int64ObservableGauge(name string, options ...Int64ObservableGaugeOption) (Int64ObservableGauge, error) Int64ObservableGauge(name string, options ...Int64ObservableGaugeOption) (Int64ObservableGauge, error)
// Float64Counter returns a new Float64Counter instrument identified by // Float64Counter returns a new Float64Counter instrument identified by
// name and configured with options. The instrument is used to // name and configured with options. The instrument is used to
// synchronously record increasing float64 measurements during a // synchronously record increasing float64 measurements during a
// computational operation. // computational operation.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Float64Counter(name string, options ...Float64CounterOption) (Float64Counter, error) Float64Counter(name string, options ...Float64CounterOption) (Float64Counter, error)
// Float64UpDownCounter returns a new Float64UpDownCounter instrument // Float64UpDownCounter returns a new Float64UpDownCounter instrument
// identified by name and configured with options. The instrument is used // identified by name and configured with options. The instrument is used
// to synchronously record float64 measurements during a computational // to synchronously record float64 measurements during a computational
// operation. // operation.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Float64UpDownCounter(name string, options ...Float64UpDownCounterOption) (Float64UpDownCounter, error) Float64UpDownCounter(name string, options ...Float64UpDownCounterOption) (Float64UpDownCounter, error)
// Float64Histogram returns a new Float64Histogram instrument identified by // Float64Histogram returns a new Float64Histogram instrument identified by
// name and configured with options. The instrument is used to // name and configured with options. The instrument is used to
// synchronously record the distribution of float64 measurements during a // synchronously record the distribution of float64 measurements during a
// computational operation. // computational operation.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Float64Histogram(name string, options ...Float64HistogramOption) (Float64Histogram, error) Float64Histogram(name string, options ...Float64HistogramOption) (Float64Histogram, error)
// Float64Gauge returns a new Float64Gauge instrument identified by name and
// configured with options. The instrument is used to synchronously record
// instantaneous float64 measurements during a computational operation.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Float64Gauge(name string, options ...Float64GaugeOption) (Float64Gauge, error)
// Float64ObservableCounter returns a new Float64ObservableCounter // Float64ObservableCounter returns a new Float64ObservableCounter
// instrument identified by name and configured with options. The // instrument identified by name and configured with options. The
// instrument is used to asynchronously record increasing float64 // instrument is used to asynchronously record increasing float64
@ -113,6 +165,10 @@ type Meter interface {
// the WithFloat64Callback option to register the callback here, or use the // the WithFloat64Callback option to register the callback here, or use the
// RegisterCallback method of this Meter to register one later. See the // RegisterCallback method of this Meter to register one later. See the
// Measurements section of the package documentation for more information. // Measurements section of the package documentation for more information.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Float64ObservableCounter(name string, options ...Float64ObservableCounterOption) (Float64ObservableCounter, error) Float64ObservableCounter(name string, options ...Float64ObservableCounterOption) (Float64ObservableCounter, error)
// Float64ObservableUpDownCounter returns a new // Float64ObservableUpDownCounter returns a new
// Float64ObservableUpDownCounter instrument identified by name and // Float64ObservableUpDownCounter instrument identified by name and
@ -123,6 +179,10 @@ type Meter interface {
// the WithFloat64Callback option to register the callback here, or use the // the WithFloat64Callback option to register the callback here, or use the
// RegisterCallback method of this Meter to register one later. See the // RegisterCallback method of this Meter to register one later. See the
// Measurements section of the package documentation for more information. // Measurements section of the package documentation for more information.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Float64ObservableUpDownCounter(name string, options ...Float64ObservableUpDownCounterOption) (Float64ObservableUpDownCounter, error) Float64ObservableUpDownCounter(name string, options ...Float64ObservableUpDownCounterOption) (Float64ObservableUpDownCounter, error)
// Float64ObservableGauge returns a new Float64ObservableGauge instrument // Float64ObservableGauge returns a new Float64ObservableGauge instrument
// identified by name and configured with options. The instrument is used // identified by name and configured with options. The instrument is used
@ -133,6 +193,10 @@ type Meter interface {
// the WithFloat64Callback option to register the callback here, or use the // the WithFloat64Callback option to register the callback here, or use the
// RegisterCallback method of this Meter to register one later. See the // RegisterCallback method of this Meter to register one later. See the
// Measurements section of the package documentation for more information. // Measurements section of the package documentation for more information.
//
// The name needs to conform to the OpenTelemetry instrument name syntax.
// See the Instrument Name section of the package documentation for more
// information.
Float64ObservableGauge(name string, options ...Float64ObservableGaugeOption) (Float64ObservableGauge, error) Float64ObservableGauge(name string, options ...Float64ObservableGaugeOption) (Float64ObservableGauge, error)
// RegisterCallback registers f to be called during the collection of a // RegisterCallback registers f to be called during the collection of a

View File

@ -32,6 +32,8 @@ var (
_ metric.Float64UpDownCounter = Float64UpDownCounter{} _ metric.Float64UpDownCounter = Float64UpDownCounter{}
_ metric.Int64Histogram = Int64Histogram{} _ metric.Int64Histogram = Int64Histogram{}
_ metric.Float64Histogram = Float64Histogram{} _ metric.Float64Histogram = Float64Histogram{}
_ metric.Int64Gauge = Int64Gauge{}
_ metric.Float64Gauge = Float64Gauge{}
_ metric.Int64ObservableCounter = Int64ObservableCounter{} _ metric.Int64ObservableCounter = Int64ObservableCounter{}
_ metric.Float64ObservableCounter = Float64ObservableCounter{} _ metric.Float64ObservableCounter = Float64ObservableCounter{}
_ metric.Int64ObservableGauge = Int64ObservableGauge{} _ metric.Int64ObservableGauge = Int64ObservableGauge{}
@ -76,6 +78,12 @@ func (Meter) Int64Histogram(string, ...metric.Int64HistogramOption) (metric.Int6
return Int64Histogram{}, nil return Int64Histogram{}, nil
} }
// Int64Gauge returns a Gauge used to record int64 measurements that
// produces no telemetry.
func (Meter) Int64Gauge(string, ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
return Int64Gauge{}, nil
}
// Int64ObservableCounter returns an ObservableCounter used to record int64 // Int64ObservableCounter returns an ObservableCounter used to record int64
// measurements that produces no telemetry. // measurements that produces no telemetry.
func (Meter) Int64ObservableCounter(string, ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) { func (Meter) Int64ObservableCounter(string, ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) {
@ -112,6 +120,12 @@ func (Meter) Float64Histogram(string, ...metric.Float64HistogramOption) (metric.
return Float64Histogram{}, nil return Float64Histogram{}, nil
} }
// Float64Gauge returns a Gauge used to record float64 measurements that
// produces no telemetry.
func (Meter) Float64Gauge(string, ...metric.Float64GaugeOption) (metric.Float64Gauge, error) {
return Float64Gauge{}, nil
}
// Float64ObservableCounter returns an ObservableCounter used to record int64 // Float64ObservableCounter returns an ObservableCounter used to record int64
// measurements that produces no telemetry. // measurements that produces no telemetry.
func (Meter) Float64ObservableCounter(string, ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) { func (Meter) Float64ObservableCounter(string, ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) {
@ -197,6 +211,20 @@ type Float64Histogram struct{ embedded.Float64Histogram }
// Record performs no operation. // Record performs no operation.
func (Float64Histogram) Record(context.Context, float64, ...metric.RecordOption) {} func (Float64Histogram) Record(context.Context, float64, ...metric.RecordOption) {}
// Int64Gauge is an OpenTelemetry Gauge used to record instantaneous int64
// measurements. It produces no telemetry.
type Int64Gauge struct{ embedded.Int64Gauge }
// Record performs no operation.
func (Int64Gauge) Record(context.Context, int64, ...metric.RecordOption) {}
// Float64Gauge is an OpenTelemetry Gauge used to record instantaneous float64
// measurements. It produces no telemetry.
type Float64Gauge struct{ embedded.Float64Gauge }
// Record performs no operation.
func (Float64Gauge) Record(context.Context, float64, ...metric.RecordOption) {}
// Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record // Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record
// int64 measurements. It produces no telemetry. // int64 measurements. It produces no telemetry.
type Int64ObservableCounter struct { type Int64ObservableCounter struct {

View File

@ -28,7 +28,7 @@ type Float64Counter interface {
} }
// Float64CounterConfig contains options for synchronous counter instruments that // Float64CounterConfig contains options for synchronous counter instruments that
// record int64 values. // record float64 values.
type Float64CounterConfig struct { type Float64CounterConfig struct {
description string description string
unit string unit string
@ -81,7 +81,7 @@ type Float64UpDownCounter interface {
} }
// Float64UpDownCounterConfig contains options for synchronous counter // Float64UpDownCounterConfig contains options for synchronous counter
// instruments that record int64 values. // instruments that record float64 values.
type Float64UpDownCounterConfig struct { type Float64UpDownCounterConfig struct {
description string description string
unit string unit string
@ -133,8 +133,8 @@ type Float64Histogram interface {
Record(ctx context.Context, incr float64, options ...RecordOption) Record(ctx context.Context, incr float64, options ...RecordOption)
} }
// Float64HistogramConfig contains options for synchronous counter instruments // Float64HistogramConfig contains options for synchronous histogram
// that record int64 values. // instruments that record float64 values.
type Float64HistogramConfig struct { type Float64HistogramConfig struct {
description string description string
unit string unit string
@ -172,3 +172,55 @@ func (c Float64HistogramConfig) ExplicitBucketBoundaries() []float64 {
type Float64HistogramOption interface { type Float64HistogramOption interface {
applyFloat64Histogram(Float64HistogramConfig) Float64HistogramConfig applyFloat64Histogram(Float64HistogramConfig) Float64HistogramConfig
} }
// Float64Gauge is an instrument that records instantaneous float64 values.
//
// Warning: Methods may be added to this interface in minor releases. See
// package documentation on API implementation for information on how to set
// default behavior for unimplemented methods.
type Float64Gauge interface {
// Users of the interface can ignore this. This embedded type is only used
// by implementations of this interface. See the "API Implementations"
// section of the package documentation for more information.
embedded.Float64Gauge
// Record records the instantaneous value.
//
// Use the WithAttributeSet (or, if performance is not a concern,
// the WithAttributes) option to include measurement attributes.
Record(ctx context.Context, value float64, options ...RecordOption)
}
// Float64GaugeConfig contains options for synchronous gauge instruments that
// record float64 values.
type Float64GaugeConfig struct {
description string
unit string
}
// NewFloat64GaugeConfig returns a new [Float64GaugeConfig] with all opts
// applied.
func NewFloat64GaugeConfig(opts ...Float64GaugeOption) Float64GaugeConfig {
var config Float64GaugeConfig
for _, o := range opts {
config = o.applyFloat64Gauge(config)
}
return config
}
// Description returns the configured description.
func (c Float64GaugeConfig) Description() string {
return c.description
}
// Unit returns the configured unit.
func (c Float64GaugeConfig) Unit() string {
return c.unit
}
// Float64GaugeOption applies options to a [Float64GaugeConfig]. See
// [InstrumentOption] for other options that can be used as a
// Float64GaugeOption.
type Float64GaugeOption interface {
applyFloat64Gauge(Float64GaugeConfig) Float64GaugeConfig
}

View File

@ -133,7 +133,7 @@ type Int64Histogram interface {
Record(ctx context.Context, incr int64, options ...RecordOption) Record(ctx context.Context, incr int64, options ...RecordOption)
} }
// Int64HistogramConfig contains options for synchronous counter instruments // Int64HistogramConfig contains options for synchronous histogram instruments
// that record int64 values. // that record int64 values.
type Int64HistogramConfig struct { type Int64HistogramConfig struct {
description string description string
@ -172,3 +172,55 @@ func (c Int64HistogramConfig) ExplicitBucketBoundaries() []float64 {
type Int64HistogramOption interface { type Int64HistogramOption interface {
applyInt64Histogram(Int64HistogramConfig) Int64HistogramConfig applyInt64Histogram(Int64HistogramConfig) Int64HistogramConfig
} }
// Int64Gauge is an instrument that records instantaneous int64 values.
//
// Warning: Methods may be added to this interface in minor releases. See
// package documentation on API implementation for information on how to set
// default behavior for unimplemented methods.
type Int64Gauge interface {
// Users of the interface can ignore this. This embedded type is only used
// by implementations of this interface. See the "API Implementations"
// section of the package documentation for more information.
embedded.Int64Gauge
// Record records the instantaneous value.
//
// Use the WithAttributeSet (or, if performance is not a concern,
// the WithAttributes) option to include measurement attributes.
Record(ctx context.Context, value int64, options ...RecordOption)
}
// Int64GaugeConfig contains options for synchronous gauge instruments that
// record int64 values.
type Int64GaugeConfig struct {
description string
unit string
}
// NewInt64GaugeConfig returns a new [Int64GaugeConfig] with all opts
// applied.
func NewInt64GaugeConfig(opts ...Int64GaugeOption) Int64GaugeConfig {
var config Int64GaugeConfig
for _, o := range opts {
config = o.applyInt64Gauge(config)
}
return config
}
// Description returns the configured description.
func (c Int64GaugeConfig) Description() string {
return c.description
}
// Unit returns the configured unit.
func (c Int64GaugeConfig) Unit() string {
return c.unit
}
// Int64GaugeOption applies options to a [Int64GaugeConfig]. See
// [InstrumentOption] for other options that can be used as a
// Int64GaugeOption.
type Int64GaugeOption interface {
applyInt64Gauge(Int64GaugeConfig) Int64GaugeConfig
}

24
vendor/go.opentelemetry.io/otel/renovate.json generated vendored Normal file
View File

@ -0,0 +1,24 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"ignorePaths": [],
"labels": ["Skip Changelog", "dependencies"],
"postUpdateOptions" : [
"gomodTidy"
],
"packageRules": [
{
"matchManagers": ["gomod"],
"matchDepTypes": ["indirect"],
"enabled": true
},
{
"matchFileNames": ["internal/tools/**"],
"matchManagers": ["gomod"],
"matchDepTypes": ["indirect"],
"enabled": false
}
]
}

View File

@ -1 +1 @@
codespell==2.2.6 codespell==2.3.0

View File

@ -22,7 +22,7 @@ const (
BatchSpanProcessorMaxQueueSizeKey = "OTEL_BSP_MAX_QUEUE_SIZE" BatchSpanProcessorMaxQueueSizeKey = "OTEL_BSP_MAX_QUEUE_SIZE"
// BatchSpanProcessorMaxExportBatchSizeKey is the maximum batch size (i.e. // BatchSpanProcessorMaxExportBatchSizeKey is the maximum batch size (i.e.
// 512). Note: it must be less than or equal to // 512). Note: it must be less than or equal to
// EnvBatchSpanProcessorMaxQueueSize. // BatchSpanProcessorMaxQueueSize.
BatchSpanProcessorMaxExportBatchSizeKey = "OTEL_BSP_MAX_EXPORT_BATCH_SIZE" BatchSpanProcessorMaxExportBatchSizeKey = "OTEL_BSP_MAX_EXPORT_BATCH_SIZE"
// AttributeValueLengthKey is the maximum allowed attribute value size. // AttributeValueLengthKey is the maximum allowed attribute value size.

View File

@ -1,18 +0,0 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/otel/sdk/internal"
//go:generate gotmpl --body=../../internal/shared/matchers/expectation.go.tmpl "--data={}" --out=matchers/expectation.go
//go:generate gotmpl --body=../../internal/shared/matchers/expecter.go.tmpl "--data={}" --out=matchers/expecter.go
//go:generate gotmpl --body=../../internal/shared/matchers/temporal_matcher.go.tmpl "--data={}" --out=matchers/temporal_matcher.go
//go:generate gotmpl --body=../../internal/shared/internaltest/alignment.go.tmpl "--data={}" --out=internaltest/alignment.go
//go:generate gotmpl --body=../../internal/shared/internaltest/env.go.tmpl "--data={}" --out=internaltest/env.go
//go:generate gotmpl --body=../../internal/shared/internaltest/env_test.go.tmpl "--data={}" --out=internaltest/env_test.go
//go:generate gotmpl --body=../../internal/shared/internaltest/errors.go.tmpl "--data={}" --out=internaltest/errors.go
//go:generate gotmpl --body=../../internal/shared/internaltest/harness.go.tmpl "--data={\"matchersImportPath\": \"go.opentelemetry.io/otel/sdk/internal/matchers\"}" --out=internaltest/harness.go
//go:generate gotmpl --body=../../internal/shared/internaltest/text_map_carrier.go.tmpl "--data={}" --out=internaltest/text_map_carrier.go
//go:generate gotmpl --body=../../internal/shared/internaltest/text_map_carrier_test.go.tmpl "--data={}" --out=internaltest/text_map_carrier_test.go
//go:generate gotmpl --body=../../internal/shared/internaltest/text_map_propagator.go.tmpl "--data={}" --out=internaltest/text_map_propagator.go
//go:generate gotmpl --body=../../internal/shared/internaltest/text_map_propagator_test.go.tmpl "--data={}" --out=internaltest/text_map_propagator_test.go

View File

@ -1,17 +0,0 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/otel/sdk/internal"
import "time"
// MonotonicEndTime returns the end time at present
// but offset from start, monotonically.
//
// The monotonic clock is used in subtractions hence
// the duration since start added back to start gives
// end as a monotonic time.
// See https://golang.org/pkg/time/#hdr-Monotonic_Clocks
func MonotonicEndTime(start time.Time) time.Time {
return start.Add(time.Since(start))
}

View File

@ -0,0 +1,46 @@
# Experimental Features
The SDK contains features that have not yet stabilized in the OpenTelemetry specification.
These features are added to the OpenTelemetry Go SDK prior to stabilization in the specification so that users can start experimenting with them and provide feedback.
These feature may change in backwards incompatible ways as feedback is applied.
See the [Compatibility and Stability](#compatibility-and-stability) section for more information.
## Features
- [Resource](#resource)
### Resource
[OpenTelemetry resource semantic conventions] include many attribute definitions that are defined as experimental.
To have experimental semantic conventions be added by [resource detectors] set the `OTEL_GO_X_RESOURCE` environment variable.
The value set must be the case-insensitive string of `"true"` to enable the feature.
All other values are ignored.
<!-- TODO: document what attributes are added by which detector -->
[OpenTelemetry resource semantic conventions]: https://opentelemetry.io/docs/specs/semconv/resource/
[resource detectors]: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/resource#Detector
#### Examples
Enable experimental resource semantic conventions.
```console
export OTEL_GO_X_RESOURCE=true
```
Disable experimental resource semantic conventions.
```console
unset OTEL_GO_X_RESOURCE
```
## Compatibility and Stability
Experimental features do not fall within the scope of the OpenTelemetry Go versioning and stability [policy](../../../VERSIONING.md).
These features may be removed or modified in successive version releases, including patch versions.
When an experimental feature is promoted to a stable feature, a migration path will be included in the changelog entry of the release.
There is no guarantee that any environment variable feature flags that enabled the experimental feature will be supported by the stable version.
If they are supported, they may be accompanied with a deprecation notice stating a timeline for the removal of that support.

66
vendor/go.opentelemetry.io/otel/sdk/internal/x/x.go generated vendored Normal file
View File

@ -0,0 +1,66 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package x contains support for OTel SDK experimental features.
//
// This package should only be used for features defined in the specification.
// It should not be used for experiments or new project ideas.
package x // import "go.opentelemetry.io/otel/sdk/internal/x"
import (
"os"
"strings"
)
// Resource is an experimental feature flag that defines if resource detectors
// should be included experimental semantic conventions.
//
// To enable this feature set the OTEL_GO_X_RESOURCE environment variable
// to the case-insensitive string value of "true" (i.e. "True" and "TRUE"
// will also enable this).
var Resource = newFeature("RESOURCE", func(v string) (string, bool) {
if strings.ToLower(v) == "true" {
return v, true
}
return "", false
})
// Feature is an experimental feature control flag. It provides a uniform way
// to interact with these feature flags and parse their values.
type Feature[T any] struct {
key string
parse func(v string) (T, bool)
}
func newFeature[T any](suffix string, parse func(string) (T, bool)) Feature[T] {
const envKeyRoot = "OTEL_GO_X_"
return Feature[T]{
key: envKeyRoot + suffix,
parse: parse,
}
}
// Key returns the environment variable key that needs to be set to enable the
// feature.
func (f Feature[T]) Key() string { return f.key }
// Lookup returns the user configured value for the feature and true if the
// user has enabled the feature. Otherwise, if the feature is not enabled, a
// zero-value and false are returned.
func (f Feature[T]) Lookup() (v T, ok bool) {
// https://github.com/open-telemetry/opentelemetry-specification/blob/62effed618589a0bec416a87e559c0a9d96289bb/specification/configuration/sdk-environment-variables.md#parsing-empty-value
//
// > The SDK MUST interpret an empty value of an environment variable the
// > same way as when the variable is unset.
vRaw := os.Getenv(f.key)
if vRaw == "" {
return v, ok
}
return f.parse(vRaw)
}
// Enabled returns if the feature is enabled.
func (f Feature[T]) Enabled() bool {
_, ok := f.Lookup()
return ok
}

View File

@ -9,9 +9,11 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/google/uuid"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk" "go.opentelemetry.io/otel/sdk"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0" semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
) )
type ( type (
@ -36,6 +38,8 @@ type (
} }
defaultServiceNameDetector struct{} defaultServiceNameDetector struct{}
defaultServiceInstanceIDDetector struct{}
) )
var ( var (
@ -43,6 +47,7 @@ var (
_ Detector = host{} _ Detector = host{}
_ Detector = stringDetector{} _ Detector = stringDetector{}
_ Detector = defaultServiceNameDetector{} _ Detector = defaultServiceNameDetector{}
_ Detector = defaultServiceInstanceIDDetector{}
) )
// Detect returns a *Resource that describes the OpenTelemetry SDK used. // Detect returns a *Resource that describes the OpenTelemetry SDK used.
@ -95,3 +100,19 @@ func (defaultServiceNameDetector) Detect(ctx context.Context) (*Resource, error)
}, },
).Detect(ctx) ).Detect(ctx)
} }
// Detect implements Detector.
func (defaultServiceInstanceIDDetector) Detect(ctx context.Context) (*Resource, error) {
return StringDetector(
semconv.SchemaURL,
semconv.ServiceInstanceIDKey,
func() (string, error) {
version4Uuid, err := uuid.NewRandom()
if err != nil {
return "", err
}
return version4Uuid.String(), nil
},
).Detect(ctx)
}

View File

@ -11,7 +11,7 @@ import (
"os" "os"
"regexp" "regexp"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0" semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
) )
type containerIDProvider func() (string, error) type containerIDProvider func() (string, error)

View File

@ -12,7 +12,7 @@ import (
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0" semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
) )
const ( const (

View File

@ -8,7 +8,7 @@ import (
"errors" "errors"
"strings" "strings"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0" semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
) )
type hostIDProvider func() (string, error) type hostIDProvider func() (string, error)

View File

@ -8,7 +8,7 @@ import (
"strings" "strings"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0" semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
) )
type osDescriptionProvider func() (string, error) type osDescriptionProvider func() (string, error)

View File

@ -11,7 +11,7 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0" semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
) )
type ( type (

View File

@ -11,6 +11,7 @@ import (
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/internal/x"
) )
// Resource describes an entity about which identifying information // Resource describes an entity about which identifying information
@ -218,11 +219,17 @@ func Empty() *Resource {
func Default() *Resource { func Default() *Resource {
defaultResourceOnce.Do(func() { defaultResourceOnce.Do(func() {
var err error var err error
defaultResource, err = Detect( defaultDetectors := []Detector{
context.Background(),
defaultServiceNameDetector{}, defaultServiceNameDetector{},
fromEnv{}, fromEnv{},
telemetrySDK{}, telemetrySDK{},
}
if x.Resource.Enabled() {
defaultDetectors = append([]Detector{defaultServiceInstanceIDDetector{}}, defaultDetectors...)
}
defaultResource, err = Detect(
context.Background(),
defaultDetectors...,
) )
if err != nil { if err != nil {
otel.Handle(err) otel.Handle(err)

View File

@ -381,7 +381,7 @@ func (bsp *batchSpanProcessor) enqueueBlockOnQueueFull(ctx context.Context, sd R
} }
} }
func (bsp *batchSpanProcessor) enqueueDrop(ctx context.Context, sd ReadOnlySpan) bool { func (bsp *batchSpanProcessor) enqueueDrop(_ context.Context, sd ReadOnlySpan) bool {
if !sd.SpanContext().IsSampled() { if !sd.SpanContext().IsSampled() {
return false return false
} }

View File

@ -3,23 +3,43 @@
package trace // import "go.opentelemetry.io/otel/sdk/trace" package trace // import "go.opentelemetry.io/otel/sdk/trace"
import (
"slices"
"sync"
"go.opentelemetry.io/otel/internal/global"
)
// evictedQueue is a FIFO queue with a configurable capacity. // evictedQueue is a FIFO queue with a configurable capacity.
type evictedQueue struct { type evictedQueue[T any] struct {
queue []interface{} queue []T
capacity int capacity int
droppedCount int droppedCount int
logDropped func()
} }
func newEvictedQueue(capacity int) evictedQueue { func newEvictedQueueEvent(capacity int) evictedQueue[Event] {
// Do not pre-allocate queue, do this lazily. // Do not pre-allocate queue, do this lazily.
return evictedQueue{capacity: capacity} return evictedQueue[Event]{
capacity: capacity,
logDropped: sync.OnceFunc(func() { global.Warn("limit reached: dropping trace trace.Event") }),
}
}
func newEvictedQueueLink(capacity int) evictedQueue[Link] {
// Do not pre-allocate queue, do this lazily.
return evictedQueue[Link]{
capacity: capacity,
logDropped: sync.OnceFunc(func() { global.Warn("limit reached: dropping trace trace.Link") }),
}
} }
// add adds value to the evictedQueue eq. If eq is at capacity, the oldest // add adds value to the evictedQueue eq. If eq is at capacity, the oldest
// queued value will be discarded and the drop count incremented. // queued value will be discarded and the drop count incremented.
func (eq *evictedQueue) add(value interface{}) { func (eq *evictedQueue[T]) add(value T) {
if eq.capacity == 0 { if eq.capacity == 0 {
eq.droppedCount++ eq.droppedCount++
eq.logDropped()
return return
} }
@ -28,6 +48,12 @@ func (eq *evictedQueue) add(value interface{}) {
copy(eq.queue[:eq.capacity-1], eq.queue[1:]) copy(eq.queue[:eq.capacity-1], eq.queue[1:])
eq.queue = eq.queue[:eq.capacity-1] eq.queue = eq.queue[:eq.capacity-1]
eq.droppedCount++ eq.droppedCount++
eq.logDropped()
} }
eq.queue = append(eq.queue, value) eq.queue = append(eq.queue, value)
} }
// copy returns a copy of the evictedQueue.
func (eq *evictedQueue[T]) copy() []T {
return slices.Clone(eq.queue)
}

View File

@ -41,7 +41,12 @@ func (gen *randomIDGenerator) NewSpanID(ctx context.Context, traceID trace.Trace
gen.Lock() gen.Lock()
defer gen.Unlock() defer gen.Unlock()
sid := trace.SpanID{} sid := trace.SpanID{}
_, _ = gen.randSource.Read(sid[:]) for {
_, _ = gen.randSource.Read(sid[:])
if sid.IsValid() {
break
}
}
return sid return sid
} }
@ -51,9 +56,19 @@ func (gen *randomIDGenerator) NewIDs(ctx context.Context) (trace.TraceID, trace.
gen.Lock() gen.Lock()
defer gen.Unlock() defer gen.Unlock()
tid := trace.TraceID{} tid := trace.TraceID{}
_, _ = gen.randSource.Read(tid[:])
sid := trace.SpanID{} sid := trace.SpanID{}
_, _ = gen.randSource.Read(sid[:]) for {
_, _ = gen.randSource.Read(tid[:])
if tid.IsValid() {
break
}
}
for {
_, _ = gen.randSource.Read(sid[:])
if sid.IsValid() {
break
}
}
return tid, sid return tid, sid
} }

View File

@ -291,7 +291,7 @@ func (p *TracerProvider) Shutdown(ctx context.Context) error {
retErr = err retErr = err
} else { } else {
// Poor man's list of errors // Poor man's list of errors
retErr = fmt.Errorf("%v; %v", retErr, err) retErr = fmt.Errorf("%w; %w", retErr, err)
} }
} }
} }

View File

@ -17,10 +17,10 @@ import (
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/internal/global"
"go.opentelemetry.io/otel/sdk/instrumentation" "go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/internal"
"go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0" semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/embedded" "go.opentelemetry.io/otel/trace/embedded"
) )
@ -137,12 +137,13 @@ type recordingSpan struct {
// ReadOnlySpan exported when the span ends. // ReadOnlySpan exported when the span ends.
attributes []attribute.KeyValue attributes []attribute.KeyValue
droppedAttributes int droppedAttributes int
logDropAttrsOnce sync.Once
// events are stored in FIFO queue capped by configured limit. // events are stored in FIFO queue capped by configured limit.
events evictedQueue events evictedQueue[Event]
// links are stored in FIFO queue capped by configured limit. // links are stored in FIFO queue capped by configured limit.
links evictedQueue links evictedQueue[Link]
// executionTracerTaskEnd ends the execution tracer span. // executionTracerTaskEnd ends the execution tracer span.
executionTracerTaskEnd func() executionTracerTaskEnd func()
@ -219,7 +220,7 @@ func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) {
limit := s.tracer.provider.spanLimits.AttributeCountLimit limit := s.tracer.provider.spanLimits.AttributeCountLimit
if limit == 0 { if limit == 0 {
// No attributes allowed. // No attributes allowed.
s.droppedAttributes += len(attributes) s.addDroppedAttr(len(attributes))
return return
} }
@ -236,7 +237,7 @@ func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) {
for _, a := range attributes { for _, a := range attributes {
if !a.Valid() { if !a.Valid() {
// Drop all invalid attributes. // Drop all invalid attributes.
s.droppedAttributes++ s.addDroppedAttr(1)
continue continue
} }
a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a) a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a)
@ -244,6 +245,22 @@ func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) {
} }
} }
// Declared as a var so tests can override.
var logDropAttrs = func() {
global.Warn("limit reached: dropping trace Span attributes")
}
// addDroppedAttr adds incr to the count of dropped attributes.
//
// The first, and only the first, time this method is called a warning will be
// logged.
//
// This method assumes s.mu.Lock is held by the caller.
func (s *recordingSpan) addDroppedAttr(incr int) {
s.droppedAttributes += incr
s.logDropAttrsOnce.Do(logDropAttrs)
}
// addOverCapAttrs adds the attributes attrs to the span s while // addOverCapAttrs adds the attributes attrs to the span s while
// de-duplicating the attributes of s and attrs and dropping attributes that // de-duplicating the attributes of s and attrs and dropping attributes that
// exceed the limit. // exceed the limit.
@ -273,7 +290,7 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) {
for _, a := range attrs { for _, a := range attrs {
if !a.Valid() { if !a.Valid() {
// Drop all invalid attributes. // Drop all invalid attributes.
s.droppedAttributes++ s.addDroppedAttr(1)
continue continue
} }
@ -286,7 +303,7 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) {
if len(s.attributes) >= limit { if len(s.attributes) >= limit {
// Do not just drop all of the remaining attributes, make sure // Do not just drop all of the remaining attributes, make sure
// updates are checked and performed. // updates are checked and performed.
s.droppedAttributes++ s.addDroppedAttr(1)
} else { } else {
a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a) a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a)
s.attributes = append(s.attributes, a) s.attributes = append(s.attributes, a)
@ -367,7 +384,7 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {
// Store the end time as soon as possible to avoid artificially increasing // Store the end time as soon as possible to avoid artificially increasing
// the span's duration in case some operation below takes a while. // the span's duration in case some operation below takes a while.
et := internal.MonotonicEndTime(s.startTime) et := monotonicEndTime(s.startTime)
// Do relative expensive check now that we have an end time and see if we // Do relative expensive check now that we have an end time and see if we
// need to do any more processing. // need to do any more processing.
@ -418,6 +435,16 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {
} }
} }
// monotonicEndTime returns the end time at present but offset from start,
// monotonically.
//
// The monotonic clock is used in subtractions hence the duration since start
// added back to start gives end as a monotonic time. See
// https://golang.org/pkg/time/#hdr-Monotonic_Clocks
func monotonicEndTime(start time.Time) time.Time {
return start.Add(time.Since(start))
}
// RecordError will record err as a span event for this span. An additional call to // RecordError will record err as a span event for this span. An additional call to
// SetStatus is required if the Status of the Span should be set to Error, this method // SetStatus is required if the Status of the Span should be set to Error, this method
// does not change the Span status. If this span is not being recorded or err is nil // does not change the Span status. If this span is not being recorded or err is nil
@ -585,7 +612,7 @@ func (s *recordingSpan) Links() []Link {
if len(s.links.queue) == 0 { if len(s.links.queue) == 0 {
return []Link{} return []Link{}
} }
return s.interfaceArrayToLinksArray() return s.links.copy()
} }
// Events returns the events of this span. // Events returns the events of this span.
@ -595,7 +622,7 @@ func (s *recordingSpan) Events() []Event {
if len(s.events.queue) == 0 { if len(s.events.queue) == 0 {
return []Event{} return []Event{}
} }
return s.interfaceArrayToEventArray() return s.events.copy()
} }
// Status returns the status of this span. // Status returns the status of this span.
@ -630,7 +657,11 @@ func (s *recordingSpan) Resource() *resource.Resource {
} }
func (s *recordingSpan) AddLink(link trace.Link) { func (s *recordingSpan) AddLink(link trace.Link) {
if !s.IsRecording() || !link.SpanContext.IsValid() { if !s.IsRecording() {
return
}
if !link.SpanContext.IsValid() && len(link.Attributes) == 0 &&
link.SpanContext.TraceState().Len() == 0 {
return return
} }
@ -713,32 +744,16 @@ func (s *recordingSpan) snapshot() ReadOnlySpan {
} }
sd.droppedAttributeCount = s.droppedAttributes sd.droppedAttributeCount = s.droppedAttributes
if len(s.events.queue) > 0 { if len(s.events.queue) > 0 {
sd.events = s.interfaceArrayToEventArray() sd.events = s.events.copy()
sd.droppedEventCount = s.events.droppedCount sd.droppedEventCount = s.events.droppedCount
} }
if len(s.links.queue) > 0 { if len(s.links.queue) > 0 {
sd.links = s.interfaceArrayToLinksArray() sd.links = s.links.copy()
sd.droppedLinkCount = s.links.droppedCount sd.droppedLinkCount = s.links.droppedCount
} }
return &sd return &sd
} }
func (s *recordingSpan) interfaceArrayToLinksArray() []Link {
linkArr := make([]Link, 0)
for _, value := range s.links.queue {
linkArr = append(linkArr, value.(Link))
}
return linkArr
}
func (s *recordingSpan) interfaceArrayToEventArray() []Event {
eventArr := make([]Event, 0)
for _, value := range s.events.queue {
eventArr = append(eventArr, value.(Event))
}
return eventArr
}
func (s *recordingSpan) addChild() { func (s *recordingSpan) addChild() {
if !s.IsRecording() { if !s.IsRecording() {
return return

View File

@ -132,8 +132,8 @@ func (tr *tracer) newRecordingSpan(psc, sc trace.SpanContext, name string, sr Sa
spanKind: trace.ValidateSpanKind(config.SpanKind()), spanKind: trace.ValidateSpanKind(config.SpanKind()),
name: name, name: name,
startTime: startTime, startTime: startTime,
events: newEvictedQueue(tr.provider.spanLimits.EventCountLimit), events: newEvictedQueueEvent(tr.provider.spanLimits.EventCountLimit),
links: newEvictedQueue(tr.provider.spanLimits.LinkCountLimit), links: newEvictedQueueLink(tr.provider.spanLimits.LinkCountLimit),
tracer: tr, tracer: tr,
} }

View File

@ -5,5 +5,5 @@ package sdk // import "go.opentelemetry.io/otel/sdk"
// Version is the current release version of the OpenTelemetry SDK in use. // Version is the current release version of the OpenTelemetry SDK in use.
func Version() string { func Version() string {
return "1.26.0" return "1.28.0"
} }

View File

@ -0,0 +1,3 @@
# Semconv v1.26.0
[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/semconv/v1.26.0)](https://pkg.go.dev/go.opentelemetry.io/otel/semconv/v1.26.0)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package semconv implements OpenTelemetry semantic conventions.
//
// OpenTelemetry semantic conventions are agreed standardized naming
// patterns for OpenTelemetry things. This package represents the v1.26.0
// version of the OpenTelemetry semantic conventions.
package semconv // import "go.opentelemetry.io/otel/semconv/v1.26.0"

View File

@ -0,0 +1,9 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package semconv // import "go.opentelemetry.io/otel/semconv/v1.26.0"
const (
// ExceptionEventName is the name of the Span event representing an exception.
ExceptionEventName = "exception"
)

1307
vendor/go.opentelemetry.io/otel/semconv/v1.26.0/metric.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package semconv // import "go.opentelemetry.io/otel/semconv/v1.26.0"
// SchemaURL is the schema URL that matches the version of the semantic conventions
// that this package defines. Semconv packages starting from v1.4.0 must declare
// non-empty schema URL in the form https://opentelemetry.io/schemas/<version>
const SchemaURL = "https://opentelemetry.io/schemas/1.26.0"

View File

@ -67,11 +67,13 @@ func (t Tracer) Start(ctx context.Context, _ string, _ ...trace.SpanStartOption)
span = Span{sc: sc} span = Span{sc: sc}
} else { } else {
// No parent, return a No-Op span with an empty span context. // No parent, return a No-Op span with an empty span context.
span = Span{} span = noopSpanInstance
} }
return trace.ContextWithSpan(ctx, span), span return trace.ContextWithSpan(ctx, span), span
} }
var noopSpanInstance trace.Span = Span{}
// Span is an OpenTelemetry No-Op Span. // Span is an OpenTelemetry No-Op Span.
type Span struct { type Span struct {
embedded.Span embedded.Span

View File

@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel"
// Version is the current release version of OpenTelemetry in use. // Version is the current release version of OpenTelemetry in use.
func Version() string { func Version() string {
return "1.26.0" return "1.28.0"
} }

View File

@ -3,7 +3,7 @@
module-sets: module-sets:
stable-v1: stable-v1:
version: v1.26.0 version: v1.28.0
modules: modules:
- go.opentelemetry.io/otel - go.opentelemetry.io/otel
- go.opentelemetry.io/otel/bridge/opencensus - go.opentelemetry.io/otel/bridge/opencensus
@ -29,12 +29,12 @@ module-sets:
- go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/sdk/metric
- go.opentelemetry.io/otel/trace - go.opentelemetry.io/otel/trace
experimental-metrics: experimental-metrics:
version: v0.48.0 version: v0.50.0
modules: modules:
- go.opentelemetry.io/otel/example/prometheus - go.opentelemetry.io/otel/example/prometheus
- go.opentelemetry.io/otel/exporters/prometheus - go.opentelemetry.io/otel/exporters/prometheus
experimental-logs: experimental-logs:
version: v0.2.0-alpha version: v0.4.0
modules: modules:
- go.opentelemetry.io/otel/log - go.opentelemetry.io/otel/log
- go.opentelemetry.io/otel/sdk/log - go.opentelemetry.io/otel/sdk/log
@ -46,3 +46,4 @@ module-sets:
- go.opentelemetry.io/otel/schema - go.opentelemetry.io/otel/schema
excluded-modules: excluded-modules:
- go.opentelemetry.io/otel/internal/tools - go.opentelemetry.io/otel/internal/tools
- go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc

31
vendor/modules.txt vendored
View File

@ -258,7 +258,7 @@ github.com/fsnotify/fsnotify
github.com/go-jose/go-jose/v4 github.com/go-jose/go-jose/v4
github.com/go-jose/go-jose/v4/cipher github.com/go-jose/go-jose/v4/cipher
github.com/go-jose/go-jose/v4/json github.com/go-jose/go-jose/v4/json
# github.com/go-logr/logr v1.4.1 # github.com/go-logr/logr v1.4.2
## explicit; go 1.18 ## explicit; go 1.18
github.com/go-logr/logr github.com/go-logr/logr
github.com/go-logr/logr/funcr github.com/go-logr/logr/funcr
@ -303,8 +303,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus
# github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 # github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0
## explicit; go 1.19 ## explicit; go 1.19
github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors
# github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 # github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
## explicit; go 1.19 ## explicit; go 1.20
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/runtime
github.com/grpc-ecosystem/grpc-gateway/v2/utilities github.com/grpc-ecosystem/grpc-gateway/v2/utilities
@ -475,16 +475,16 @@ go.opencensus.io/internal
go.opencensus.io/trace go.opencensus.io/trace
go.opencensus.io/trace/internal go.opencensus.io/trace/internal
go.opencensus.io/trace/tracestate go.opencensus.io/trace/tracestate
# go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 # go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal
# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 # go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil
# go.opentelemetry.io/otel v1.26.0 # go.opentelemetry.io/otel v1.28.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/otel go.opentelemetry.io/otel
go.opentelemetry.io/otel/attribute go.opentelemetry.io/otel/attribute
@ -499,44 +499,45 @@ go.opentelemetry.io/otel/semconv/v1.17.0
go.opentelemetry.io/otel/semconv/v1.20.0 go.opentelemetry.io/otel/semconv/v1.20.0
go.opentelemetry.io/otel/semconv/v1.21.0 go.opentelemetry.io/otel/semconv/v1.21.0
go.opentelemetry.io/otel/semconv/v1.24.0 go.opentelemetry.io/otel/semconv/v1.24.0
# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 go.opentelemetry.io/otel/semconv/v1.26.0
# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace go.opentelemetry.io/otel/exporters/otlp/otlptrace
go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform
# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 # go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry
# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 # go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry
# go.opentelemetry.io/otel/metric v1.26.0 # go.opentelemetry.io/otel/metric v1.28.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric
go.opentelemetry.io/otel/metric/embedded go.opentelemetry.io/otel/metric/embedded
go.opentelemetry.io/otel/metric/noop go.opentelemetry.io/otel/metric/noop
# go.opentelemetry.io/otel/sdk v1.26.0 # go.opentelemetry.io/otel/sdk v1.28.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/otel/sdk go.opentelemetry.io/otel/sdk
go.opentelemetry.io/otel/sdk/instrumentation go.opentelemetry.io/otel/sdk/instrumentation
go.opentelemetry.io/otel/sdk/internal
go.opentelemetry.io/otel/sdk/internal/env go.opentelemetry.io/otel/sdk/internal/env
go.opentelemetry.io/otel/sdk/internal/x
go.opentelemetry.io/otel/sdk/resource go.opentelemetry.io/otel/sdk/resource
go.opentelemetry.io/otel/sdk/trace go.opentelemetry.io/otel/sdk/trace
go.opentelemetry.io/otel/sdk/trace/tracetest go.opentelemetry.io/otel/sdk/trace/tracetest
# go.opentelemetry.io/otel/trace v1.26.0 # go.opentelemetry.io/otel/trace v1.28.0
## explicit; go 1.21 ## explicit; go 1.21
go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace
go.opentelemetry.io/otel/trace/embedded go.opentelemetry.io/otel/trace/embedded
go.opentelemetry.io/otel/trace/noop go.opentelemetry.io/otel/trace/noop
# go.opentelemetry.io/proto/otlp v1.2.0 # go.opentelemetry.io/proto/otlp v1.3.1
## explicit; go 1.17 ## explicit; go 1.17
go.opentelemetry.io/proto/otlp/collector/trace/v1 go.opentelemetry.io/proto/otlp/collector/trace/v1
go.opentelemetry.io/proto/otlp/common/v1 go.opentelemetry.io/proto/otlp/common/v1
@ -604,7 +605,7 @@ golang.org/x/text/unicode/norm
# golang.org/x/time v0.3.0 # golang.org/x/time v0.3.0
## explicit ## explicit
golang.org/x/time/rate golang.org/x/time/rate
# google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 # google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094
## explicit; go 1.20 ## explicit; go 1.20
google.golang.org/genproto/googleapis/api/httpbody google.golang.org/genproto/googleapis/api/httpbody
# google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 # google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094