Skip to content

Commit 7781bdb

Browse files
authored
[pkg/ottl] Add PMapGetSetter and StandardPMapGetSetter (#39657)
#### Description Adds PMapGetSetter interface and StandardPMapGetSetter to improve type-safety in OTTL functions. Split out of #39416 where this changes are already in use.
1 parent 597613b commit 7781bdb

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

.chloggen/ottl-add-pmapgetsetter.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. 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: Add PMapGetSetter interface and StandardPMapGetSetter 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: [39657]
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: [api]

pkg/ottl/expression.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,24 @@ func (g StandardFunctionGetter[K]) Get(args Arguments) (Expr[K], error) {
406406
return Expr[K]{exprFunc: fn}, nil
407407
}
408408

409+
type PMapGetSetter[K any] interface {
410+
Get(ctx context.Context, tCtx K) (pcommon.Map, error)
411+
Set(ctx context.Context, tCtx K, val pcommon.Map) error
412+
}
413+
414+
type StandardPMapGetSetter[K any] struct {
415+
Getter func(ctx context.Context, tCtx K) (pcommon.Map, error)
416+
Setter func(ctx context.Context, tCtx K, val any) error
417+
}
418+
419+
func (path StandardPMapGetSetter[K]) Get(ctx context.Context, tCtx K) (pcommon.Map, error) {
420+
return path.Getter(ctx, tCtx)
421+
}
422+
423+
func (path StandardPMapGetSetter[K]) Set(ctx context.Context, tCtx K, val pcommon.Map) error {
424+
return path.Setter(ctx, tCtx, val)
425+
}
426+
409427
// PMapGetter is a Getter that must return a pcommon.Map.
410428
type PMapGetter[K any] interface {
411429
// Get retrieves a pcommon.Map value.

pkg/ottl/functions.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,16 @@ func (p *Parser[K]) buildArg(argVal value, argType reflect.Type) (any, error) {
590590
return nil, err
591591
}
592592
return StandardIntLikeGetter[K]{Getter: arg.Get}, nil
593+
case strings.HasPrefix(name, "PMapGetSetter"):
594+
if argVal.Literal == nil || argVal.Literal.Path == nil {
595+
return nil, errors.New("must be a path")
596+
}
597+
pathGetSetter, err := p.buildGetSetterFromPath(argVal.Literal.Path)
598+
if err != nil {
599+
return nil, err
600+
}
601+
stdMapGetter := StandardPMapGetter[K]{Getter: pathGetSetter.Get}
602+
return StandardPMapGetSetter[K]{Getter: stdMapGetter.Get, Setter: pathGetSetter.Set}, nil
593603
case strings.HasPrefix(name, "PMapGetter"):
594604
arg, err := p.newGetter(argVal)
595605
if err != nil {

pkg/ottl/functions_test.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ func Test_NewFunctionCall_invalid(t *testing.T) {
2424
&errorFunctionArguments{},
2525
functionThatHasAnError,
2626
),
27+
createFactory[any](
28+
"testing_pmapgetsetter",
29+
&pMapGetSetterArguments{},
30+
functionWithPMapGetSetter,
31+
),
2732
createFactory[any](
2833
"testing_getsetter",
2934
&getSetterArguments{},
@@ -112,6 +117,19 @@ func Test_NewFunctionCall_invalid(t *testing.T) {
112117
},
113118
},
114119
},
120+
{
121+
name: "not accessor (pmap)",
122+
inv: editor{
123+
Function: "testing_pmapgetsetter",
124+
Arguments: []argument{
125+
{
126+
Value: value{
127+
String: ottltest.Strp("not path"),
128+
},
129+
},
130+
},
131+
},
132+
},
115133
{
116134
name: "not accessor",
117135
inv: editor{
@@ -391,6 +409,30 @@ func Test_NewFunctionCall_invalid(t *testing.T) {
391409
Function: "non_pointer",
392410
},
393411
},
412+
{
413+
name: "path parts not all used (pmap)",
414+
inv: editor{
415+
Function: "testing_pmapgetsetter",
416+
Arguments: []argument{
417+
{
418+
Value: value{
419+
Literal: &mathExprLiteral{
420+
Path: &path{
421+
Fields: []field{
422+
{
423+
Name: "name",
424+
},
425+
{
426+
Name: "not-used",
427+
},
428+
},
429+
},
430+
},
431+
},
432+
},
433+
},
434+
},
435+
},
394436
{
395437
name: "path parts not all used",
396438
inv: editor{
@@ -415,6 +457,35 @@ func Test_NewFunctionCall_invalid(t *testing.T) {
415457
},
416458
},
417459
},
460+
{
461+
name: "Keys not allowed (pmap)",
462+
inv: editor{
463+
Function: "testing_pmapgetsetter",
464+
Arguments: []argument{
465+
{
466+
Value: value{
467+
Literal: &mathExprLiteral{
468+
Path: &path{
469+
Fields: []field{
470+
{
471+
Name: "name",
472+
Keys: []key{
473+
{
474+
String: ottltest.Strp("foo"),
475+
},
476+
{
477+
String: ottltest.Strp("bar"),
478+
},
479+
},
480+
},
481+
},
482+
},
483+
},
484+
},
485+
},
486+
},
487+
},
488+
},
418489
{
419490
name: "Keys not allowed",
420491
inv: editor{
@@ -806,6 +877,28 @@ func Test_NewFunctionCall(t *testing.T) {
806877
},
807878
want: 2,
808879
},
880+
{
881+
name: "pmapgetsetter arg",
882+
inv: editor{
883+
Function: "testing_pmapgetsetter",
884+
Arguments: []argument{
885+
{
886+
Value: value{
887+
Literal: &mathExprLiteral{
888+
Path: &path{
889+
Fields: []field{
890+
{
891+
Name: "name",
892+
},
893+
},
894+
},
895+
},
896+
},
897+
},
898+
},
899+
},
900+
want: nil,
901+
},
809902
{
810903
name: "pmapgetter slice arg",
811904
inv: editor{
@@ -1452,6 +1545,36 @@ func Test_NewFunctionCall(t *testing.T) {
14521545
},
14531546
want: nil,
14541547
},
1548+
{
1549+
name: "Complex Indexing (pmap)",
1550+
inv: editor{
1551+
Function: "testing_pmapgetsetter",
1552+
Arguments: []argument{
1553+
{
1554+
Value: value{
1555+
Literal: &mathExprLiteral{
1556+
Path: &path{
1557+
Fields: []field{
1558+
{
1559+
Name: "attributes",
1560+
Keys: []key{
1561+
{
1562+
String: ottltest.Strp("foo"),
1563+
},
1564+
{
1565+
String: ottltest.Strp("bar"),
1566+
},
1567+
},
1568+
},
1569+
},
1570+
},
1571+
},
1572+
},
1573+
},
1574+
},
1575+
},
1576+
want: nil,
1577+
},
14551578
{
14561579
name: "Complex Indexing",
14571580
inv: editor{
@@ -1482,6 +1605,28 @@ func Test_NewFunctionCall(t *testing.T) {
14821605
},
14831606
want: nil,
14841607
},
1608+
{
1609+
name: "path that allows keys but none have been specified (pmap)",
1610+
inv: editor{
1611+
Function: "testing_pmapgetsetter",
1612+
Arguments: []argument{
1613+
{
1614+
Value: value{
1615+
Literal: &mathExprLiteral{
1616+
Path: &path{
1617+
Fields: []field{
1618+
{
1619+
Name: "attributes",
1620+
},
1621+
},
1622+
},
1623+
},
1624+
},
1625+
},
1626+
},
1627+
},
1628+
want: nil,
1629+
},
14851630
{
14861631
name: "path that allows keys but none have been specified",
14871632
inv: editor{
@@ -1888,6 +2033,16 @@ func functionWithByteSliceLikeGetter(ByteSliceLikeGetter[any]) (ExprFunc[any], e
18882033
}, nil
18892034
}
18902035

2036+
type pMapGetSetterArguments struct {
2037+
PMapGetSetterArg PMapGetSetter[any]
2038+
}
2039+
2040+
func functionWithPMapGetSetter(PMapGetSetter[any]) (ExprFunc[any], error) {
2041+
return func(context.Context, any) (any, error) {
2042+
return "anything", nil
2043+
}, nil
2044+
}
2045+
18912046
type pMapGetterArguments struct {
18922047
PMapArg PMapGetter[any]
18932048
}
@@ -2109,6 +2264,11 @@ func defaultFunctionsForTests() map[string]Factory[any] {
21092264
&setterArguments{},
21102265
functionWithSetter,
21112266
),
2267+
createFactory[any](
2268+
"testing_pmapgetsetter",
2269+
&pMapGetSetterArguments{},
2270+
functionWithPMapGetSetter,
2271+
),
21122272
createFactory[any](
21132273
"testing_getsetter",
21142274
&getSetterArguments{},

0 commit comments

Comments
 (0)