From c3dc713aa6213f787e4b3e1864657dfb73cc06e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Fri, 29 Mar 2024 10:10:02 +0100 Subject: [PATCH 1/4] log: Add String method to Value and KeyValue --- log/keyvalue.go | 43 +++++++++++++++++++++++++++++++++++++++++++ log/keyvalue_test.go | 19 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/log/keyvalue.go b/log/keyvalue.go index da3d55c4fc8..8ce76eba667 100644 --- a/log/keyvalue.go +++ b/log/keyvalue.go @@ -8,8 +8,10 @@ package log // import "go.opentelemetry.io/otel/log" import ( "bytes" "errors" + "fmt" "math" "slices" + "strconv" "unsafe" "go.opentelemetry.io/otel/internal/global" @@ -265,6 +267,39 @@ func (v Value) Equal(w Value) bool { } } +// String returns Value's value as a string, formatted like [fmt.Sprint]. +// +// The returned string is meant for debugging; +// the string representation is not stable. +func (v Value) String() string { + switch v.Kind() { + case KindString: + return v.asString() + case KindInt64: + return strconv.FormatInt(int64(v.num), 10) + case KindFloat64: + return strconv.FormatFloat(v.asFloat64(), 'g', -1, 64) + case KindBool: + return strconv.FormatBool(v.asBool()) + case KindBytes: + return fmt.Sprint(v.asBytes()) + case KindMap: + return fmt.Sprint(v.asMap()) + case KindSlice: + return fmt.Sprint(v.asSlice()) + case KindEmpty: + return "" + default: + // Try to handle this as gracefully as possible. + // + // Don't panic here. The goal here is to have developers find this + // first if a slog.Kind is is not handled. It is + // preferable to have user's open issue asking why their attributes + // have a "unhandled: " prefix than say that their code is panicking. + return fmt.Sprintf("", v.Kind()) + } +} + // A KeyValue is a key-value pair used to represent a log attribute (a // superset of [go.opentelemetry.io/otel/attribute.KeyValue]) and map item. type KeyValue struct { @@ -321,3 +356,11 @@ func Map(key string, value ...KeyValue) KeyValue { func Empty(key string) KeyValue { return KeyValue{key, Value{}} } + +// String returns key-value pair as a string, formatted like "key=value". +// +// The returned string is meant for debugging; +// the string representation is not stable. +func (a KeyValue) String() string { + return fmt.Sprintf("%s=%s", a.Key, a.Value) +} diff --git a/log/keyvalue_test.go b/log/keyvalue_test.go index f7c6602de74..aa895b2c5e7 100644 --- a/log/keyvalue_test.go +++ b/log/keyvalue_test.go @@ -264,6 +264,25 @@ func TestEmpty(t *testing.T) { t.Run("AsMap", testErrKind(v.AsMap, "AsMap", k)) } +func TestValueString(t *testing.T) { + for _, test := range []struct { + v log.Value + want string + }{ + {log.Int64Value(-3), "-3"}, + {log.Float64Value(.15), "0.15"}, + {log.BoolValue(true), "true"}, + {log.StringValue("foo"), "foo"}, + {log.BytesValue([]byte{2, 4, 6}), "[2 4 6]"}, + {log.SliceValue(log.IntValue(3), log.StringValue("foo")), "[3 foo]"}, + {log.MapValue(log.Int("a", 1), log.Bool("b", true)), "[a=1 b=true]"}, + {log.Value{}, ""}, + } { + got := test.v.String() + assert.Equal(t, test.want, got) + } +} + type logSink struct { logr.LogSink From 67ca630f618f1fdde62c86d6bbbe9e1121a91329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Fri, 29 Mar 2024 10:11:21 +0100 Subject: [PATCH 2/4] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59d54dcca22..f51803722b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm At which point, users will be required to migrage their code, and this package will be deprecated then removed. (#5085) - Add support for `Summary` metrics in the `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` exporters. (#5100) - Add `otel.scope.name` and `otel.scope.version` tags to spans exported by `go.opentelemetry.io/otel/exporters/zipkin`. (#5108) +- Add `String method` to `Value` and `KeyValue` in `go.opentelemetry.io/otel/log`. (#5117) ### Changed From 3342c79b60a4656770f1b5c1a40c4e829ae37adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Fri, 29 Mar 2024 17:49:26 +0100 Subject: [PATCH 3/4] Update CHANGELOG.md Co-authored-by: Tyler Yahn --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f51803722b5..83a3bb0244b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm At which point, users will be required to migrage their code, and this package will be deprecated then removed. (#5085) - Add support for `Summary` metrics in the `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` exporters. (#5100) - Add `otel.scope.name` and `otel.scope.version` tags to spans exported by `go.opentelemetry.io/otel/exporters/zipkin`. (#5108) -- Add `String method` to `Value` and `KeyValue` in `go.opentelemetry.io/otel/log`. (#5117) +- Add `String` method to `Value` and `KeyValue` in `go.opentelemetry.io/otel/log`. (#5117) ### Changed From a55b71c78b48152828813fee230e957fd658fbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Fri, 29 Mar 2024 17:53:26 +0100 Subject: [PATCH 4/4] Colon instead of equality --- log/keyvalue.go | 4 ++-- log/keyvalue_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/log/keyvalue.go b/log/keyvalue.go index 8ce76eba667..10920d21f4a 100644 --- a/log/keyvalue.go +++ b/log/keyvalue.go @@ -357,10 +357,10 @@ func Empty(key string) KeyValue { return KeyValue{key, Value{}} } -// String returns key-value pair as a string, formatted like "key=value". +// String returns key-value pair as a string, formatted like "key:value". // // The returned string is meant for debugging; // the string representation is not stable. func (a KeyValue) String() string { - return fmt.Sprintf("%s=%s", a.Key, a.Value) + return fmt.Sprintf("%s:%s", a.Key, a.Value) } diff --git a/log/keyvalue_test.go b/log/keyvalue_test.go index aa895b2c5e7..2f0211160cf 100644 --- a/log/keyvalue_test.go +++ b/log/keyvalue_test.go @@ -275,7 +275,7 @@ func TestValueString(t *testing.T) { {log.StringValue("foo"), "foo"}, {log.BytesValue([]byte{2, 4, 6}), "[2 4 6]"}, {log.SliceValue(log.IntValue(3), log.StringValue("foo")), "[3 foo]"}, - {log.MapValue(log.Int("a", 1), log.Bool("b", true)), "[a=1 b=true]"}, + {log.MapValue(log.Int("a", 1), log.Bool("b", true)), "[a:1 b:true]"}, {log.Value{}, ""}, } { got := test.v.String()