diff --git a/bridges/otelzap/bench_test.go b/bridges/otelzap/bench_test.go new file mode 100644 index 00000000000..de3577d15e6 --- /dev/null +++ b/bridges/otelzap/bench_test.go @@ -0,0 +1,109 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otelzap + +import ( + "fmt" + "testing" + "time" + + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +func BenchmarkCoreWrite(b *testing.B) { + benchmarks := []struct { + name string + fields []zapcore.Field + }{ + { + name: "10 fields", + fields: []zapcore.Field{ + zap.Int16("a", 1), + zap.String("k", "a"), + zap.Bool("k", true), + zap.Time("k", time.Unix(1000, 1000)), + zap.Binary("k", []byte{1, 2}), + zap.ByteString("k", []byte{1, 2}), + zap.Object("k", loggable{true}), + zap.Array("k", loggable{true}), + zap.String("k", "a"), + zap.Ints("k", []int{1, 2}), + }, + }, + { + name: "20 fields", + fields: []zapcore.Field{ + zap.Int16("a", 1), + zap.String("k", "a"), + zap.Bool("k", true), + zap.Time("k", time.Unix(1000, 1000)), + zap.Binary("k", []byte{1, 2}), + zap.ByteString("k", []byte{1, 2}), + zap.Object("k", loggable{true}), + zap.String("k", "a"), + zap.Array("k", loggable{true}), + zap.Ints("k", []int{1, 2}), + zap.Int16("a", 1), + zap.String("k", "a"), + zap.Bool("k", true), + zap.Time("k", time.Unix(1000, 1000)), + zap.Binary("k", []byte{1, 2}), + zap.ByteString("k", []byte{1, 2}), + zap.Object("k", loggable{true}), + zap.Array("k", loggable{true}), + zap.String("k", "a"), + zap.Ints("k", []int{1, 2}), + }, + }, + { // Benchmark with nested namespace + name: "Namespace", + fields: []zapcore.Field{ + zap.Namespace("a"), + zap.Int16("a", 1), + zap.String("k", "a"), + zap.Bool("k", true), + zap.Time("k", time.Unix(1000, 1000)), + zap.Binary("k", []byte{1, 2}), + zap.Namespace("b"), + zap.Binary("k", []byte{1, 2}), + zap.Object("k", loggable{true}), + zap.String("k", "a"), + zap.Array("k", loggable{true}), + zap.Ints("k", []int{1, 2}), + }, + }, + } + + for _, bm := range benchmarks { + b.Run(bm.name, func(b *testing.B) { + zc := NewCore(loggerName) + b.ReportAllocs() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + err := zc.Write(testEntry, bm.fields) + if err != nil { + b.Errorf("Unexpected error: %v", err) + } + } + }) + }) + } + + for _, bm := range benchmarks { + b.Run(fmt.Sprint("With", bm.name), func(b *testing.B) { + zc := NewCore(loggerName) + zc1 := zc.With(bm.fields) + b.ReportAllocs() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + err := zc1.Write(testEntry, []zapcore.Field{}) + if err != nil { + b.Errorf("Unexpected error: %v", err) + } + } + }) + }) + } +} diff --git a/bridges/otelzap/core_test.go b/bridges/otelzap/core_test.go index 1b5c01ffa18..bcdd52ebd80 100644 --- a/bridges/otelzap/core_test.go +++ b/bridges/otelzap/core_test.go @@ -5,12 +5,9 @@ package otelzap import ( "context" - "fmt" + "strings" "testing" - "time" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -21,6 +18,7 @@ import ( ) var ( + ctx = context.WithValue(context.Background(), testEntry, false) testMessage = "log message" loggerName = "name" testKey = "key" @@ -32,133 +30,167 @@ var ( ) func TestCore(t *testing.T) { - rec := logtest.NewRecorder() - zc := NewCore(loggerName, WithLoggerProvider(rec)) - logger := zap.New(zc) - - t.Run("Write", func(t *testing.T) { - logger.Info(testMessage, zap.String(testKey, testValue)) - got := rec.Result()[0].Records[0] - assert.Equal(t, testMessage, got.Body().AsString()) - assert.Equal(t, log.SeverityInfo, got.Severity()) - assert.Equal(t, zap.InfoLevel.String(), got.SeverityText()) - assert.Equal(t, 1, got.AttributesLen()) - got.WalkAttributes(func(kv log.KeyValue) bool { - assert.Equal(t, testKey, kv.Key) - assert.Equal(t, testValue, value2Result(kv.Value)) - return true - }) - }) - - rec.Reset() - - t.Run("Write Context", func(t *testing.T) { - ctx := context.Background() - ctx = context.WithValue(ctx, testEntry, true) - logger.Info(testMessage, zap.Any("ctx", ctx)) - got := rec.Result()[0].Records[0] - assert.Equal(t, got.Context(), ctx) - }) - - rec.Reset() - - t.Run("With Context", func(t *testing.T) { - ctx := context.Background() - ctx = context.WithValue(ctx, testEntry, false) - childlogger := logger.With(zap.Reflect("ctx", ctx)) - childlogger.Info(testMessage) - got := rec.Result()[0].Records[0] - assert.Equal(t, got.Context(), ctx) - }) - - rec.Reset() - - // test child logger with accumulated fields - t.Run("With", func(t *testing.T) { - testCases := [][]string{{"test1", "value1"}, {"test2", "value2"}} - childlogger := logger.With(zap.String(testCases[0][0], testCases[0][1])) - childlogger.Info(testMessage, zap.String(testCases[1][0], testCases[1][1])) - - got := rec.Result()[0].Records[0] - assert.Equal(t, testMessage, got.Body().AsString()) - assert.Equal(t, log.SeverityInfo, got.Severity()) - assert.Equal(t, zap.InfoLevel.String(), got.SeverityText()) - assert.Equal(t, 2, got.AttributesLen()) - - index := 0 - got.WalkAttributes(func(kv log.KeyValue) bool { - assert.Equal(t, testCases[index][0], kv.Key) - assert.Equal(t, testCases[index][1], value2Result(kv.Value)) - index++ - return true - }) - }) - - rec.Reset() - - t.Run("Named", func(t *testing.T) { - name := "my/pkg" - childlogger := logger.Named(name) - childlogger.Info(testMessage, zap.String(testKey, testValue)) - - found := false - for _, got := range rec.Result() { - found = got.Name == name - if found { - break - } - } - assert.True(t, found) - }) - - rec.Reset() - - t.Run("WithMultiple", func(t *testing.T) { - testCases := [][]string{{"test1", "value1"}, {"test2", "value2"}, {"test3", "value3"}} - childlogger := logger.With(zap.String(testCases[0][0], testCases[0][1])) - childlogger2 := childlogger.With(zap.String(testCases[1][0], testCases[1][1])) - childlogger2.Info(testMessage, zap.String(testCases[2][0], testCases[2][1])) - - got := rec.Result()[0].Records[0] - assert.Equal(t, testMessage, got.Body().AsString()) - assert.Equal(t, log.SeverityInfo, got.Severity()) - assert.Equal(t, zap.InfoLevel.String(), got.SeverityText()) - assert.Equal(t, 3, got.AttributesLen()) - - index := 0 - got.WalkAttributes(func(kv log.KeyValue) bool { - assert.Equal(t, testCases[index][0], kv.Key) - assert.Equal(t, testCases[index][1], value2Result(kv.Value)) - index++ - return true + testCases := []struct { + name string + fn func(l *zap.Logger) + want logtest.Recording + }{ + { + name: "Info", + fn: func(l *zap.Logger) { + l.Info(testMessage, zap.String(testKey, testValue)) + }, + want: logtest.Recording{ + logtest.Scope{Name: loggerName}: []logtest.Record{ + { + Context: context.Background(), + Severity: log.SeverityInfo, + SeverityText: zap.InfoLevel.String(), + Body: log.StringValue(testMessage), + Attributes: []log.KeyValue{ + log.String(testKey, testValue), + }, + }, + }, + }, + }, + { + name: "InfoContextField", + fn: func(l *zap.Logger) { + l.Info(testMessage, zap.Any("ctx", ctx)) + }, + want: logtest.Recording{ + logtest.Scope{Name: loggerName}: []logtest.Record{ + { + Context: ctx, + Severity: log.SeverityInfo, + SeverityText: zap.InfoLevel.String(), + Body: log.StringValue(testMessage), + }, + }, + }, + }, + { + name: "WithContextInfo", + fn: func(l *zap.Logger) { + l = l.With(zap.Reflect("ctx", ctx)) + l.Info(testMessage) + }, + want: logtest.Recording{ + logtest.Scope{Name: loggerName}: []logtest.Record{ + { + Context: ctx, + Severity: log.SeverityInfo, + SeverityText: zap.InfoLevel.String(), + Body: log.StringValue(testMessage), + }, + }, + }, + }, + { + name: "WithFields", + fn: func(l *zap.Logger) { + l = l.With(zap.String("foo", "bar")) + l.Info(testMessage, zap.String("fizz", "buzz")) + }, + want: logtest.Recording{ + logtest.Scope{Name: loggerName}: []logtest.Record{ + { + Context: context.Background(), + Severity: log.SeverityInfo, + SeverityText: zap.InfoLevel.String(), + Body: log.StringValue(testMessage), + Attributes: []log.KeyValue{ + log.String("foo", "bar"), + log.String("fizz", "buzz"), + }, + }, + }, + }, + }, + { + name: "WithMultiple", + fn: func(l *zap.Logger) { + l = l.With(zap.String("foo", "bar")) + l = l.With(zap.String("a", "b")) + l.Info(testMessage, zap.String("fizz", "buzz")) + }, + want: logtest.Recording{ + logtest.Scope{Name: loggerName}: []logtest.Record{ + { + Context: context.Background(), + Severity: log.SeverityInfo, + SeverityText: zap.InfoLevel.String(), + Body: log.StringValue(testMessage), + Attributes: []log.KeyValue{ + log.String("a", "b"), + log.String("fizz", "buzz"), + log.String("foo", "bar"), + }, + }, + }, + }, + }, + { + name: "Named", + fn: func(l *zap.Logger) { + l = l.Named("custom") + l.Info(testMessage) + }, + want: logtest.Recording{ + logtest.Scope{Name: "name"}: nil, // Acquired but not used. + logtest.Scope{Name: "custom"}: []logtest.Record{ + { + Context: context.Background(), + Severity: log.SeverityInfo, + SeverityText: zap.InfoLevel.String(), + Body: log.StringValue(testMessage), + }, + }, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + rec := logtest.NewRecorder() + zc := NewCore(loggerName, WithLoggerProvider(rec)) + l := zap.New(zc) + tc.fn(l) + got := rec.Result() + logtest.AssertEqual(t, got, tc.want, logtest.IgnoreTimestamp()) }) - }) + } } func TestCoreEnabled(t *testing.T) { enabledFunc := func(c context.Context, param log.EnabledParameters) bool { return param.Severity >= log.SeverityInfo } - - r := logtest.NewRecorder(logtest.WithEnabledFunc(enabledFunc)) - logger := zap.New(NewCore(loggerName, WithLoggerProvider(r))) + rec := logtest.NewRecorder(logtest.WithEnabledFunc(enabledFunc)) + logger := zap.New(NewCore(loggerName, WithLoggerProvider(rec))) logger.Debug(testMessage) - assert.Empty(t, r.Result()[0].Records) if ce := logger.Check(zap.DebugLevel, testMessage); ce != nil { ce.Write() } - assert.Empty(t, r.Result()[0].Records) if ce := logger.Check(zap.InfoLevel, testMessage); ce != nil { ce.Write() } - require.Len(t, r.Result()[0].Records, 1) - got := r.Result()[0].Records[0] - assert.Equal(t, testMessage, got.Body().AsString()) - assert.Equal(t, log.SeverityInfo, got.Severity()) - assert.Equal(t, zap.InfoLevel.String(), got.SeverityText()) + + want := logtest.Recording{ + logtest.Scope{Name: loggerName}: []logtest.Record{ + { + Context: context.Background(), + Severity: log.SeverityInfo, + SeverityText: zap.InfoLevel.String(), + Body: log.StringValue(testMessage), + }, + }, + } + got := rec.Result() + logtest.AssertEqual(t, got, want, logtest.IgnoreTimestamp()) } func TestCoreWithCaller(t *testing.T) { @@ -167,26 +199,37 @@ func TestCoreWithCaller(t *testing.T) { logger := zap.New(zc, zap.AddCaller()) logger.Info(testMessage) - got := rec.Result()[0].Records[0] - assert.Equal(t, testMessage, got.Body().AsString()) - assert.Equal(t, log.SeverityInfo, got.Severity()) - assert.Equal(t, zap.InfoLevel.String(), got.SeverityText()) - assert.Equal(t, 4, got.AttributesLen()) - got.WalkAttributes(func(kv log.KeyValue) bool { - switch kv.Key { - case string(semconv.CodeFilepathKey): - assert.Contains(t, kv.Value.AsString(), "core_test.go") - case string(semconv.CodeLineNumberKey): - assert.Positive(t, kv.Value.AsInt64()) - case string(semconv.CodeFunctionKey): - assert.Equal(t, t.Name(), kv.Value.AsString()) - case string(semconv.CodeNamespaceKey): - assert.Equal(t, "go.opentelemetry.io/contrib/bridges/otelzap", kv.Value.AsString()) - default: - assert.Fail(t, "unexpected attribute key", kv.Key) - } - return true - }) + + attrs := recordedAttributes(t, rec.Result()) + var key string + + key = string(semconv.CodeFilepathKey) + if v, ok := attrs[key]; !ok { + t.Errorf("%q attribute is missing, got = %v", key, attrs) + } else if !strings.Contains(v.AsString(), "core_test.go") { + t.Errorf("%q attribute has bad value, got = %v", key, v) + } + + key = string(semconv.CodeLineNumberKey) + if v, ok := attrs[key]; !ok { + t.Errorf("%q attribute is missing, got = %v", key, attrs) + } else if v.AsInt64() <= 0 { + t.Errorf("%q attribute is not a number, got = %v", key, v) + } + + key = string(semconv.CodeFunctionKey) + if v, ok := attrs[key]; !ok { + t.Errorf("%q attribute is missing, got = %v", key, attrs) + } else if want := t.Name(); v.AsString() != want { + t.Errorf("%q attribute has bad value, got = %v, want = %q", key, v, want) + } + + key = string(semconv.CodeNamespaceKey) + if v, ok := attrs[key]; !ok { + t.Errorf("%q attribute is missing, got = %v", key, attrs) + } else if want := "go.opentelemetry.io/contrib/bridges/otelzap"; v.AsString() != want { + t.Errorf("%q attribute has bad value, got = %v, want = %q", key, v, want) + } } func TestCoreWithStacktrace(t *testing.T) { @@ -195,52 +238,51 @@ func TestCoreWithStacktrace(t *testing.T) { logger := zap.New(zc, zap.AddStacktrace(zapcore.ErrorLevel)) logger.Error(testMessage) - got := rec.Result()[0].Records[0] - assert.Equal(t, testMessage, got.Body().AsString()) - assert.Equal(t, log.SeverityError, got.Severity()) - assert.Equal(t, zap.ErrorLevel.String(), got.SeverityText()) - assert.Equal(t, 1, got.AttributesLen()) - got.WalkAttributes(func(kv log.KeyValue) bool { - assert.Equal(t, string(semconv.CodeStacktraceKey), kv.Key) - assert.NotEmpty(t, kv.Value.AsString()) - return true - }) + + attrs := recordedAttributes(t, rec.Result()) + + key := string(semconv.CodeStacktraceKey) + if v, ok := attrs[key]; !ok { + t.Errorf("%q attribute is missing, got = %v", key, attrs) + } else if v.AsString() == "" { + t.Fatalf("%q attribute does not contain a stacktrace, got = %v", key, v) + } } func TestNewCoreConfiguration(t *testing.T) { t.Run("Default", func(t *testing.T) { - r := logtest.NewRecorder() + rec := logtest.NewRecorder() prev := global.GetLoggerProvider() defer global.SetLoggerProvider(prev) - global.SetLoggerProvider(r) + global.SetLoggerProvider(rec) - var h *Core - require.NotPanics(t, func() { h = NewCore(loggerName) }) - require.NotNil(t, h.logger) - require.Len(t, r.Result(), 1) + NewCore(loggerName) - want := &logtest.ScopeRecords{Name: loggerName} - got := r.Result()[0] - assert.Equal(t, want, got) + want := logtest.Recording{ + logtest.Scope{Name: loggerName}: nil, + } + got := rec.Result() + logtest.AssertEqual(t, got, want) }) t.Run("Options", func(t *testing.T) { - r := logtest.NewRecorder() - var h *Core - require.NotPanics(t, func() { - h = NewCore( - loggerName, - WithLoggerProvider(r), - WithVersion("1.0.0"), - WithSchemaURL("url"), - ) - }) - require.NotNil(t, h.logger) - require.Len(t, r.Result(), 1) - - want := &logtest.ScopeRecords{Name: loggerName, Version: "1.0.0", SchemaURL: "url"} - got := r.Result()[0] - assert.Equal(t, want, got) + rec := logtest.NewRecorder() + NewCore( + loggerName, + WithLoggerProvider(rec), + WithVersion("1.0.0"), + WithSchemaURL("url"), + ) + + want := logtest.Recording{ + logtest.Scope{ + Name: loggerName, + Version: "1.0.0", + SchemaURL: "url", + }: nil, + } + got := rec.Result() + logtest.AssertEqual(t, got, want) }) } @@ -303,104 +345,33 @@ func TestSplitFuncName(t *testing.T) { for _, tc := range testCases { t.Run(tc.fullFuncName, func(t *testing.T) { gotFuncName, gotNamespace := splitFuncName(tc.fullFuncName) - assert.Equal(t, tc.wantFuncName, gotFuncName) - assert.Equal(t, tc.wantNamespace, gotNamespace) + if gotFuncName != tc.wantFuncName || gotNamespace != tc.wantNamespace { + t.Errorf("splitFuncName(%q) = (%q, %q), want (%q, %q)", + tc.fullFuncName, gotFuncName, gotNamespace, tc.wantFuncName, tc.wantNamespace) + } }) } } -func BenchmarkCoreWrite(b *testing.B) { - benchmarks := []struct { - name string - fields []zapcore.Field - }{ - { - name: "10 fields", - fields: []zapcore.Field{ - zap.Int16("a", 1), - zap.String("k", "a"), - zap.Bool("k", true), - zap.Time("k", time.Unix(1000, 1000)), - zap.Binary("k", []byte{1, 2}), - zap.ByteString("k", []byte{1, 2}), - zap.Object("k", loggable{true}), - zap.Array("k", loggable{true}), - zap.String("k", "a"), - zap.Ints("k", []int{1, 2}), - }, - }, - { - name: "20 fields", - fields: []zapcore.Field{ - zap.Int16("a", 1), - zap.String("k", "a"), - zap.Bool("k", true), - zap.Time("k", time.Unix(1000, 1000)), - zap.Binary("k", []byte{1, 2}), - zap.ByteString("k", []byte{1, 2}), - zap.Object("k", loggable{true}), - zap.String("k", "a"), - zap.Array("k", loggable{true}), - zap.Ints("k", []int{1, 2}), - zap.Int16("a", 1), - zap.String("k", "a"), - zap.Bool("k", true), - zap.Time("k", time.Unix(1000, 1000)), - zap.Binary("k", []byte{1, 2}), - zap.ByteString("k", []byte{1, 2}), - zap.Object("k", loggable{true}), - zap.Array("k", loggable{true}), - zap.String("k", "a"), - zap.Ints("k", []int{1, 2}), - }, - }, - { // Benchmark with nested namespace - name: "Namespace", - fields: []zapcore.Field{ - zap.Namespace("a"), - zap.Int16("a", 1), - zap.String("k", "a"), - zap.Bool("k", true), - zap.Time("k", time.Unix(1000, 1000)), - zap.Binary("k", []byte{1, 2}), - zap.Namespace("b"), - zap.Binary("k", []byte{1, 2}), - zap.Object("k", loggable{true}), - zap.String("k", "a"), - zap.Array("k", loggable{true}), - zap.Ints("k", []int{1, 2}), - }, - }, - } +// recordedAttributes returns record's attributes when only a single record was emitted. +func recordedAttributes(t *testing.T, rec logtest.Recording) map[string]log.Value { + t.Helper() - for _, bm := range benchmarks { - b.Run(bm.name, func(b *testing.B) { - zc := NewCore(loggerName) - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - err := zc.Write(testEntry, bm.fields) - if err != nil { - b.Errorf("Unexpected error: %v", err) - } - } - }) - }) + if len(rec) != 1 { + t.Fatalf("should have only 1 scope as a single logger is used, got = %v", rec) } - for _, bm := range benchmarks { - b.Run(fmt.Sprint("With", bm.name), func(b *testing.B) { - zc := NewCore(loggerName) - zc1 := zc.With(bm.fields) - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - err := zc1.Write(testEntry, []zapcore.Field{}) - if err != nil { - b.Errorf("Unexpected error: %v", err) - } - } - }) - }) + var records []logtest.Record + for _, v := range rec { + records = v + } + if len(records) != 1 { + t.Fatalf("should have 1 record, got = %v", records) + } + a := records[0].Attributes + attrs := make(map[string]log.Value, len(a)) + for _, v := range a { + attrs[v.Key] = v.Value } + return attrs } diff --git a/bridges/otelzap/go.mod b/bridges/otelzap/go.mod index a8a691a049a..603c6a650f2 100644 --- a/bridges/otelzap/go.mod +++ b/bridges/otelzap/go.mod @@ -1,10 +1,10 @@ module go.opentelemetry.io/contrib/bridges/otelzap -go 1.22.0 +go 1.23.0 require ( github.com/stretchr/testify v1.10.0 - go.opentelemetry.io/otel v1.34.0 + go.opentelemetry.io/otel v1.35.0 go.opentelemetry.io/otel/log v0.10.0 go.uber.org/zap v1.27.0 ) @@ -13,10 +13,13 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.35.0 // indirect + go.opentelemetry.io/otel/trace v1.35.0 // indirect go.uber.org/multierr v1.11.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace go.opentelemetry.io/otel/log => github.com/pellared/opentelemetry-go/log v0.0.0-20250318101357-27296575fedd diff --git a/bridges/otelzap/go.sum b/bridges/otelzap/go.sum index 97a70cc14d0..fd7b0b7b23b 100644 --- a/bridges/otelzap/go.sum +++ b/bridges/otelzap/go.sum @@ -5,12 +5,14 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/pellared/opentelemetry-go/log v0.0.0-20250318101357-27296575fedd h1:/9Po0+25YUSBBZ6RPqf1vEuL2fdDXkLMlzGKSBq8atw= +github.com/pellared/opentelemetry-go/log v0.0.0-20250318101357-27296575fedd/go.mod h1:m0xj5SEPUFCHDcSIgtdhitNVnmI1Gldv4c0NEcT/eNo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= @@ -19,14 +21,12 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= -go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=