rebase: bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc

Bumps [go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.35.0 to 0.46.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.35.0...zpages/v0.46.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2023-12-21 14:13:18 +00:00 committed by mergify[bot]
parent e3e2560512
commit 30150c3be9
32 changed files with 924 additions and 173 deletions

8
go.mod
View File

@ -137,14 +137,14 @@ require (
go.etcd.io/etcd/api/v3 v3.5.10 // indirect go.etcd.io/etcd/api/v3 v3.5.10 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
go.etcd.io/etcd/client/v3 v3.5.10 // indirect go.etcd.io/etcd/client/v3 v3.5.10 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/otel v1.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.20.0 // indirect
go.opentelemetry.io/otel/sdk v1.19.0 // indirect go.opentelemetry.io/otel/sdk v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.20.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect go.uber.org/zap v1.25.0 // indirect

12
go.sum
View File

@ -1646,15 +1646,17 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
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.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 h1:ZOLJc06r4CB42laIXg/7udr0pbZyuAihN10A/XuiQRY=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0/go.mod h1:5z+/ZWJQKXa9YT34fQNx5K8Hd1EoIhvtUygUQPqEOgQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0/go.mod h1:5z+/ZWJQKXa9YT34fQNx5K8Hd1EoIhvtUygUQPqEOgQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48=
go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI=
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc=
go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
@ -1663,16 +1665,18 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S2
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k=
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
go.opentelemetry.io/otel/metric v1.20.0 h1:ZlrO8Hu9+GAhnepmRGhSU7/VkpjrNowxRN9GyKR4wzA=
go.opentelemetry.io/otel/metric v1.20.0/go.mod h1:90DRw3nfK4D7Sm/75yQ00gTJxtkBxX+wu6YaNymbpVM=
go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI=
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0=
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ=
go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg=
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=

View File

@ -24,8 +24,8 @@ import (
) )
const ( const (
// instrumentationName is the name of this instrumentation package. // ScopeName is the instrumentation scope name.
instrumentationName = "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" ScopeName = "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
// GRPCStatusCodeKey is convention for numeric status code of a gRPC request. // GRPCStatusCodeKey is convention for numeric status code of a gRPC request.
GRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code") GRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code")
) )
@ -41,9 +41,19 @@ type config struct {
Propagators propagation.TextMapPropagator Propagators propagation.TextMapPropagator
TracerProvider trace.TracerProvider TracerProvider trace.TracerProvider
MeterProvider metric.MeterProvider MeterProvider metric.MeterProvider
SpanStartOptions []trace.SpanStartOption
ReceivedEvent bool
SentEvent bool
tracer trace.Tracer
meter metric.Meter meter metric.Meter
rpcServerDuration metric.Int64Histogram
rpcDuration metric.Float64Histogram
rpcRequestSize metric.Int64Histogram
rpcResponseSize metric.Int64Histogram
rpcRequestsPerRPC metric.Int64Histogram
rpcResponsesPerRPC metric.Int64Histogram
} }
// Option applies an option value for a config. // Option applies an option value for a config.
@ -52,7 +62,7 @@ type Option interface {
} }
// newConfig returns a config configured with all the passed Options. // newConfig returns a config configured with all the passed Options.
func newConfig(opts []Option) *config { func newConfig(opts []Option, role string) *config {
c := &config{ c := &config{
Propagators: otel.GetTextMapPropagator(), Propagators: otel.GetTextMapPropagator(),
TracerProvider: otel.GetTracerProvider(), TracerProvider: otel.GetTracerProvider(),
@ -62,13 +72,50 @@ func newConfig(opts []Option) *config {
o.apply(c) o.apply(c)
} }
c.tracer = c.TracerProvider.Tracer(
ScopeName,
trace.WithInstrumentationVersion(SemVersion()),
)
c.meter = c.MeterProvider.Meter( c.meter = c.MeterProvider.Meter(
instrumentationName, ScopeName,
metric.WithInstrumentationVersion(Version()), metric.WithInstrumentationVersion(Version()),
metric.WithSchemaURL(semconv.SchemaURL), metric.WithSchemaURL(semconv.SchemaURL),
) )
var err error var err error
if c.rpcServerDuration, err = c.meter.Int64Histogram("rpc.server.duration", metric.WithUnit("ms")); err != nil { c.rpcDuration, err = c.meter.Float64Histogram("rpc."+role+".duration",
metric.WithDescription("Measures the duration of inbound RPC."),
metric.WithUnit("ms"))
if err != nil {
otel.Handle(err)
}
c.rpcRequestSize, err = c.meter.Int64Histogram("rpc."+role+".request.size",
metric.WithDescription("Measures size of RPC request messages (uncompressed)."),
metric.WithUnit("By"))
if err != nil {
otel.Handle(err)
}
c.rpcResponseSize, err = c.meter.Int64Histogram("rpc."+role+".response.size",
metric.WithDescription("Measures size of RPC response messages (uncompressed)."),
metric.WithUnit("By"))
if err != nil {
otel.Handle(err)
}
c.rpcRequestsPerRPC, err = c.meter.Int64Histogram("rpc."+role+".requests_per_rpc",
metric.WithDescription("Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs."),
metric.WithUnit("{count}"))
if err != nil {
otel.Handle(err)
}
c.rpcResponsesPerRPC, err = c.meter.Int64Histogram("rpc."+role+".responses_per_rpc",
metric.WithDescription("Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs."),
metric.WithUnit("{count}"))
if err != nil {
otel.Handle(err) otel.Handle(err)
} }
@ -98,6 +145,8 @@ 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.
func WithInterceptorFilter(f Filter) Option { func WithInterceptorFilter(f Filter) Option {
return interceptorFilterOption{f: f} return interceptorFilterOption{f: f}
} }
@ -131,3 +180,50 @@ func (o meterProviderOption) apply(c *config) {
func WithMeterProvider(mp metric.MeterProvider) Option { func WithMeterProvider(mp metric.MeterProvider) Option {
return meterProviderOption{mp: mp} return meterProviderOption{mp: mp}
} }
// Event type that can be recorded, see WithMessageEvents.
type Event int
// Different types of events that can be recorded, see WithMessageEvents.
const (
ReceivedEvents Event = iota
SentEvents
)
type messageEventsProviderOption struct {
events []Event
}
func (m messageEventsProviderOption) apply(c *config) {
for _, e := range m.events {
switch e {
case ReceivedEvents:
c.ReceivedEvent = true
case SentEvents:
c.SentEvent = true
}
}
}
// WithMessageEvents configures the Handler to record the specified events
// (span.AddEvent) on spans. By default only summary attributes are added at the
// end of the request.
//
// Valid events are:
// - ReceivedEvents: Record the number of bytes read after every gRPC read operation.
// - SentEvents: Record the number of bytes written after every gRPC write operation.
func WithMessageEvents(events ...Event) Option {
return messageEventsProviderOption{events: events}
}
type spanStartOption struct{ opts []trace.SpanStartOption }
func (o spanStartOption) apply(c *config) {
c.SpanStartOptions = append(c.SpanStartOptions, o.opts...)
}
// WithSpanOptions configures an additional set of
// trace.SpanOptions, which are applied to each new span.
func WithSpanOptions(opts ...trace.SpanStartOption) Option {
return spanStartOption{opts}
}

View File

@ -0,0 +1,22 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Package otelgrpc is the instrumentation library for [google.golang.org/grpc].
Use [NewClientHandler] with [grpc.WithStatsHandler] to instrument a gRPC client.
Use [NewServerHandler] with [grpc.StatsHandler] to instrument a gRPC server.
*/
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"

View File

@ -60,10 +60,12 @@ var (
// UnaryClientInterceptor returns a grpc.UnaryClientInterceptor suitable // UnaryClientInterceptor returns a grpc.UnaryClientInterceptor suitable
// for use in a grpc.Dial call. // for use in a grpc.Dial call.
//
// Deprecated: Use [NewClientHandler] instead.
func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor { func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor {
cfg := newConfig(opts) cfg := newConfig(opts, "client")
tracer := cfg.TracerProvider.Tracer( tracer := cfg.TracerProvider.Tracer(
instrumentationName, ScopeName,
trace.WithInstrumentationVersion(Version()), trace.WithInstrumentationVersion(Version()),
) )
@ -83,23 +85,33 @@ func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor {
return invoker(ctx, method, req, reply, cc, callOpts...) return invoker(ctx, method, req, reply, cc, callOpts...)
} }
name, attr := spanInfo(method, cc.Target()) name, attr, _ := telemetryAttributes(method, cc.Target())
var span trace.Span
ctx, span = tracer.Start( startOpts := append([]trace.SpanStartOption{
ctx,
name,
trace.WithSpanKind(trace.SpanKindClient), trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(attr...), trace.WithAttributes(attr...),
},
cfg.SpanStartOptions...,
)
ctx, span := tracer.Start(
ctx,
name,
startOpts...,
) )
defer span.End() defer span.End()
ctx = inject(ctx, cfg.Propagators) ctx = inject(ctx, cfg.Propagators)
if cfg.SentEvent {
messageSent.Event(ctx, 1, req) messageSent.Event(ctx, 1, req)
}
err := invoker(ctx, method, req, reply, cc, callOpts...) err := invoker(ctx, method, req, reply, cc, callOpts...)
if cfg.ReceivedEvent {
messageReceived.Event(ctx, 1, reply) messageReceived.Event(ctx, 1, reply)
}
if err != nil { if err != nil {
s, _ := status.FromError(err) s, _ := status.FromError(err)
@ -135,6 +147,9 @@ type clientStream struct {
eventsDone chan struct{} eventsDone chan struct{}
finished chan error finished chan error
receivedEvent bool
sentEvent bool
receivedMessageID int receivedMessageID int
sentMessageID int sentMessageID int
} }
@ -152,8 +167,11 @@ func (w *clientStream) RecvMsg(m interface{}) error {
w.sendStreamEvent(errorEvent, err) w.sendStreamEvent(errorEvent, err)
} else { } else {
w.receivedMessageID++ w.receivedMessageID++
if w.receivedEvent {
messageReceived.Event(w.Context(), w.receivedMessageID, m) messageReceived.Event(w.Context(), w.receivedMessageID, m)
} }
}
return err return err
} }
@ -162,7 +180,10 @@ func (w *clientStream) SendMsg(m interface{}) error {
err := w.ClientStream.SendMsg(m) err := w.ClientStream.SendMsg(m)
w.sentMessageID++ w.sentMessageID++
if w.sentEvent {
messageSent.Event(w.Context(), w.sentMessageID, m) messageSent.Event(w.Context(), w.sentMessageID, m)
}
if err != nil { if err != nil {
w.sendStreamEvent(errorEvent, err) w.sendStreamEvent(errorEvent, err)
@ -173,7 +194,6 @@ func (w *clientStream) SendMsg(m interface{}) error {
func (w *clientStream) Header() (metadata.MD, error) { func (w *clientStream) Header() (metadata.MD, error) {
md, err := w.ClientStream.Header() md, err := w.ClientStream.Header()
if err != nil { if err != nil {
w.sendStreamEvent(errorEvent, err) w.sendStreamEvent(errorEvent, err)
} }
@ -183,7 +203,6 @@ func (w *clientStream) Header() (metadata.MD, error) {
func (w *clientStream) CloseSend() error { func (w *clientStream) CloseSend() error {
err := w.ClientStream.CloseSend() err := w.ClientStream.CloseSend()
if err != nil { if err != nil {
w.sendStreamEvent(errorEvent, err) w.sendStreamEvent(errorEvent, err)
} }
@ -191,7 +210,7 @@ func (w *clientStream) CloseSend() error {
return err return err
} }
func wrapClientStream(ctx context.Context, s grpc.ClientStream, desc *grpc.StreamDesc) *clientStream { func wrapClientStream(ctx context.Context, s grpc.ClientStream, desc *grpc.StreamDesc, cfg *config) *clientStream {
events := make(chan streamEvent) events := make(chan streamEvent)
eventsDone := make(chan struct{}) eventsDone := make(chan struct{})
finished := make(chan error) finished := make(chan error)
@ -223,6 +242,8 @@ func wrapClientStream(ctx context.Context, s grpc.ClientStream, desc *grpc.Strea
events: events, events: events,
eventsDone: eventsDone, eventsDone: eventsDone,
finished: finished, finished: finished,
receivedEvent: cfg.ReceivedEvent,
sentEvent: cfg.SentEvent,
} }
} }
@ -235,10 +256,12 @@ func (w *clientStream) sendStreamEvent(eventType streamEventType, err error) {
// StreamClientInterceptor returns a grpc.StreamClientInterceptor suitable // StreamClientInterceptor returns a grpc.StreamClientInterceptor suitable
// for use in a grpc.Dial call. // for use in a grpc.Dial call.
//
// Deprecated: Use [NewClientHandler] instead.
func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor { func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
cfg := newConfig(opts) cfg := newConfig(opts, "client")
tracer := cfg.TracerProvider.Tracer( tracer := cfg.TracerProvider.Tracer(
instrumentationName, ScopeName,
trace.WithInstrumentationVersion(Version()), trace.WithInstrumentationVersion(Version()),
) )
@ -258,13 +281,19 @@ func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
return streamer(ctx, desc, cc, method, callOpts...) return streamer(ctx, desc, cc, method, callOpts...)
} }
name, attr := spanInfo(method, cc.Target()) name, attr, _ := telemetryAttributes(method, cc.Target())
var span trace.Span
ctx, span = tracer.Start( startOpts := append([]trace.SpanStartOption{
ctx,
name,
trace.WithSpanKind(trace.SpanKindClient), trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(attr...), trace.WithAttributes(attr...),
},
cfg.SpanStartOptions...,
)
ctx, span := tracer.Start(
ctx,
name,
startOpts...,
) )
ctx = inject(ctx, cfg.Propagators) ctx = inject(ctx, cfg.Propagators)
@ -277,7 +306,7 @@ func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
span.End() span.End()
return s, err return s, err
} }
stream := wrapClientStream(ctx, s, desc) stream := wrapClientStream(ctx, s, desc, cfg)
go func() { go func() {
err := <-stream.finished err := <-stream.finished
@ -299,10 +328,12 @@ func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
// UnaryServerInterceptor returns a grpc.UnaryServerInterceptor suitable // UnaryServerInterceptor returns a grpc.UnaryServerInterceptor suitable
// for use in a grpc.NewServer call. // for use in a grpc.NewServer call.
//
// Deprecated: Use [NewServerHandler] instead.
func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor { func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
cfg := newConfig(opts) cfg := newConfig(opts, "server")
tracer := cfg.TracerProvider.Tracer( tracer := cfg.TracerProvider.Tracer(
instrumentationName, ScopeName,
trace.WithInstrumentationVersion(Version()), trace.WithInstrumentationVersion(Version()),
) )
@ -321,38 +352,48 @@ func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
} }
ctx = extract(ctx, cfg.Propagators) ctx = extract(ctx, cfg.Propagators)
name, attr, metricAttrs := telemetryAttributes(info.FullMethod, peerFromCtx(ctx))
startOpts := append([]trace.SpanStartOption{
trace.WithSpanKind(trace.SpanKindServer),
trace.WithAttributes(attr...),
},
cfg.SpanStartOptions...,
)
name, attr := spanInfo(info.FullMethod, peerFromCtx(ctx))
ctx, span := tracer.Start( ctx, span := tracer.Start(
trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)), trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)),
name, name,
trace.WithSpanKind(trace.SpanKindServer), startOpts...,
trace.WithAttributes(attr...),
) )
defer span.End() defer span.End()
if cfg.ReceivedEvent {
messageReceived.Event(ctx, 1, req) messageReceived.Event(ctx, 1, req)
}
var statusCode grpc_codes.Code before := time.Now()
defer func(t time.Time) {
elapsedTime := time.Since(t) / time.Millisecond
attr = append(attr, semconv.RPCGRPCStatusCodeKey.Int64(int64(statusCode)))
o := metric.WithAttributes(attr...)
cfg.rpcServerDuration.Record(ctx, int64(elapsedTime), o)
}(time.Now())
resp, err := handler(ctx, req) resp, err := handler(ctx, req)
if err != nil {
s, _ := status.FromError(err) s, _ := status.FromError(err)
if err != nil {
statusCode, msg := serverStatus(s) statusCode, msg := serverStatus(s)
span.SetStatus(statusCode, msg) span.SetStatus(statusCode, msg)
span.SetAttributes(statusCodeAttr(s.Code())) if cfg.SentEvent {
messageSent.Event(ctx, 1, s.Proto()) messageSent.Event(ctx, 1, s.Proto())
}
} else { } else {
statusCode = grpc_codes.OK if cfg.SentEvent {
span.SetAttributes(statusCodeAttr(grpc_codes.OK))
messageSent.Event(ctx, 1, resp) messageSent.Event(ctx, 1, resp)
} }
}
grpcStatusCodeAttr := statusCodeAttr(s.Code())
span.SetAttributes(grpcStatusCodeAttr)
elapsedTime := time.Since(before).Milliseconds()
metricAttrs = append(metricAttrs, grpcStatusCodeAttr)
cfg.rpcDuration.Record(ctx, float64(elapsedTime), metric.WithAttributes(metricAttrs...))
return resp, err return resp, err
} }
@ -366,6 +407,9 @@ type serverStream struct {
receivedMessageID int receivedMessageID int
sentMessageID int sentMessageID int
receivedEvent bool
sentEvent bool
} }
func (w *serverStream) Context() context.Context { func (w *serverStream) Context() context.Context {
@ -377,8 +421,10 @@ func (w *serverStream) RecvMsg(m interface{}) error {
if err == nil { if err == nil {
w.receivedMessageID++ w.receivedMessageID++
if w.receivedEvent {
messageReceived.Event(w.Context(), w.receivedMessageID, m) messageReceived.Event(w.Context(), w.receivedMessageID, m)
} }
}
return err return err
} }
@ -387,24 +433,30 @@ func (w *serverStream) SendMsg(m interface{}) error {
err := w.ServerStream.SendMsg(m) err := w.ServerStream.SendMsg(m)
w.sentMessageID++ w.sentMessageID++
if w.sentEvent {
messageSent.Event(w.Context(), w.sentMessageID, m) messageSent.Event(w.Context(), w.sentMessageID, m)
}
return err return err
} }
func wrapServerStream(ctx context.Context, ss grpc.ServerStream) *serverStream { func wrapServerStream(ctx context.Context, ss grpc.ServerStream, cfg *config) *serverStream {
return &serverStream{ return &serverStream{
ServerStream: ss, ServerStream: ss,
ctx: ctx, ctx: ctx,
receivedEvent: cfg.ReceivedEvent,
sentEvent: cfg.SentEvent,
} }
} }
// StreamServerInterceptor returns a grpc.StreamServerInterceptor suitable // StreamServerInterceptor returns a grpc.StreamServerInterceptor suitable
// for use in a grpc.NewServer call. // for use in a grpc.NewServer call.
//
// Deprecated: Use [NewServerHandler] instead.
func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor { func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
cfg := newConfig(opts) cfg := newConfig(opts, "server")
tracer := cfg.TracerProvider.Tracer( tracer := cfg.TracerProvider.Tracer(
instrumentationName, ScopeName,
trace.WithInstrumentationVersion(Version()), trace.WithInstrumentationVersion(Version()),
) )
@ -420,21 +472,27 @@ func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
Type: StreamServer, Type: StreamServer,
} }
if cfg.Filter != nil && !cfg.Filter(i) { if cfg.Filter != nil && !cfg.Filter(i) {
return handler(srv, wrapServerStream(ctx, ss)) return handler(srv, wrapServerStream(ctx, ss, cfg))
} }
ctx = extract(ctx, cfg.Propagators) ctx = extract(ctx, cfg.Propagators)
name, attr, _ := telemetryAttributes(info.FullMethod, peerFromCtx(ctx))
startOpts := append([]trace.SpanStartOption{
trace.WithSpanKind(trace.SpanKindServer),
trace.WithAttributes(attr...),
},
cfg.SpanStartOptions...,
)
name, attr := spanInfo(info.FullMethod, peerFromCtx(ctx))
ctx, span := tracer.Start( ctx, span := tracer.Start(
trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)), trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)),
name, name,
trace.WithSpanKind(trace.SpanKindServer), startOpts...,
trace.WithAttributes(attr...),
) )
defer span.End() defer span.End()
err := handler(srv, wrapServerStream(ctx, ss)) err := handler(srv, wrapServerStream(ctx, ss, cfg))
if err != nil { if err != nil {
s, _ := status.FromError(err) s, _ := status.FromError(err)
statusCode, msg := serverStatus(s) statusCode, msg := serverStatus(s)
@ -448,21 +506,25 @@ func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
} }
} }
// spanInfo returns a span name and all appropriate attributes from the gRPC // telemetryAttributes returns a span name and span and metric attributes from
// method and peer address. // the gRPC method and peer address.
func spanInfo(fullMethod, peerAddress string) (string, []attribute.KeyValue) { func telemetryAttributes(fullMethod, peerAddress string) (string, []attribute.KeyValue, []attribute.KeyValue) {
attrs := []attribute.KeyValue{RPCSystemGRPC} name, methodAttrs := internal.ParseFullMethod(fullMethod)
name, mAttrs := internal.ParseFullMethod(fullMethod) peerAttrs := peerAttr(peerAddress)
attrs = append(attrs, mAttrs...)
attrs = append(attrs, peerAttr(peerAddress)...) attrs := make([]attribute.KeyValue, 0, 1+len(methodAttrs)+len(peerAttrs))
return name, attrs attrs = append(attrs, RPCSystemGRPC)
attrs = append(attrs, methodAttrs...)
metricAttrs := attrs[:1+len(methodAttrs)]
attrs = append(attrs, peerAttrs...)
return name, attrs, metricAttrs
} }
// peerAttr returns attributes about the peer address. // peerAttr returns attributes about the peer address.
func peerAttr(addr string) []attribute.KeyValue { func peerAttr(addr string) []attribute.KeyValue {
host, p, err := net.SplitHostPort(addr) host, p, err := net.SplitHostPort(addr)
if err != nil { if err != nil {
return []attribute.KeyValue(nil) return nil
} }
if host == "" { if host == "" {
@ -470,7 +532,7 @@ func peerAttr(addr string) []attribute.KeyValue {
} }
port, err := strconv.Atoi(p) port, err := strconv.Atoi(p)
if err != nil { if err != nil {
return []attribute.KeyValue(nil) return nil
} }
var attr []attribute.KeyValue var attr []attribute.KeyValue

View File

@ -24,13 +24,21 @@ import (
// ParseFullMethod returns a span name following the OpenTelemetry semantic // ParseFullMethod returns a span name following the OpenTelemetry semantic
// conventions as well as all applicable span attribute.KeyValue attributes based // conventions as well as all applicable span attribute.KeyValue attributes based
// on a gRPC's FullMethod. // on a gRPC's FullMethod.
//
// Parsing is consistent with grpc-go implementation:
// https://github.com/grpc/grpc-go/blob/v1.57.0/internal/grpcutil/method.go#L26-L39
func ParseFullMethod(fullMethod string) (string, []attribute.KeyValue) { func ParseFullMethod(fullMethod string) (string, []attribute.KeyValue) {
name := strings.TrimLeft(fullMethod, "/") if !strings.HasPrefix(fullMethod, "/") {
service, method, found := strings.Cut(name, "/") // Invalid format, does not follow `/package.service/method`.
if !found { return fullMethod, nil
}
name := fullMethod[1:]
pos := strings.LastIndex(name, "/")
if pos < 0 {
// Invalid format, does not follow `/package.service/method`. // Invalid format, does not follow `/package.service/method`.
return name, nil return name, nil
} }
service, method := name[:pos], name[pos+1:]
var attrs []attribute.KeyValue var attrs []attribute.KeyValue
if service != "" { if service != "" {

View File

@ -56,7 +56,7 @@ func (s *metadataSupplier) Keys() []string {
// requests. // requests.
// Deprecated: Unnecessary public func. // Deprecated: Unnecessary public func.
func Inject(ctx context.Context, md *metadata.MD, opts ...Option) { func Inject(ctx context.Context, md *metadata.MD, opts ...Option) {
c := newConfig(opts) c := newConfig(opts, "")
c.Propagators.Inject(ctx, &metadataSupplier{ c.Propagators.Inject(ctx, &metadataSupplier{
metadata: md, metadata: md,
}) })
@ -78,7 +78,7 @@ func inject(ctx context.Context, propagators propagation.TextMapPropagator) cont
// This function is meant to be used on incoming requests. // This function is meant to be used on incoming requests.
// Deprecated: Unnecessary public func. // Deprecated: Unnecessary public func.
func Extract(ctx context.Context, md *metadata.MD, opts ...Option) (baggage.Baggage, trace.SpanContext) { func Extract(ctx context.Context, md *metadata.MD, opts ...Option) (baggage.Baggage, trace.SpanContext) {
c := newConfig(opts) c := newConfig(opts, "")
ctx = c.Propagators.Extract(ctx, &metadataSupplier{ ctx = c.Propagators.Extract(ctx, &metadataSupplier{
metadata: md, metadata: md,
}) })

View File

@ -0,0 +1,235 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
import (
"context"
"sync/atomic"
"time"
grpc_codes "google.golang.org/grpc/codes"
"google.golang.org/grpc/stats"
"google.golang.org/grpc/status"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/metric"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
"go.opentelemetry.io/otel/trace"
)
type gRPCContextKey struct{}
type gRPCContext struct {
messagesReceived int64
messagesSent int64
metricAttrs []attribute.KeyValue
}
type serverHandler struct {
*config
}
// NewServerHandler creates a stats.Handler for gRPC server.
func NewServerHandler(opts ...Option) stats.Handler {
h := &serverHandler{
config: newConfig(opts, "server"),
}
return h
}
// TagConn can attach some information to the given context.
func (h *serverHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
span := trace.SpanFromContext(ctx)
attrs := peerAttr(peerFromCtx(ctx))
span.SetAttributes(attrs...)
return ctx
}
// HandleConn processes the Conn stats.
func (h *serverHandler) HandleConn(ctx context.Context, info stats.ConnStats) {
}
// TagRPC can attach some information to the given context.
func (h *serverHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
ctx = extract(ctx, h.config.Propagators)
name, attrs := internal.ParseFullMethod(info.FullMethodName)
attrs = append(attrs, RPCSystemGRPC)
ctx, _ = h.tracer.Start(
trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)),
name,
trace.WithSpanKind(trace.SpanKindServer),
trace.WithAttributes(attrs...),
)
gctx := gRPCContext{
metricAttrs: attrs,
}
return context.WithValue(ctx, gRPCContextKey{}, &gctx)
}
// HandleRPC processes the RPC stats.
func (h *serverHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
h.handleRPC(ctx, rs)
}
type clientHandler struct {
*config
}
// NewClientHandler creates a stats.Handler for gRPC client.
func NewClientHandler(opts ...Option) stats.Handler {
h := &clientHandler{
config: newConfig(opts, "client"),
}
return h
}
// TagRPC can attach some information to the given context.
func (h *clientHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
name, attrs := internal.ParseFullMethod(info.FullMethodName)
attrs = append(attrs, RPCSystemGRPC)
ctx, _ = h.tracer.Start(
ctx,
name,
trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(attrs...),
)
gctx := gRPCContext{
metricAttrs: attrs,
}
return inject(context.WithValue(ctx, gRPCContextKey{}, &gctx), h.config.Propagators)
}
// HandleRPC processes the RPC stats.
func (h *clientHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
h.handleRPC(ctx, rs)
}
// TagConn can attach some information to the given context.
func (h *clientHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context {
span := trace.SpanFromContext(ctx)
attrs := peerAttr(cti.RemoteAddr.String())
span.SetAttributes(attrs...)
return ctx
}
// HandleConn processes the Conn stats.
func (h *clientHandler) HandleConn(context.Context, stats.ConnStats) {
// no-op
}
func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) {
span := trace.SpanFromContext(ctx)
gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext)
var messageId int64
metricAttrs := make([]attribute.KeyValue, 0, len(gctx.metricAttrs)+1)
metricAttrs = append(metricAttrs, gctx.metricAttrs...)
wctx := withoutCancel(ctx)
switch rs := rs.(type) {
case *stats.Begin:
case *stats.InPayload:
if gctx != nil {
messageId = atomic.AddInt64(&gctx.messagesReceived, 1)
c.rpcRequestSize.Record(wctx, int64(rs.Length), metric.WithAttributes(metricAttrs...))
}
if c.ReceivedEvent {
span.AddEvent("message",
trace.WithAttributes(
semconv.MessageTypeReceived,
semconv.MessageIDKey.Int64(messageId),
semconv.MessageCompressedSizeKey.Int(rs.CompressedLength),
semconv.MessageUncompressedSizeKey.Int(rs.Length),
),
)
}
case *stats.OutPayload:
if gctx != nil {
messageId = atomic.AddInt64(&gctx.messagesSent, 1)
c.rpcResponseSize.Record(wctx, int64(rs.Length), metric.WithAttributes(metricAttrs...))
}
if c.SentEvent {
span.AddEvent("message",
trace.WithAttributes(
semconv.MessageTypeSent,
semconv.MessageIDKey.Int64(messageId),
semconv.MessageCompressedSizeKey.Int(rs.CompressedLength),
semconv.MessageUncompressedSizeKey.Int(rs.Length),
),
)
}
case *stats.OutTrailer:
case *stats.End:
var rpcStatusAttr attribute.KeyValue
if rs.Error != nil {
s, _ := status.FromError(rs.Error)
span.SetStatus(codes.Error, s.Message())
rpcStatusAttr = semconv.RPCGRPCStatusCodeKey.Int(int(s.Code()))
} else {
rpcStatusAttr = semconv.RPCGRPCStatusCodeKey.Int(int(grpc_codes.OK))
}
span.SetAttributes(rpcStatusAttr)
span.End()
metricAttrs = append(metricAttrs, rpcStatusAttr)
c.rpcDuration.Record(wctx, float64(rs.EndTime.Sub(rs.BeginTime)), metric.WithAttributes(metricAttrs...))
c.rpcRequestsPerRPC.Record(wctx, gctx.messagesReceived, metric.WithAttributes(metricAttrs...))
c.rpcResponsesPerRPC.Record(wctx, gctx.messagesSent, metric.WithAttributes(metricAttrs...))
default:
return
}
}
func withoutCancel(parent context.Context) context.Context {
if parent == nil {
panic("cannot create context from nil parent")
}
return withoutCancelCtx{parent}
}
type withoutCancelCtx struct {
c context.Context
}
func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func (withoutCancelCtx) Done() <-chan struct{} {
return nil
}
func (withoutCancelCtx) Err() error {
return nil
}
func (w withoutCancelCtx) Value(key any) any {
return w.c.Value(key)
}
func (w withoutCancelCtx) String() string {
return "withoutCancel"
}

View File

@ -16,7 +16,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.42.0" return "0.46.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

@ -18,8 +18,9 @@ gen/
/example/fib/traces.txt /example/fib/traces.txt
/example/jaeger/jaeger /example/jaeger/jaeger
/example/namedtracer/namedtracer /example/namedtracer/namedtracer
/example/otel-collector/otel-collector
/example/opencensus/opencensus /example/opencensus/opencensus
/example/passthrough/passthrough /example/passthrough/passthrough
/example/prometheus/prometheus /example/prometheus/prometheus
/example/view/view
/example/zipkin/zipkin /example/zipkin/zipkin
/example/otel-collector/otel-collector

View File

@ -12,8 +12,9 @@ linters:
- depguard - depguard
- errcheck - errcheck
- godot - godot
- gofmt - gofumpt
- goimports - goimports
- gosec
- gosimple - gosimple
- govet - govet
- ineffassign - ineffassign
@ -53,6 +54,20 @@ issues:
text: "calls to (.+) only in main[(][)] or init[(][)] functions" text: "calls to (.+) only in main[(][)] or init[(][)] functions"
linters: linters:
- revive - revive
# It's okay to not run gosec in a test.
- path: _test\.go
linters:
- gosec
# Igonoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand)
# as we commonly use it in tests and examples.
- text: "G404:"
linters:
- gosec
# Igonoring gosec G402: TLS MinVersion too low
# as the https://pkg.go.dev/crypto/tls#Config handles MinVersion default well.
- text: "G402: TLS MinVersion too low."
linters:
- gosec
include: include:
# revive exported should have comment or be unexported. # revive exported should have comment or be unexported.
- EXC0012 - EXC0012

View File

@ -8,6 +8,71 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased] ## [Unreleased]
## [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.
### Added
- Add `go.opentelemetry.io/otel/bridge/opencensus.InstallTraceBridge`, which installs the OpenCensus trace bridge, and replaces `opencensus.NewTracer`. (#4567)
- Add scope version to trace and metric bridges in `go.opentelemetry.io/otel/bridge/opencensus`. (#4584)
- Add the `go.opentelemetry.io/otel/trace/embedded` package to be embedded in the exported trace API interfaces. (#4620)
- Add the `go.opentelemetry.io/otel/trace/noop` package as a default no-op implementation of the trace API. (#4620)
- Add context propagation in `go.opentelemetry.io/otel/example/dice`. (#4644)
- Add view configuration to `go.opentelemetry.io/otel/example/prometheus`. (#4649)
- Add `go.opentelemetry.io/otel/metric.WithExplicitBucketBoundaries`, which allows defining default explicit bucket boundaries when creating histogram instruments. (#4603)
- Add `Version` function in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#4660)
- Add `Version` function in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#4660)
- Add Summary, SummaryDataPoint, and QuantileValue to `go.opentelemetry.io/sdk/metric/metricdata`. (#4622)
- `go.opentelemetry.io/otel/bridge/opencensus.NewMetricProducer` now supports exemplars from OpenCensus. (#4585)
- Add support for `WithExplicitBucketBoundaries` in `go.opentelemetry.io/otel/sdk/metric`. (#4605)
- Add support for Summary metrics in `go.opentelemetry.io/otel/bridge/opencensus`. (#4668)
### Deprecated
- Deprecate `go.opentelemetry.io/otel/bridge/opencensus.NewTracer` in favor of `opencensus.InstallTraceBridge`. (#4567)
- Deprecate `go.opentelemetry.io/otel/example/fib` package is in favor of `go.opentelemetry.io/otel/example/dice`. (#4618)
- Deprecate `go.opentelemetry.io/otel/trace.NewNoopTracerProvider`.
Use the added `NewTracerProvider` function in `go.opentelemetry.io/otel/trace/noop` instead. (#4620)
- Deprecate `go.opentelemetry.io/otel/example/view` package in favor of `go.opentelemetry.io/otel/example/prometheus`. (#4649)
- Deprecate `go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#4693)
### Changed
- `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.
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.
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.
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.
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.
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.
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/otlpmetrichttp` does no longer depend on `go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#4660)
- Retry for `502 Bad Gateway` and `504 Gateway Timeout` HTTP statuses in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#4670)
- Retry for `502 Bad Gateway` and `504 Gateway Timeout` HTTP statuses in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#4670)
- Retry for `RESOURCE_EXHAUSTED` only if RetryInfo is returned in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#4669)
- Retry for `RESOURCE_EXHAUSTED` only if RetryInfo is returned in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#4669)
- Retry temporary HTTP request failures in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#4679)
- Retry temporary HTTP request failures in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#4679)
### Fixed
- Fix improper parsing of characters such us `+`, `/` by `Parse` in `go.opentelemetry.io/otel/baggage` as they were rendered as a whitespace. (#4667)
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_RESOURCE_ATTRIBUTES` in `go.opentelemetry.io/otel/sdk/resource` as they were rendered as a whitespace. (#4699)
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_METRICS_HEADERS` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` as they were rendered as a whitespace. (#4699)
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_METRICS_HEADERS` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` as they were rendered as a whitespace. (#4699)
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_TRACES_HEADERS` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlptracegrpc` as they were rendered as a whitespace. (#4699)
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_TRACES_HEADERS` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlptracehttp` as they were rendered as a whitespace. (#4699)
- In `go.opentelemetry.op/otel/exporters/prometheus`, the exporter no longer `Collect`s metrics after `Shutdown` is invoked. (#4648)
- Fix documentation for `WithCompressor` in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#4695)
- Fix documentation for `WithCompressor` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#4695)
## [1.19.0/0.42.0/0.0.7] 2023-09-28 ## [1.19.0/0.42.0/0.0.7] 2023-09-28
This release contains the first stable release of the OpenTelemetry Go [metric SDK]. This release contains the first stable release of the OpenTelemetry Go [metric SDK].
@ -2656,7 +2721,8 @@ 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.19.0...HEAD [Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.20.0...HEAD
[1.20.0/0.43.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.20.0
[1.19.0/0.42.0/0.0.7]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.19.0 [1.19.0/0.42.0/0.0.7]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.19.0
[1.19.0-rc.1/0.42.0-rc.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.19.0-rc.1 [1.19.0-rc.1/0.42.0-rc.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.19.0-rc.1
[1.18.0/0.41.0/0.0.6]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.18.0 [1.18.0/0.41.0/0.0.6]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.18.0
@ -2731,7 +2797,7 @@ It contains api and sdk for trace and meter.
[Go 1.20]: https://go.dev/doc/go1.20 [Go 1.20]: https://go.dev/doc/go1.20
[Go 1.19]: https://go.dev/doc/go1.19 [Go 1.19]: https://go.dev/doc/go1.19
[Go 1.18]: https://go.dev/doc/go1.18 [Go 1.18]: https://go.dev/doc/go1.18
[Go 1.19]: https://go.dev/doc/go1.19
[metric API]:https://pkg.go.dev/go.opentelemetry.io/otel/metric [metric API]:https://pkg.go.dev/go.opentelemetry.io/otel/metric
[metric SDK]:https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric [metric SDK]:https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric
[trace API]:https://pkg.go.dev/go.opentelemetry.io/otel/trace

View File

@ -77,6 +77,9 @@ $(GOTMPL): PACKAGE=go.opentelemetry.io/build-tools/gotmpl
GORELEASE = $(TOOLS)/gorelease GORELEASE = $(TOOLS)/gorelease
$(GORELEASE): PACKAGE=golang.org/x/exp/cmd/gorelease $(GORELEASE): PACKAGE=golang.org/x/exp/cmd/gorelease
GOVULNCHECK = $(TOOLS)/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) $(DBOTCONF) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(GOJQ) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE)
@ -189,6 +192,18 @@ test-coverage: | $(GOCOVMERGE)
done; \ done; \
$(GOCOVMERGE) $$(find . -name coverage.out) > coverage.txt $(GOCOVMERGE) $$(find . -name coverage.out) > coverage.txt
# Adding a directory will include all benchmarks in that direcotry if a filter is not specified.
BENCHMARK_TARGETS := sdk/trace
.PHONY: benchmark
benchmark: $(BENCHMARK_TARGETS:%=benchmark/%)
BENCHMARK_FILTER = .
# You can override the filter for a particular directory by adding a rule here.
benchmark/sdk/trace: BENCHMARK_FILTER = SpanWithAttributes_8/AlwaysSample
benchmark/%:
@echo "$(GO) test -timeout $(TIMEOUT)s -run=xxxxxMatchNothingxxxxx -bench=$(BENCHMARK_FILTER) $*..." \
&& cd $* \
$(foreach filter, $(BENCHMARK_FILTER), && $(GO) test -timeout $(TIMEOUT)s -run=xxxxxMatchNothingxxxxx -bench=$(filter))
.PHONY: golangci-lint golangci-lint-fix .PHONY: golangci-lint golangci-lint-fix
golangci-lint-fix: ARGS=--fix golangci-lint-fix: ARGS=--fix
golangci-lint-fix: golangci-lint golangci-lint-fix: golangci-lint
@ -216,7 +231,7 @@ go-mod-tidy/%: | crosslink
lint-modules: go-mod-tidy lint-modules: go-mod-tidy
.PHONY: lint .PHONY: lint
lint: misspell lint-modules golangci-lint lint: misspell lint-modules golangci-lint govulncheck
.PHONY: vanity-import-check .PHONY: vanity-import-check
vanity-import-check: | $(PORTO) vanity-import-check: | $(PORTO)
@ -226,6 +241,14 @@ vanity-import-check: | $(PORTO)
misspell: | $(MISSPELL) misspell: | $(MISSPELL)
@$(MISSPELL) -w $(ALL_DOCS) @$(MISSPELL) -w $(ALL_DOCS)
.PHONY: govulncheck
govulncheck: $(OTEL_GO_MOD_DIRS:%=govulncheck/%)
govulncheck/%: DIR=$*
govulncheck/%: | $(GOVULNCHECK)
@echo "govulncheck ./... in $(DIR)" \
&& cd $(DIR) \
&& $(GOVULNCHECK) ./...
.PHONY: codespell .PHONY: codespell
codespell: | $(CODESPELL) codespell: | $(CODESPELL)
@$(DOCKERPY) $(CODESPELL) @$(DOCKERPY) $(CODESPELL)
@ -289,3 +312,7 @@ COMMIT ?= "HEAD"
add-tags: | $(MULTIMOD) add-tags: | $(MULTIMOD)
@[ "${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) verify && $(MULTIMOD) tag -m ${MODSET} -c ${COMMIT}
.PHONY: lint-markdown
lint-markdown:
docker run -v "$(CURDIR):$(WORKDIR)" docker://avtodev/markdown-lint:v1 -c $(WORKDIR)/.markdownlint.yaml $(WORKDIR)/**/*.md

View File

@ -11,16 +11,13 @@ It provides a set of APIs to directly measure performance and behavior of your s
## Project Status ## Project Status
| Signal | Status | Project | | Signal | Status |
|---------|------------|-----------------------| |---------|------------|
| Traces | Stable | N/A | | Traces | Stable |
| Metrics | Mixed [1] | [Go: Metric SDK (GA)] | | Metrics | Stable |
| Logs | Frozen [2] | N/A | | Logs | Design [1] |
[Go: Metric SDK (GA)]: https://github.com/orgs/open-telemetry/projects/34 - [1]: Currently the logs signal development is in a design phase ([#4696](https://github.com/open-telemetry/opentelemetry-go/issues/4696)).
- [1]: [Metrics API](https://pkg.go.dev/go.opentelemetry.io/otel/metric) is Stable. [Metrics SDK](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric) is Beta.
- [2]: The Logs signal development is halted for this project while we stabilize the Metrics SDK.
No Logs Pull Requests are currently being accepted. No Logs Pull Requests are currently being accepted.
Progress and status specific to this repository is tracked in our Progress and status specific to this repository is tracked in our

View File

@ -254,7 +254,7 @@ func NewMember(key, value string, props ...Property) (Member, error) {
if err := m.validate(); err != nil { if err := m.validate(); err != nil {
return newInvalidMember(), err return newInvalidMember(), err
} }
decodedValue, err := url.QueryUnescape(value) decodedValue, err := url.PathUnescape(value)
if err != nil { if err != nil {
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value) return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value)
} }
@ -301,7 +301,7 @@ func parseMember(member string) (Member, error) {
// when converting the header into a data structure." // when converting the header into a data structure."
key = strings.TrimSpace(k) key = strings.TrimSpace(k)
var err error var err error
value, err = url.QueryUnescape(strings.TrimSpace(v)) value, err = url.PathUnescape(strings.TrimSpace(v))
if err != nil { if err != nil {
return newInvalidMember(), fmt.Errorf("%w: %q", err, value) return newInvalidMember(), fmt.Errorf("%w: %q", err, value)
} }

View File

@ -34,11 +34,13 @@ type afCounter struct {
name string name string
opts []metric.Float64ObservableCounterOption opts []metric.Float64ObservableCounterOption
delegate atomic.Value //metric.Float64ObservableCounter delegate atomic.Value // metric.Float64ObservableCounter
} }
var _ unwrapper = (*afCounter)(nil) var (
var _ metric.Float64ObservableCounter = (*afCounter)(nil) _ unwrapper = (*afCounter)(nil)
_ metric.Float64ObservableCounter = (*afCounter)(nil)
)
func (i *afCounter) setDelegate(m metric.Meter) { func (i *afCounter) setDelegate(m metric.Meter) {
ctr, err := m.Float64ObservableCounter(i.name, i.opts...) ctr, err := m.Float64ObservableCounter(i.name, i.opts...)
@ -63,11 +65,13 @@ type afUpDownCounter struct {
name string name string
opts []metric.Float64ObservableUpDownCounterOption opts []metric.Float64ObservableUpDownCounterOption
delegate atomic.Value //metric.Float64ObservableUpDownCounter delegate atomic.Value // metric.Float64ObservableUpDownCounter
} }
var _ unwrapper = (*afUpDownCounter)(nil) var (
var _ metric.Float64ObservableUpDownCounter = (*afUpDownCounter)(nil) _ unwrapper = (*afUpDownCounter)(nil)
_ metric.Float64ObservableUpDownCounter = (*afUpDownCounter)(nil)
)
func (i *afUpDownCounter) setDelegate(m metric.Meter) { func (i *afUpDownCounter) setDelegate(m metric.Meter) {
ctr, err := m.Float64ObservableUpDownCounter(i.name, i.opts...) ctr, err := m.Float64ObservableUpDownCounter(i.name, i.opts...)
@ -92,11 +96,13 @@ type afGauge struct {
name string name string
opts []metric.Float64ObservableGaugeOption opts []metric.Float64ObservableGaugeOption
delegate atomic.Value //metric.Float64ObservableGauge delegate atomic.Value // metric.Float64ObservableGauge
} }
var _ unwrapper = (*afGauge)(nil) var (
var _ metric.Float64ObservableGauge = (*afGauge)(nil) _ unwrapper = (*afGauge)(nil)
_ metric.Float64ObservableGauge = (*afGauge)(nil)
)
func (i *afGauge) setDelegate(m metric.Meter) { func (i *afGauge) setDelegate(m metric.Meter) {
ctr, err := m.Float64ObservableGauge(i.name, i.opts...) ctr, err := m.Float64ObservableGauge(i.name, i.opts...)
@ -121,11 +127,13 @@ type aiCounter struct {
name string name string
opts []metric.Int64ObservableCounterOption opts []metric.Int64ObservableCounterOption
delegate atomic.Value //metric.Int64ObservableCounter delegate atomic.Value // metric.Int64ObservableCounter
} }
var _ unwrapper = (*aiCounter)(nil) var (
var _ metric.Int64ObservableCounter = (*aiCounter)(nil) _ unwrapper = (*aiCounter)(nil)
_ metric.Int64ObservableCounter = (*aiCounter)(nil)
)
func (i *aiCounter) setDelegate(m metric.Meter) { func (i *aiCounter) setDelegate(m metric.Meter) {
ctr, err := m.Int64ObservableCounter(i.name, i.opts...) ctr, err := m.Int64ObservableCounter(i.name, i.opts...)
@ -150,11 +158,13 @@ type aiUpDownCounter struct {
name string name string
opts []metric.Int64ObservableUpDownCounterOption opts []metric.Int64ObservableUpDownCounterOption
delegate atomic.Value //metric.Int64ObservableUpDownCounter delegate atomic.Value // metric.Int64ObservableUpDownCounter
} }
var _ unwrapper = (*aiUpDownCounter)(nil) var (
var _ metric.Int64ObservableUpDownCounter = (*aiUpDownCounter)(nil) _ unwrapper = (*aiUpDownCounter)(nil)
_ metric.Int64ObservableUpDownCounter = (*aiUpDownCounter)(nil)
)
func (i *aiUpDownCounter) setDelegate(m metric.Meter) { func (i *aiUpDownCounter) setDelegate(m metric.Meter) {
ctr, err := m.Int64ObservableUpDownCounter(i.name, i.opts...) ctr, err := m.Int64ObservableUpDownCounter(i.name, i.opts...)
@ -179,11 +189,13 @@ type aiGauge struct {
name string name string
opts []metric.Int64ObservableGaugeOption opts []metric.Int64ObservableGaugeOption
delegate atomic.Value //metric.Int64ObservableGauge delegate atomic.Value // metric.Int64ObservableGauge
} }
var _ unwrapper = (*aiGauge)(nil) var (
var _ metric.Int64ObservableGauge = (*aiGauge)(nil) _ unwrapper = (*aiGauge)(nil)
_ metric.Int64ObservableGauge = (*aiGauge)(nil)
)
func (i *aiGauge) setDelegate(m metric.Meter) { func (i *aiGauge) setDelegate(m metric.Meter) {
ctr, err := m.Int64ObservableGauge(i.name, i.opts...) ctr, err := m.Int64ObservableGauge(i.name, i.opts...)
@ -208,7 +220,7 @@ type sfCounter struct {
name string name string
opts []metric.Float64CounterOption opts []metric.Float64CounterOption
delegate atomic.Value //metric.Float64Counter delegate atomic.Value // metric.Float64Counter
} }
var _ metric.Float64Counter = (*sfCounter)(nil) var _ metric.Float64Counter = (*sfCounter)(nil)
@ -234,7 +246,7 @@ type sfUpDownCounter struct {
name string name string
opts []metric.Float64UpDownCounterOption opts []metric.Float64UpDownCounterOption
delegate atomic.Value //metric.Float64UpDownCounter delegate atomic.Value // metric.Float64UpDownCounter
} }
var _ metric.Float64UpDownCounter = (*sfUpDownCounter)(nil) var _ metric.Float64UpDownCounter = (*sfUpDownCounter)(nil)
@ -260,7 +272,7 @@ type sfHistogram struct {
name string name string
opts []metric.Float64HistogramOption opts []metric.Float64HistogramOption
delegate atomic.Value //metric.Float64Histogram delegate atomic.Value // metric.Float64Histogram
} }
var _ metric.Float64Histogram = (*sfHistogram)(nil) var _ metric.Float64Histogram = (*sfHistogram)(nil)
@ -286,7 +298,7 @@ type siCounter struct {
name string name string
opts []metric.Int64CounterOption opts []metric.Int64CounterOption
delegate atomic.Value //metric.Int64Counter delegate atomic.Value // metric.Int64Counter
} }
var _ metric.Int64Counter = (*siCounter)(nil) var _ metric.Int64Counter = (*siCounter)(nil)
@ -312,7 +324,7 @@ type siUpDownCounter struct {
name string name string
opts []metric.Int64UpDownCounterOption opts []metric.Int64UpDownCounterOption
delegate atomic.Value //metric.Int64UpDownCounter delegate atomic.Value // metric.Int64UpDownCounter
} }
var _ metric.Int64UpDownCounter = (*siUpDownCounter)(nil) var _ metric.Int64UpDownCounter = (*siUpDownCounter)(nil)
@ -338,7 +350,7 @@ type siHistogram struct {
name string name string
opts []metric.Int64HistogramOption opts []metric.Int64HistogramOption
delegate atomic.Value //metric.Int64Histogram delegate atomic.Value // metric.Int64Histogram
} }
var _ metric.Int64Histogram = (*siHistogram)(nil) var _ metric.Int64Histogram = (*siHistogram)(nil)

View File

@ -39,6 +39,7 @@ 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/trace" "go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/embedded"
) )
// tracerProvider is a placeholder for a configured SDK TracerProvider. // tracerProvider is a placeholder for a configured SDK TracerProvider.
@ -46,6 +47,8 @@ import (
// All TracerProvider functionality is forwarded to a delegate once // All TracerProvider functionality is forwarded to a delegate once
// configured. // configured.
type tracerProvider struct { type tracerProvider struct {
embedded.TracerProvider
mtx sync.Mutex mtx sync.Mutex
tracers map[il]*tracer tracers map[il]*tracer
delegate trace.TracerProvider delegate trace.TracerProvider
@ -119,6 +122,8 @@ type il struct {
// All Tracer functionality is forwarded to a delegate once configured. // All Tracer functionality is forwarded to a delegate once configured.
// Otherwise, all functionality is forwarded to a NoopTracer. // Otherwise, all functionality is forwarded to a NoopTracer.
type tracer struct { type tracer struct {
embedded.Tracer
name string name string
opts []trace.TracerOption opts []trace.TracerOption
provider *tracerProvider provider *tracerProvider
@ -156,6 +161,8 @@ func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStart
// SpanContext. It performs no operations other than to return the wrapped // SpanContext. It performs no operations other than to return the wrapped
// SpanContext. // SpanContext.
type nonRecordingSpan struct { type nonRecordingSpan struct {
embedded.Span
sc trace.SpanContext sc trace.SpanContext
tracer *tracer tracer *tracer
} }

View File

@ -149,7 +149,7 @@ of [go.opentelemetry.io/otel/metric].
Finally, an author can embed another implementation in theirs. The embedded Finally, an author can embed another implementation in theirs. The embedded
implementation will be used for methods not defined by the author. For example, implementation will be used for methods not defined by the author. For example,
an author who want to default to silently dropping the call can use an author who wants to default to silently dropping the call can use
[go.opentelemetry.io/otel/metric/noop]: [go.opentelemetry.io/otel/metric/noop]:
import "go.opentelemetry.io/otel/metric/noop" import "go.opentelemetry.io/otel/metric/noop"

View File

@ -39,6 +39,12 @@ type InstrumentOption interface {
Float64ObservableGaugeOption Float64ObservableGaugeOption
} }
// HistogramOption applies options to histogram instruments.
type HistogramOption interface {
Int64HistogramOption
Float64HistogramOption
}
type descOpt string type descOpt string
func (o descOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig { func (o descOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig {
@ -171,6 +177,23 @@ func (o unitOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64Ob
// The unit u should be defined using the appropriate [UCUM](https://ucum.org) case-sensitive code. // The unit u should be defined using the appropriate [UCUM](https://ucum.org) case-sensitive code.
func WithUnit(u string) InstrumentOption { return unitOpt(u) } func WithUnit(u string) InstrumentOption { return unitOpt(u) }
// WithExplicitBucketBoundaries sets the instrument explicit bucket boundaries.
//
// This option is considered "advisory", and may be ignored by API implementations.
func WithExplicitBucketBoundaries(bounds ...float64) HistogramOption { return bucketOpt(bounds) }
type bucketOpt []float64
func (o bucketOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
c.explicitBucketBoundaries = o
return c
}
func (o bucketOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
c.explicitBucketBoundaries = o
return c
}
// AddOption applies options to an addition measurement. See // AddOption applies options to an addition measurement. See
// [MeasurementOption] for other options that can be used as an AddOption. // [MeasurementOption] for other options that can be used as an AddOption.
type AddOption interface { type AddOption interface {

View File

@ -149,6 +149,7 @@ type Float64Histogram interface {
type Float64HistogramConfig struct { type Float64HistogramConfig struct {
description string description string
unit string unit string
explicitBucketBoundaries []float64
} }
// NewFloat64HistogramConfig returns a new [Float64HistogramConfig] with all // NewFloat64HistogramConfig returns a new [Float64HistogramConfig] with all
@ -171,6 +172,11 @@ func (c Float64HistogramConfig) Unit() string {
return c.unit return c.unit
} }
// ExplicitBucketBoundaries returns the configured explicit bucket boundaries.
func (c Float64HistogramConfig) ExplicitBucketBoundaries() []float64 {
return c.explicitBucketBoundaries
}
// Float64HistogramOption applies options to a [Float64HistogramConfig]. See // Float64HistogramOption applies options to a [Float64HistogramConfig]. See
// [InstrumentOption] for other options that can be used as a // [InstrumentOption] for other options that can be used as a
// Float64HistogramOption. // Float64HistogramOption.

View File

@ -149,6 +149,7 @@ type Int64Histogram interface {
type Int64HistogramConfig struct { type Int64HistogramConfig struct {
description string description string
unit string unit string
explicitBucketBoundaries []float64
} }
// NewInt64HistogramConfig returns a new [Int64HistogramConfig] with all opts // NewInt64HistogramConfig returns a new [Int64HistogramConfig] with all opts
@ -171,6 +172,11 @@ func (c Int64HistogramConfig) Unit() string {
return c.unit return c.unit
} }
// ExplicitBucketBoundaries returns the configured explicit bucket boundaries.
func (c Int64HistogramConfig) ExplicitBucketBoundaries() []float64 {
return c.explicitBucketBoundaries
}
// Int64HistogramOption applies options to a [Int64HistogramConfig]. See // Int64HistogramOption applies options to a [Int64HistogramConfig]. See
// [InstrumentOption] for other options that can be used as an // [InstrumentOption] for other options that can be used as an
// Int64HistogramOption. // Int64HistogramOption.

View File

@ -40,8 +40,10 @@ const (
// their proprietary information. // their proprietary information.
type TraceContext struct{} type TraceContext struct{}
var _ TextMapPropagator = TraceContext{} var (
var traceCtxRegExp = regexp.MustCompile("^(?P<version>[0-9a-f]{2})-(?P<traceID>[a-f0-9]{32})-(?P<spanID>[a-f0-9]{16})-(?P<traceFlags>[a-f0-9]{2})(?:-.*)?$") _ TextMapPropagator = TraceContext{}
traceCtxRegExp = regexp.MustCompile("^(?P<version>[0-9a-f]{2})-(?P<traceID>[a-f0-9]{32})-(?P<spanID>[a-f0-9]{16})-(?P<traceFlags>[a-f0-9]{2})(?:-.*)?$")
)
// Inject set tracecontext from the Context into the carrier. // Inject set tracecontext from the Context into the carrier.
func (tc TraceContext) Inject(ctx context.Context, carrier TextMapCarrier) { func (tc TraceContext) Inject(ctx context.Context, carrier TextMapCarrier) {

View File

@ -1 +1 @@
codespell==2.2.5 codespell==2.2.6

View File

@ -268,6 +268,7 @@ func (o stackTraceOption) applyEvent(c EventConfig) EventConfig {
c.stackTrace = bool(o) c.stackTrace = bool(o)
return c return c
} }
func (o stackTraceOption) applySpan(c SpanConfig) SpanConfig { func (o stackTraceOption) applySpan(c SpanConfig) SpanConfig {
c.stackTrace = bool(o) c.stackTrace = bool(o)
return c return c

View File

@ -62,5 +62,69 @@ a default.
defer span.End() defer span.End()
// ... // ...
} }
# API Implementations
This package does not conform to the standard Go versioning policy; all of its
interfaces may have methods added to them without a package major version bump.
This non-standard API evolution could surprise an uninformed implementation
author. They could unknowingly build their implementation in a way that would
result in a runtime panic for their users that update to the new API.
The API is designed to help inform an instrumentation author about this
non-standard API evolution. It requires them to choose a default behavior for
unimplemented interface methods. There are three behavior choices they can
make:
- Compilation failure
- Panic
- Default to another implementation
All interfaces in this API embed a corresponding interface from
[go.opentelemetry.io/otel/trace/embedded]. If an author wants the default
behavior of their implementations to be a compilation failure, signaling to
their users they need to update to the latest version of that implementation,
they need to embed the corresponding interface from
[go.opentelemetry.io/otel/trace/embedded] in their implementation. For
example,
import "go.opentelemetry.io/otel/trace/embedded"
type TracerProvider struct {
embedded.TracerProvider
// ...
}
If an author wants the default behavior of their implementations to panic, they
can embed the API interface directly.
import "go.opentelemetry.io/otel/trace"
type TracerProvider struct {
trace.TracerProvider
// ...
}
This option is not recommended. It will lead to publishing packages that
contain runtime panics when users update to newer versions of
[go.opentelemetry.io/otel/trace], which may be done with a trasitive
dependency.
Finally, an author can embed another implementation in theirs. The embedded
implementation will be used for methods not defined by the author. For example,
an author who wants to default to silently dropping the call can use
[go.opentelemetry.io/otel/trace/noop]:
import "go.opentelemetry.io/otel/trace/noop"
type TracerProvider struct {
noop.TracerProvider
// ...
}
It is strongly recommended that authors only embed
[go.opentelemetry.io/otel/trace/noop] if they choose this default behavior.
That implementation is the only one OpenTelemetry authors can guarantee will
fully implement all the API interfaces when a user updates their API.
*/ */
package trace // import "go.opentelemetry.io/otel/trace" package trace // import "go.opentelemetry.io/otel/trace"

View File

@ -0,0 +1,56 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package embedded provides interfaces embedded within the [OpenTelemetry
// trace API].
//
// Implementers of the [OpenTelemetry trace API] can embed the relevant type
// from this package into their implementation directly. Doing so will result
// in a compilation error for users when the [OpenTelemetry trace API] is
// extended (which is something that can happen without a major version bump of
// the API package).
//
// [OpenTelemetry trace API]: https://pkg.go.dev/go.opentelemetry.io/otel/trace
package embedded // import "go.opentelemetry.io/otel/trace/embedded"
// TracerProvider is embedded in
// [go.opentelemetry.io/otel/trace.TracerProvider].
//
// Embed this interface in your implementation of the
// [go.opentelemetry.io/otel/trace.TracerProvider] if you want users to
// experience a compilation error, signaling they need to update to your latest
// implementation, when the [go.opentelemetry.io/otel/trace.TracerProvider]
// interface is extended (which is something that can happen without a major
// version bump of the API package).
type TracerProvider interface{ tracerProvider() }
// Tracer is embedded in [go.opentelemetry.io/otel/trace.Tracer].
//
// Embed this interface in your implementation of the
// [go.opentelemetry.io/otel/trace.Tracer] if you want users to experience a
// compilation error, signaling they need to update to your latest
// implementation, when the [go.opentelemetry.io/otel/trace.Tracer] interface
// is extended (which is something that can happen without a major version bump
// of the API package).
type Tracer interface{ tracer() }
// Span is embedded in [go.opentelemetry.io/otel/trace.Span].
//
// Embed this interface in your implementation of the
// [go.opentelemetry.io/otel/trace.Span] if you want users to experience a
// compilation error, signaling they need to update to your latest
// implementation, when the [go.opentelemetry.io/otel/trace.Span] interface is
// extended (which is something that can happen without a major version bump of
// the API package).
type Span interface{ span() }

View File

@ -19,16 +19,20 @@ 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/trace/embedded"
) )
// NewNoopTracerProvider returns an implementation of TracerProvider that // NewNoopTracerProvider returns an implementation of TracerProvider that
// performs no operations. The Tracer and Spans created from the returned // performs no operations. The Tracer and Spans created from the returned
// TracerProvider also perform no operations. // TracerProvider also perform no operations.
//
// Deprecated: Use [go.opentelemetry.io/otel/trace/noop.NewTracerProvider]
// instead.
func NewNoopTracerProvider() TracerProvider { func NewNoopTracerProvider() TracerProvider {
return noopTracerProvider{} return noopTracerProvider{}
} }
type noopTracerProvider struct{} type noopTracerProvider struct{ embedded.TracerProvider }
var _ TracerProvider = noopTracerProvider{} var _ TracerProvider = noopTracerProvider{}
@ -38,7 +42,7 @@ func (p noopTracerProvider) Tracer(string, ...TracerOption) Tracer {
} }
// noopTracer is an implementation of Tracer that performs no operations. // noopTracer is an implementation of Tracer that performs no operations.
type noopTracer struct{} type noopTracer struct{ embedded.Tracer }
var _ Tracer = noopTracer{} var _ Tracer = noopTracer{}
@ -54,7 +58,7 @@ func (t noopTracer) Start(ctx context.Context, name string, _ ...SpanStartOption
} }
// noopSpan is an implementation of Span that performs no operations. // noopSpan is an implementation of Span that performs no operations.
type noopSpan struct{} type noopSpan struct{ embedded.Span }
var _ Span = noopSpan{} var _ Span = noopSpan{}

View File

@ -22,6 +22,7 @@ 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/trace/embedded"
) )
const ( const (
@ -48,8 +49,10 @@ func (e errorConst) Error() string {
// nolint:revive // revive complains about stutter of `trace.TraceID`. // nolint:revive // revive complains about stutter of `trace.TraceID`.
type TraceID [16]byte type TraceID [16]byte
var nilTraceID TraceID var (
var _ json.Marshaler = nilTraceID nilTraceID TraceID
_ json.Marshaler = nilTraceID
)
// IsValid checks whether the trace TraceID is valid. A valid trace ID does // IsValid checks whether the trace TraceID is valid. A valid trace ID does
// not consist of zeros only. // not consist of zeros only.
@ -71,8 +74,10 @@ func (t TraceID) String() string {
// SpanID is a unique identity of a span in a trace. // SpanID is a unique identity of a span in a trace.
type SpanID [8]byte type SpanID [8]byte
var nilSpanID SpanID var (
var _ json.Marshaler = nilSpanID nilSpanID SpanID
_ json.Marshaler = nilSpanID
)
// IsValid checks whether the SpanID is valid. A valid SpanID does not consist // IsValid checks whether the SpanID is valid. A valid SpanID does not consist
// of zeros only. // of zeros only.
@ -338,8 +343,15 @@ func (sc SpanContext) MarshalJSON() ([]byte, error) {
// create a Span and it is then up to the operation the Span represents to // create a Span and it is then up to the operation the Span represents to
// properly end the Span when the operation itself ends. // properly end the Span when the operation itself ends.
// //
// Warning: methods may be added to this interface in minor releases. // 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 Span interface { type Span 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.Span
// End completes the Span. The Span is considered complete and ready to be // End completes the Span. The Span is considered complete and ready to be
// delivered through the rest of the telemetry pipeline after this method // delivered through the rest of the telemetry pipeline after this method
// is called. Therefore, updates to the Span are not allowed after this // is called. Therefore, updates to the Span are not allowed after this
@ -486,8 +498,15 @@ func (sk SpanKind) String() string {
// Tracer is the creator of Spans. // Tracer is the creator of Spans.
// //
// Warning: methods may be added to this interface in minor releases. // 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 Tracer interface { type Tracer 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.Tracer
// Start creates a span and a context.Context containing the newly-created span. // Start creates a span and a context.Context containing the newly-created span.
// //
// If the context.Context provided in `ctx` contains a Span then the newly-created // If the context.Context provided in `ctx` contains a Span then the newly-created
@ -518,8 +537,15 @@ type Tracer interface {
// at runtime from its users or it can simply use the globally registered one // at runtime from its users or it can simply use the globally registered one
// (see https://pkg.go.dev/go.opentelemetry.io/otel#GetTracerProvider). // (see https://pkg.go.dev/go.opentelemetry.io/otel#GetTracerProvider).
// //
// Warning: methods may be added to this interface in minor releases. // 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 TracerProvider interface { type TracerProvider 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.TracerProvider
// Tracer returns a unique Tracer scoped to be used by instrumentation code // Tracer returns a unique Tracer scoped to be used by instrumentation code
// to trace computational workflows. The scope and identity of that // to trace computational workflows. The scope and identity of that
// instrumentation code is uniquely defined by the name and options passed. // instrumentation code is uniquely defined by the name and options passed.

View File

@ -28,9 +28,9 @@ const (
// based on the W3C Trace Context specification, see // based on the W3C Trace Context specification, see
// https://www.w3.org/TR/trace-context-1/#tracestate-header // https://www.w3.org/TR/trace-context-1/#tracestate-header
noTenantKeyFormat = `[a-z][_0-9a-z\-\*\/]{0,255}` noTenantKeyFormat = `[a-z][_0-9a-z\-\*\/]*`
withTenantKeyFormat = `[a-z0-9][_0-9a-z\-\*\/]{0,240}@[a-z][_0-9a-z\-\*\/]{0,13}` withTenantKeyFormat = `[a-z0-9][_0-9a-z\-\*\/]*@[a-z][_0-9a-z\-\*\/]*`
valueFormat = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]{0,255}[\x21-\x2b\x2d-\x3c\x3e-\x7e]` valueFormat = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]*[\x21-\x2b\x2d-\x3c\x3e-\x7e]`
errInvalidKey errorConst = "invalid tracestate key" errInvalidKey errorConst = "invalid tracestate key"
errInvalidValue errorConst = "invalid tracestate value" errInvalidValue errorConst = "invalid tracestate value"
@ -40,9 +40,10 @@ const (
) )
var ( var (
keyRe = regexp.MustCompile(`^((` + noTenantKeyFormat + `)|(` + withTenantKeyFormat + `))$`) noTenantKeyRe = regexp.MustCompile(`^` + noTenantKeyFormat + `$`)
valueRe = regexp.MustCompile(`^(` + valueFormat + `)$`) withTenantKeyRe = regexp.MustCompile(`^` + withTenantKeyFormat + `$`)
memberRe = regexp.MustCompile(`^\s*((` + noTenantKeyFormat + `)|(` + withTenantKeyFormat + `))=(` + valueFormat + `)\s*$`) valueRe = regexp.MustCompile(`^` + valueFormat + `$`)
memberRe = regexp.MustCompile(`^\s*((?:` + noTenantKeyFormat + `)|(?:` + withTenantKeyFormat + `))=(` + valueFormat + `)\s*$`)
) )
type member struct { type member struct {
@ -51,10 +52,19 @@ type member struct {
} }
func newMember(key, value string) (member, error) { func newMember(key, value string) (member, error) {
if !keyRe.MatchString(key) { if len(key) > 256 {
return member{}, fmt.Errorf("%w: %s", errInvalidKey, key) return member{}, fmt.Errorf("%w: %s", errInvalidKey, key)
} }
if !valueRe.MatchString(value) { if !noTenantKeyRe.MatchString(key) {
if !withTenantKeyRe.MatchString(key) {
return member{}, fmt.Errorf("%w: %s", errInvalidKey, key)
}
atIndex := strings.LastIndex(key, "@")
if atIndex > 241 || len(key)-1-atIndex > 14 {
return member{}, fmt.Errorf("%w: %s", errInvalidKey, key)
}
}
if len(value) > 256 || !valueRe.MatchString(value) {
return member{}, fmt.Errorf("%w: %s", errInvalidValue, value) return member{}, fmt.Errorf("%w: %s", errInvalidValue, value)
} }
return member{Key: key, Value: value}, nil return member{Key: key, Value: value}, nil
@ -62,14 +72,14 @@ func newMember(key, value string) (member, error) {
func parseMember(m string) (member, error) { func parseMember(m string) (member, error) {
matches := memberRe.FindStringSubmatch(m) matches := memberRe.FindStringSubmatch(m)
if len(matches) != 5 { if len(matches) != 3 {
return member{}, fmt.Errorf("%w: %s", errInvalidMember, m) return member{}, fmt.Errorf("%w: %s", errInvalidMember, m)
} }
result, e := newMember(matches[1], matches[2])
return member{ if e != nil {
Key: matches[1], return member{}, fmt.Errorf("%w: %s", errInvalidMember, m)
Value: matches[4], }
}, nil return result, nil
} }
// String encodes member into a string compliant with the W3C Trace Context // String encodes member into a string compliant with the W3C Trace Context

View File

@ -16,5 +16,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.19.0" return "1.20.0"
} }

View File

@ -14,7 +14,7 @@
module-sets: module-sets:
stable-v1: stable-v1:
version: v1.19.0 version: v1.20.0
modules: modules:
- go.opentelemetry.io/otel - go.opentelemetry.io/otel
- go.opentelemetry.io/otel/bridge/opentracing - go.opentelemetry.io/otel/bridge/opentracing
@ -35,7 +35,7 @@ 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.42.0 version: v0.43.0
modules: modules:
- go.opentelemetry.io/otel/bridge/opencensus - go.opentelemetry.io/otel/bridge/opencensus
- go.opentelemetry.io/otel/bridge/opencensus/test - go.opentelemetry.io/otel/bridge/opencensus/test

11
vendor/modules.txt vendored
View File

@ -565,15 +565,15 @@ go.etcd.io/etcd/client/v3
go.etcd.io/etcd/client/v3/credentials go.etcd.io/etcd/client/v3/credentials
go.etcd.io/etcd/client/v3/internal/endpoint go.etcd.io/etcd/client/v3/internal/endpoint
go.etcd.io/etcd/client/v3/internal/resolver go.etcd.io/etcd/client/v3/internal/resolver
# go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 # go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0
## explicit; go 1.19 ## explicit; go 1.20
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.44.0 # go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0
## explicit; go 1.19 ## explicit; go 1.19
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/semconvutil go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil
# go.opentelemetry.io/otel v1.19.0 # go.opentelemetry.io/otel v1.20.0
## explicit; go 1.20 ## explicit; go 1.20
go.opentelemetry.io/otel go.opentelemetry.io/otel
go.opentelemetry.io/otel/attribute go.opentelemetry.io/otel/attribute
@ -599,7 +599,7 @@ 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/metric v1.19.0 # go.opentelemetry.io/otel/metric v1.20.0
## explicit; go 1.20 ## explicit; go 1.20
go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric
go.opentelemetry.io/otel/metric/embedded go.opentelemetry.io/otel/metric/embedded
@ -611,9 +611,10 @@ 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/resource go.opentelemetry.io/otel/sdk/resource
go.opentelemetry.io/otel/sdk/trace go.opentelemetry.io/otel/sdk/trace
# go.opentelemetry.io/otel/trace v1.19.0 # go.opentelemetry.io/otel/trace v1.20.0
## explicit; go 1.20 ## explicit; go 1.20
go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace
go.opentelemetry.io/otel/trace/embedded
# go.opentelemetry.io/proto/otlp v1.0.0 # go.opentelemetry.io/proto/otlp v1.0.0
## explicit; go 1.17 ## explicit; go 1.17
go.opentelemetry.io/proto/otlp/collector/trace/v1 go.opentelemetry.io/proto/otlp/collector/trace/v1