Skip to content

Commit 7c44647

Browse files
lkwronskisbylica-splunk
authored andcommitted
Allow indexing string slice type (open-telemetry#35581)
**Description:** Allow indexing string slice type. I can also add support for other types such as []int if needed. Let me know if this approach is good enough. I haven't found a more generic solution, thank you for any feedback. **Link to tracking Issue:** Fixes open-telemetry#29441 **Testing:** Unit test **Documentation:**
1 parent 9df7f20 commit 7c44647

File tree

4 files changed

+79
-3
lines changed

4 files changed

+79
-3
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: bug_fix
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
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: Allow indexing string slice 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: [29441]
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: [user]

pkg/ottl/e2e/e2e_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,13 @@ func Test_e2e_ottl_features(t *testing.T) {
10101010
tCtx.GetLogRecord().Attributes().PutBool("isMap", true)
10111011
},
10121012
},
1013+
{
1014+
name: "extract value from Split function result slice of type []string",
1015+
statement: `set(attributes["my.environment.2"], Split(resource.attributes["host.name"],"h")[1])`,
1016+
want: func(tCtx ottllog.TransformContext) {
1017+
tCtx.GetLogRecord().Attributes().PutStr("my.environment.2", "ost")
1018+
},
1019+
},
10131020
}
10141021

10151022
for _, tt := range tests {

pkg/ottl/expression.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,15 @@ func (g exprGetter[K]) Get(ctx context.Context, tCtx K) (any, error) {
111111
}
112112
result = ottlcommon.GetValue(r.At(int(*k.Int)))
113113
case []any:
114-
if int(*k.Int) >= len(r) || int(*k.Int) < 0 {
115-
return nil, fmt.Errorf("index %v out of bounds", *k.Int)
114+
result, err = getElementByIndex(r, k.Int)
115+
if err != nil {
116+
return nil, err
117+
}
118+
case []string:
119+
result, err = getElementByIndex(r, k.Int)
120+
if err != nil {
121+
return nil, err
116122
}
117-
result = r[*k.Int]
118123
default:
119124
return nil, fmt.Errorf("type, %T, does not support int indexing", result)
120125
}
@@ -125,6 +130,13 @@ func (g exprGetter[K]) Get(ctx context.Context, tCtx K) (any, error) {
125130
return result, nil
126131
}
127132

133+
func getElementByIndex[T any](r []T, idx *int64) (any, error) {
134+
if int(*idx) >= len(r) || int(*idx) < 0 {
135+
return nil, fmt.Errorf("index %v out of bounds", *idx)
136+
}
137+
return r[*idx], nil
138+
}
139+
128140
type listGetter[K any] struct {
129141
slice []Getter[K]
130142
}

pkg/ottl/expression_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ func basicSlice() (ExprFunc[any], error) {
5959
}, nil
6060
}
6161

62+
func basicSliceString() (ExprFunc[any], error) {
63+
return func(_ context.Context, _ any) (any, error) {
64+
return []any{
65+
[]string{
66+
"pass",
67+
},
68+
}, nil
69+
}, nil
70+
}
71+
6272
func Test_newGetter(t *testing.T) {
6373
tests := []struct {
6474
name string
@@ -237,6 +247,25 @@ func Test_newGetter(t *testing.T) {
237247
},
238248
want: "pass",
239249
},
250+
{
251+
name: "function call nested SliceString",
252+
val: value{
253+
Literal: &mathExprLiteral{
254+
Converter: &converter{
255+
Function: "SliceString",
256+
Keys: []key{
257+
{
258+
Int: ottltest.Intp(0),
259+
},
260+
{
261+
Int: ottltest.Intp(0),
262+
},
263+
},
264+
},
265+
},
266+
},
267+
want: "pass",
268+
},
240269
{
241270
name: "enum",
242271
val: value{
@@ -532,6 +561,7 @@ func Test_newGetter(t *testing.T) {
532561
createFactory("Map", &struct{}{}, basicMap),
533562
createFactory("PSlice", &struct{}{}, pslice),
534563
createFactory("Slice", &struct{}{}, basicSlice),
564+
createFactory("SliceString", &struct{}{}, basicSliceString),
535565
)
536566

537567
p, _ := NewParser[any](

0 commit comments

Comments
 (0)