Skip to content

Commit

Permalink
feat: signoztransformprocessor: add custom ottl function for converti…
Browse files Browse the repository at this point in the history
…ng hex strings to int (#292)

* feat: signoztransformprocessor: add custom ottl function for converting hex strings to int

* chore: add one more test case for HexToInt function

* chore: signoztransformprocessor: HexToInt: allow odd length hex values

* chore: signoztransformprocessor: hextoint: compile hex value regex only when constructing statement

* chore: signoztransformprocessor: hextoint: let strconv.ParseInt do relevant validation
  • Loading branch information
raj-k-singh committed Feb 20, 2024
1 parent 098c8bc commit 1795156
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func SignozLogFunctions() map[string]ottl.Factory[ottllog.TransformContext] {
for _, f := range []ottl.Factory[ottllog.TransformContext]{
signozFuncs.NewExprFactory(),
signozFuncs.NewGrokParseFactory[ottllog.TransformContext](),
signozFuncs.NewHexToIntFactory[ottllog.TransformContext](),
} {
factoryMap[f.Name()] = f
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ottlfunctions

import (
"context"
"fmt"
"strconv"
"strings"

"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
)

type HexToIntArguments[K any] struct {
Target ottl.StandardStringGetter[K]
}

func NewHexToIntFactory[K any]() ottl.Factory[K] {
return ottl.NewFactory("HexToInt", &HexToIntArguments[K]{}, createHexToIntFunction[K])
}

func createHexToIntFunction[K any](_ ottl.FunctionContext, oArgs ottl.Arguments) (ottl.ExprFunc[K], error) {
args, ok := oArgs.(*HexToIntArguments[K])

if !ok {
return nil, fmt.Errorf("HexToIntFactory args must be of type *HexToIntArguments[K]")
}

return hexToInt(args.Target)
}

func hexToInt[K any](target ottl.StandardStringGetter[K]) (ottl.ExprFunc[K], error) {

return func(ctx context.Context, tCtx K) (interface{}, error) {
val, err := target.Get(ctx, tCtx)
if err != nil {
return nil, err
}

normalized := strings.TrimPrefix(strings.ToLower(val), "0x")
result, err := strconv.ParseInt(normalized, 16, 64)
if err != nil {
return nil, fmt.Errorf("could not parse hex value %s: %w", val, err)
}
return result, nil
}, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package ottlfunctions

import (
"context"
"testing"

"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
"github.com/stretchr/testify/assert"
)

func TestHexToInt(t *testing.T) {
tests := []struct {
name string
target string
expected int64
shouldError bool
}{
{
name: "value with prefix",
target: "0xaB",
expected: int64(171),
shouldError: false,
}, {
name: "value without prefix",
target: "ab",
expected: int64(171),
shouldError: false,
}, {
name: "odd length value",
target: "aAa",
expected: int64(2730),
shouldError: false,
}, {
name: "non-hex value",
target: "zz",
shouldError: true,
expected: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
target := ottl.StandardStringGetter[any]{
Getter: func(ctx context.Context, tCtx any) (interface{}, error) {
return tt.target, nil
},
}

fn, err := hexToInt(target)
assert.NoError(t, err)

result, err := fn(context.Background(), nil)
if tt.shouldError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, result, tt.expected)
}
})
}
}

0 comments on commit 1795156

Please sign in to comment.