Skip to content

Commit

Permalink
feat(otelecho): add SpanNameFormatter config and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
flc1125 committed Nov 24, 2024
1 parent 73c4165 commit 14ba828
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 6 deletions.
25 changes: 22 additions & 3 deletions instrumentation/github.com/labstack/echo/otelecho/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@
package otelecho // import "go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"

import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"

"go.opentelemetry.io/otel/propagation"
oteltrace "go.opentelemetry.io/otel/trace"
)

// defaultSpanNameFormatter is the default function used for formatting span names.
var defaultSpanNameFormatter = func(c echo.Context) string {
return c.Path()
}

// SpanNameFormatter is a function that takes an echo.Context and returns a span name.
type SpanNameFormatter func(c echo.Context) string

// config is used to configure the mux middleware.
type config struct {
TracerProvider oteltrace.TracerProvider
Propagators propagation.TextMapPropagator
Skipper middleware.Skipper
TracerProvider oteltrace.TracerProvider
Propagators propagation.TextMapPropagator
Skipper middleware.Skipper
spanNameFormatter SpanNameFormatter
}

// Option specifies instrumentation configuration options.
Expand Down Expand Up @@ -55,3 +65,12 @@ func WithSkipper(skipper middleware.Skipper) Option {
cfg.Skipper = skipper
})
}

// WithSpanNameFormatter specifies a function to use for formatting span names.
func WithSpanNameFormatter(formatter SpanNameFormatter) Option {
return optionFunc(func(cfg *config) {
if formatter != nil {
cfg.spanNameFormatter = formatter
}
})
}
9 changes: 7 additions & 2 deletions instrumentation/github.com/labstack/echo/otelecho/echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import (

"go.opentelemetry.io/otel"

"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho/internal/semconvutil"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/propagation"
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
oteltrace "go.opentelemetry.io/otel/trace"

"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho/internal/semconvutil"
)

const (
Expand Down Expand Up @@ -45,6 +46,10 @@ func Middleware(service string, opts ...Option) echo.MiddlewareFunc {
cfg.Skipper = middleware.DefaultSkipper
}

if cfg.spanNameFormatter == nil {
cfg.spanNameFormatter = defaultSpanNameFormatter
}

return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if cfg.Skipper(c) {
Expand All @@ -67,7 +72,7 @@ func Middleware(service string, opts ...Option) echo.MiddlewareFunc {
rAttr := semconv.HTTPRoute(path)
opts = append(opts, oteltrace.WithAttributes(rAttr))
}
spanName := c.Path()
spanName := cfg.spanNameFormatter(c)
if spanName == "" {
spanName = fmt.Sprintf("HTTP %s route not found", request.Method)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"

"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"

"go.opentelemetry.io/otel/attribute"
oteltrace "go.opentelemetry.io/otel/trace"
)
Expand Down Expand Up @@ -202,3 +203,50 @@ func TestErrorNotSwallowedByMiddleware(t *testing.T) {
err := h(c)
assert.Equal(t, assert.AnError, err)
}

func TestSpanNameFormatter(t *testing.T) {
imsb := tracetest.NewInMemoryExporter()
otel.SetTracerProvider(trace.NewTracerProvider(
trace.WithSyncer(imsb),
))

tests := []struct {
name string
formatter otelecho.SpanNameFormatter
expected string
}{
{
name: "default",
formatter: nil,
expected: "/user/:id",
},
{
name: "custom",
formatter: func(c echo.Context) string {
return "custom " + c.Path()
},
expected: "custom /user/:id",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
defer imsb.Reset()

router := echo.New()
router.Use(otelecho.Middleware("foobar", otelecho.WithSpanNameFormatter(test.formatter)))
router.GET("/user/:id", func(c echo.Context) error {
return c.NoContent(http.StatusOK)
})

r := httptest.NewRequest("GET", "/user/123", nil)
w := httptest.NewRecorder()

router.ServeHTTP(w, r)

spans := imsb.GetSpans()
assert.Len(t, spans, 1)
assert.Equal(t, test.expected, spans[0].Name)
})
}
}

0 comments on commit 14ba828

Please sign in to comment.