Skip to content

Commit 1a96bc6

Browse files
committed
Document that changing pcommon.Map invalidates Value references
Signed-off-by: Bogdan Drutu <[email protected]>
1 parent e2954b9 commit 1a96bc6

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

.chloggen/document-13073.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
7+
component: pdata
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Document that changing pcommon.Map (Remove/removeIf/Put*) invalidates Value references obtained via Get.
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [13073]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# Optional: The change log or logs in which this entry should be included.
21+
# e.g. '[user]' or '[user, api]'
22+
# Include 'user' if the change is relevant to end users.
23+
# Include 'api' if there is a change to a library API.
24+
# Default: '[user]'
25+
change_logs: [api]

pdata/pcommon/map.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,14 @@ func (m Map) EnsureCapacity(capacity int) {
5555
copy(*m.getOrig(), oldOrig)
5656
}
5757

58-
// Get returns the Value associated with the key and true. Returned
58+
// Get returns the Value associated with the key and true. The returned
5959
// Value is not a copy, it is a reference to the value stored in this map.
6060
// It is allowed to modify the returned value using Value.Set* functions.
6161
// Such modification will be applied to the value stored in this map.
62+
// Accessing the returned value after modifying the underlying map
63+
// (removing or adding new values) is an undefined behavior.
6264
//
63-
// If the key does not exist returns a zero-initialized KeyValue and false.
65+
// If the key does not exist, returns a zero-initialized KeyValue and false.
6466
// Calling any functions on the returned invalid instance may cause a panic.
6567
func (m Map) Get(key string) (Value, bool) {
6668
for i := range *m.getOrig() {

pdata/plog/logs_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,31 @@ func BenchmarkLogsUsage(b *testing.B) {
172172
}
173173
}
174174
}
175+
176+
func Test_minimal_reproducer(t *testing.T) {
177+
logs := NewLogs()
178+
resourceLogs1 := logs.ResourceLogs().AppendEmpty()
179+
attrs1 := resourceLogs1.Resource().Attributes()
180+
attrs1.PutStr("attr.to.move", "mover")
181+
attrs1.PutStr("service.name", "dummy-service")
182+
attrs1.PutStr("service.namespace", "dash0")
183+
184+
// Create a second Resource
185+
resourceLogs2 := logs.ResourceLogs().AppendEmpty()
186+
attrs2 := resourceLogs2.Resource().Attributes()
187+
attrs2.PutStr("service.name", "another-dummy-service")
188+
attrs2.PutStr("service.namespace", "dash0")
189+
190+
// Now we pick up the attribute and remove from the first Resource, then add to the second Resource
191+
// Normally this would happen e.g. in some loop or other logic, but shortened just to make the issue clear
192+
if v, ok := logs.ResourceLogs().At(0).Resource().Attributes().Get("attr.to.move"); ok {
193+
// !! the Remove happens FIRST !!
194+
logs.ResourceLogs().At(0).Resource().Attributes().Remove("attr.to.move")
195+
196+
logs.ResourceLogs().At(1).Resource().Attributes().PutStr("attr.to.move", v.AsString())
197+
}
198+
199+
movedValue, ok := logs.ResourceLogs().At(1).Resource().Attributes().Get("attr.to.move")
200+
assert.True(t, ok)
201+
assert.Equal(t, "mover", movedValue.AsString()) // FAILS, value is "dash0" from the service.namespace
202+
}

0 commit comments

Comments
 (0)