Skip to content

Commit b7c1918

Browse files
committed
[FEAT] migrate to semconv for otelecho
1 parent 7af8c94 commit b7c1918

File tree

19 files changed

+3127
-9
lines changed

19 files changed

+3127
-9
lines changed

instrumentation/github.com/labstack/echo/otelecho/echo.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ import (
1111
"github.com/labstack/echo/v4"
1212
"github.com/labstack/echo/v4/middleware"
1313

14-
"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho/internal/semconvutil"
14+
"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho/internal/semconv"
1515
"go.opentelemetry.io/otel"
1616
"go.opentelemetry.io/otel/attribute"
1717
"go.opentelemetry.io/otel/propagation"
18-
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
1918
oteltrace "go.opentelemetry.io/otel/trace"
2019
)
2120

@@ -46,6 +45,8 @@ func Middleware(service string, opts ...Option) echo.MiddlewareFunc {
4645
cfg.Skipper = middleware.DefaultSkipper
4746
}
4847

48+
var hs semconv.HTTPServer
49+
4950
return func(next echo.HandlerFunc) echo.HandlerFunc {
5051
return func(c echo.Context) error {
5152
if cfg.Skipper(c) {
@@ -61,13 +62,10 @@ func Middleware(service string, opts ...Option) echo.MiddlewareFunc {
6162
}()
6263
ctx := cfg.Propagators.Extract(savedCtx, propagation.HeaderCarrier(request.Header))
6364
opts := []oteltrace.SpanStartOption{
64-
oteltrace.WithAttributes(semconvutil.HTTPServerRequest(service, request)...),
65+
oteltrace.WithAttributes(hs.RequestTraceAttrs(service, request)...),
66+
oteltrace.WithAttributes(hs.Route(c.Path())),
6567
oteltrace.WithSpanKind(oteltrace.SpanKindServer),
6668
}
67-
if path := c.Path(); path != "" {
68-
rAttr := semconv.HTTPRoute(path)
69-
opts = append(opts, oteltrace.WithAttributes(rAttr))
70-
}
7169
spanName := spanNameFormatter(c)
7270

7371
ctx, span := tracer.Start(ctx, spanName, opts...)
@@ -85,7 +83,7 @@ func Middleware(service string, opts ...Option) echo.MiddlewareFunc {
8583
}
8684

8785
status := c.Response().Status
88-
span.SetStatus(semconvutil.HTTPServerStatus(status))
86+
span.SetStatus(hs.Status(status))
8987
if status > 0 {
9088
span.SetAttributes(semconv.HTTPStatusCode(status))
9189
}

instrumentation/github.com/labstack/echo/otelecho/echo_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
b3prop "go.opentelemetry.io/contrib/propagators/b3"
1818
"go.opentelemetry.io/otel"
1919
"go.opentelemetry.io/otel/propagation"
20+
sdktrace "go.opentelemetry.io/otel/sdk/trace"
21+
"go.opentelemetry.io/otel/sdk/trace/tracetest"
2022
"go.opentelemetry.io/otel/trace"
2123
"go.opentelemetry.io/otel/trace/noop"
2224
)
@@ -117,3 +119,37 @@ func TestSkipper(t *testing.T) {
117119
router.ServeHTTP(w, r)
118120
assert.Equal(t, http.StatusOK, w.Result().StatusCode, "should call the 'ping' handler") //nolint:bodyclose // False positive for httptest.ResponseRecorder: https://github.com/timakin/bodyclose/issues/59.
119121
}
122+
123+
func TestHTTPRouteAttribute(t *testing.T) {
124+
// Set up an in-memory span recorder
125+
sr := tracetest.NewSpanRecorder()
126+
tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))
127+
128+
// Create Echo instance with middleware
129+
e := echo.New()
130+
e.Use(Middleware("test-service", WithTracerProvider(tp)))
131+
e.GET("/users/:id", func(c echo.Context) error {
132+
return c.String(http.StatusOK, "ok")
133+
})
134+
135+
// Simulate a request
136+
r := httptest.NewRequest("GET", "/users/123", nil)
137+
w := httptest.NewRecorder()
138+
e.ServeHTTP(w, r)
139+
140+
// Check response
141+
assert.Equal(t, http.StatusOK, w.Result().StatusCode)
142+
143+
// Verify span attributes
144+
spans := sr.Ended()
145+
assert.Len(t, spans, 1, "expected one span")
146+
147+
found := false
148+
for _, attr := range spans[0].Attributes() {
149+
if attr.Key == "http.route" && attr.Value.AsString() == "/users/:id" {
150+
found = true
151+
break
152+
}
153+
}
154+
assert.True(t, found, "http.route attribute not found or incorrect, got %v", spans[0].Attributes())
155+
}

