Skip to content

Commit

Permalink
Add Log() to ottlfuncs
Browse files Browse the repository at this point in the history
Addresses issue open-telemetry#18076
  • Loading branch information
mterhar committed May 11, 2023
1 parent c8e0014 commit b7c2a89
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 0 deletions.
24 changes: 24 additions & 0 deletions pkg/ottl/ottlfuncs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Available Functions:
- [delete_matching_keys](#delete_matching_keys)
- [keep_keys](#keep_keys)
- [limit](#limit)
- [log](#log)
- [merge_maps](#merge_maps)
- [replace_all_matches](#replace_all_matches)
- [replace_all_patterns](#replace_all_patterns)
Expand Down Expand Up @@ -116,6 +117,29 @@ Examples:

- `limit(resource.attributes, 50, ["http.host", "http.method"])`

### Log

`Log(value)`

The `Log` factory function takes a logarithm of the value if it's numeric.

The returned type is float64.

The input `value` types:
* float64, string, and Int64. Converts to a Float64 and returns `math.Log()` of the converted value
* bool. Returns `nil` because log(1) is zero and log(0) is undefined so neither are useful.

If `value` is another type or parsing failed nil is always returned.

The `value` is either a path expression to a telemetry field to retrieve or a literal.

Examples:

- `Log(attributes["duration_ms"])`


- `Int(Log(attributes["duration_ms"])`

### merge_maps

`merge_maps(target, source, strategy)`
Expand Down
48 changes: 48 additions & 0 deletions pkg/ottl/ottlfuncs/func_log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ottlfuncs // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/ottlfuncs"

import (
"context"
"math"
"strconv"

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

func Log[K any](target ottl.Getter[K]) (ottl.ExprFunc[K], error) {
return func(ctx context.Context, tCtx K) (interface{}, error) {
value, err := target.Get(ctx, tCtx)
if err != nil {
return nil, err
}

switch value := value.(type) {
case int64:
return math.Log((float64)(value)), nil
case string:
fltValue, err := strconv.ParseFloat(value, 64)
if err != nil {
return nil, nil
}

return math.Log(fltValue), nil
case float64:
return math.Log(value), nil
default:
return nil, nil
}
}, nil
}
97 changes: 97 additions & 0 deletions pkg/ottl/ottlfuncs/func_log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ottlfuncs

import (
"context"
"math"
"testing"

"github.com/stretchr/testify/assert"

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

func Test_Log(t *testing.T) {
tests := []struct {
name string
value interface{}
expected interface{}
}{
{
name: "string",
value: "50",
expected: math.Log(50),
},
{
name: "empty string",
value: "",
expected: nil,
},
{
name: "not a number string",
value: "test",
expected: nil,
},
{
name: "int64",
value: int64(333),
expected: float64(math.Log(333)),
},
{
name: "float64",
value: float64(2.7),
expected: math.Log(2.7),
},
{
name: "float64 without decimal",
value: float64(55),
expected: math.Log(55),
},
{
name: "true",
value: true,
expected: nil,
},
{
name: "false",
value: false,
expected: nil,
},
{
name: "nil",
value: nil,
expected: nil,
},
{
name: "some struct",
value: struct{}{},
expected: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
exprFunc, err := Log[interface{}](&ottl.StandardGetSetter[interface{}]{
Getter: func(context.Context, interface{}) (interface{}, error) {
return tt.value, nil
},
})
assert.NoError(t, err)
result, err := exprFunc(nil, nil)
assert.NoError(t, err)
assert.Equal(t, tt.expected, result)
})
}
}

0 comments on commit b7c2a89

Please sign in to comment.