Skip to content

Commit

Permalink
Add route tag to metrics as well as traces when using WithRouteTag.
Browse files Browse the repository at this point in the history
Resolves #611.
  • Loading branch information
charleskorn committed Nov 19, 2022
1 parent 871ebe7 commit a28312d
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 2 deletions.
8 changes: 7 additions & 1 deletion instrumentation/net/http/otelhttp/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,14 @@ func setAfterServeAttributes(span trace.Span, read, wrote int64, statusCode int,
// RouteKey Tag.
func WithRouteTag(route string, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
attr := semconv.HTTPRouteKey.String(route)

span := trace.SpanFromContext(r.Context())
span.SetAttributes(semconv.HTTPRouteKey.String(route))
span.SetAttributes(attr)

labeler, _ := LabelerFromContext(r.Context())
labeler.Add(attr)

h.ServeHTTP(w, r)
})
}
1 change: 1 addition & 0 deletions instrumentation/net/http/otelhttp/test/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.36.4
go.opentelemetry.io/otel v1.11.1
go.opentelemetry.io/otel/sdk v1.11.1
go.opentelemetry.io/otel/sdk/metric v0.33.0
go.opentelemetry.io/otel/trace v1.11.1
)

Expand Down
2 changes: 2 additions & 0 deletions instrumentation/net/http/otelhttp/test/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ go.opentelemetry.io/otel/metric v0.33.0 h1:xQAyl7uGEYvrLAiV/09iTJlp1pZnQ9Wl793qb
go.opentelemetry.io/otel/metric v0.33.0/go.mod h1:QlTYc+EnYNq/M2mNk1qDDMRLpqCOj2f/r5c7Fd5FYaI=
go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs=
go.opentelemetry.io/otel/sdk v1.11.1/go.mod h1:/l3FE4SupHJ12TduVjUkZtlfFqDCQJlOlithYrdktys=
go.opentelemetry.io/otel/sdk/metric v0.33.0 h1:oTqyWfksgKoJmbrs2q7O7ahkJzt+Ipekihf8vhpa9qo=
go.opentelemetry.io/otel/sdk/metric v0.33.0/go.mod h1:xdypMeA21JBOvjjzDUtD0kzIcHO/SPez+a8HOzJPGp0=
go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ=
go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc=
Expand Down
58 changes: 57 additions & 1 deletion instrumentation/net/http/otelhttp/test/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"

"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/metric"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
"go.opentelemetry.io/otel/trace"

"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)

// TODO(#2759): Add metric integration tests for the instrumentation. These
Expand Down Expand Up @@ -334,3 +338,55 @@ func TestSpanStatus(t *testing.T) {
})
}
}

func TestWithRouteTag(t *testing.T) {
route := "/some/route"

spanRecorder := tracetest.NewSpanRecorder()
tracerProvider := sdktrace.NewTracerProvider()
tracerProvider.RegisterSpanProcessor(spanRecorder)

metricReader := metric.NewManualReader()
meterProvider := metric.NewMeterProvider(metric.WithReader(metricReader))

h := otelhttp.NewHandler(
otelhttp.WithRouteTag(
route,
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusTeapot)
}),
),
"test_handler",
otelhttp.WithTracerProvider(tracerProvider),
otelhttp.WithMeterProvider(meterProvider),
)

h.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(http.MethodGet, "/", nil))
expectedAttribute := semconv.HTTPRouteKey.String(route)

require.Len(t, spanRecorder.Ended(), 1, "should emit a span")
span := spanRecorder.Ended()[0]
require.Contains(t, span.Attributes(), expectedAttribute, "should add route to span attributes")

collectedMetrics, err := metricReader.Collect(context.Background())
require.NoError(t, err)
require.Len(t, collectedMetrics.ScopeMetrics, 1, "should emit metrics for one scope")
scopeMetrics := collectedMetrics.ScopeMetrics[0]

for _, m := range scopeMetrics.Metrics {
switch m.Data.(type) {
case metricdata.Sum[int64]:
d := m.Data.(metricdata.Sum[int64])
require.Len(t, d.DataPoints, 1, "metric '%v' should have exactly one data point", m.Name)
require.Contains(t, d.DataPoints[0].Attributes.ToSlice(), expectedAttribute, "should add route to attributes for metric '%v'", m.Name)

case metricdata.Histogram:
d := m.Data.(metricdata.Histogram)
require.Len(t, d.DataPoints, 1, "metric '%v' should have exactly one data point", m.Name)
require.Contains(t, d.DataPoints[0].Attributes.ToSlice(), expectedAttribute, "should add route to attributes for metric '%v'", m.Name)

default:
require.Fail(t, "metric has unexpected data type", "metric '%v' has unexpected data type %T", m.Name, m.Data)
}
}
}

0 comments on commit a28312d

Please sign in to comment.