diff --git a/operator/builtin/parser/regex/config_test.go b/operator/builtin/parser/regex/config_test.go new file mode 100644 index 000000000000..46b54c594512 --- /dev/null +++ b/operator/builtin/parser/regex/config_test.go @@ -0,0 +1,181 @@ +// 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 regex + +import ( + "fmt" + "io/ioutil" + "path" + "testing" + + "github.com/open-telemetry/opentelemetry-log-collection/entry" + "github.com/open-telemetry/opentelemetry-log-collection/operator/helper" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" +) + +type testCase struct { + name string + expectErr bool + expect *RegexParserConfig +} + +func TestRegexParserGoldenConfig(t *testing.T) { + cases := []testCase{ + { + "default", + false, + defaultCfg(), + }, + { + "parse_from_simple", + false, + func() *RegexParserConfig { + cfg := defaultCfg() + cfg.ParseFrom = entry.NewRecordField("from") + return cfg + }(), + }, + { + "parse_to_simple", + false, + func() *RegexParserConfig { + cfg := defaultCfg() + cfg.ParseTo = entry.NewRecordField("log") + return cfg + }(), + }, + { + "on_error_drop", + false, + func() *RegexParserConfig { + cfg := defaultCfg() + cfg.OnError = "drop" + return cfg + }(), + }, + { + "timestamp", + false, + func() *RegexParserConfig { + cfg := defaultCfg() + parseField := entry.NewRecordField("timestamp_field") + newTime := helper.TimeParser{ + LayoutType: "strptime", + Layout: "%Y-%m-%d", + ParseFrom: &parseField, + } + cfg.TimeParser = &newTime + return cfg + }(), + }, + { + "severity", + false, + func() *RegexParserConfig { + cfg := defaultCfg() + parseField := entry.NewRecordField("severity_field") + severityField := helper.NewSeverityParserConfig() + severityField.ParseFrom = &parseField + mapping := map[interface{}]interface{}{ + "critical": "5xx", + "error": "4xx", + "info": "3xx", + "debug": "2xx", + } + severityField.Mapping = mapping + cfg.SeverityParserConfig = &severityField + return cfg + }(), + }, + { + "preserve_to", + false, + func() *RegexParserConfig { + cfg := defaultCfg() + preserve := entry.NewRecordField("aField") + cfg.PreserveTo = &preserve + return cfg + }(), + }, + { + "regex", + false, + func() *RegexParserConfig { + cfg := defaultCfg() + cfg.Regex = "^Host=(?P[^,]+), Type=(?P.*)$" + return cfg + }(), + }, + } + + for _, tc := range cases { + t.Run("yaml/"+tc.name, func(t *testing.T) { + cfgFromYaml, yamlErr := configFromFileViaYaml(path.Join(".", "testdata", fmt.Sprintf("%s.yaml", tc.name))) + if tc.expectErr { + require.Error(t, yamlErr) + } else { + require.NoError(t, yamlErr) + require.Equal(t, tc.expect, cfgFromYaml) + } + }) + t.Run("mapstructure/"+tc.name, func(t *testing.T) { + cfgFromMapstructure := defaultCfg() + mapErr := configFromFileViaMapstructure( + path.Join(".", "testdata", fmt.Sprintf("%s.yaml", tc.name)), + cfgFromMapstructure, + ) + if tc.expectErr { + require.Error(t, mapErr) + } else { + require.NoError(t, mapErr) + require.Equal(t, tc.expect, cfgFromMapstructure) + } + }) + } +} + +func configFromFileViaYaml(file string) (*RegexParserConfig, error) { + bytes, err := ioutil.ReadFile(file) + if err != nil { + return nil, fmt.Errorf("could not find config file: %s", err) + } + + config := defaultCfg() + if err := yaml.Unmarshal(bytes, config); err != nil { + return nil, fmt.Errorf("failed to read config file as yaml: %s", err) + } + + return config, nil +} + +func configFromFileViaMapstructure(file string, result *RegexParserConfig) error { + bytes, err := ioutil.ReadFile(file) + if err != nil { + return fmt.Errorf("could not find config file: %s", err) + } + + raw := map[string]interface{}{} + + if err := yaml.Unmarshal(bytes, raw); err != nil { + return fmt.Errorf("failed to read data from yaml: %s", err) + } + + err = helper.UnmarshalMapstructure(raw, result) + return err +} + +func defaultCfg() *RegexParserConfig { + return NewRegexParserConfig("regex_parser") +} diff --git a/operator/builtin/parser/regex/testdata/default.yaml b/operator/builtin/parser/regex/testdata/default.yaml new file mode 100644 index 000000000000..ba2157ae5b5d --- /dev/null +++ b/operator/builtin/parser/regex/testdata/default.yaml @@ -0,0 +1 @@ +type: regex_parser \ No newline at end of file diff --git a/operator/builtin/parser/regex/testdata/on_error_drop.yaml b/operator/builtin/parser/regex/testdata/on_error_drop.yaml new file mode 100644 index 000000000000..53764a2d06f8 --- /dev/null +++ b/operator/builtin/parser/regex/testdata/on_error_drop.yaml @@ -0,0 +1,2 @@ +type: regex_parser +on_error: "drop" \ No newline at end of file diff --git a/operator/builtin/parser/regex/testdata/parse_from_simple.yaml b/operator/builtin/parser/regex/testdata/parse_from_simple.yaml new file mode 100644 index 000000000000..c70cce7fc71b --- /dev/null +++ b/operator/builtin/parser/regex/testdata/parse_from_simple.yaml @@ -0,0 +1,2 @@ +type: regex_parser +parse_from: "$.from" \ No newline at end of file diff --git a/operator/builtin/parser/regex/testdata/parse_to_simple.yaml b/operator/builtin/parser/regex/testdata/parse_to_simple.yaml new file mode 100644 index 000000000000..620366b21da0 --- /dev/null +++ b/operator/builtin/parser/regex/testdata/parse_to_simple.yaml @@ -0,0 +1,2 @@ +type: regex_parser +parse_to: "log" \ No newline at end of file diff --git a/operator/builtin/parser/regex/testdata/preserve_to.yaml b/operator/builtin/parser/regex/testdata/preserve_to.yaml new file mode 100644 index 000000000000..30265a288820 --- /dev/null +++ b/operator/builtin/parser/regex/testdata/preserve_to.yaml @@ -0,0 +1,2 @@ +type: regex_parser +preserve_to: "aField" \ No newline at end of file diff --git a/operator/builtin/parser/regex/testdata/regex.yaml b/operator/builtin/parser/regex/testdata/regex.yaml new file mode 100644 index 000000000000..87f6d50d53c9 --- /dev/null +++ b/operator/builtin/parser/regex/testdata/regex.yaml @@ -0,0 +1,2 @@ +type: regex_parser +regex: '^Host=(?P[^,]+), Type=(?P.*)$' \ No newline at end of file diff --git a/operator/builtin/parser/regex/testdata/severity.yaml b/operator/builtin/parser/regex/testdata/severity.yaml new file mode 100644 index 000000000000..95a7b93985eb --- /dev/null +++ b/operator/builtin/parser/regex/testdata/severity.yaml @@ -0,0 +1,8 @@ +type: regex_parser +severity: + parse_from: severity_field + mapping: + critical: 5xx + error: 4xx + info: 3xx + debug: 2xx \ No newline at end of file diff --git a/operator/builtin/parser/regex/testdata/timestamp.yaml b/operator/builtin/parser/regex/testdata/timestamp.yaml new file mode 100644 index 000000000000..38aa3bbf37ad --- /dev/null +++ b/operator/builtin/parser/regex/testdata/timestamp.yaml @@ -0,0 +1,5 @@ +type: regex_parser +timestamp: + parse_from: timestamp_field + layout_type: strptime + layout: '%Y-%m-%d' \ No newline at end of file