Skip to content

Commit e43fec0

Browse files
authored
[pkg/ottl] support dynamic prefix/suffix in HasPrefix() and HasSuffix() functions (#43590)
1 parent 1b9ad34 commit e43fec0

File tree

6 files changed

+115
-24
lines changed

6 files changed

+115
-24
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: "Added support for dynamic prefix/suffix in HasPrefix and HasSuffix functions in OTTL."
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: [43555]
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/e2e/e2e_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,13 +1394,27 @@ func Test_e2e_ottl_features(t *testing.T) {
13941394
tCtx.GetLogRecord().Attributes().PutStr("test", "pass")
13951395
},
13961396
},
1397+
{
1398+
name: "Using HasPrefix with dynamic prefix",
1399+
statement: `set(attributes["test"], "pass") where HasPrefix(body, attributes["dynamicprefix"])`,
1400+
want: func(tCtx ottllog.TransformContext) {
1401+
tCtx.GetLogRecord().Attributes().PutStr("test", "pass")
1402+
},
1403+
},
13971404
{
13981405
name: "Using HasSuffix",
13991406
statement: `set(attributes["test"], "pass") where HasSuffix(body, "tionA")`,
14001407
want: func(tCtx ottllog.TransformContext) {
14011408
tCtx.GetLogRecord().Attributes().PutStr("test", "pass")
14021409
},
14031410
},
1411+
{
1412+
name: "Using HasSuffix with dynamic suffix",
1413+
statement: `set(attributes["test"], "pass") where HasSuffix(body, attributes["dynamicsuffix"])`,
1414+
want: func(tCtx ottllog.TransformContext) {
1415+
tCtx.GetLogRecord().Attributes().PutStr("test", "pass")
1416+
},
1417+
},
14041418
{
14051419
name: "Using hex",
14061420
statement: `set(attributes["test"], "pass") where trace_id == TraceID(0x0102030405060708090a0b0c0d0e0f10)`,
@@ -1859,6 +1873,8 @@ func constructLogTransformContext() ottllog.TransformContext {
18591873
logRecord.SetTraceID(traceID)
18601874
logRecord.SetSpanID(spanID)
18611875
logRecord.Attributes().PutStr("http.method", "get")
1876+
logRecord.Attributes().PutStr("dynamicprefix", "operation")
1877+
logRecord.Attributes().PutStr("dynamicsuffix", "tionA")
18621878
logRecord.Attributes().PutStr("http.path", "/health")
18631879
logRecord.Attributes().PutStr("http.url", "http://localhost/health")
18641880
logRecord.Attributes().PutStr("flags", "A|B|C")

pkg/ottl/ottlfuncs/func_has_prefix.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313

1414
type HasPrefixArguments[K any] struct {
1515
Target ottl.StringGetter[K]
16-
Prefix string
16+
Prefix ottl.StringGetter[K]
1717
}
1818

1919
func NewHasPrefixFactory[K any]() ottl.Factory[K] {
@@ -27,15 +27,19 @@ func createHasPrefixFunction[K any](_ ottl.FunctionContext, oArgs ottl.Arguments
2727
return nil, errors.New("HasPrefixFactory args must be of type *HasPrefixArguments[K]")
2828
}
2929

30-
return HasPrefix(args.Target, args.Prefix)
30+
return HasPrefix(args.Target, args.Prefix), nil
3131
}
3232

33-
func HasPrefix[K any](target ottl.StringGetter[K], prefix string) (ottl.ExprFunc[K], error) {
33+
func HasPrefix[K any](target, prefix ottl.StringGetter[K]) ottl.ExprFunc[K] {
3434
return func(ctx context.Context, tCtx K) (any, error) {
3535
val, err := target.Get(ctx, tCtx)
3636
if err != nil {
3737
return nil, err
3838
}
39-
return strings.HasPrefix(val, prefix), nil
40-
}, nil
39+
prefixVal, err := prefix.Get(ctx, tCtx)
40+
if err != nil {
41+
return nil, err
42+
}
43+
return strings.HasPrefix(val, prefixVal), nil
44+
}
4145
}

pkg/ottl/ottlfuncs/func_has_prefix_test.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,25 @@ func Test_HasPrefix(t *testing.T) {
1818
tests := []struct {
1919
name string
2020
target any
21-
prefix string
21+
prefix ottl.StringGetter[any]
2222
expected bool
2323
}{
2424
{
2525
name: "has prefix true",
2626
target: "hello world",
27-
prefix: "hello ",
27+
prefix: &ottl.StandardStringGetter[any]{Getter: func(context.Context, any) (any, error) { return "hello ", nil }},
2828
expected: true,
2929
},
3030
{
3131
name: "has prefix false",
3232
target: "hello world",
33-
prefix: " world",
33+
prefix: &ottl.StandardStringGetter[any]{Getter: func(context.Context, any) (any, error) { return " world", nil }},
3434
expected: false,
3535
},
3636
{
3737
name: "target pcommon.Value",
3838
target: pcommon.NewValueStr("hello world"),
39-
prefix: `hello`,
39+
prefix: &ottl.StandardStringGetter[any]{Getter: func(context.Context, any) (any, error) { return "hello", nil }},
4040
expected: true,
4141
},
4242
}
@@ -67,8 +67,28 @@ func Test_HasPrefix_Error(t *testing.T) {
6767
return true, nil
6868
},
6969
}
70-
exprFunc, err := HasPrefix[any](target, "test")
71-
assert.NoError(t, err)
72-
_, err = exprFunc(t.Context(), nil)
70+
prefix := &ottl.StandardStringGetter[any]{
71+
Getter: func(context.Context, any) (any, error) {
72+
return "test", nil
73+
},
74+
}
75+
exprFunc := HasPrefix[any](target, prefix)
76+
_, err := exprFunc(t.Context(), nil)
77+
require.Error(t, err)
78+
}
79+
80+
func Test_HasPrefix_Error_prefix(t *testing.T) {
81+
target := &ottl.StandardStringGetter[any]{
82+
Getter: func(context.Context, any) (any, error) {
83+
return true, nil
84+
},
85+
}
86+
prefix := &ottl.StandardStringGetter[any]{
87+
Getter: func(context.Context, any) (any, error) {
88+
return true, nil
89+
},
90+
}
91+
exprFunc := HasPrefix[any](target, prefix)
92+
_, err := exprFunc(t.Context(), nil)
7393
require.Error(t, err)
7494
}

pkg/ottl/ottlfuncs/func_has_suffix.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313

1414
type HasSuffixArguments[K any] struct {
1515
Target ottl.StringGetter[K]
16-
Suffix string
16+
Suffix ottl.StringGetter[K]
1717
}
1818

1919
func NewHasSuffixFactory[K any]() ottl.Factory[K] {
@@ -27,15 +27,19 @@ func createHasSuffixFunction[K any](_ ottl.FunctionContext, oArgs ottl.Arguments
2727
return nil, errors.New("HasSuffixFactory args must be of type *HasSuffixArguments[K]")
2828
}
2929

30-
return HasSuffix(args.Target, args.Suffix)
30+
return HasSuffix(args.Target, args.Suffix), nil
3131
}
3232

33-
func HasSuffix[K any](target ottl.StringGetter[K], suffix string) (ottl.ExprFunc[K], error) {
33+
func HasSuffix[K any](target, suffix ottl.StringGetter[K]) ottl.ExprFunc[K] {
3434
return func(ctx context.Context, tCtx K) (any, error) {
3535
val, err := target.Get(ctx, tCtx)
3636
if err != nil {
3737
return nil, err
3838
}
39-
return strings.HasSuffix(val, suffix), nil
40-
}, nil
39+
suffixVal, err := suffix.Get(ctx, tCtx)
40+
if err != nil {
41+
return nil, err
42+
}
43+
return strings.HasSuffix(val, suffixVal), nil
44+
}
4145
}

pkg/ottl/ottlfuncs/func_has_suffix_test.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,25 @@ func Test_HasSuffix(t *testing.T) {
1818
tests := []struct {
1919
name string
2020
target any
21-
suffix string
21+
suffix ottl.StringGetter[any]
2222
expected bool
2323
}{
2424
{
2525
name: "has suffix true",
2626
target: "hello world",
27-
suffix: " world",
27+
suffix: &ottl.StandardStringGetter[any]{Getter: func(context.Context, any) (any, error) { return " world", nil }},
2828
expected: true,
2929
},
3030
{
3131
name: "has suffix false",
3232
target: "hello world",
33-
suffix: "hello ",
33+
suffix: &ottl.StandardStringGetter[any]{Getter: func(context.Context, any) (any, error) { return "hello ", nil }},
3434
expected: false,
3535
},
3636
{
3737
name: "target pcommon.Value",
3838
target: pcommon.NewValueStr("hello world"),
39-
suffix: `world`,
39+
suffix: &ottl.StandardStringGetter[any]{Getter: func(context.Context, any) (any, error) { return "world", nil }},
4040
expected: true,
4141
},
4242
}
@@ -67,8 +67,28 @@ func Test_HasSuffix_Error(t *testing.T) {
6767
return true, nil
6868
},
6969
}
70-
exprFunc, err := HasSuffix[any](target, "test")
71-
assert.NoError(t, err)
72-
_, err = exprFunc(t.Context(), nil)
70+
suffix := &ottl.StandardStringGetter[any]{
71+
Getter: func(context.Context, any) (any, error) {
72+
return "test", nil
73+
},
74+
}
75+
exprFunc := HasSuffix[any](target, suffix)
76+
_, err := exprFunc(t.Context(), nil)
77+
require.Error(t, err)
78+
}
79+
80+
func Test_HasSuffix_Error_suffix(t *testing.T) {
81+
target := &ottl.StandardStringGetter[any]{
82+
Getter: func(context.Context, any) (any, error) {
83+
return true, nil
84+
},
85+
}
86+
suffix := &ottl.StandardStringGetter[any]{
87+
Getter: func(context.Context, any) (any, error) {
88+
return true, nil
89+
},
90+
}
91+
exprFunc := HasSuffix[any](target, suffix)
92+
_, err := exprFunc(t.Context(), nil)
7393
require.Error(t, err)
7494
}

0 commit comments

Comments
 (0)