Skip to content

Commit

Permalink
testutils: Support <RE2()> directives for resource logs and metrics (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
rmfitzpatrick authored Aug 24, 2023
1 parent 453d900 commit 48c64ca
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,47 @@ resource_metrics:
attributes:
foo: bar
system.type: prometheus-exporter
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_process_memory_rss
type: DoubleGauge
attributes:
foo: bar
system.type: prometheus-exporter
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_process_cpu_seconds
type: DoubleMonotonicCumulativeSum
attributes:
foo: bar
system.type: prometheus-exporter
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_process_uptime
type: DoubleMonotonicCumulativeSum
attributes:
foo: bar
system.type: prometheus-exporter
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_process_runtime_total_alloc_bytes
type: DoubleMonotonicCumulativeSum
attributes:
foo: bar
system.type: prometheus-exporter
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_process_runtime_heap_alloc_bytes
type: DoubleGauge
attributes:
foo: bar
system.type: prometheus-exporter
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_exporter_enqueue_failed_log_records
Expand All @@ -55,7 +55,7 @@ resource_metrics:
system.type: prometheus-exporter
exporter: otlp
foo: bar
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_exporter_enqueue_failed_metric_points
Expand All @@ -64,7 +64,7 @@ resource_metrics:
system.type: prometheus-exporter
exporter: otlp
foo: bar
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_exporter_enqueue_failed_spans
Expand All @@ -73,7 +73,7 @@ resource_metrics:
system.type: prometheus-exporter
exporter: otlp
foo: bar
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_exporter_queue_capacity
Expand All @@ -82,7 +82,7 @@ resource_metrics:
system.type: prometheus-exporter
exporter: otlp
foo: bar
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_exporter_queue_size
Expand All @@ -91,7 +91,7 @@ resource_metrics:
system.type: prometheus-exporter
exporter: otlp
foo: bar
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_exporter_sent_metric_points
Expand All @@ -100,7 +100,7 @@ resource_metrics:
system.type: prometheus-exporter
exporter: otlp
foo: bar
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
- name: otelcol_receiver_accepted_metric_points
Expand All @@ -109,7 +109,7 @@ resource_metrics:
foo: bar
system.type: prometheus-exporter
receiver: smartagent/prometheus-exporter
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
transport: internal
Expand All @@ -119,7 +119,7 @@ resource_metrics:
foo: bar
system.type: prometheus-exporter
receiver: smartagent/prometheus-exporter
service_instance_id: <ANY>
service_instance_id: <RE2(^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$)>
service_name: otelcol
service_version: <VERSION_FROM_BUILD>
transport: internal
81 changes: 67 additions & 14 deletions tests/testutils/telemetry/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"crypto/md5" // #nosec this is not for cryptographic purposes
"fmt"
"reflect"
"regexp"

"gopkg.in/yaml.v3"

Expand All @@ -28,17 +29,10 @@ import (
const (
anyValue = "<ANY>"
buildVersionPlaceholder = "<VERSION_FROM_BUILD>"
regexValue = "^<RE2\\((?P<pattern>.*)\\)>$"
)

func marshal(y any) string {
b := &bytes.Buffer{}
enc := yaml.NewEncoder(b)
enc.SetIndent(2)
if err := enc.Encode(y); err != nil {
panic(err)
}
return b.String()
}
var reValueRegexp = regexp.MustCompile(regexValue)

type Resource struct {
Attributes *map[string]any `yaml:"attributes,omitempty"`
Expand All @@ -59,11 +53,27 @@ func (resource Resource) Equals(toCompare Resource) bool {
}

func (resource Resource) FillDefaultValues() {
if resource.Attributes != nil {
for k, v := range *resource.Attributes {
if v == buildVersionPlaceholder {
(*resource.Attributes)[k] = version.Version
populateDirectives(resource.Attributes)
}

func populateDirectives(attrs *map[string]any) {
if attrs == nil {
return
}
attributes := *attrs
for k, v := range attributes {
if v == buildVersionPlaceholder {
attributes[k] = version.Version
continue
}

if subs := reValueRegexp.FindStringSubmatch(toString(v)); len(subs) == 2 {
pattern := subs[1]
rec, err := regexp.Compile(pattern)
if err != nil {
panic(fmt.Errorf("failed compiling resource attributes RE2: %w", err))
}
attributes[k] = rec
}
}
}
Expand Down Expand Up @@ -119,7 +129,10 @@ func attributesAreEqual(attrs, toCompare *map[string]any) bool {
if !ok {
return false
}
if v == anyValue {
if isDirective, equal := directiveEquality(v, tcV); isDirective {
if !equal {
return false
}
continue
}
rAttrs[k] = v
Expand All @@ -128,3 +141,43 @@ func attributesAreEqual(attrs, toCompare *map[string]any) bool {

return reflect.DeepEqual(rAttrs, tcAttrs)
}

func directiveEquality(expected, actual any) (isDirective, equal bool) {
switch t := expected.(type) {
case string:
if t == anyValue {
return true, true
}
case *regexp.Regexp:
if t == nil {
return true, false
}
return true, t.MatchString(toString(actual))
}
return false, false
}

func marshal(y any) string {
b := &bytes.Buffer{}
enc := yaml.NewEncoder(b)
enc.SetIndent(2)
if err := enc.Encode(y); err != nil {
panic(err)
}
return b.String()
}

func directiveMapToMarshal(m map[string]any) map[string]any {
cp := map[string]any{}
for k, v := range m {
if t, ok := v.(*regexp.Regexp); ok {
v = fmt.Sprintf("<RE2(%s)>", t.String())
}
cp[k] = v
}
return cp
}

func toString(v any) string {
return fmt.Sprintf("%v", v)
}
35 changes: 27 additions & 8 deletions tests/testutils/telemetry/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,16 @@ func (resourceLogs *ResourceLogs) FillDefaultValues() {
if sls.Scope.Version == buildVersionPlaceholder {
resourceLogs.ResourceLogs[i].ScopeLogs[j].Scope.Version = version.Version
}
for _, sl := range sls.Logs {
if sl.Attributes != nil {
for k, v := range *sl.Attributes {
if v == buildVersionPlaceholder {
(*sl.Attributes)[k] = version.Version
}
for k, sl := range sls.Logs {
if sl.Body != nil {
bodyMap := &map[string]any{
"body": sl.Body,
}
populateDirectives(bodyMap)
sl.Body = (*bodyMap)["body"]
sls.Logs[k] = sl
}
populateDirectives(sl.Attributes)
}
}
}
Expand Down Expand Up @@ -129,7 +131,19 @@ func (scopeLogs ScopeLogs) String() string {
}

func (log Log) String() string {
return marshal(log)
cp := log
if cp.Body != "" {
bodyMap := map[string]any{
"body": cp.Body,
}
directiveMapToMarshal(bodyMap)
cp.Body = bodyMap["body"]
}
if cp.Attributes != nil {
attrs := directiveMapToMarshal(*cp.Attributes)
cp.Attributes = &attrs
}
return marshal(cp)
}

// Hash provides an md5 hash determined by Log content.
Expand All @@ -150,9 +164,14 @@ func (log Log) RelaxedEquals(toCompare Log) bool {

// equals determines if receiver Log is equal to toCompare Log, relaxed if not strict
func (log Log) equals(toCompare Log, strict bool) bool {
if log.Body != toCompare.Body && (strict || log.Body != nil) {
if isDirective, equal := directiveEquality(log.Body, toCompare.Body); isDirective {
if !equal {
return false
}
} else if log.Body != toCompare.Body && (strict || log.Body != nil) {
return false
}

if log.SeverityText != toCompare.SeverityText && (strict || log.SeverityText != "") {
return false
}
Expand Down
10 changes: 7 additions & 3 deletions tests/testutils/telemetry/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,14 @@ func TestLoadLogsHappyPath(t *testing.T) {
require.Equal(t, 2, len(secondRLFirstSL.Logs))
secondRLFirstSLFirstLog := secondRLFirstSL.Logs[0]
require.NotNil(t, secondRLFirstSLFirstLog)
assert.Equal(t, true, secondRLFirstSLFirstLog.Body)
assert.Equal(t, "this should match an RE2 directive", secondRLFirstSLFirstLog.Body)
assert.Equal(t, plog.SeverityNumber(24), *secondRLFirstSLFirstLog.Severity)
assert.Equal(t, "arbitrary", secondRLFirstSLFirstLog.SeverityText)
assert.Nil(t, secondRLFirstSLFirstLog.Attributes)
assert.Equal(t, &map[string]any{
"log_attr_a": "one_value",
"log_attr_b": "this should match another RE2 directive",
"log_attr_c": "this should match an ANY directive",
}, secondRLFirstSLFirstLog.Attributes)

secondRLFirstScopeLogSecondLog := secondRLFirstSL.Logs[1]
require.NotNil(t, secondRLFirstScopeLogSecondLog)
Expand Down Expand Up @@ -358,7 +362,7 @@ func TestLogContainsAllNoBijection(t *testing.T) {
require.False(t, containsAll)
require.Error(t, err)
require.Contains(t, err.Error(),
"Missing Logs: [body: true\nseverity: 24\nseverity_text: arbitrary\n body: 0.123\nseverity: 9\n]",
"Missing Logs: [body: this should match an RE2 directive\nattributes:\n log_attr_a: one_value\n log_attr_b: this should match another RE2 directive\n log_attr_c: this should match an ANY directive\nseverity: 24\nseverity_text: arbitrary\n body: 0.123\nseverity: 9\n]",
)
}

Expand Down
10 changes: 2 additions & 8 deletions tests/testutils/telemetry/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,7 @@ func (resourceMetrics *ResourceMetrics) FillDefaultValues() {
}

for _, m := range sms.Metrics {
if m.Attributes != nil {
for k, v := range *m.Attributes {
if v == buildVersionPlaceholder {
(*m.Attributes)[k] = version.Version
}
}
}
populateDirectives(m.Attributes)
}
}
}
Expand Down Expand Up @@ -197,7 +191,7 @@ func (metric Metric) MarshalYAML() (any, error) {
ms["description"] = metric.Description
}
if metric.Attributes != nil && len(*metric.Attributes) > 0 {
ms["attributes"] = metric.Attributes
ms["attributes"] = directiveMapToMarshal(*metric.Attributes)
}
for _, s := range []struct {
v any
Expand Down
2 changes: 1 addition & 1 deletion tests/testutils/telemetry/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ func TestMetricContainsAllNoBijection(t *testing.T) {
require.False(t, containsAll)
require.Error(t, err)
require.Contains(t, err.Error(),
"Missing Metrics: [name: another_int_gauge\ntype: IntGauge\nvalue: 456\n name: another_double_gauge\ntype: DoubleGauge\nvalue: 567.89\n]",
"Missing Metrics: [attributes:\n metric_attr_a: one_value\n metric_attr_b: this should match an RE2 directive\n metric_attr_c: this should match an ANY directive\nname: another_int_gauge\ntype: IntGauge\nvalue: 456\n name: another_double_gauge\ntype: DoubleGauge\nvalue: 567.89\n",
)
}

Expand Down
6 changes: 5 additions & 1 deletion tests/testutils/telemetry/testdata/logs/expected-logs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ resource_logs:
name: with_logs
version: another_version
logs:
- body: true
- body: <RE2(^this should match an .* directive$)>
attributes:
log_attr_a: one_value
log_attr_b: <RE2(^this.*match an.* RE2.*$)>
log_attr_c: <ANY>
severity_text: arbitrary
- body: 0.123
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ resource_logs:
name: with_logs
version: another_version
logs:
- body: true
- body: <RE2(^this should match .* directive$)>
severity_text: arbitrary
severity: 24
- body: 0.123
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ resource_logs:
name: with_logs
version: another_version
logs:
- body: true
- body: <RE2(.*)>
severity_text: arbitrary
severity: 24
- body: 0.123
Expand Down
Loading

0 comments on commit 48c64ca

Please sign in to comment.