Skip to content

Commit

Permalink
[datadogexporter] Fix missing resource attributes default mapping whe…
Browse files Browse the repository at this point in the history
…n resource_attributes_as_tags: false (#6359)

* [datadogexporter] Fix missing resource attributes default mapping when resource_attributes_as_tags: false

* Add unit tests

* Remove debug logs

* Variable renaming

* Pass Options to newTranslator

* Remove unneeded param from newSketchWithHostname
  • Loading branch information
KSerrania authored Nov 17, 2021
1 parent 80fac75 commit df3eff6
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,8 @@ func (t *Translator) MapMetrics(ctx context.Context, md pdata.Metrics, consumer
var additionalTags []string
if t.cfg.InstrumentationLibraryMetadataAsTags {
additionalTags = append(attributeTags, instrumentationlibrary.TagsFromInstrumentationLibraryMetadata(ilm.InstrumentationLibrary())...)
} else {
additionalTags = attributeTags
}

for k := 0; k < metricsArray.Len(); k++ {
Expand Down
247 changes: 199 additions & 48 deletions exporter/datadogexporter/internal/translator/metrics_translator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package translator

import (
"context"
"fmt"
"math"
"testing"
"time"
Expand All @@ -26,6 +27,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/model/pdata"
conventions "go.opentelemetry.io/collector/model/semconv/v1.5.0"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
Expand Down Expand Up @@ -106,12 +108,16 @@ func (t testProvider) Hostname(context.Context) (string, error) {
return string(t), nil
}

func newTranslator(t *testing.T, logger *zap.Logger) *Translator {
tr, err := New(
logger,
func newTranslator(t *testing.T, logger *zap.Logger, opts ...Option) *Translator {
options := append([]Option{
WithFallbackHostnameProvider(testProvider("fallbackHostname")),
WithHistogramMode(HistogramModeDistributions),
WithNumberMode(NumberModeCumulativeToDelta),
}, opts...)

tr, err := New(
logger,
options...,
)

require.NoError(t, err)
Expand Down Expand Up @@ -934,16 +940,22 @@ const (
testHostname = "res-hostname"
)

func createTestMetrics() pdata.Metrics {
func createTestMetrics(additionalAttributes map[string]string, name, version string) pdata.Metrics {
md := pdata.NewMetrics()
rms := md.ResourceMetrics()
rm := rms.AppendEmpty()

attrs := rm.Resource().Attributes()
attrs.InsertString(attributes.AttributeDatadogHostname, testHostname)
for attr, val := range additionalAttributes {
attrs.InsertString(attr, val)
}
ilms := rm.InstrumentationLibraryMetrics()

metricsArray := ilms.AppendEmpty().Metrics()
ilm := ilms.AppendEmpty()
ilm.InstrumentationLibrary().SetName(name)
ilm.InstrumentationLibrary().SetVersion(version)
metricsArray := ilm.Metrics()
metricsArray.AppendEmpty() // first one is TypeNone to test that it's ignored

// IntGauge
Expand Down Expand Up @@ -1096,64 +1108,203 @@ func createTestMetrics() pdata.Metrics {
return md
}

func newGaugeWithHostname(name string, val float64) metric {
m := newGauge(name, 0, val, []string{})
func newGaugeWithHostname(name string, val float64, tags []string) metric {
m := newGauge(name, 0, val, tags)
m.host = testHostname
return m
}

func newCountWithHostname(name string, val float64, seconds uint64) metric {
m := newCount(name, seconds*1e9, val, []string{})
func newCountWithHostname(name string, val float64, seconds uint64, tags []string) metric {
m := newCount(name, seconds*1e9, val, tags)
m.host = testHostname
return m
}

func newSketchWithHostname(name string, summary summary.Summary, seconds uint64) sketch {
s := newSketch(name, seconds, summary, []string{})
func newSketchWithHostname(name string, summary summary.Summary, tags []string) sketch {
s := newSketch(name, 0, summary, tags)
s.host = testHostname
return s
}

func TestMapMetrics(t *testing.T) {
md := createTestMetrics()
attrs := map[string]string{
conventions.AttributeDeploymentEnvironment: "dev",
"custom_attribute": "custom_value",
}
// When ResourceAttributesAsTags is true, attributes are
// converted into labels by the resourcetotelemetry helper,
// so MapMetrics doesn't do any conversion.
// When ResourceAttributesAsTags is false, attributes
// defined in internal/attributes get converted to tags.
// Other tags do not get converted.
attrTags := []string{
"env:dev",
}

core, observed := observer.New(zapcore.DebugLevel)
testLogger := zap.New(core)
ctx := context.Background()
consumer := &mockFullConsumer{}
tr := newTranslator(t, testLogger)
err := tr.MapMetrics(ctx, md, consumer)
require.NoError(t, err)
ilName := "instrumentation_library"
ilVersion := "1.0.0"
ilTags := []string{
fmt.Sprintf("instrumentation_library:%s", ilName),
fmt.Sprintf("instrumentation_library_version:%s", ilVersion),
}

assert.ElementsMatch(t, consumer.metrics, []metric{
newGaugeWithHostname("int.gauge", 1),
newGaugeWithHostname("double.gauge", math.Pi),
newCountWithHostname("int.delta.sum", 2, 0),
newCountWithHostname("double.delta.sum", math.E, 0),
newCountWithHostname("int.delta.monotonic.sum", 2, 0),
newCountWithHostname("double.delta.monotonic.sum", math.E, 0),
newCountWithHostname("summary.sum", 10_000, 2),
newCountWithHostname("summary.count", 100, 2),
newGaugeWithHostname("int.cumulative.sum", 4),
newGaugeWithHostname("double.cumulative.sum", 4),
newCountWithHostname("int.cumulative.monotonic.sum", 3, 2),
newCountWithHostname("double.cumulative.monotonic.sum", math.Pi, 2),
})
tests := []struct {
name string
resourceAttributesAsTags bool
instrumentationLibraryMetadataAsTags bool
expectedMetrics []metric
expectedSketches []sketch
expectedUnknownMetricType int
expectedUnsupportedAggregationTemporality int
}{
{
name: "ResourceAttributesAsTags: false, InstrumentationLibraryMetadataAsTags: false",
resourceAttributesAsTags: false,
instrumentationLibraryMetadataAsTags: false,
expectedMetrics: []metric{
newGaugeWithHostname("int.gauge", 1, attrTags),
newGaugeWithHostname("double.gauge", math.Pi, attrTags),
newCountWithHostname("int.delta.sum", 2, 0, attrTags),
newCountWithHostname("double.delta.sum", math.E, 0, attrTags),
newCountWithHostname("int.delta.monotonic.sum", 2, 0, attrTags),
newCountWithHostname("double.delta.monotonic.sum", math.E, 0, attrTags),
newCountWithHostname("summary.sum", 10_000, 2, attrTags),
newCountWithHostname("summary.count", 100, 2, attrTags),
newGaugeWithHostname("int.cumulative.sum", 4, attrTags),
newGaugeWithHostname("double.cumulative.sum", 4, attrTags),
newCountWithHostname("int.cumulative.monotonic.sum", 3, 2, attrTags),
newCountWithHostname("double.cumulative.monotonic.sum", math.Pi, 2, attrTags),
},
expectedSketches: []sketch{
newSketchWithHostname("double.histogram", summary.Summary{
Min: 0,
Max: 0,
Sum: 0,
Avg: 0,
Cnt: 20,
}, attrTags),
},
expectedUnknownMetricType: 1,
expectedUnsupportedAggregationTemporality: 2,
},
{
name: "ResourceAttributesAsTags: true, InstrumentationLibraryMetadataAsTags: false",
resourceAttributesAsTags: true,
instrumentationLibraryMetadataAsTags: false,
expectedMetrics: []metric{
newGaugeWithHostname("int.gauge", 1, []string{}),
newGaugeWithHostname("double.gauge", math.Pi, []string{}),
newCountWithHostname("int.delta.sum", 2, 0, []string{}),
newCountWithHostname("double.delta.sum", math.E, 0, []string{}),
newCountWithHostname("int.delta.monotonic.sum", 2, 0, []string{}),
newCountWithHostname("double.delta.monotonic.sum", math.E, 0, []string{}),
newCountWithHostname("summary.sum", 10_000, 2, []string{}),
newCountWithHostname("summary.count", 100, 2, []string{}),
newGaugeWithHostname("int.cumulative.sum", 4, []string{}),
newGaugeWithHostname("double.cumulative.sum", 4, []string{}),
newCountWithHostname("int.cumulative.monotonic.sum", 3, 2, []string{}),
newCountWithHostname("double.cumulative.monotonic.sum", math.Pi, 2, []string{}),
},
expectedSketches: []sketch{
newSketchWithHostname("double.histogram", summary.Summary{
Min: 0,
Max: 0,
Sum: 0,
Avg: 0,
Cnt: 20,
}, []string{}),
},
expectedUnknownMetricType: 1,
expectedUnsupportedAggregationTemporality: 2,
},
{
name: "ResourceAttributesAsTags: false, InstrumentationLibraryMetadataAsTags: true",
resourceAttributesAsTags: false,
instrumentationLibraryMetadataAsTags: true,
expectedMetrics: []metric{
newGaugeWithHostname("int.gauge", 1, append(attrTags, ilTags...)),
newGaugeWithHostname("double.gauge", math.Pi, append(attrTags, ilTags...)),
newCountWithHostname("int.delta.sum", 2, 0, append(attrTags, ilTags...)),
newCountWithHostname("double.delta.sum", math.E, 0, append(attrTags, ilTags...)),
newCountWithHostname("int.delta.monotonic.sum", 2, 0, append(attrTags, ilTags...)),
newCountWithHostname("double.delta.monotonic.sum", math.E, 0, append(attrTags, ilTags...)),
newCountWithHostname("summary.sum", 10_000, 2, append(attrTags, ilTags...)),
newCountWithHostname("summary.count", 100, 2, append(attrTags, ilTags...)),
newGaugeWithHostname("int.cumulative.sum", 4, append(attrTags, ilTags...)),
newGaugeWithHostname("double.cumulative.sum", 4, append(attrTags, ilTags...)),
newCountWithHostname("int.cumulative.monotonic.sum", 3, 2, append(attrTags, ilTags...)),
newCountWithHostname("double.cumulative.monotonic.sum", math.Pi, 2, append(attrTags, ilTags...)),
},
expectedSketches: []sketch{
newSketchWithHostname("double.histogram", summary.Summary{
Min: 0,
Max: 0,
Sum: 0,
Avg: 0,
Cnt: 20,
}, append(attrTags, ilTags...)),
},
expectedUnknownMetricType: 1,
expectedUnsupportedAggregationTemporality: 2,
},
{
name: "ResourceAttributesAsTags: true, InstrumentationLibraryMetadataAsTags: true",
resourceAttributesAsTags: true,
instrumentationLibraryMetadataAsTags: true,
expectedMetrics: []metric{
newGaugeWithHostname("int.gauge", 1, ilTags),
newGaugeWithHostname("double.gauge", math.Pi, ilTags),
newCountWithHostname("int.delta.sum", 2, 0, ilTags),
newCountWithHostname("double.delta.sum", math.E, 0, ilTags),
newCountWithHostname("int.delta.monotonic.sum", 2, 0, ilTags),
newCountWithHostname("double.delta.monotonic.sum", math.E, 0, ilTags),
newCountWithHostname("summary.sum", 10_000, 2, ilTags),
newCountWithHostname("summary.count", 100, 2, ilTags),
newGaugeWithHostname("int.cumulative.sum", 4, ilTags),
newGaugeWithHostname("double.cumulative.sum", 4, ilTags),
newCountWithHostname("int.cumulative.monotonic.sum", 3, 2, ilTags),
newCountWithHostname("double.cumulative.monotonic.sum", math.Pi, 2, ilTags),
},
expectedSketches: []sketch{
newSketchWithHostname("double.histogram", summary.Summary{
Min: 0,
Max: 0,
Sum: 0,
Avg: 0,
Cnt: 20,
}, ilTags),
},
expectedUnknownMetricType: 1,
expectedUnsupportedAggregationTemporality: 2,
},
}

assert.ElementsMatch(t, consumer.sketches, []sketch{
newSketchWithHostname("double.histogram", summary.Summary{
Min: 0,
Max: 0,
Sum: 0,
Avg: 0,
Cnt: 20,
}, 0),
})
for _, testInstance := range tests {
t.Run(testInstance.name, func(t *testing.T) {
md := createTestMetrics(attrs, ilName, ilVersion)

// One metric type was unknown or unsupported
assert.Equal(t, observed.FilterMessage("Unknown or unsupported metric type").Len(), 1)
// Two metric aggregation temporality was unknown or unsupported
assert.Equal(t, observed.FilterMessage("Unknown or unsupported aggregation temporality").Len(), 2)
core, observed := observer.New(zapcore.DebugLevel)
testLogger := zap.New(core)
ctx := context.Background()
consumer := &mockFullConsumer{}

options := []Option{}
if testInstance.resourceAttributesAsTags {
options = append(options, WithResourceAttributesAsTags())
}
if testInstance.instrumentationLibraryMetadataAsTags {
options = append(options, WithInstrumentationLibraryMetadataAsTags())
}
tr := newTranslator(t, testLogger, options...)
err := tr.MapMetrics(ctx, md, consumer)
require.NoError(t, err)

assert.ElementsMatch(t, consumer.metrics, testInstance.expectedMetrics)
assert.ElementsMatch(t, consumer.sketches, testInstance.expectedSketches)
assert.Equal(t, observed.FilterMessage("Unknown or unsupported metric type").Len(), testInstance.expectedUnknownMetricType)
assert.Equal(t, observed.FilterMessage("Unknown or unsupported aggregation temporality").Len(), testInstance.expectedUnsupportedAggregationTemporality)
})
}
}

func createNaNMetrics() pdata.Metrics {
Expand Down Expand Up @@ -1259,7 +1410,7 @@ func TestNaNMetrics(t *testing.T) {
require.NoError(t, err)

assert.ElementsMatch(t, consumer.metrics, []metric{
newCountWithHostname("nan.summary.count", 100, 2),
newCountWithHostname("nan.summary.count", 100, 2, []string{}),
})

assert.ElementsMatch(t, consumer.sketches, []sketch{
Expand All @@ -1269,7 +1420,7 @@ func TestNaNMetrics(t *testing.T) {
Sum: 0,
Avg: 0,
Cnt: 20,
}, 0),
}, []string{}),
})

// One metric type was unknown or unsupported
Expand Down

0 comments on commit df3eff6

Please sign in to comment.