Skip to content

Commit 94c4f57

Browse files
authored
Merge branch 'open-telemetry:main' into main
2 parents fa7ff02 + 0ac93cd commit 94c4f57

File tree

9 files changed

+257
-54
lines changed

9 files changed

+257
-54
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: "Support taking match patterns from runtime data in the `replace_all_patterns` and `replace_pattern` functions."
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: []

.chloggen/ottl-split-dynamic.yaml

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 delimiter in Split() function 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: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,13 @@ func Test_e2e_editors(t *testing.T) {
272272
tCtx.GetLogRecord().Attributes().PutStr("http.path", "test")
273273
},
274274
},
275+
{
276+
statement: `replace_all_patterns(attributes, "value", Concat(["/","health"],""), "@")`,
277+
want: func(tCtx ottllog.TransformContext) {
278+
tCtx.GetLogRecord().Attributes().PutStr("http.path", "@")
279+
tCtx.GetLogRecord().Attributes().PutStr("http.url", "http://localhost@")
280+
},
281+
},
275282
{
276283
statement: `replace_match(attributes["http.path"], "*/*", "test")`,
277284
want: func(tCtx ottllog.TransformContext) {
@@ -284,6 +291,12 @@ func Test_e2e_editors(t *testing.T) {
284291
tCtx.GetLogRecord().Attributes().PutStr("http.path", "@health")
285292
},
286293
},
294+
{
295+
statement: `replace_pattern(attributes["http.path"], Concat(["/","health"],""), "@")`,
296+
want: func(tCtx ottllog.TransformContext) {
297+
tCtx.GetLogRecord().Attributes().PutStr("http.path", "@")
298+
},
299+
},
287300
{
288301
statement: `replace_pattern(attributes["http.path"], "/", "@", SHA256)`,
289302
want: func(tCtx ottllog.TransformContext) {
@@ -1015,6 +1028,15 @@ func Test_e2e_converters(t *testing.T) {
10151028
s.AppendEmpty().SetStr("A")
10161029
},
10171030
},
1031+
{
1032+
statement: `set(attributes["test"], Sort(Split(attributes["flags"], attributes["split_delimiter"]), "desc"))`,
1033+
want: func(tCtx ottllog.TransformContext) {
1034+
s := tCtx.GetLogRecord().Attributes().PutEmptySlice("test")
1035+
s.AppendEmpty().SetStr("C")
1036+
s.AppendEmpty().SetStr("B")
1037+
s.AppendEmpty().SetStr("A")
1038+
},
1039+
},
10181040
{
10191041
statement: `set(attributes["test"], Sort([true, false, false]))`,
10201042
want: func(tCtx ottllog.TransformContext) {
@@ -1886,6 +1908,7 @@ func constructLogTransformContext() ottllog.TransformContext {
18861908
logRecord.SetSpanID(spanID)
18871909
logRecord.Attributes().PutStr("encoding", "base64")
18881910
logRecord.Attributes().PutStr("http.method", "get")
1911+
logRecord.Attributes().PutStr("split_delimiter", "|")
18891912
logRecord.Attributes().PutStr("dynamicprefix", "operation")
18901913
logRecord.Attributes().PutStr("dynamicsuffix", "tionA")
18911914
logRecord.Attributes().PutStr("http.path", "/health")

pkg/ottl/ottlfuncs/func_replace_all_patterns.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"context"
88
"errors"
99
"fmt"
10-
"regexp"
1110

1211
"go.opentelemetry.io/collector/pdata/pcommon"
1312

@@ -22,7 +21,7 @@ const (
2221
type ReplaceAllPatternsArguments[K any] struct {
2322
Target ottl.PMapGetSetter[K]
2423
Mode string
25-
RegexPattern string
24+
RegexPattern ottl.StringGetter[K]
2625
Replacement ottl.StringGetter[K]
2726
Function ottl.Optional[ottl.FunctionGetter[K]]
2827
ReplacementFormat ottl.Optional[ottl.StringGetter[K]]
@@ -42,10 +41,10 @@ func createReplaceAllPatternsFunction[K any](_ ottl.FunctionContext, oArgs ottl.
4241
return replaceAllPatterns(args.Target, args.Mode, args.RegexPattern, args.Replacement, args.Function, args.ReplacementFormat)
4342
}
4443

45-
func replaceAllPatterns[K any](target ottl.PMapGetSetter[K], mode, regexPattern string, replacement ottl.StringGetter[K], fn ottl.Optional[ottl.FunctionGetter[K]], replacementFormat ottl.Optional[ottl.StringGetter[K]]) (ottl.ExprFunc[K], error) {
46-
compiledPattern, err := regexp.Compile(regexPattern)
44+
func replaceAllPatterns[K any](target ottl.PMapGetSetter[K], mode string, regexPattern, replacement ottl.StringGetter[K], fn ottl.Optional[ottl.FunctionGetter[K]], replacementFormat ottl.Optional[ottl.StringGetter[K]]) (ottl.ExprFunc[K], error) {
45+
compiledPattern, err := newDynamicRegex("replace_all_patterns", regexPattern)
4746
if err != nil {
48-
return nil, fmt.Errorf("the regex pattern supplied to replace_all_patterns is not a valid pattern: %w", err)
47+
return nil, err
4948
}
5049
if mode != modeValue && mode != modeKey {
5150
return nil, fmt.Errorf("invalid mode %v, must be either 'key' or 'value'", mode)
@@ -63,20 +62,25 @@ func replaceAllPatterns[K any](target ottl.PMapGetSetter[K], mode, regexPattern
6362
return nil, err
6463
}
6564

65+
cp, err := compiledPattern.compile(ctx, tCtx)
66+
if err != nil {
67+
return nil, err
68+
}
69+
6670
switch mode {
6771
case modeValue:
6872
for _, value := range val.All() {
69-
if value.Type() != pcommon.ValueTypeStr || !compiledPattern.MatchString(value.Str()) {
73+
if value.Type() != pcommon.ValueTypeStr || !cp.MatchString(value.Str()) {
7074
continue
7175
}
7276
if !fn.IsEmpty() {
73-
updatedString, err := applyOptReplaceFunction(ctx, tCtx, compiledPattern, fn, value.Str(), replacementVal, replacementFormat)
77+
updatedString, err := applyOptReplaceFunction(ctx, tCtx, cp, fn, value.Str(), replacementVal, replacementFormat)
7478
if err != nil {
7579
continue
7680
}
7781
value.SetStr(updatedString)
7882
} else {
79-
value.SetStr(compiledPattern.ReplaceAllString(value.Str(), replacementVal))
83+
value.SetStr(cp.ReplaceAllString(value.Str(), replacementVal))
8084
}
8185
}
8286
case modeKey:
@@ -86,18 +90,18 @@ func replaceAllPatterns[K any](target ottl.PMapGetSetter[K], mode, regexPattern
8690
updated := pcommon.NewMap()
8791
updated.EnsureCapacity(val.Len())
8892
for key, value := range val.All() {
89-
if !compiledPattern.MatchString(key) {
93+
if !cp.MatchString(key) {
9094
value.MoveTo(updated.PutEmpty(key))
9195
continue
9296
}
9397
if !fn.IsEmpty() {
94-
updatedKey, err := applyOptReplaceFunction(ctx, tCtx, compiledPattern, fn, key, replacementVal, replacementFormat)
98+
updatedKey, err := applyOptReplaceFunction(ctx, tCtx, cp, fn, key, replacementVal, replacementFormat)
9599
if err != nil {
96100
continue
97101
}
98102
value.MoveTo(updated.PutEmpty(updatedKey))
99103
} else {
100-
value.MoveTo(updated.PutEmpty(compiledPattern.ReplaceAllString(key, replacementVal)))
104+
value.MoveTo(updated.PutEmpty(cp.ReplaceAllString(key, replacementVal)))
101105
}
102106
}
103107
updated.MoveTo(val)

pkg/ottl/ottlfuncs/func_replace_all_patterns_test.go

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,13 @@ func Test_replaceAllPatterns(t *testing.T) {
534534
},
535535
}
536536

537-
exprFunc, err := replaceAllPatterns[pcommon.Map](target, tt.mode, tt.pattern, tt.replacement, tt.function, tt.replacementFormat)
537+
pattern := &ottl.StandardStringGetter[pcommon.Map]{
538+
Getter: func(_ context.Context, _ pcommon.Map) (any, error) {
539+
return tt.pattern, nil
540+
},
541+
}
542+
543+
exprFunc, err := replaceAllPatterns[pcommon.Map](target, tt.mode, pattern, tt.replacement, tt.function, tt.replacementFormat)
538544
assert.NoError(t, err)
539545

540546
_, err = exprFunc(nil, scenarioMap)
@@ -567,7 +573,13 @@ func Test_replaceAllPatterns_bad_input(t *testing.T) {
567573
function := ottl.Optional[ottl.FunctionGetter[any]]{}
568574
replacementFormat := ottl.Optional[ottl.StringGetter[any]]{}
569575

570-
exprFunc, err := replaceAllPatterns[any](target, modeValue, "regexpattern", replacement, function, replacementFormat)
576+
pattern := &ottl.StandardStringGetter[any]{
577+
Getter: func(_ context.Context, _ any) (any, error) {
578+
return "regexpattern", nil
579+
},
580+
}
581+
582+
exprFunc, err := replaceAllPatterns[any](target, modeValue, pattern, replacement, function, replacementFormat)
571583
assert.NoError(t, err)
572584

573585
_, err = exprFunc(nil, input)
@@ -592,7 +604,13 @@ func Test_replaceAllPatterns_bad_function_input(t *testing.T) {
592604
function := ottl.Optional[ottl.FunctionGetter[any]]{}
593605
replacementFormat := ottl.Optional[ottl.StringGetter[any]]{}
594606

595-
exprFunc, err := replaceAllPatterns[any](target, modeValue, "regexp", replacement, function, replacementFormat)
607+
pattern := &ottl.StandardStringGetter[any]{
608+
Getter: func(_ context.Context, _ any) (any, error) {
609+
return "regexp", nil
610+
},
611+
}
612+
613+
exprFunc, err := replaceAllPatterns[any](target, modeValue, pattern, replacement, function, replacementFormat)
596614
assert.NoError(t, err)
597615

598616
result, err := exprFunc(nil, input)
@@ -634,7 +652,13 @@ func Test_replaceAllPatterns_bad_function_result(t *testing.T) {
634652
function := ottl.NewTestingOptional[ottl.FunctionGetter[any]](ottlValue)
635653
replacementFormat := ottl.Optional[ottl.StringGetter[any]]{}
636654

637-
exprFunc, err := replaceAllPatterns[any](target, modeValue, "regexp", replacement, function, replacementFormat)
655+
pattern := &ottl.StandardStringGetter[any]{
656+
Getter: func(_ context.Context, _ any) (any, error) {
657+
return "regexp", nil
658+
},
659+
}
660+
661+
exprFunc, err := replaceAllPatterns[any](target, modeValue, pattern, replacement, function, replacementFormat)
638662
assert.NoError(t, err)
639663

640664
result, err := exprFunc(nil, input)
@@ -666,7 +690,13 @@ func Test_replaceAllPatterns_get_nil(t *testing.T) {
666690
function := ottl.Optional[ottl.FunctionGetter[any]]{}
667691
replacementFormat := ottl.Optional[ottl.StringGetter[any]]{}
668692

669-
exprFunc, err := replaceAllPatterns[any](target, modeValue, "regexp", replacement, function, replacementFormat)
693+
pattern := &ottl.StandardStringGetter[any]{
694+
Getter: func(_ context.Context, _ any) (any, error) {
695+
return "regexp", nil
696+
},
697+
}
698+
699+
exprFunc, err := replaceAllPatterns[any](target, modeValue, pattern, replacement, function, replacementFormat)
670700
assert.NoError(t, err)
671701

672702
_, err = exprFunc(nil, nil)
@@ -676,7 +706,7 @@ func Test_replaceAllPatterns_get_nil(t *testing.T) {
676706
func Test_replaceAllPatterns_invalid_pattern(t *testing.T) {
677707
target := &ottl.StandardPMapGetSetter[any]{
678708
Getter: func(context.Context, any) (pcommon.Map, error) {
679-
return pcommon.Map{}, errors.New("nothing should be received in this scenario")
709+
return pcommon.Map{}, nil
680710
},
681711
}
682712
replacement := &ottl.StandardStringGetter[any]{
@@ -687,11 +717,15 @@ func Test_replaceAllPatterns_invalid_pattern(t *testing.T) {
687717
function := ottl.Optional[ottl.FunctionGetter[any]]{}
688718
replacementFormat := ottl.Optional[ottl.StringGetter[any]]{}
689719

690-
invalidRegexPattern := "*"
691-
exprFunc, err := replaceAllPatterns[any](target, modeValue, invalidRegexPattern, replacement, function, replacementFormat)
692-
require.Error(t, err)
720+
pattern := &ottl.StandardStringGetter[any]{
721+
Getter: func(_ context.Context, _ any) (any, error) {
722+
return "*", nil
723+
},
724+
}
725+
exprFunc, err := replaceAllPatterns[any](target, modeValue, pattern, replacement, function, replacementFormat)
726+
require.NoError(t, err)
727+
_, err = exprFunc(nil, nil)
693728
assert.ErrorContains(t, err, "error parsing regexp:")
694-
assert.Nil(t, exprFunc)
695729
}
696730

697731
func Test_replaceAllPatterns_invalid_model(t *testing.T) {
@@ -709,7 +743,12 @@ func Test_replaceAllPatterns_invalid_model(t *testing.T) {
709743
replacementFormat := ottl.Optional[ottl.StringGetter[any]]{}
710744

711745
invalidMode := "invalid"
712-
exprFunc, err := replaceAllPatterns[any](target, invalidMode, "regex", replacement, function, replacementFormat)
746+
pattern := &ottl.StandardStringGetter[any]{
747+
Getter: func(_ context.Context, _ any) (any, error) {
748+
return "regex", nil
749+
},
750+
}
751+
exprFunc, err := replaceAllPatterns[any](target, invalidMode, pattern, replacement, function, replacementFormat)
713752
assert.Nil(t, exprFunc)
714753
assert.ErrorContains(t, err, "invalid mode")
715754
}

pkg/ottl/ottlfuncs/func_replace_pattern.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515

1616
type ReplacePatternArguments[K any] struct {
1717
Target ottl.GetSetter[K]
18-
RegexPattern string
18+
RegexPattern ottl.StringGetter[K]
1919
Replacement ottl.StringGetter[K]
2020
Function ottl.Optional[ottl.FunctionGetter[K]]
2121
ReplacementFormat ottl.Optional[ottl.StringGetter[K]]
@@ -98,10 +98,10 @@ func applyOptReplaceFunction[K any](ctx context.Context, tCtx K, compiledPattern
9898
return updatedString, nil
9999
}
100100

101-
func replacePattern[K any](target ottl.GetSetter[K], regexPattern string, replacement ottl.StringGetter[K], fn ottl.Optional[ottl.FunctionGetter[K]], replacementFormat ottl.Optional[ottl.StringGetter[K]]) (ottl.ExprFunc[K], error) {
102-
compiledPattern, err := regexp.Compile(regexPattern)
101+
func replacePattern[K any](target ottl.GetSetter[K], regexPattern, replacement ottl.StringGetter[K], fn ottl.Optional[ottl.FunctionGetter[K]], replacementFormat ottl.Optional[ottl.StringGetter[K]]) (ottl.ExprFunc[K], error) {
102+
compiledPattern, err := newDynamicRegex("replace_pattern", regexPattern)
103103
if err != nil {
104-
return nil, fmt.Errorf("the regex pattern supplied to replace_pattern is not a valid pattern: %w", err)
104+
return nil, err
105105
}
106106
return func(ctx context.Context, tCtx K) (any, error) {
107107
originalVal, err := target.Get(ctx, tCtx)
@@ -117,10 +117,14 @@ func replacePattern[K any](target ottl.GetSetter[K], regexPattern string, replac
117117
return nil, err
118118
}
119119
if originalValStr, ok := originalVal.(string); ok {
120-
if compiledPattern.MatchString(originalValStr) {
120+
cp, err := compiledPattern.compile(ctx, tCtx)
121+
if err != nil {
122+
return nil, err
123+
}
124+
if cp.MatchString(originalValStr) {
121125
if !fn.IsEmpty() {
122126
var updatedString string
123-
updatedString, err = applyOptReplaceFunction[K](ctx, tCtx, compiledPattern, fn, originalValStr, replacementVal, replacementFormat)
127+
updatedString, err = applyOptReplaceFunction[K](ctx, tCtx, cp, fn, originalValStr, replacementVal, replacementFormat)
124128
if err != nil {
125129
return nil, err
126130
}
@@ -129,7 +133,7 @@ func replacePattern[K any](target ottl.GetSetter[K], regexPattern string, replac
129133
return nil, err
130134
}
131135
} else {
132-
updatedStr := compiledPattern.ReplaceAllString(originalValStr, replacementVal)
136+
updatedStr := cp.ReplaceAllString(originalValStr, replacementVal)
133137
err = target.Set(ctx, tCtx, updatedStr)
134138
if err != nil {
135139
return nil, err

0 commit comments

Comments
 (0)