Skip to content

Commit 7b62f0c

Browse files
dmathieuFiery-Fenix
authored andcommitted
[chore] add profiles support to the golden package (open-telemetry#39473)
#### Description This adds profiles support to the `pkg/golden` package, so other modules, such as `countconnector` can use it.
1 parent 826e5a0 commit 7b62f0c

File tree

21 files changed

+212
-14
lines changed

21 files changed

+212
-14
lines changed

internal/exp/metrics/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
2020
github.com/modern-go/reflect2 v1.0.2 // indirect
2121
github.com/pmezard/go-difflib v1.0.0 // indirect
22+
go.opentelemetry.io/collector/pdata/pprofile v0.124.0 // indirect
2223
go.uber.org/multierr v1.11.0 // indirect
2324
golang.org/x/net v0.38.0 // indirect
2425
golang.org/x/sys v0.31.0 // indirect

internal/exp/metrics/go.sum

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/pdatautil/go.sum

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/golden/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<!-- status autogenerated section -->
33
| Status | |
44
| ------------- |-----------|
5-
| Stability | [alpha]: traces, metrics, logs |
5+
| Stability | [alpha]: traces, metrics, logs, profiles |
66
| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Apkg%2Fgolden%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Apkg%2Fgolden) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Apkg%2Fgolden%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Apkg%2Fgolden) |
77
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@djaglowski](https://www.github.com/djaglowski), [@atoulme](https://www.github.com/atoulme) |
88

pkg/golden/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.124.1
77
github.com/stretchr/testify v1.10.0
88
go.opentelemetry.io/collector/pdata v1.30.0
9+
go.opentelemetry.io/collector/pdata/pprofile v0.124.0
910
go.uber.org/goleak v1.3.0
1011
gopkg.in/yaml.v3 v3.0.1
1112
)
@@ -18,6 +19,7 @@ require (
1819
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
1920
github.com/modern-go/reflect2 v1.0.2 // indirect
2021
github.com/pmezard/go-difflib v1.0.0 // indirect
22+
github.com/rogpeppe/go-internal v1.13.1 // indirect
2123
go.uber.org/multierr v1.11.0 // indirect
2224
golang.org/x/net v0.38.0 // indirect
2325
golang.org/x/sys v0.31.0 // indirect

pkg/golden/go.sum

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/golden/golden.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"go.opentelemetry.io/collector/pdata/plog"
1414
"go.opentelemetry.io/collector/pdata/pmetric"
15+
"go.opentelemetry.io/collector/pdata/pprofile"
1516
"go.opentelemetry.io/collector/pdata/ptrace"
1617
"gopkg.in/yaml.v3"
1718
)
@@ -190,3 +191,54 @@ func writeTraces(filePath string, traces ptrace.Traces) error {
190191
}
191192
return os.WriteFile(filePath, b.Bytes(), 0o600)
192193
}
194+
195+
// ReadProfiles reads a pprofile.Profiles from the specified YAML or JSON file.
196+
func ReadProfiles(filePath string) (pprofile.Profiles, error) {
197+
b, err := os.ReadFile(filePath)
198+
if err != nil {
199+
return pprofile.Profiles{}, err
200+
}
201+
if strings.HasSuffix(filePath, ".yaml") || strings.HasSuffix(filePath, ".yml") {
202+
var m map[string]any
203+
if err = yaml.Unmarshal(b, &m); err != nil {
204+
return pprofile.Profiles{}, err
205+
}
206+
b, err = json.Marshal(m)
207+
if err != nil {
208+
return pprofile.Profiles{}, err
209+
}
210+
}
211+
unmarshaler := pprofile.JSONUnmarshaler{}
212+
return unmarshaler.UnmarshalProfiles(b)
213+
}
214+
215+
// WriteProfiles writes a pprofile.Profiles to the specified file in YAML format.
216+
func WriteProfiles(tb testing.TB, filePath string, profiles pprofile.Profiles) error {
217+
if err := writeProfiles(filePath, profiles); err != nil {
218+
return err
219+
}
220+
tb.Logf("Golden file successfully written to %s.", filePath)
221+
tb.Log("NOTE: The WriteProfiles call must be removed in order to pass the test.")
222+
tb.Fail()
223+
return nil
224+
}
225+
226+
// writeProfiles writes a pprofile.Profiles to the specified file in YAML format.
227+
func writeProfiles(filePath string, profiles pprofile.Profiles) error {
228+
unmarshaler := &pprofile.JSONMarshaler{}
229+
fileBytes, err := unmarshaler.MarshalProfiles(profiles)
230+
if err != nil {
231+
return err
232+
}
233+
var jsonVal map[string]any
234+
if err = json.Unmarshal(fileBytes, &jsonVal); err != nil {
235+
return err
236+
}
237+
b := &bytes.Buffer{}
238+
enc := yaml.NewEncoder(b)
239+
enc.SetIndent(2)
240+
if err := enc.Encode(jsonVal); err != nil {
241+
return err
242+
}
243+
return os.WriteFile(filePath, b.Bytes(), 0o600)
244+
}

pkg/golden/golden_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"go.opentelemetry.io/collector/pdata/pcommon"
1717
"go.opentelemetry.io/collector/pdata/plog"
1818
"go.opentelemetry.io/collector/pdata/pmetric"
19+
"go.opentelemetry.io/collector/pdata/pprofile"
1920
"go.opentelemetry.io/collector/pdata/ptrace"
2021
)
2122

