Skip to content

Commit

Permalink
logs: Add empty value for KeyValue (#5076)
Browse files Browse the repository at this point in the history
* Add empty value for KeyValue

* Update CHANGELOG

* Apply suggestions from code review

Co-authored-by: Robert Pająk <pellared@hotmail.com>
Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>

* Fix comments

* Update log/keyvalue.go

Co-authored-by: Damien Mathieu <42@dmathieu.com>

---------

Co-authored-by: Robert Pająk <pellared@hotmail.com>
Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
Co-authored-by: Damien Mathieu <42@dmathieu.com>
  • Loading branch information
4 people committed Mar 15, 2024
1 parent 42c1708 commit 47ac0d4
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 10 deletions.
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
- Add `WithProxy` option in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlptracehttp`. (#4906)
- Add `SeverityUndefined` `const` to `go.opentelemetry.io/otel/log`.
This value represents an unset severity level. (#5072)
- Add `Empty` function in `go.opentelemetry.io/otel/log` to return a `KeyValue` for an empty value. (#5076)

### Changed

Expand Down
24 changes: 15 additions & 9 deletions log/keyvalue.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (
)

// A Value represents a structured log value.
// A zero value is valid and represents an empty value.
type Value struct {
// Ensure forward compatibility by explicitly making this not comparable.
noCmp [0]func() //nolint: unused // This is indeed used.
Expand Down Expand Up @@ -264,7 +265,7 @@ func (v Value) Equal(w Value) bool {
}
}

// An KeyValue is a key-value pair used to represent a log attribute (a
// 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 {
Key string
Expand All @@ -276,42 +277,47 @@ func (a KeyValue) Equal(b KeyValue) bool {
return a.Key == b.Key && a.Value.Equal(b.Value)
}

// String returns an KeyValue for a string value.
// String returns a KeyValue for a string value.
func String(key, value string) KeyValue {
return KeyValue{key, StringValue(value)}
}

// Int64 returns an KeyValue for an int64 value.
// Int64 returns a KeyValue for an int64 value.
func Int64(key string, value int64) KeyValue {
return KeyValue{key, Int64Value(value)}
}

// Int returns an KeyValue for an int value.
// Int returns a KeyValue for an int value.
func Int(key string, value int) KeyValue {
return KeyValue{key, IntValue(value)}
}

// Float64 returns an KeyValue for a float64 value.
// Float64 returns a KeyValue for a float64 value.
func Float64(key string, value float64) KeyValue {
return KeyValue{key, Float64Value(value)}
}

// Bool returns an KeyValue for a bool value.
// Bool returns a KeyValue for a bool value.
func Bool(key string, value bool) KeyValue {
return KeyValue{key, BoolValue(value)}
}

// Bytes returns an KeyValue for a []byte value.
// Bytes returns a KeyValue for a []byte value.
func Bytes(key string, value []byte) KeyValue {
return KeyValue{key, BytesValue(value)}
}

// Slice returns an KeyValue for a []Value value.
// Slice returns a KeyValue for a []Value value.
func Slice(key string, value ...Value) KeyValue {
return KeyValue{key, SliceValue(value...)}
}

// Map returns an KeyValue for a map value.
// Map returns a KeyValue for a map value.
func Map(key string, value ...KeyValue) KeyValue {
return KeyValue{key, MapValue(value...)}
}

// Empty returns a KeyValue with an empty value.
func Empty(key string) KeyValue {
return KeyValue{key, Value{}}
}
20 changes: 19 additions & 1 deletion log/keyvalue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func TestValueEqual(t *testing.T) {
log.MapValue(
log.Slice("l", log.IntValue(3), log.StringValue("foo")),
log.Bytes("b", []byte{3, 5, 7}),
log.Empty("e"),
),
}
for i, v1 := range vals {
Expand All @@ -69,7 +70,7 @@ func TestValueEqual(t *testing.T) {
}
}

func TestEmpty(t *testing.T) {
func TestValueEmpty(t *testing.T) {
v := log.Value{}
t.Run("Value.Empty", func(t *testing.T) {
assert.True(t, v.Empty())
Expand Down Expand Up @@ -246,6 +247,23 @@ func TestMap(t *testing.T) {
})
}

func TestEmpty(t *testing.T) {
const key = "key"
kv := log.Empty(key)

assert.Equal(t, key, kv.Key, "incorrect key")
assert.True(t, kv.Value.Empty(), "value not empty")

v, k := kv.Value, log.KindEmpty
t.Run("AsBool", testErrKind(v.AsBool, "AsBool", k))
t.Run("AsFloat64", testErrKind(v.AsFloat64, "AsFloat64", k))
t.Run("AsInt64", testErrKind(v.AsInt64, "AsInt64", k))
t.Run("AsString", testErrKind(v.AsString, "AsString", k))
t.Run("AsBytes", testErrKind(v.AsBytes, "AsBytes", k))
t.Run("AsSlice", testErrKind(v.AsSlice, "AsSlice", k))
t.Run("AsMap", testErrKind(v.AsMap, "AsMap", k))
}

type logSink struct {
logr.LogSink

Expand Down

0 comments on commit 47ac0d4

Please sign in to comment.