Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

otellogr: Fix nil context panic #6527

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Fixed

- Use `context.Background()` as default context instead of nil in `go.opentelemetry.io/contrib/bridges/otellogr`. (#6527)
- Fix error logged by Jaeger remote sampler on empty or unset `OTEL_TRACES_SAMPLER_ARG` environment variable (#6511)

## [1.33.0/0.58.0/0.27.0/0.13.0/0.8.0/0.6.0/0.5.0] - 2024-12-12
Expand Down
29 changes: 22 additions & 7 deletions bridges/otellogr/logsink.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ import (
)

type config struct {
provider log.LoggerProvider
version string
schemaURL string

flc1125 marked this conversation as resolved.
Show resolved Hide resolved
provider log.LoggerProvider
version string
schemaURL string
ctx context.Context
levelSeverity func(int) log.Severity
}

Expand All @@ -82,6 +82,10 @@ func newConfig(options []Option) config {
c.provider = global.GetLoggerProvider()
}

if c.ctx == nil {
flc1125 marked this conversation as resolved.
Show resolved Hide resolved
c.ctx = context.Background()
}

if c.levelSeverity == nil {
c.levelSeverity = func(level int) log.Severity {
switch level {
Expand Down Expand Up @@ -176,6 +180,7 @@ func NewLogSink(name string, options ...Option) *LogSink {
logger: c.provider.Logger(name, opts...),
levelSeverity: c.levelSeverity,
opts: opts,
ctx: c.ctx,
}
}

Expand All @@ -201,9 +206,8 @@ var _ logr.LogSink = (*LogSink)(nil)
// For example, commandline flags might be used to set the logging
// verbosity and disable some info logs.
func (l *LogSink) Enabled(level int) bool {
ctx := context.Background()
param := log.EnabledParameters{Severity: l.levelSeverity(level)}
return l.logger.Enabled(ctx, param)
return l.logger.Enabled(l.ctx, param)
flc1125 marked this conversation as resolved.
Show resolved Hide resolved
}

// Error logs an error, with the given message and key/value pairs.
Expand Down Expand Up @@ -238,9 +242,20 @@ func (l *LogSink) Info(level int, msg string, keysAndValues ...any) {
l.logger.Emit(ctx, record)
}

// WithContext returns a new LogSink with the specified context.
func (l *LogSink) WithContext(ctx context.Context) *LogSink {
flc1125 marked this conversation as resolved.
Show resolved Hide resolved
if ctx == nil {
return l
}
sink := new(LogSink)
*sink = *l
sink.ctx = ctx
return sink
}

// Init receives optional information about the logr library this
// implementation does not use it.
func (l *LogSink) Init(info logr.RuntimeInfo) {
func (l *LogSink) Init(logr.RuntimeInfo) {
// We don't need to do anything here.
// CallDepth is used to calculate the caller's PC.
// PC is dropped as part of the conversion to the OpenTelemetry log.Record.
Expand Down
70 changes: 53 additions & 17 deletions bridges/otellogr/logsink_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,44 +30,44 @@ func TestNewConfig(t *testing.T) {
customLoggerProvider := mockLoggerProvider{}

for _, tt := range []struct {
name string
options []Option

wantConfig config
name string
options []Option
wantFunc func(config)
flc1125 marked this conversation as resolved.
Show resolved Hide resolved
}{
{
name: "with no options",

wantConfig: config{
provider: global.GetLoggerProvider(),
wantFunc: func(c config) {
assert.Equal(t, global.GetLoggerProvider(), c.provider)
},
},
{
name: "with a custom instrumentation scope",
options: []Option{
WithVersion("42.0"),
},

wantConfig: config{
version: "42.0",
provider: global.GetLoggerProvider(),
wantFunc: func(c config) {
assert.Equal(t, "42.0", c.version)
},
},
{
name: "with a custom logger provider",
options: []Option{
WithLoggerProvider(customLoggerProvider),
},

wantConfig: config{
provider: customLoggerProvider,
wantFunc: func(c config) {
assert.Equal(t, customLoggerProvider, c.provider)
},
},
{
name: "default context",
options: []Option{},
wantFunc: func(c config) {
assert.Equal(t, context.Background(), c.ctx)
},
},
} {
t.Run(tt.name, func(t *testing.T) {
config := newConfig(tt.options)
config.levelSeverity = nil // Ignore asserting level severity function, assert.Equal does not support function comparison
assert.Equal(t, tt.wantConfig, config)
tt.wantFunc(newConfig(tt.options))
})
}
}
Expand Down Expand Up @@ -375,6 +375,42 @@ func TestLogSinkEnabled(t *testing.T) {
assert.False(t, ls.Enabled(1))
}

func TestLogSinkWithContext(t *testing.T) {
rec := logtest.NewRecorder()
ls := NewLogSink(
"name",
WithLoggerProvider(rec),
)

t.Run("no context", func(t *testing.T) {
defer rec.Reset()
ls.Info(0, "msg")
require.Len(t, rec.Result(), 1)
require.Len(t, rec.Result()[0].Records, 1)
assert.Empty(t, rec.Result()[0].Records[0].Context())
})

t.Run("with nil context", func(t *testing.T) {
defer rec.Reset()

ls2 := ls.WithContext(nil) //nolint:staticcheck
assert.Same(t, ls, ls2)
})

t.Run("with context", func(t *testing.T) {
defer rec.Reset()

ctx := context.WithValue(context.Background(), "key", "value") //nolint:revive,staticcheck
ls2 := ls.WithContext(ctx)
assert.NotSame(t, ls, ls2)

ls2.Info(0, "msg")
require.Len(t, rec.Result(), 1)
require.Len(t, rec.Result()[0].Records, 1)
assert.Equal(t, "value", rec.Result()[0].Records[0].Context().Value("key"))
})
}

func buildRecord(body log.Value, timestamp time.Time, severity log.Severity, attrs []log.KeyValue) log.Record {
var record log.Record
record.SetBody(body)
Expand Down
Loading