Skip to content

Commit aea8c65

Browse files
authored
[pkg/ottl] Add type and unit subpaths for profile.sample_type and profile.period_type (open-telemetry#43773)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description This PR adds the following paths to the profile's context: - `profile.sample_type.type` - `profile.sample_type.unit` - `profile.period_type.type` - `profile.period_type.unit` <!-- Issue number (e.g. open-telemetry#1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes open-telemetry#43723 <!--Describe what testing was performed and which tests were added.--> #### Testing Unit/e2e tests <!--Describe the documentation added.--> #### Documentation Updated profile's context README <!--Please delete paragraphs that you did not use before submitting.-->
1 parent 2a6f710 commit aea8c65

File tree

7 files changed

+713
-53
lines changed

7 files changed

+713
-53
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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. receiver/filelog)
7+
component: pkg/ottl
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add `unit` and `type` subpaths for `profile.sample_type` and `profile.period_type`.
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [43723]
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+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

pkg/ottl/contexts/internal/ctxprofile/profile.go

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func PathGetSetter[K Context](path ottl.Path[K]) (ottl.GetSetter[K], error) {
2525
}
2626
switch path.Name() {
2727
case "sample_type":
28-
return accessSampleType[K](), nil
28+
return accessSampleType(path)
2929
case "sample":
3030
return accessSample[K](), nil
3131
case "time_unix_nano":
@@ -37,7 +37,7 @@ func PathGetSetter[K Context](path ottl.Path[K]) (ottl.GetSetter[K], error) {
3737
case "duration":
3838
return accessDuration[K](), nil
3939
case "period_type":
40-
return accessPeriodType[K](), nil
40+
return accessPeriodType[K](path)
4141
case "period":
4242
return accessPeriod[K](), nil
4343
case "comment_string_indices":
@@ -142,18 +142,11 @@ func accessDuration[K Context]() ottl.StandardGetSetter[K] {
142142
}
143143
}
144144

145-
func accessPeriodType[K Context]() ottl.StandardGetSetter[K] {
146-
return ottl.StandardGetSetter[K]{
147-
Getter: func(_ context.Context, tCtx K) (any, error) {
148-
return tCtx.GetProfile().PeriodType(), nil
149-
},
150-
Setter: func(_ context.Context, tCtx K, val any) error {
151-
if v, ok := val.(pprofile.ValueType); ok {
152-
v.CopyTo(tCtx.GetProfile().PeriodType())
153-
}
154-
return nil
155-
},
145+
func accessPeriodType[K Context](path ottl.Path[K]) (ottl.GetSetter[K], error) {
146+
periodTypeTarget := func(tCtx K) pprofile.ValueType {
147+
return tCtx.GetProfile().PeriodType()
156148
}
149+
return valueTypeGetterSetter(path, periodTypeTarget)
157150
}
158151

159152
func accessPeriod[K Context]() ottl.StandardGetSetter[K] {
@@ -181,18 +174,11 @@ func accessCommentStringIndices[K Context]() ottl.StandardGetSetter[K] {
181174
}
182175
}
183176

184-
func accessSampleType[K Context]() ottl.StandardGetSetter[K] {
185-
return ottl.StandardGetSetter[K]{
186-
Getter: func(_ context.Context, tCtx K) (any, error) {
187-
return tCtx.GetProfile().SampleType(), nil
188-
},
189-
Setter: func(_ context.Context, tCtx K, val any) error {
190-
if v, ok := val.(pprofile.ValueType); ok {
191-
v.CopyTo(tCtx.GetProfile().SampleType())
192-
}
193-
return nil
194-
},
177+
func accessSampleType[K Context](path ottl.Path[K]) (ottl.GetSetter[K], error) {
178+
sampleTypeTarget := func(tCtx K) pprofile.ValueType {
179+
return tCtx.GetProfile().SampleType()
195180
}
181+
return valueTypeGetterSetter(path, sampleTypeTarget)
196182
}
197183

198184
func accessProfileID[K Context]() ottl.StandardGetSetter[K] {

pkg/ottl/contexts/internal/ctxprofile/profile_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ func TestPathGetSetter(t *testing.T) {
3131
path: "sample_type",
3232
val: createValueType(),
3333
},
34+
{
35+
path: "sample_type type",
36+
val: "cpu",
37+
},
38+
{
39+
path: "sample_type unit",
40+
val: "cycles",
41+
},
3442
{
3543
path: "sample",
3644
val: createSampleSlice(),
@@ -55,6 +63,14 @@ func TestPathGetSetter(t *testing.T) {
5563
path: "period_type",
5664
val: createValueType(),
5765
},
66+
{
67+
path: "period_type type",
68+
val: "heap",
69+
},
70+
{
71+
path: "period_type unit",
72+
val: "bytes",
73+
},
5874
{
5975
path: "period",
6076
val: int64(234),
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package ctxprofile // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/internal/ctxprofile"
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"go.opentelemetry.io/collector/pdata/pprofile"
11+
12+
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
13+
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/internal/ctxerror"
14+
)
15+
16+
type valueTypeSource[K Context] = func(ctx K) pprofile.ValueType
17+
18+
func valueTypeGetterSetter[K Context](
19+
path ottl.Path[K],
20+
source valueTypeSource[K],
21+
) (ottl.GetSetter[K], error) {
22+
if path == nil || path.Next() == nil {
23+
return accessValueType(path, source), nil
24+
}
25+
26+
nextPath := path.Next()
27+
switch nextPath.Name() {
28+
case "type":
29+
return accessValueTypeType[K](nextPath, source), nil
30+
case "unit":
31+
return accessValueTypeUnit[K](nextPath, source), nil
32+
default:
33+
return nil, ctxerror.New(path.Name(), nextPath.String(), Name, DocRef)
34+
}
35+
}
36+
37+
func accessValueType[K Context](path ottl.Path[K], getValueType valueTypeSource[K]) ottl.GetSetter[K] {
38+
return ottl.StandardGetSetter[K]{
39+
Getter: func(_ context.Context, tCtx K) (any, error) {
40+
return getValueType(tCtx), nil
41+
},
42+
Setter: func(_ context.Context, tCtx K, val any) error {
43+
newValue, ok := val.(pprofile.ValueType)
44+
if !ok {
45+
return fmt.Errorf("expected a pprofile.ValueType value for path %q, got %T", path.String(), val)
46+
}
47+
newValue.CopyTo(getValueType(tCtx))
48+
return nil
49+
},
50+
}
51+
}
52+
53+
func accessValueTypeType[K Context](path ottl.Path[K], getValueType valueTypeSource[K]) ottl.GetSetter[K] {
54+
return ottl.StandardGetSetter[K]{
55+
Getter: func(_ context.Context, tCtx K) (any, error) {
56+
valueType := getValueType(tCtx)
57+
return getValueTypeString(path, tCtx.GetProfilesDictionary(), valueType.TypeStrindex())
58+
},
59+
Setter: func(_ context.Context, tCtx K, val any) error {
60+
valueType := getValueType(tCtx)
61+
newIndex, err := setValueTypeString(path, tCtx.GetProfilesDictionary(), valueType.TypeStrindex(), val)
62+
if err != nil {
63+
return err
64+
}
65+
valueType.SetTypeStrindex(newIndex)
66+
return nil
67+
},
68+
}
69+
}
70+
71+
func accessValueTypeUnit[K Context](path ottl.Path[K], getValueType valueTypeSource[K]) ottl.GetSetter[K] {
72+
return ottl.StandardGetSetter[K]{
73+
Getter: func(_ context.Context, tCtx K) (any, error) {
74+
valueType := getValueType(tCtx)
75+
return getValueTypeString(path, tCtx.GetProfilesDictionary(), valueType.UnitStrindex())
76+
},
77+
Setter: func(_ context.Context, tCtx K, val any) error {
78+
valueType := getValueType(tCtx)
79+
newIndex, err := setValueTypeString(path, tCtx.GetProfilesDictionary(), valueType.UnitStrindex(), val)
80+
if err != nil {
81+
return err
82+
}
83+
valueType.SetUnitStrindex(newIndex)
84+
return nil
85+
},
86+
}
87+
}
88+
89+
func getValueTypeString[K Context](
90+
path ottl.Path[K],
91+
dict pprofile.ProfilesDictionary,
92+
currIndex int32,
93+
) (string, error) {
94+
if currIndex < 0 || int(currIndex) >= dict.StringTable().Len() {
95+
return "", fmt.Errorf("path %q with strindex %d is out of range", path.String(), currIndex)
96+
}
97+
return dict.StringTable().At(int(currIndex)), nil
98+
}
99+
100+
func setValueTypeString[K Context](
101+
path ottl.Path[K],
102+
dict pprofile.ProfilesDictionary,
103+
currIndex int32,
104+
val any,
105+
) (int32, error) {
106+
newValue, ok := val.(string)
107+
if !ok {
108+
return 0, fmt.Errorf("expected a string value for path %q, got %T", path.String(), val)
109+
}
110+
if currIndex != 0 && int(currIndex) < dict.StringTable().Len() {
111+
currValue := dict.StringTable().At(int(currIndex))
112+
if currValue == newValue {
113+
return currIndex, nil
114+
}
115+
}
116+
newIndex, err := pprofile.SetString(dict.StringTable(), newValue)
117+
if err != nil {
118+
return 0, err
119+
}
120+
return newIndex, nil
121+
}

0 commit comments

Comments
 (0)