Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ee35e14
add test cases for keyvalue collections with duplicates in log body
Mojachieee Jul 14, 2025
6d291b2
update SetBody to deduplicate keyvalue collections
Mojachieee Jul 14, 2025
642daca
refactor dedupeandlimit func into separate funcs
Mojachieee Jul 14, 2025
d09263a
lint
Mojachieee Jul 14, 2025
319c086
fix allowDuplicates bug and add test
Mojachieee Jul 14, 2025
07d610f
changelog
Mojachieee Jul 14, 2025
3e64aa9
fix dedupe body using wrong function, update changelog
Mojachieee Jul 15, 2025
efc658a
Update CHANGELOG.md
pellared Jul 15, 2025
0c54eab
Apply suggestions from code review
Mojachieee Jul 15, 2025
fbade72
Update sdk/log/record_test.go
pellared Jul 15, 2025
5acf33a
Merge branch 'main' into dedup-keyvals-in-log-body
pellared Jul 15, 2025
80f0893
lint
Mojachieee Jul 15, 2025
e9bd161
Merge branch 'main' into dedup-keyvals-in-log-body
pellared Jul 16, 2025
4df978d
Merge branch 'main' into dedup-keyvals-in-log-body
pellared Jul 22, 2025
565eba4
Merge branch 'main' into dedup-keyvals-in-log-body
Mojachieee Jul 25, 2025
5cddc9a
add benchmark for record.SetBody
Mojachieee Jul 25, 2025
4cb8459
Merge branch 'main' into dedup-keyvals-in-log-body
Mojachieee Jul 30, 2025
6242fef
newRecord dedupes body collections & add test
Mojachieee Jul 30, 2025
69af503
Merge branch 'main' into dedup-keyvals-in-log-body
pellared Aug 12, 2025
12a9d7c
Merge branch 'main' into dedup-keyvals-in-log-body
pellared Aug 25, 2025
e382ce9
Merge branch 'main' into dedup-keyvals-in-log-body
pellared Aug 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
<!-- Released section -->
<!-- Don't change this section unless doing release -->

### Fixes

- sdk/log: Deduplicate key-value collections in log body in `go.opentelemetry.io/otel/sdk/log`, as per OTel spec. (#7002)

## [1.37.0/0.59.0/0.13.0] 2025-06-25

### Added
Expand Down
24 changes: 23 additions & 1 deletion sdk/log/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,11 @@ func (r *Record) Body() log.Value {

// SetBody sets the body of the log record.
func (r *Record) SetBody(v log.Value) {
r.body = v
if !r.allowDupKeys {
r.body = r.dedupeBodyCollections(v)
} else {
r.body = v
}
}

// WalkAttributes walks all attributes the log record holds by calling f for
Expand Down Expand Up @@ -452,6 +456,24 @@ func (r *Record) applyValueLimits(val log.Value) log.Value {
return val
}

func (r *Record) dedupeBodyCollections(val log.Value) log.Value {
switch val.Kind() {
case log.KindSlice:
sl := val.AsSlice()
for i := range sl {
sl[i] = r.applyValueLimits(sl[i])
}
val = log.SliceValue(sl...)
case log.KindMap:
kvs, _ := dedup(val.AsMap())
for i := range kvs {
kvs[i].Value = r.dedupeBodyCollections(kvs[i].Value)
}
val = log.MapValue(kvs...)
}
return val
}

// truncate returns a truncated version of s such that it contains less than
// the limit number of characters. Truncation is applied by returning the limit
// number of valid characters contained in s.
Expand Down
79 changes: 75 additions & 4 deletions sdk/log/record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,81 @@ func TestRecordSeverityText(t *testing.T) {
}

func TestRecordBody(t *testing.T) {
v := log.BoolValue(true)
r := new(Record)
r.SetBody(v)
assert.True(t, v.Equal(r.Body()))
testcases := []struct {
name string
body log.Value
want log.Value
allowDuplicates bool
}{
{
name: "Bool",
body: log.BoolValue(true),
want: log.BoolValue(true),
},
{
name: "slice",
body: log.SliceValue(log.BoolValue(true), log.BoolValue(false)),
want: log.SliceValue(log.BoolValue(true), log.BoolValue(false)),
},
{
name: "map",
body: log.MapValue(
log.Bool("0", true),
log.Int64("1", 2), // This should be removed
log.Float64("2", 3.0),
log.String("3", "forth"),
log.Slice("4", log.Int64Value(1)),
log.Map("5", log.Int("key", 2)),
log.Bytes("6", []byte("six")),
log.Int64("1", 3),
),
want: log.MapValue(
log.Bool("0", true),
log.Float64("2", 3.0),
log.String("3", "forth"),
log.Slice("4", log.Int64Value(1)),
log.Map("5", log.Int("key", 2)),
log.Bytes("6", []byte("six")),
log.Int64("1", 3),
),
},
{
name: "nestedMap",
body: log.MapValue(
log.Map("key",
log.Int64("key", 1),
log.Int64("key", 2),
),
),
want: log.MapValue(
log.Map("key",
log.Int64("key", 2),
),
),
},
{
name: "map - allow duplicates",
body: log.MapValue(
log.Int64("1", 2),
log.Int64("1", 3),
),
want: log.MapValue(
log.Int64("1", 2),
log.Int64("1", 3),
),
allowDuplicates: true,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
r := new(Record)
r.allowDupKeys = tc.allowDuplicates
r.SetBody(tc.body)
assert.True(t, tc.want.Equal(r.Body()), "body is not equal")
t.Logf("wanted %v", tc.want)
t.Logf("got %v", r.Body())
})
}
}

func TestRecordAttributes(t *testing.T) {
Expand Down
Loading