-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Expand file tree
/
Copy pathfunc_extract_grok_patterns.go
More file actions
126 lines (105 loc) · 3.74 KB
/
func_extract_grok_patterns.go
File metadata and controls
126 lines (105 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package ottlfuncs // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/ottlfuncs"
import (
"context"
"errors"
"fmt"
"strings"
"github.com/elastic/go-grok"
"go.opentelemetry.io/collector/pdata/pcommon"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
)
type ExtractGrokPatternsArguments[K any] struct {
Target ottl.StringGetter[K]
Pattern ottl.StringGetter[K]
NamedCapturesOnly ottl.Optional[bool]
PatternDefinitions ottl.Optional[[]string]
}
func NewExtractGrokPatternsFactory[K any]() ottl.Factory[K] {
return ottl.NewFactory("ExtractGrokPatterns", &ExtractGrokPatternsArguments[K]{}, createExtractGrokPatternsFunction[K])
}
func createExtractGrokPatternsFunction[K any](_ ottl.FunctionContext, oArgs ottl.Arguments) (ottl.ExprFunc[K], error) {
args, ok := oArgs.(*ExtractGrokPatternsArguments[K])
if !ok {
return nil, errors.New("ExtractGrokPatternsFactory args must be of type *ExtractGrokPatternsArguments[K]")
}
return extractGrokPatterns(args.Target, args.Pattern, args.NamedCapturesOnly, args.PatternDefinitions)
}
func extractGrokPatterns[K any](target, pattern ottl.StringGetter[K], nco ottl.Optional[bool], patternDefinitions ottl.Optional[[]string]) (ottl.ExprFunc[K], error) {
g, err := grok.NewComplete()
if err != nil {
return nil, fmt.Errorf("failed to initialize grok parser: %w", err)
}
namedCapturesOnly := !nco.IsEmpty() && nco.Get()
if !patternDefinitions.IsEmpty() {
for i, patternDefinition := range patternDefinitions.Get() {
// split pattern in format key=val
parts := strings.SplitN(patternDefinition, "=", 2)
if len(parts) == 1 {
trimmedPattern := patternDefinition
if len(patternDefinition) > 20 {
trimmedPattern = fmt.Sprintf("%s...", patternDefinition[:17]) // keep whole string 20 characters long including ...
}
return nil, fmt.Errorf("pattern %q supplied to ExtractGrokPatterns at index %d has incorrect format, expecting PATTERNNAME=pattern definition", trimmedPattern, i)
}
if strings.ContainsRune(parts[0], ':') {
return nil, fmt.Errorf("pattern ID %q should not contain ':'", parts[0])
}
err = g.AddPattern(parts[0], parts[1])
if err != nil {
return nil, fmt.Errorf("failed to add pattern %q=%q: %w", parts[0], parts[1], err)
}
}
}
literalPattern, ok := ottl.GetLiteralValue(pattern)
compiled := false
if ok {
err = g.Compile(literalPattern, namedCapturesOnly)
if err != nil {
return nil, fmt.Errorf(invalidRegexErrMsg, "ExtractGrokPatterns", literalPattern, err)
}
compiled = true
}
if compiled && namedCapturesOnly && !g.HasCaptureGroups() {
return nil, errors.New("at least 1 named capture group must be supplied in the given regex")
}
return func(ctx context.Context, tCtx K) (any, error) {
if !compiled {
patternVal, err := pattern.Get(ctx, tCtx)
if err != nil {
return nil, err
}
err = g.Compile(patternVal, namedCapturesOnly)
if err != nil {
return nil, fmt.Errorf(invalidRegexErrMsg, "ExtractGrokPatterns", patternVal, err)
}
}
if namedCapturesOnly && !g.HasCaptureGroups() {
return nil, errors.New("at least 1 named capture group must be supplied in the given regex")
}
val, err := target.Get(ctx, tCtx)
if err != nil {
return nil, err
}
matches, err := g.ParseTypedString(val)
if err != nil {
return nil, err
}
result := pcommon.NewMap()
result.EnsureCapacity(len(matches))
for k, v := range matches {
switch val := v.(type) {
case bool:
result.PutBool(k, val)
case float64:
result.PutDouble(k, val)
case int:
result.PutInt(k, int64(val))
case string:
result.PutStr(k, val)
}
}
return result, err
}, nil
}