Skip to content

Commit

Permalink
Update New Relic exporter error conditions. (open-telemetry#3322)
Browse files Browse the repository at this point in the history
* Update New Relic error text to include http response code.

* Export cumulative metrics as gauges.
  • Loading branch information
a-feld committed May 4, 2021
1 parent 189e504 commit b2d3a11
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 43 deletions.
5 changes: 4 additions & 1 deletion exporter/newrelicexporter/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package newrelicexporter

import (
"fmt"
"net/http"
"net/url"
"strconv"
Expand Down Expand Up @@ -63,7 +64,9 @@ type httpError struct {
Response *http.Response
}

func (e *httpError) Error() string { return "New Relic HTTP call failed" }
func (e *httpError) Error() string {
return fmt.Sprintf("New Relic HTTP call failed. Status Code: %d", e.Response.StatusCode)
}

func (e *httpError) GRPCStatus() *grpcStatus.Status {
mapEntry, ok := httpGrpcMapping[e.Response.StatusCode]
Expand Down
2 changes: 1 addition & 1 deletion exporter/newrelicexporter/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func TestHttpError_GRPCStatus(t *testing.T) {

func TestHttpError_Error(t *testing.T) {
httpError := &httpError{Response: responseOf(http.StatusTeapot)}
assert.Equal(t, httpError.Error(), "New Relic HTTP call failed")
assert.Equal(t, httpError.Error(), "New Relic HTTP call failed. Status Code: 418")
}

func responseOf(statusCode int) *http.Response {
Expand Down
6 changes: 3 additions & 3 deletions exporter/newrelicexporter/newrelic.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (e exporter) pushTraceData(ctx context.Context, td pdata.Traces) (outputErr
func (e exporter) buildTraceBatch(details *exportMetadata, td pdata.Traces) ([]telemetry.Batch, error) {
var errs []error

transform := newTransformer(e.buildInfo, details)
transform := newTransformer(e.logger, e.buildInfo, details)
batches := make([]telemetry.Batch, 0, calcSpanBatches(td))

for i := 0; i < td.ResourceSpans().Len(); i++ {
Expand Down Expand Up @@ -184,7 +184,7 @@ func (e exporter) pushLogData(ctx context.Context, ld pdata.Logs) (outputErr err
func (e exporter) buildLogBatch(details *exportMetadata, ld pdata.Logs) ([]telemetry.Batch, error) {
var errs []error

transform := newTransformer(e.buildInfo, details)
transform := newTransformer(e.logger, e.buildInfo, details)
batches := make([]telemetry.Batch, 0, calcLogBatches(ld))

for i := 0; i < ld.ResourceLogs().Len(); i++ {
Expand Down Expand Up @@ -237,7 +237,7 @@ func (e exporter) pushMetricData(ctx context.Context, md pdata.Metrics) (outputE
func (e exporter) buildMetricBatch(details *exportMetadata, md pdata.Metrics) ([]telemetry.Batch, error) {
var errs []error

transform := newTransformer(e.buildInfo, details)
transform := newTransformer(e.logger, e.buildInfo, details)
batches := make([]telemetry.Batch, 0, calcMetricBatches(md))

for i := 0; i < md.ResourceMetrics().Len(); i++ {
Expand Down
72 changes: 48 additions & 24 deletions exporter/newrelicexporter/transformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/consumer/pdata"
tracetranslator "go.opentelemetry.io/collector/translator/trace"
"go.uber.org/zap"
)

const (
Expand All @@ -44,11 +45,12 @@ const (
)

type transformer struct {
logger *zap.Logger
OverrideAttributes map[string]interface{}
details *exportMetadata
}

func newTransformer(buildInfo *component.BuildInfo, details *exportMetadata) *transformer {
func newTransformer(logger *zap.Logger, buildInfo *component.BuildInfo, details *exportMetadata) *transformer {
overrideAttributes := make(map[string]interface{})
if buildInfo != nil {
overrideAttributes[collectorNameKey] = buildInfo.Command
Expand All @@ -57,7 +59,7 @@ func newTransformer(buildInfo *component.BuildInfo, details *exportMetadata) *tr
}
}

return &transformer{OverrideAttributes: overrideAttributes, details: details}
return &transformer{logger: logger, OverrideAttributes: overrideAttributes, details: details}
}

func (t *transformer) CommonAttributes(resource pdata.Resource, lib pdata.InstrumentationLibrary) map[string]interface{} {
Expand Down Expand Up @@ -289,49 +291,71 @@ func (t *transformer) Metric(m pdata.Metric) ([]telemetry.Metric, error) {
k.MetricTemporality = temporality
t.details.metricMetadataCount[k]++

if temporality != pdata.AggregationTemporalityDelta {
return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: sum.DataPoints().Len()}
}

points := sum.DataPoints()
output = make([]telemetry.Metric, 0, points.Len())
for l := 0; l < points.Len(); l++ {
point := points.At(l)
attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

nrMetric := telemetry.Count{
Name: m.Name(),
Attributes: attributes,
Value: float64(point.Value()),
Timestamp: point.StartTimestamp().AsTime(),
Interval: time.Duration(point.Timestamp() - point.StartTimestamp()),
if temporality != pdata.AggregationTemporalityDelta {
t.logger.Debug("Converting metric to gauge where AggregationTemporality != Delta",
zap.String("MetricName", m.Name()),
zap.Stringer("Temporality", temporality),
zap.Stringer("MetricType", dataType),
)
nrMetric := telemetry.Gauge{
Name: m.Name(),
Attributes: attributes,
Value: float64(point.Value()),
Timestamp: point.StartTimestamp().AsTime(),
}
output = append(output, nrMetric)
} else {
nrMetric := telemetry.Count{
Name: m.Name(),
Attributes: attributes,
Value: float64(point.Value()),
Timestamp: point.StartTimestamp().AsTime(),
Interval: time.Duration(point.Timestamp() - point.StartTimestamp()),
}
output = append(output, nrMetric)
}
output = append(output, nrMetric)
}
case pdata.MetricDataTypeDoubleSum:
sum := m.DoubleSum()
temporality := sum.AggregationTemporality()
k.MetricTemporality = temporality
t.details.metricMetadataCount[k]++

if temporality != pdata.AggregationTemporalityDelta {
return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: sum.DataPoints().Len()}
}

points := sum.DataPoints()
output = make([]telemetry.Metric, 0, points.Len())
for l := 0; l < points.Len(); l++ {
point := points.At(l)
attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

nrMetric := telemetry.Count{
Name: m.Name(),
Attributes: attributes,
Value: point.Value(),
Timestamp: point.StartTimestamp().AsTime(),
Interval: time.Duration(point.Timestamp() - point.StartTimestamp()),
if temporality != pdata.AggregationTemporalityDelta {
t.logger.Debug("Converting metric to gauge where AggregationTemporality != Delta",
zap.String("MetricName", m.Name()),
zap.Stringer("Temporality", temporality),
zap.Stringer("MetricType", dataType),
)
nrMetric := telemetry.Gauge{
Name: m.Name(),
Attributes: attributes,
Value: point.Value(),
Timestamp: point.StartTimestamp().AsTime(),
}
output = append(output, nrMetric)
} else {
nrMetric := telemetry.Count{
Name: m.Name(),
Attributes: attributes,
Value: point.Value(),
Timestamp: point.StartTimestamp().AsTime(),
Interval: time.Duration(point.Timestamp() - point.StartTimestamp()),
}
output = append(output, nrMetric)
}
output = append(output, nrMetric)
}
case pdata.MetricDataTypeIntHistogram:
t.details.metricMetadataCount[k]++
Expand Down
40 changes: 26 additions & 14 deletions exporter/newrelicexporter/transformer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/consumer/pdata"
"go.opentelemetry.io/collector/translator/internaldata"
"go.uber.org/zap"
)

func TestCommonAttributes(t *testing.T) {
Expand All @@ -44,7 +45,7 @@ func TestCommonAttributes(t *testing.T) {
ilm.SetVersion("test version")

details := newTraceMetadata(context.TODO())
commonAttrs := newTransformer(buildInfo, &details).CommonAttributes(resource, ilm)
commonAttrs := newTransformer(zap.NewNop(), buildInfo, &details).CommonAttributes(resource, ilm)
assert.Equal(t, "the-collector", commonAttrs[collectorNameKey])
assert.Equal(t, "0.0.1", commonAttrs[collectorVersionKey])
assert.Equal(t, "R1", commonAttrs["resource"])
Expand All @@ -68,15 +69,15 @@ func TestDoesNotCaptureResourceAttributeMetadata(t *testing.T) {
ilm.SetVersion("test version")

details := newTraceMetadata(context.TODO())
commonAttrs := newTransformer(buildInfo, &details).CommonAttributes(resource, ilm)
commonAttrs := newTransformer(zap.NewNop(), buildInfo, &details).CommonAttributes(resource, ilm)

assert.Greater(t, len(commonAttrs), 0)
assert.Equal(t, 0, len(details.attributeMetadataCount))
}

func TestCaptureSpanMetadata(t *testing.T) {
details := newTraceMetadata(context.TODO())
transform := newTransformer(nil, &details)
transform := newTransformer(zap.NewNop(), nil, &details)

tests := []struct {
name string
Expand Down Expand Up @@ -150,7 +151,7 @@ func TestCaptureSpanMetadata(t *testing.T) {

func TestCaptureSpanAttributeMetadata(t *testing.T) {
details := newTraceMetadata(context.TODO())
transform := newTransformer(nil, &details)
transform := newTransformer(zap.NewNop(), nil, &details)

s := pdata.NewSpan()
s.SetTraceID(pdata.NewTraceID([...]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}))
Expand All @@ -173,7 +174,7 @@ func TestCaptureSpanAttributeMetadata(t *testing.T) {

func TestDoesNotCaptureSpanAttributeMetadata(t *testing.T) {
details := newTraceMetadata(context.TODO())
transform := newTransformer(nil, &details)
transform := newTransformer(zap.NewNop(), nil, &details)

s := pdata.NewSpan()
s.SetTraceID(pdata.NewTraceID([...]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}))
Expand All @@ -191,7 +192,7 @@ func TestDoesNotCaptureSpanAttributeMetadata(t *testing.T) {
func TestTransformSpan(t *testing.T) {
now := time.Unix(100, 0)
details := newTraceMetadata(context.TODO())
transform := newTransformer(nil, &details)
transform := newTransformer(zap.NewNop(), nil, &details)

tests := []struct {
name string
Expand Down Expand Up @@ -466,7 +467,7 @@ func testTransformMetric(t *testing.T, metric pdata.Metric, want []telemetry.Met

func testTransformMetricWithComparer(t *testing.T, metric pdata.Metric, want []telemetry.Metric, compare func(t *testing.T, want []telemetry.Metric, got []telemetry.Metric)) {
details := newMetricMetadata(context.Background())
transform := newTransformer(&component.BuildInfo{
transform := newTransformer(zap.NewNop(), &component.BuildInfo{
Command: testCollectorName,
Version: testCollectorVersion,
}, &details)
Expand All @@ -483,7 +484,7 @@ func testTransformMetricWithComparer(t *testing.T, metric pdata.Metric, want []t

func testTransformMetricWithError(t *testing.T, metric pdata.Metric, expectedErrorType interface{}) {
details := newMetricMetadata(context.Background())
transform := newTransformer(&component.BuildInfo{
transform := newTransformer(zap.NewNop(), &component.BuildInfo{
Command: testCollectorName,
Version: testCollectorVersion,
}, &details)
Expand Down Expand Up @@ -552,6 +553,17 @@ func TestTransformSum(t *testing.T) {
},
},
}
expectedGauge := []telemetry.Metric{
telemetry.Gauge{
Name: "sum",
Value: 42.0,
Timestamp: start.AsTime(),
Attributes: map[string]interface{}{
"unit": "1",
"description": "description",
},
},
}

{
m := pdata.NewMetric()
Expand Down Expand Up @@ -579,7 +591,7 @@ func TestTransformSum(t *testing.T) {
dp.SetStartTimestamp(start)
dp.SetTimestamp(end)
dp.SetValue(42.0)
t.Run("DoubleSum-Cumulative", func(t *testing.T) { testTransformMetricWithError(t, m, &errUnsupportedMetricType{}) })
t.Run("DoubleSum-Cumulative", func(t *testing.T) { testTransformMetric(t, m, expectedGauge) })
}
{
m := pdata.NewMetric()
Expand Down Expand Up @@ -607,7 +619,7 @@ func TestTransformSum(t *testing.T) {
dp.SetStartTimestamp(start)
dp.SetTimestamp(end)
dp.SetValue(42.0)
t.Run("IntSum-Cumulative", func(t *testing.T) { testTransformMetricWithError(t, m, &errUnsupportedMetricType{}) })
t.Run("IntSum-Cumulative", func(t *testing.T) { testTransformMetric(t, m, expectedGauge) })
}
}

Expand Down Expand Up @@ -738,7 +750,7 @@ func TestUnsupportedMetricTypes(t *testing.T) {
func TestTransformUnknownMetricType(t *testing.T) {
metric := pdata.NewMetric()
details := newMetricMetadata(context.Background())
transform := newTransformer(&component.BuildInfo{
transform := newTransformer(zap.NewNop(), &component.BuildInfo{
Command: testCollectorName,
Version: testCollectorVersion,
}, &details)
Expand Down Expand Up @@ -837,7 +849,7 @@ func TestTransformer_Log(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
details := newLogMetadata(context.TODO())
transform := newTransformer(nil, &details)
transform := newTransformer(zap.NewNop(), nil, &details)
got, _ := transform.Log(test.logFunc())
assert.EqualValues(t, test.want, got)
})
Expand All @@ -851,7 +863,7 @@ func TestCaptureLogAttributeMetadata(t *testing.T) {
log.Body().SetStringVal("Hello World")

details := newLogMetadata(context.TODO())
transform := newTransformer(nil, &details)
transform := newTransformer(zap.NewNop(), nil, &details)
_, err := transform.Log(log)

require.NoError(t, err)
Expand All @@ -865,7 +877,7 @@ func TestDoesNotCaptureLogAttributeMetadata(t *testing.T) {
log.Body().SetStringVal("Hello World")

details := newLogMetadata(context.TODO())
transform := newTransformer(nil, &details)
transform := newTransformer(zap.NewNop(), nil, &details)
_, err := transform.Log(log)

require.NoError(t, err)
Expand Down

0 comments on commit b2d3a11

Please sign in to comment.