Skip to content

Commit

Permalink
Add FromAttributeIndices helper to pprofile (#12176)
Browse files Browse the repository at this point in the history
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description

Profiles attributes are stored in a single `AttributeTable` attribute,
and then referenced in each substruct as `AttributeIndices`.

This means to read them as a `pcommon.Map`, a bit of pre-processing is
required.
This adds an helper method so each component manipulating profiles
doesn't have to reimplement it.

Benchmark:

```
go test -bench=BenchmarkFromAttributeIndices ./...
goos: darwin
goarch: arm64
pkg: go.opentelemetry.io/collector/pdata/pprofile
cpu: Apple M1 Max
BenchmarkFromAttributeIndices-10         9789714               123.2 ns/op           140 B/op          4 allocs/op
PASS
ok      go.opentelemetry.io/collector/pdata/pprofile    1.952s
PASS
ok      go.opentelemetry.io/collector/pdata/pprofile/pprofileotlp       0.407s
```
  • Loading branch information
dmathieu authored Jan 31, 2025
1 parent 50b76b9 commit 8de90e7
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .chloggen/pprofile-build-attributes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: pdata/pprofile

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add new helper method `FromAttributeIndices` to build a `pcommon.Map` out of `AttributeIndices`.

# One or more tracking issues or pull requests related to the change
issues: [12176]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [api]
28 changes: 28 additions & 0 deletions pdata/pprofile/attributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile"

import (
"go.opentelemetry.io/collector/pdata/pcommon"
)

type attributable interface {
AttributeIndices() pcommon.Int32Slice
}

// FromAttributeIndices builds a [pcommon.Map] containing the attributes of a
// record.
// The record can by any struct that implements an `AttributeIndices` method.
// Updates made to the return map will not be applied back to the record.
func FromAttributeIndices(table AttributeTableSlice, record attributable) pcommon.Map {
m := pcommon.NewMap()
m.EnsureCapacity(record.AttributeIndices().Len())

for i := 0; i < record.AttributeIndices().Len(); i++ {
kv := table.At(int(record.AttributeIndices().At(i)))
kv.Value().CopyTo(m.PutEmpty(kv.Key()))
}

return m
}
64 changes: 64 additions & 0 deletions pdata/pprofile/attributes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package pprofile

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"

"go.opentelemetry.io/collector/pdata/pcommon"
)

func TestFromAttributeIndices(t *testing.T) {
table := NewAttributeTableSlice()
att := table.AppendEmpty()
att.SetKey("hello")
att.Value().SetStr("world")
att2 := table.AppendEmpty()
att2.SetKey("bonjour")
att2.Value().SetStr("monde")

attrs := FromAttributeIndices(table, NewProfile())
assert.Equal(t, attrs, pcommon.NewMap())

// A Location with a single attribute
loc := NewLocation()
loc.AttributeIndices().Append(0)

attrs = FromAttributeIndices(table, loc)

m := map[string]any{"hello": "world"}
assert.Equal(t, attrs.AsRaw(), m)

// A Mapping with two attributes
mapp := NewLocation()
mapp.AttributeIndices().Append(0, 1)

attrs = FromAttributeIndices(table, mapp)

m = map[string]any{"hello": "world", "bonjour": "monde"}
assert.Equal(t, attrs.AsRaw(), m)
}

func BenchmarkFromAttributeIndices(b *testing.B) {
table := NewAttributeTableSlice()

for i := range 10 {
att := table.AppendEmpty()
att.SetKey(fmt.Sprintf("key_%d", i))
att.Value().SetStr(fmt.Sprintf("value_%d", i))
}

obj := NewLocation()
obj.AttributeIndices().Append(1, 3, 7)

b.ResetTimer()
b.ReportAllocs()

for n := 0; n < b.N; n++ {
_ = FromAttributeIndices(table, obj)
}
}

0 comments on commit 8de90e7

Please sign in to comment.