You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-08-10 22:31:50 +02:00
log: Add Record.Clone (#7001)
Fixes #6986 This PR adds a `Clone()` method to the `log.Record` type. The `Clone` method returns a copy of the record with no shared state, allowing both the original and the clone to be modified independently. This functionality mirrors the existing `sdk/log.Record.Clone()` behavior and includes a corresponding unit test (`TestRecordClone`) to ensure correctness. --------- Co-authored-by: Robert Pająk <pellared@hotmail.com>
This commit is contained in:
@@ -41,6 +41,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
- `RPCGRPCResponseMetadata`
|
||||
- Add `ErrorType` attribute helper function to the `go.opentelmetry.io/otel/semconv/v1.34.0` package. (#6962)
|
||||
- Add `WithAllowKeyDuplication` in `go.opentelemetry.io/otel/sdk/log` which can be used to disable deduplication for log records. (#6968)
|
||||
- Add `Clone` method to `Record` in `go.opentelemetry.io/otel/log` that returns a copy of the record with no shared state. (#7001)
|
||||
|
||||
### Changed
|
||||
|
||||
|
@@ -142,3 +142,11 @@ func (r *Record) AddAttributes(attrs ...KeyValue) {
|
||||
func (r *Record) AttributesLen() int {
|
||||
return r.nFront + len(r.back)
|
||||
}
|
||||
|
||||
// Clone returns a copy of the record with no shared state.
|
||||
// The original record and the clone can both be modified without interfering with each other.
|
||||
func (r *Record) Clone() Record {
|
||||
res := *r
|
||||
res.back = slices.Clone(r.back)
|
||||
return res
|
||||
}
|
||||
|
@@ -160,3 +160,64 @@ func TestRecordAllocationLimits(t *testing.T) {
|
||||
// Convince the linter these values are used.
|
||||
_, _, _, _, _, _ = tStamp, sev, text, body, n, attr
|
||||
}
|
||||
|
||||
func TestRecordClone(t *testing.T) {
|
||||
now0 := time.Now()
|
||||
sev0 := log.SeverityInfo
|
||||
text0 := "text"
|
||||
val0 := log.BoolValue(true)
|
||||
attr0 := log.Bool("0", true)
|
||||
|
||||
r0 := log.Record{}
|
||||
r0.SetTimestamp(now0)
|
||||
r0.SetObservedTimestamp(now0)
|
||||
r0.SetSeverity(sev0)
|
||||
r0.SetSeverityText(text0)
|
||||
r0.SetBody(val0)
|
||||
r0.AddAttributes(attr0)
|
||||
|
||||
// Clone and modify the clone
|
||||
now1 := now0.Add(time.Second)
|
||||
sev1 := log.SeverityDebug
|
||||
text1 := "string"
|
||||
val1 := log.IntValue(1)
|
||||
attr1 := log.Int64("1", 2)
|
||||
|
||||
r1 := r0.Clone()
|
||||
r1.SetTimestamp(now1)
|
||||
r1.SetObservedTimestamp(now1)
|
||||
r1.SetSeverity(sev1)
|
||||
r1.SetSeverityText(text1)
|
||||
r1.SetBody(val1)
|
||||
r1.AddAttributes(attr1)
|
||||
|
||||
// Assertions on original record (r0)
|
||||
assert.Equal(t, now0, r0.Timestamp())
|
||||
assert.Equal(t, now0, r0.ObservedTimestamp())
|
||||
assert.Equal(t, sev0, r0.Severity())
|
||||
assert.Equal(t, text0, r0.SeverityText())
|
||||
assert.True(t, val0.Equal(r0.Body()))
|
||||
|
||||
var r0Attrs []log.KeyValue
|
||||
r0.WalkAttributes(func(kv log.KeyValue) bool {
|
||||
r0Attrs = append(r0Attrs, kv)
|
||||
return true
|
||||
})
|
||||
assert.Contains(t, r0Attrs, attr0)
|
||||
assert.NotContains(t, r0Attrs, attr1)
|
||||
|
||||
// Assertions on cloned record (r1)
|
||||
assert.Equal(t, now1, r1.Timestamp())
|
||||
assert.Equal(t, now1, r1.ObservedTimestamp())
|
||||
assert.Equal(t, sev1, r1.Severity())
|
||||
assert.Equal(t, text1, r1.SeverityText())
|
||||
assert.True(t, val1.Equal(r1.Body()))
|
||||
|
||||
var r1Attrs []log.KeyValue
|
||||
r1.WalkAttributes(func(kv log.KeyValue) bool {
|
||||
r1Attrs = append(r1Attrs, kv)
|
||||
return true
|
||||
})
|
||||
assert.Contains(t, r1Attrs, attr0)
|
||||
assert.Contains(t, r1Attrs, attr1)
|
||||
}
|
||||
|
Reference in New Issue
Block a user