diff --git a/.chloggen/lkwronski.issue-30420-p-slice-getter.yaml b/.chloggen/lkwronski.issue-30420-p-slice-getter.yaml new file mode 100644 index 000000000000..72b84a3a46a1 --- /dev/null +++ b/.chloggen/lkwronski.issue-30420-p-slice-getter.yaml @@ -0,0 +1,27 @@ +# 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. filelogreceiver) +component: pkg/ottl + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add typed getter for `pcommon.Slice` + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [30420] + +# (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: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# 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: [user] diff --git a/pkg/ottl/e2e/e2e_test.go b/pkg/ottl/e2e/e2e_test.go index 026102115992..116862ddecad 100644 --- a/pkg/ottl/e2e/e2e_test.go +++ b/pkg/ottl/e2e/e2e_test.go @@ -732,9 +732,16 @@ func Test_e2e_ottl_features(t *testing.T) { tCtx.GetLogRecord().Attributes().PutStr("test", "pass") }, }, + { + name: "where clause with Contains ints return value", + statement: []string{`set(attributes["test"], "pass") where Contains([1, 2, 3, 4], 4)`}, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, { name: "where clause with Contains floats return value", - statement: []string{`set(attributes["test"], "pass") where Contains([1.1, 2.2, 3.3, 4.4], "4.4")`}, + statement: []string{`set(attributes["test"], "pass") where Contains([1.1, 2.2, 3.3, 4.4], 4.4)`}, want: func(tCtx ottllog.TransformContext) { tCtx.GetLogRecord().Attributes().PutStr("test", "pass") }, diff --git a/pkg/ottl/expression.go b/pkg/ottl/expression.go index ce54cc9e43fc..f00204486e00 100644 --- a/pkg/ottl/expression.go +++ b/pkg/ottl/expression.go @@ -401,7 +401,7 @@ func (g StandardPMapGetter[K]) Get(ctx context.Context, tCtx K) (pcommon.Map, er if v.Type() == pcommon.ValueTypeMap { return v.Map(), nil } - return pcommon.Map{}, TypeError(fmt.Sprintf("expected pcommon.Map but got %v", v.Type())) + return pcommon.Map{}, TypeError(fmt.Sprintf("expected pcommon.Map but got %T", v)) case map[string]any: m := pcommon.NewMap() err = m.FromRaw(v) diff --git a/pkg/ottl/ottlfuncs/README.md b/pkg/ottl/ottlfuncs/README.md index c2a0f36543d9..fced42343b3e 100644 --- a/pkg/ottl/ottlfuncs/README.md +++ b/pkg/ottl/ottlfuncs/README.md @@ -464,15 +464,15 @@ Examples: The Contains function checks if an item is present in a given slice `target`. It returns true if the `item` is found, and false otherwise. -`target` is a slices of values passed as arguments. It supports primitive types. +`target` is a slice of primitive-typed values. -`item` is the string value to check for in the `target`. +`item` is the primitive-typed value to check for in the `target`. Examples: - `Contains(attributes["tags"], "staging")` -- `Contains([1, 2, 3, 4, 5], "3")` -- `Contains([1.1, 2.2, 3.3, 4.4], "4.4")` +- `Contains([1, 2, 3, 4, 5], 3)` +- `Contains([1.1, 2.2, 3.3, 4.4], 4.4)` - `Contains(["GET", "PUT", "POST"], "GET")` ### ConvertCase diff --git a/pkg/ottl/ottlfuncs/func_contains.go b/pkg/ottl/ottlfuncs/func_contains.go index 013d8b396de2..2989889a4086 100644 --- a/pkg/ottl/ottlfuncs/func_contains.go +++ b/pkg/ottl/ottlfuncs/func_contains.go @@ -12,7 +12,7 @@ import ( type ContainsArguments[K any] struct { Target ottl.PSliceGetter[K] - Item string + Item ottl.Getter[K] } func NewContainsFactory[K any]() ottl.Factory[K] { @@ -29,16 +29,19 @@ func createContainsFunction[K any](_ ottl.FunctionContext, oArgs ottl.Arguments) return contains(args.Target, args.Item), nil } -// nolint:errorlint -func contains[K any](target ottl.PSliceGetter[K], item string) ottl.ExprFunc[K] { +func contains[K any](target ottl.PSliceGetter[K], itemGetter ottl.Getter[K]) ottl.ExprFunc[K] { return func(ctx context.Context, tCtx K) (any, error) { - slice, err := target.Get(ctx, tCtx) - if err != nil { - return nil, err + slice, sliceErr := target.Get(ctx, tCtx) + if sliceErr != nil { + return nil, sliceErr + } + item, itemErr := itemGetter.Get(ctx, tCtx) + if itemErr != nil { + return nil, itemErr } for i := 0; i < slice.Len(); i++ { - val := slice.At(i).AsString() + val := slice.At(i).AsRaw() if val == item { return true, nil } diff --git a/pkg/ottl/ottlfuncs/func_contains_test.go b/pkg/ottl/ottlfuncs/func_contains_test.go index 7cd239987047..46c89bb978a5 100644 --- a/pkg/ottl/ottlfuncs/func_contains_test.go +++ b/pkg/ottl/ottlfuncs/func_contains_test.go @@ -17,7 +17,7 @@ func Test_contains(t *testing.T) { tests := []struct { name string target ottl.StandardPSliceGetter[any] - item string + item ottl.Getter[any] expected bool }{ { @@ -27,7 +27,11 @@ func Test_contains(t *testing.T) { return []any{"hello", "world"}, nil }, }, - item: "hello", + item: ottl.StandardGetSetter[any]{ + Getter: func(_ context.Context, _ any) (any, error) { + return "hello", nil + }, + }, expected: true, }, { @@ -37,7 +41,11 @@ func Test_contains(t *testing.T) { return []any{"hello", "world"}, nil }, }, - item: "unknow", + item: ottl.StandardGetSetter[any]{ + Getter: func(_ context.Context, _ any) (any, error) { + return "unknow", nil + }, + }, expected: false, }, { @@ -47,7 +55,11 @@ func Test_contains(t *testing.T) { return []any{0, 1}, nil }, }, - item: "1", + item: ottl.StandardGetSetter[any]{ + Getter: func(_ context.Context, _ any) (any, error) { + return int64(1), nil + }, + }, expected: true, }, { @@ -57,7 +69,11 @@ func Test_contains(t *testing.T) { return []any{0, 3.14159}, nil }, }, - item: "3.14159", + item: ottl.StandardGetSetter[any]{ + Getter: func(_ context.Context, _ any) (any, error) { + return 3.14159, nil + }, + }, expected: true, }, { @@ -67,7 +83,11 @@ func Test_contains(t *testing.T) { return []any{true, false}, nil }, }, - item: "true", + item: ottl.StandardGetSetter[any]{ + Getter: func(_ context.Context, _ any) (any, error) { + return true, nil + }, + }, expected: true, }, { @@ -79,7 +99,11 @@ func Test_contains(t *testing.T) { return s, nil }, }, - item: "1", + item: ottl.StandardGetSetter[any]{ + Getter: func(_ context.Context, _ any) (any, error) { + return int64(1), nil + }, + }, expected: true, }, { @@ -91,7 +115,11 @@ func Test_contains(t *testing.T) { return s, nil }, }, - item: "4", + item: ottl.StandardGetSetter[any]{ + Getter: func(_ context.Context, _ any) (any, error) { + return int64(4), nil + }, + }, expected: false, }, } @@ -112,7 +140,13 @@ func Test_contains_error(t *testing.T) { return make(chan int), nil }, } - exprFunc := contains(target, "test") + item := &ottl.StandardGetSetter[any]{ + Getter: func(_ context.Context, _ any) (any, error) { + return "test", nil + }, + } + + exprFunc := contains(target, item) _, err := exprFunc(context.Background(), nil) assert.Error(t, err) }