From 7860af25e282446aee68c751388ba95d4154d239 Mon Sep 17 00:00:00 2001 From: Flc Date: Mon, 23 Dec 2024 22:34:29 +0800 Subject: [PATCH] fix #6509 --- bridges/otellogr/logsink.go | 40 ++++++++++++++---- bridges/otellogr/logsink_test.go | 72 ++++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 24 deletions(-) diff --git a/bridges/otellogr/logsink.go b/bridges/otellogr/logsink.go index 575736d3de4..17a0899c543 100644 --- a/bridges/otellogr/logsink.go +++ b/bridges/otellogr/logsink.go @@ -65,10 +65,10 @@ import ( ) type config struct { - provider log.LoggerProvider - version string - schemaURL string - + provider log.LoggerProvider + version string + schemaURL string + ctx context.Context levelSeverity func(int) log.Severity } @@ -82,6 +82,10 @@ func newConfig(options []Option) config { c.provider = global.GetLoggerProvider() } + if c.ctx == nil { + c.ctx = context.Background() + } + if c.levelSeverity == nil { c.levelSeverity = func(level int) log.Severity { switch level { @@ -139,6 +143,18 @@ func WithLoggerProvider(provider log.LoggerProvider) Option { }) } +// WithContext returns an [Option] that configures the [context.Context] used by +// a [LogSink]. +// +// By default if this Option is not provided, the LogSink will use the +// background context. +func WithContext(ctx context.Context) Option { + return optFunc(func(c config) config { + c.ctx = ctx + return c + }) +} + // WithLevelSeverity returns an [Option] that configures the function used to // convert logr levels to OpenTelemetry log severities. // @@ -176,6 +192,7 @@ func NewLogSink(name string, options ...Option) *LogSink { logger: c.provider.Logger(name, opts...), levelSeverity: c.levelSeverity, opts: opts, + ctx: c.ctx, } } @@ -201,9 +218,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) } // Error logs an error, with the given message and key/value pairs. @@ -238,9 +254,19 @@ func (l *LogSink) Info(level int, msg string, keysAndValues ...any) { l.logger.Emit(ctx, record) } +func (l *LogSink) WithContext(ctx context.Context) *LogSink { + 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. diff --git a/bridges/otellogr/logsink_test.go b/bridges/otellogr/logsink_test.go index 18e0c8e3ac5..dc50f70d1d6 100644 --- a/bridges/otellogr/logsink_test.go +++ b/bridges/otellogr/logsink_test.go @@ -30,16 +30,14 @@ func TestNewConfig(t *testing.T) { customLoggerProvider := mockLoggerProvider{} for _, tt := range []struct { - name string - options []Option - - wantConfig config + name string + options []Option + wantFunc func(config) }{ { name: "with no options", - - wantConfig: config{ - provider: global.GetLoggerProvider(), + wantFunc: func(c config) { + assert.Equal(t, global.GetLoggerProvider(), c.provider) }, }, { @@ -47,10 +45,8 @@ func TestNewConfig(t *testing.T) { options: []Option{ WithVersion("42.0"), }, - - wantConfig: config{ - version: "42.0", - provider: global.GetLoggerProvider(), + wantFunc: func(c config) { + assert.Equal(t, "42.0", c.version) }, }, { @@ -58,16 +54,29 @@ func TestNewConfig(t *testing.T) { 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) + }, + }, + { + name: "with a custom context", + options: []Option{ + WithContext(context.WithValue(context.Background(), "key", "value")), + }, + wantFunc: func(c config) { + assert.Equal(t, context.WithValue(context.Background(), "key", "value"), 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)) }) } } @@ -375,6 +384,35 @@ 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 context", func(t *testing.T) { + defer rec.Reset() + + ctx := context.WithValue(context.Background(), "key", "value") + 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)