From 820f19ec66be1c632e4c2a29ba700c5e65f89916 Mon Sep 17 00:00:00 2001 From: Cheng-Zhen Yang Date: Sun, 3 Nov 2024 22:32:34 +1100 Subject: [PATCH 1/5] otellogr: Implement Error and comment Init --- bridges/otellogr/logsink.go | 30 +++++++++++++++++++--- bridges/otellogr/logsink_test.go | 44 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/bridges/otellogr/logsink.go b/bridges/otellogr/logsink.go index 4e36fe18e23..1a23efb88c8 100644 --- a/bridges/otellogr/logsink.go +++ b/bridges/otellogr/logsink.go @@ -61,6 +61,11 @@ import ( "go.opentelemetry.io/otel/log/global" ) +const ( + // exceptionMessageKey is the key used for the error message. + exceptionMessageKey = "exception.message" +) + type config struct { provider log.LoggerProvider version string @@ -206,7 +211,23 @@ func (l *LogSink) Enabled(level int) bool { // Error logs an error, with the given message and key/value pairs. func (l *LogSink) Error(err error, msg string, keysAndValues ...any) { - // TODO + var record log.Record + record.SetBody(log.StringValue(msg)) + record.SetSeverity(log.SeverityError) + + record.AddAttributes( + log.KeyValue{ + Key: exceptionMessageKey, + Value: convertValue(err), + }, + ) + + record.AddAttributes(l.attr...) + + ctx, attr := convertKVs(l.ctx, keysAndValues...) + record.AddAttributes(attr...) + + l.logger.Emit(ctx, record) } // Info logs a non-error message with the given key/value pairs. @@ -223,9 +244,12 @@ func (l *LogSink) Info(level int, msg string, keysAndValues ...any) { l.logger.Emit(ctx, record) } -// Init initializes the LogSink. +// Init receives optional information about the logr library this +// implementation does not use it. func (l *LogSink) Init(info logr.RuntimeInfo) { - // TODO + // 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. } // WithName returns a new LogSink with the specified name appended. diff --git a/bridges/otellogr/logsink_test.go b/bridges/otellogr/logsink_test.go index b63a201c412..236ad3b61e6 100644 --- a/bridges/otellogr/logsink_test.go +++ b/bridges/otellogr/logsink_test.go @@ -4,6 +4,7 @@ package otellogr import ( "context" + "errors" "testing" "time" @@ -277,6 +278,49 @@ func TestLogSink(t *testing.T) { }, }, }, + { + name: "error", + f: func(l *logr.Logger) { + l.Error(errors.New("test"), "error message") + }, + wantRecords: map[string][]log.Record{ + name: { + buildRecord(log.StringValue("error message"), time.Time{}, log.SeverityError, []log.KeyValue{ + {Key: exceptionMessageKey, Value: log.StringValue("test")}, + }), + }, + }, + }, + { + name: "error_multi_attrs", + f: func(l *logr.Logger) { + l.Error(errors.New("test error"), "msg", + "struct", struct{ data int64 }{data: 1}, + "bool", true, + "duration", time.Minute, + "float64", 3.14159, + "int64", -2, + "string", "str", + "time", time.Unix(1000, 1000), + "uint64", uint64(3), + ) + }, + wantRecords: map[string][]log.Record{ + name: { + buildRecord(log.StringValue("msg"), time.Time{}, log.SeverityError, []log.KeyValue{ + {Key: exceptionMessageKey, Value: log.StringValue("test error")}, + log.String("struct", "{data:1}"), + log.Bool("bool", true), + log.Int64("duration", 60_000_000_000), + log.Float64("float64", 3.14159), + log.Int64("int64", -2), + log.String("string", "str"), + log.Int64("time", time.Unix(1000, 1000).UnixNano()), + log.Int64("uint64", 3), + }), + }, + }, + }, } { t.Run(tt.name, func(t *testing.T) { rec := logtest.NewRecorder() From f628251e65366fd458b513a8af059d1ed9d46a95 Mon Sep 17 00:00:00 2001 From: Cheng-Zhen Yang Date: Wed, 6 Nov 2024 10:07:14 +1100 Subject: [PATCH 2/5] Update changelog --- CHANGELOG.md | 1 + bridges/otellogr/logsink.go | 2 ++ versions.yaml | 1 + 3 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65dcca7a2a6..bd73fc18e40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add the `WithSource` option to the `go.opentelemetry.io/contrib/bridges/otelslog` log bridge to set the `code.*` attributes in the log record that includes the source location where the record was emitted. (#6253) - Add `ContextWithStartTime` and `StartTimeFromContext` to `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp`, which allows setting the start time using go context. (#6137) - Set the `code.*` attributes in `go.opentelemetry.io/contrib/bridges/otelzap` if the `zap.Logger` was created with the `AddCaller` or `AddStacktrace` option. (#6268) +- The `go.opentelemetry.io/contrib/bridges/otellogr` module. This module provides an OpenTelemetry logging bridge for `github.com/go-logr/logr`. ### Changed diff --git a/bridges/otellogr/logsink.go b/bridges/otellogr/logsink.go index 1a23efb88c8..127659b150f 100644 --- a/bridges/otellogr/logsink.go +++ b/bridges/otellogr/logsink.go @@ -13,6 +13,8 @@ // - Level is transformed and set as the Severity. The SeverityText is not // set. // - KeyAndValues are transformed and set as Attributes. +// - Error is always logged as an additional attribute with the key +// "exception.message" and with the severity [log.SeverityError]. // - The [context.Context] value in KeyAndValues is propagated to OpenTelemetry // log record. All non-nested [context.Context] values are ignored and not // added as attributes. If there are multiple [context.Context] the last one diff --git a/versions.yaml b/versions.yaml index c27f16b9bf8..d323679e147 100644 --- a/versions.yaml +++ b/versions.yaml @@ -74,6 +74,7 @@ module-sets: - go.opentelemetry.io/contrib/bridges/otelslog - go.opentelemetry.io/contrib/bridges/otellogrus - go.opentelemetry.io/contrib/bridges/otelzap + - go.opentelemetry.io/contrib/bridges/otellogr experimental-processors: version: v0.4.0 modules: From 3d325caa520223270d52bc0d98e7f593f8d8b0a5 Mon Sep 17 00:00:00 2001 From: Cheng-Zhen Yang Date: Thu, 14 Nov 2024 09:04:20 +1100 Subject: [PATCH 3/5] Add changes and remove release --- CHANGELOG.md | 1 - bridges/otellogr/logsink.go | 11 ++--------- bridges/otellogr/logsink_test.go | 4 ++-- versions.yaml | 1 - 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eddbb7133e2..bd47bae6343 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add a `LogProcessor` to `go.opentelemetry.io/contrib/processors/baggagecopy` to copy baggage members to log records. (#6277) - Use `baggagecopy.NewLogProcessor` when configuring a Log Provider. - `NewLogProcessor` accepts a `Filter` function type that selects which baggage members are added to the log record. -- The `go.opentelemetry.io/contrib/bridges/otellogr` module. This module provides an OpenTelemetry logging bridge for `github.com/go-logr/logr`. (#6295) ### Changed diff --git a/bridges/otellogr/logsink.go b/bridges/otellogr/logsink.go index 127659b150f..3f3857c8f3d 100644 --- a/bridges/otellogr/logsink.go +++ b/bridges/otellogr/logsink.go @@ -61,11 +61,7 @@ import ( "go.opentelemetry.io/otel/log" "go.opentelemetry.io/otel/log/global" -) - -const ( - // exceptionMessageKey is the key used for the error message. - exceptionMessageKey = "exception.message" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" ) type config struct { @@ -218,10 +214,7 @@ func (l *LogSink) Error(err error, msg string, keysAndValues ...any) { record.SetSeverity(log.SeverityError) record.AddAttributes( - log.KeyValue{ - Key: exceptionMessageKey, - Value: convertValue(err), - }, + log.String(string(semconv.ExceptionMessageKey), err.Error()), ) record.AddAttributes(l.attr...) diff --git a/bridges/otellogr/logsink_test.go b/bridges/otellogr/logsink_test.go index 236ad3b61e6..78d3bf491c4 100644 --- a/bridges/otellogr/logsink_test.go +++ b/bridges/otellogr/logsink_test.go @@ -286,7 +286,7 @@ func TestLogSink(t *testing.T) { wantRecords: map[string][]log.Record{ name: { buildRecord(log.StringValue("error message"), time.Time{}, log.SeverityError, []log.KeyValue{ - {Key: exceptionMessageKey, Value: log.StringValue("test")}, + {Key: "exception.message", Value: log.StringValue("test")}, }), }, }, @@ -308,7 +308,7 @@ func TestLogSink(t *testing.T) { wantRecords: map[string][]log.Record{ name: { buildRecord(log.StringValue("msg"), time.Time{}, log.SeverityError, []log.KeyValue{ - {Key: exceptionMessageKey, Value: log.StringValue("test error")}, + {Key: "exception.message", Value: log.StringValue("test error")}, log.String("struct", "{data:1}"), log.Bool("bool", true), log.Int64("duration", 60_000_000_000), diff --git a/versions.yaml b/versions.yaml index d323679e147..c27f16b9bf8 100644 --- a/versions.yaml +++ b/versions.yaml @@ -74,7 +74,6 @@ module-sets: - go.opentelemetry.io/contrib/bridges/otelslog - go.opentelemetry.io/contrib/bridges/otellogrus - go.opentelemetry.io/contrib/bridges/otelzap - - go.opentelemetry.io/contrib/bridges/otellogr experimental-processors: version: v0.4.0 modules: From 3faa941c4d4a39f290d398e956cb7bbdb3843b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Thu, 14 Nov 2024 09:33:27 +0100 Subject: [PATCH 4/5] Update bridges/otellogr/logsink.go --- bridges/otellogr/logsink.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridges/otellogr/logsink.go b/bridges/otellogr/logsink.go index 3f3857c8f3d..b0861dfe387 100644 --- a/bridges/otellogr/logsink.go +++ b/bridges/otellogr/logsink.go @@ -61,7 +61,7 @@ import ( "go.opentelemetry.io/otel/log" "go.opentelemetry.io/otel/log/global" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + semconv "go.opentelemetry.io/otel/semconv/v1.27.0" ) type config struct { From 29fa319eb9cbfb3845cd6242d06a0b9f23d7e904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Thu, 14 Nov 2024 09:53:31 +0100 Subject: [PATCH 5/5] go mod tidy --- bridges/otellogr/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridges/otellogr/go.mod b/bridges/otellogr/go.mod index 07acd113f5c..1dd3c721013 100644 --- a/bridges/otellogr/go.mod +++ b/bridges/otellogr/go.mod @@ -5,6 +5,7 @@ go 1.22 require ( github.com/go-logr/logr v1.4.2 github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/otel v1.32.0 go.opentelemetry.io/otel/log v0.8.0 ) @@ -12,7 +13,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect