diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0f611085b41..478cbcfc857 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -34,6 +34,6 @@ updates: schedule: interval: "weekly" groups: - otel: + all: patterns: - - "opentelemetry-*" + - "*" diff --git a/cmd/tracegen/main.go b/cmd/tracegen/main.go index 6e70b84fcbf..43c534fa761 100644 --- a/cmd/tracegen/main.go +++ b/cmd/tracegen/main.go @@ -30,7 +30,7 @@ import ( "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" "go.uber.org/zap/zapcore" diff --git a/docker-compose/monitor/requirements.txt b/docker-compose/monitor/requirements.txt index 2cc06ecc6b8..1edabe32687 100644 --- a/docker-compose/monitor/requirements.txt +++ b/docker-compose/monitor/requirements.txt @@ -1,7 +1,7 @@ backoff==2.2.1 certifi==2023.7.22 charset-normalizer==3.2.0 -Deprecated==1.2.13 +Deprecated==1.2.14 googleapis-common-protos==1.60.0 grpcio==1.56.2 idna==3.4 @@ -16,6 +16,6 @@ protobuf==4.23.4 requests==2.31.0 six==1.16.0 thrift==0.16.0 -typing_extensions==4.4.0 -urllib3==1.26.12 -wrapt==1.14.1 +typing_extensions==4.7.1 +urllib3==2.0.4 +wrapt==1.15.0 diff --git a/examples/hotrod/pkg/tracing/init.go b/examples/hotrod/pkg/tracing/init.go index 8ef811d46c6..fc89bffb639 100644 --- a/examples/hotrod/pkg/tracing/init.go +++ b/examples/hotrod/pkg/tracing/init.go @@ -31,7 +31,7 @@ import ( "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.7.0" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/examples/hotrod/pkg/tracing/rpcmetrics/observer.go b/examples/hotrod/pkg/tracing/rpcmetrics/observer.go index 383660e1c81..ffcb2e27f5e 100644 --- a/examples/hotrod/pkg/tracing/rpcmetrics/observer.go +++ b/examples/hotrod/pkg/tracing/rpcmetrics/observer.go @@ -22,7 +22,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.7.0" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" "go.opentelemetry.io/otel/trace" "github.com/jaegertracing/jaeger/pkg/metrics" diff --git a/go.mod b/go.mod index 95b255233c8..cb0e447a9f1 100644 --- a/go.mod +++ b/go.mod @@ -71,8 +71,8 @@ require ( go.uber.org/atomic v1.11.0 go.uber.org/automaxprocs v1.5.3 go.uber.org/zap v1.25.0 - golang.org/x/net v0.13.0 - golang.org/x/sys v0.10.0 + golang.org/x/net v0.14.0 + golang.org/x/sys v0.11.0 google.golang.org/grpc v1.57.0 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v2 v2.4.0 @@ -172,8 +172,8 @@ require ( go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.11.0 // indirect - golang.org/x/text v0.11.0 // indirect + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/text v0.12.0 // indirect google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect diff --git a/go.sum b/go.sum index 8f62343bc95..5eda17f991f 100644 --- a/go.sum +++ b/go.sum @@ -827,8 +827,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -916,8 +916,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220725212005-46097bf591d3/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= -golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1017,8 +1017,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1032,8 +1032,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/internal/tracegen/config.go b/internal/tracegen/config.go index 7ccb574dd2e..5e6d22a58d9 100644 --- a/internal/tracegen/config.go +++ b/internal/tracegen/config.go @@ -32,6 +32,7 @@ type Config struct { Traces int ChildSpans int Attributes int + AttrKeys int AttrValues int Marshal bool Debug bool @@ -47,8 +48,9 @@ func (c *Config) Flags(fs *flag.FlagSet) { fs.IntVar(&c.Workers, "workers", 1, "Number of workers (goroutines) to run") fs.IntVar(&c.Traces, "traces", 1, "Number of traces to generate in each worker (ignored if duration is provided)") fs.IntVar(&c.ChildSpans, "spans", 1, "Number of child spans to generate for each trace") - fs.IntVar(&c.Attributes, "attrs", 1, "Number of attributes to generate for each child span") - fs.IntVar(&c.AttrValues, "attr-values", 5, "Number of distinct values to allow for each attribute") + fs.IntVar(&c.Attributes, "attrs", 11, "Number of attributes to generate for each child span") + fs.IntVar(&c.AttrKeys, "attr-keys", 97, "Number of distinct attributes keys to use") + fs.IntVar(&c.AttrValues, "attr-values", 1000, "Number of distinct values to allow for each attribute") fs.BoolVar(&c.Debug, "debug", false, "Whether to set DEBUG flag on the spans to force sampling") fs.BoolVar(&c.Firehose, "firehose", false, "Whether to set FIREHOSE flag on the spans to skip indexing") fs.DurationVar(&c.Pause, "pause", time.Microsecond, "How long to sleep before finishing each span. If set to 0s then a fake 123µs duration is used.") diff --git a/internal/tracegen/worker.go b/internal/tracegen/worker.go index 8eeb5373263..4911f548cd6 100644 --- a/internal/tracegen/worker.go +++ b/internal/tracegen/worker.go @@ -36,6 +36,7 @@ type worker struct { // internal counters traceNo int + attrKeyNo int attrValNo int } @@ -94,10 +95,11 @@ func (w *worker) simulateChildSpans(ctx context.Context, start time.Time, tracer for c := 0; c < w.ChildSpans; c++ { var attrs []attribute.KeyValue for a := 0; a < w.Attributes; a++ { - key := fmt.Sprintf("attr_%02d", a) + key := fmt.Sprintf("attr_%02d", w.attrKeyNo) val := fmt.Sprintf("val_%02d", w.attrValNo) - w.attrValNo = (w.attrValNo + 1) % w.AttrValues attrs = append(attrs, attribute.String(key, val)) + w.attrKeyNo = (w.attrKeyNo + 1) % w.AttrKeys + w.attrValNo = (w.attrValNo + 1) % w.AttrValues } opts := []trace.SpanStartOption{ trace.WithSpanKind(trace.SpanKindClient), diff --git a/model/converter/thrift/zipkin/to_domain.go b/model/converter/thrift/zipkin/to_domain.go index 0ee67e5a6ad..f4dd3655f74 100644 --- a/model/converter/thrift/zipkin/to_domain.go +++ b/model/converter/thrift/zipkin/to_domain.go @@ -23,7 +23,7 @@ import ( "errors" "fmt" - "github.com/opentracing/opentracing-go/ext" + "go.opentelemetry.io/otel/trace" "github.com/jaegertracing/jaeger/model" "github.com/jaegertracing/jaeger/thrift-gen/zipkincore" @@ -32,14 +32,20 @@ import ( const ( // UnknownServiceName is serviceName we give to model.Process if we cannot find it anywhere in a Zipkin span UnknownServiceName = "unknown-service-name" + keySpanKind = "span.kind" + component = "component" + peerservice = "peer.service" + peerHostIPv4 = "peer.ipv4" + peerHostIPv6 = "peer.ipv6" + peerPort = "peer.port" ) var ( coreAnnotations = map[string]string{ - zipkincore.SERVER_RECV: string(ext.SpanKindRPCServerEnum), - zipkincore.SERVER_SEND: string(ext.SpanKindRPCServerEnum), - zipkincore.CLIENT_RECV: string(ext.SpanKindRPCClientEnum), - zipkincore.CLIENT_SEND: string(ext.SpanKindRPCClientEnum), + zipkincore.SERVER_RECV: trace.SpanKindServer.String(), + zipkincore.SERVER_SEND: trace.SpanKindServer.String(), + zipkincore.CLIENT_RECV: trace.SpanKindClient.String(), + zipkincore.CLIENT_SEND: trace.SpanKindClient.String(), } // Some tags on Zipkin spans really describe the process emitting them rather than an individual span. @@ -165,13 +171,13 @@ func (td toDomain) transformSpan(zSpan *zipkincore.Span) []*model.Span { } // if the first span is a client span we create server span and vice-versa. if result[0].IsRPCClient() { - s.Tags = []model.KeyValue{model.String(string(ext.SpanKind), string(ext.SpanKindRPCServerEnum))} + s.Tags = []model.KeyValue{model.String(keySpanKind, trace.SpanKindServer.String())} s.StartTime = model.EpochMicrosecondsAsTime(uint64(sr.Timestamp)) if ss := td.findAnnotation(zSpan, zipkincore.SERVER_SEND); ss != nil { s.Duration = model.MicrosecondsAsDuration(uint64(ss.Timestamp - sr.Timestamp)) } } else { - s.Tags = []model.KeyValue{model.String(string(ext.SpanKind), string(ext.SpanKindRPCClientEnum))} + s.Tags = []model.KeyValue{model.String(keySpanKind, trace.SpanKindClient.String())} s.StartTime = model.EpochMicrosecondsAsTime(uint64(cs.Timestamp)) if cr := td.findAnnotation(zSpan, zipkincore.CLIENT_RECV); cr != nil { s.Duration = model.MicrosecondsAsDuration(uint64(cr.Timestamp - cs.Timestamp)) @@ -286,7 +292,7 @@ func (td toDomain) getTags(binAnnotations []*zipkincore.BinaryAnnotation, tagInc switch annotation.Key { case zipkincore.LOCAL_COMPONENT: value := string(annotation.Value) - tag := model.String(string(ext.Component), value) + tag := model.String(component, value) retMe = append(retMe, tag) case zipkincore.SERVER_ADDR, zipkincore.CLIENT_ADDR, zipkincore.MESSAGE_ADDR: retMe = td.getPeerTags(annotation.Host, retMe) @@ -385,7 +391,7 @@ func (td toDomain) getLogFields(annotation *zipkincore.Annotation) []model.KeyVa func (td toDomain) getSpanKindTag(annotations []*zipkincore.Annotation) (model.KeyValue, bool) { for _, a := range annotations { if spanKind, ok := coreAnnotations[a.Value]; ok { - return model.String(string(ext.SpanKind), spanKind), true + return model.String(keySpanKind, spanKind), true } } return model.KeyValue{}, false @@ -395,19 +401,19 @@ func (td toDomain) getPeerTags(endpoint *zipkincore.Endpoint, tags []model.KeyVa if endpoint == nil { return tags } - tags = append(tags, model.String(string(ext.PeerService), endpoint.ServiceName)) + tags = append(tags, model.String(peerservice, endpoint.ServiceName)) if endpoint.Ipv4 != 0 { ipv4 := int64(uint32(endpoint.Ipv4)) - tags = append(tags, model.Int64(string(ext.PeerHostIPv4), ipv4)) + tags = append(tags, model.Int64(peerHostIPv4, ipv4)) } if endpoint.Ipv6 != nil { // Zipkin defines Ipv6 field as: "IPv6 host address packed into 16 bytes. Ex Inet6Address.getBytes()". // https://github.com/openzipkin/zipkin-api/blob/master/thrift/zipkinCore.thrift#L305 - tags = append(tags, model.Binary(string(ext.PeerHostIPv6), endpoint.Ipv6)) + tags = append(tags, model.Binary(peerHostIPv6, endpoint.Ipv6)) } if endpoint.Port != 0 { port := int64(uint16(endpoint.Port)) - tags = append(tags, model.Int64(string(ext.PeerPort), port)) + tags = append(tags, model.Int64(peerPort, port)) } return tags } diff --git a/model/converter/thrift/zipkin/to_domain_test.go b/model/converter/thrift/zipkin/to_domain_test.go index f8589fcddc7..865f59ea554 100644 --- a/model/converter/thrift/zipkin/to_domain_test.go +++ b/model/converter/thrift/zipkin/to_domain_test.go @@ -29,10 +29,9 @@ import ( "github.com/gogo/protobuf/jsonpb" "github.com/gogo/protobuf/proto" "github.com/kr/pretty" - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/ext" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace" "github.com/jaegertracing/jaeger/model" z "github.com/jaegertracing/jaeger/thrift-gen/zipkincore" @@ -116,9 +115,11 @@ func TestToDomainWithDurationFromClientAnnotations(t *testing.T) { func TestToDomainMultipleSpanKinds(t *testing.T) { tests := []struct { - json string - tagFirst opentracing.Tag - tagSecond opentracing.Tag + json string + tagFirstKey string + tagSecondKey string + tagFirstVal trace.SpanKind + tagSecondVal trace.SpanKind }{ { json: `[{ "trace_id": -1, "id": 31, "annotations": [ @@ -126,8 +127,10 @@ func TestToDomainMultipleSpanKinds(t *testing.T) { {"value": "sr", "timestamp": 1, "host": {"service_name": "bar", "ipv4": 23456}}, {"value": "ss", "timestamp": 2, "host": {"service_name": "bar", "ipv4": 23456}} ]}]`, - tagFirst: ext.SpanKindRPCClient, - tagSecond: ext.SpanKindRPCServer, + tagFirstKey: keySpanKind, + tagSecondKey: keySpanKind, + tagFirstVal: trace.SpanKindClient, + tagSecondVal: trace.SpanKindServer, }, { json: `[{ "trace_id": -1, "id": 31, "annotations": [ @@ -135,8 +138,10 @@ func TestToDomainMultipleSpanKinds(t *testing.T) { {"value": "cs", "timestamp": 1, "host": {"service_name": "bar", "ipv4": 23456}}, {"value": "cr", "timestamp": 2, "host": {"service_name": "bar", "ipv4": 23456}} ]}]`, - tagFirst: ext.SpanKindRPCServer, - tagSecond: ext.SpanKindRPCClient, + tagFirstKey: keySpanKind, + tagSecondKey: keySpanKind, + tagFirstVal: trace.SpanKindServer, + tagSecondVal: trace.SpanKindClient, }, } @@ -146,13 +151,13 @@ func TestToDomainMultipleSpanKinds(t *testing.T) { assert.Equal(t, 2, len(trace.Spans)) assert.Equal(t, 1, len(trace.Spans[0].Tags)) - assert.Equal(t, test.tagFirst.Key, trace.Spans[0].Tags[0].Key) - assert.Equal(t, string(test.tagFirst.Value.(ext.SpanKindEnum)), trace.Spans[0].Tags[0].VStr) + assert.Equal(t, test.tagFirstKey, trace.Spans[0].Tags[0].Key) + assert.Equal(t, test.tagFirstVal.String(), trace.Spans[0].Tags[0].VStr) assert.Equal(t, 1, len(trace.Spans[1].Tags)) - assert.Equal(t, test.tagSecond.Key, trace.Spans[1].Tags[0].Key) + assert.Equal(t, test.tagSecondKey, trace.Spans[1].Tags[0].Key) assert.Equal(t, time.Duration(1000), trace.Spans[1].Duration) - assert.Equal(t, string(test.tagSecond.Value.(ext.SpanKindEnum)), trace.Spans[1].Tags[0].VStr) + assert.Equal(t, test.tagSecondVal.String(), trace.Spans[1].Tags[0].VStr) } } diff --git a/plugin/storage/cassandra/spanstore/reader.go b/plugin/storage/cassandra/spanstore/reader.go index 62d984fca3c..522171833b5 100644 --- a/plugin/storage/cassandra/spanstore/reader.go +++ b/plugin/storage/cassandra/spanstore/reader.go @@ -23,7 +23,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" "go.opentelemetry.io/otel/trace" "go.uber.org/zap"