@@ -323,3 +324,85 @@ func TestSortAndNormalizeMetrics(t *testing.T) {
323324

324325
require.Equal(t, before, after)
325326
}
327+
328+
func TestReadProfiles(t *testing.T) {
329+
expectedProfiles := CreateTestProfiles()
330+
331+
expectedFile := filepath.Join("testdata", "profiles-roundtrip", "expected.yaml")
332+
actualProfiles, err := ReadProfiles(expectedFile)
333+
require.NoError(t, err)
334+
require.Equal(t, expectedProfiles, actualProfiles)
335+
}
336+
337+
func TestWriteProfiles(t *testing.T) {
338+
profiles := CreateTestProfiles()
339+
340+
actualFile := filepath.Join(t.TempDir(), "profiles.yaml")
341+
require.NoError(t, writeProfiles(actualFile, profiles))
342+
343+
actualBytes, err := os.ReadFile(actualFile)
344+
require.NoError(t, err)
345+
346+
expectedFile := filepath.Join("testdata", "profiles-roundtrip", "expected.yaml")
347+
expectedBytes, err := os.ReadFile(expectedFile)
348+
require.NoError(t, err)
349+
350+
if runtime.GOOS == "windows" {
351+
// os.ReadFile adds a '\r' that we don't actually expect
352+
expectedBytes = bytes.ReplaceAll(expectedBytes, []byte("\r\n"), []byte("\n"))
353+
}
354+
355+
require.Equal(t, expectedBytes, actualBytes)
356+
}
357+
358+
func TestProfilesRoundTrip(t *testing.T) {
359+
expectedProfiles := CreateTestProfiles()
360+
361+
tempDir := filepath.Join(t.TempDir(), "profiles.yaml")
362+
require.NoError(t, writeProfiles(tempDir, expectedProfiles))
363+
364+
actualProfiles, err := ReadProfiles(tempDir)
365+
require.NoError(t, err)
366+
require.Equal(t, expectedProfiles, actualProfiles)
367+
}
368+
369+
func CreateTestProfiles() pprofile.Profiles {
370+
profiles := pprofile.NewProfiles()
371+
resource := profiles.ResourceProfiles().AppendEmpty()
372+
scope := resource.ScopeProfiles().AppendEmpty()
373+
profile := scope.Profiles().AppendEmpty()
374+
375+
profile.StringTable().Append("samples", "count", "cpu", "nanoseconds")
376+
st := profile.SampleType().AppendEmpty()
377+
st.SetTypeStrindex(0)
378+
st.SetUnitStrindex(1)
379+
pt := profile.PeriodType()
380+
pt.SetTypeStrindex(2)
381+
pt.SetUnitStrindex(3)
382+
383+
a := profile.AttributeTable().AppendEmpty()
384+
a.SetKey("process.executable.build_id.htlhash")
385+
a.Value().SetStr("600DCAFE4A110000F2BF38C493F5FB92")
386+
a = profile.AttributeTable().AppendEmpty()
387+
a.SetKey("profile.frame.type")
388+
a.Value().SetStr("native")
389+
a = profile.AttributeTable().AppendEmpty()
390+
a.SetKey("host.id")
391+
a.Value().SetStr("localhost")
392+
393+
profile.AttributeIndices().Append(2)
394+
395+
sample := profile.Sample().AppendEmpty()
396+
sample.TimestampsUnixNano().Append(0)
397+
sample.SetLocationsLength(1)
398+
399+
m := profile.MappingTable().AppendEmpty()
400+
m.AttributeIndices().Append(0)
401+
402+
l := profile.LocationTable().AppendEmpty()
403+
l.SetMappingIndex(0)
404+
l.SetAddress(111)
405+
l.AttributeIndices().Append(1)
406+
407+
return profiles
408+
}

pkg/golden/metadata.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ type: golden
33
status:
44
class: pkg
55
stability:
6-
alpha: [ traces, metrics, logs ]
6+
alpha: [ traces, metrics, logs, profiles ]
77
codeowners:
8-
active: [djaglowski, atoulme]
8+
active: [djaglowski, atoulme]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
resourceProfiles:
2+
- resource: {}
3+
scopeProfiles:
4+
- profiles:
5+
- attributeIndices:
6+
- 2
7+
attributeTable:
8+
- key: process.executable.build_id.htlhash
9+
value:
10+
stringValue: 600DCAFE4A110000F2BF38C493F5FB92
11+
- key: profile.frame.type
12+
value:
13+
stringValue: native
14+
- key: host.id
15+
value:
16+
stringValue: localhost
17+
locationTable:
18+
- address: "111"
19+
attributeIndices:
20+
- 1
21+
mappingIndex: 0
22+
mappingTable:
23+
- attributeIndices:
24+
- 0
25+
periodType:
26+
typeStrindex: 2
27+
unitStrindex: 3
28+
profileId: ""
29+
sample:
30+
- locationsLength: 1
31+
timestampsUnixNano:
32+
- "0"
33+
sampleType:
34+
- unitStrindex: 1
35+
stringTable:
36+
- samples
37+
- count
38+
- cpu
39+
- nanoseconds
40+
scope: {}

0 commit comments

Comments
 (0)