instrumentation/github.com/labstack/echo/otelecho/go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,23 @@ require (
99
github.com/stretchr/testify v1.10.0
1010
go.opentelemetry.io/contrib/propagators/b3 v1.35.0
1111
go.opentelemetry.io/otel v1.35.0
12+
go.opentelemetry.io/otel/metric v1.35.0
13+
go.opentelemetry.io/otel/sdk v1.35.0
1214
go.opentelemetry.io/otel/trace v1.35.0
1315
)
1416

1517
require (
1618
github.com/davecgh/go-spew v1.1.1 // indirect
1719
github.com/go-logr/logr v1.4.2 // indirect
1820
github.com/go-logr/stdr v1.2.2 // indirect
21+
github.com/google/uuid v1.6.0 // indirect
1922
github.com/labstack/gommon v0.4.2 // indirect
2023
github.com/mattn/go-colorable v0.1.14 // indirect
2124
github.com/mattn/go-isatty v0.0.20 // indirect
2225
github.com/pmezard/go-difflib v1.0.0 // indirect
2326
github.com/valyala/bytebufferpool v1.0.0 // indirect
2427
github.com/valyala/fasttemplate v1.2.2 // indirect
2528
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
26-
go.opentelemetry.io/otel/metric v1.35.0 // indirect
2729
golang.org/x/crypto v0.36.0 // indirect
2830
golang.org/x/net v0.37.0 // indirect
2931
golang.org/x/sys v0.31.0 // indirect

instrumentation/github.com/labstack/echo/otelecho/go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
77
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
88
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
99
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
10+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
11+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1012
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
1113
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
1214
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -35,8 +37,12 @@ go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
3537
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
3638
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
3739
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
40+
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
41+
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
3842
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
3943
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
44+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
45+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
4046
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
4147
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
4248
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Code created by gotmpl. DO NOT MODIFY.
2+
// source: internal/shared/semconv/bench_test.go.tmpl
3+
4+
// Copyright The OpenTelemetry Authors
5+
// SPDX-License-Identifier: Apache-2.0
6+
7+
package semconv
8+
9+
import (
10+
"net/http"
11+
"net/url"
12+
"testing"
13+
14+
"go.opentelemetry.io/otel/attribute"
15+
)
16+
17+
var benchHTTPServerRequestResults []attribute.KeyValue
18+
19+
// BenchmarkHTTPServerRequest allows comparison between different version of the HTTP server.
20+
// To use an alternative start this test with OTEL_SEMCONV_STABILITY_OPT_IN set to the
21+
// version under test.
22+
func BenchmarkHTTPServerRequest(b *testing.B) {
23+
// Request was generated from TestHTTPServerRequest request.
24+
req := &http.Request{
25+
Method: http.MethodGet,
26+
URL: &url.URL{
27+
Path: "/",
28+
},
29+
Proto: "HTTP/1.1",
30+
ProtoMajor: 1,
31+
ProtoMinor: 1,
32+
Header: http.Header{
33+
"User-Agent": []string{"Go-http-client/1.1"},
34+
"Accept-Encoding": []string{"gzip"},
35+
},
36+
Body: http.NoBody,
37+
Host: "127.0.0.1:39093",
38+
RemoteAddr: "127.0.0.1:38738",
39+
RequestURI: "/",
40+
}
41+
serv := NewHTTPServer(nil)
42+
43+
b.ReportAllocs()
44+
b.ResetTimer()
45+
for i := 0; i < b.N; i++ {
46+
benchHTTPServerRequestResults = serv.RequestTraceAttrs("", req)
47+
}
48+
}

0 commit comments

Comments
 (0)