From 9de11d8599232d8bea9e04df05298ba18579ec38 Mon Sep 17 00:00:00 2001 From: arshukla98 Date: Wed, 30 Apr 2025 12:45:54 +0530 Subject: [PATCH 1/2] otelgin: Add a WithSpanStartOptions option --- CHANGELOG.md | 1 + .../gin-gonic/gin/otelgin/config.go | 9 +++++++ .../github.com/gin-gonic/gin/otelgin/gin.go | 3 +++ .../gin-gonic/gin/otelgin/test/gin_test.go | 25 +++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8a9b967536..947b7f893e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Allow configuring samplers in `go.opentelemetry.io/contrib/otelconf`. (#7148) - Slog log bridge now sets `SeverityText` attribute using source value in `go.opentelemetry.io/contrib/bridges/otelslog`. (#7198) - Add `http.route` metric attribute in `go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin`. (#7275) +- Add the `WithSpanStartOptions` option to add extra attributes, links, etc. to the spans it generates in `go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin`. (#7261) ### Changed diff --git a/instrumentation/github.com/gin-gonic/gin/otelgin/config.go b/instrumentation/github.com/gin-gonic/gin/otelgin/config.go index c69fc3b3d41..10cf06228b5 100644 --- a/instrumentation/github.com/gin-gonic/gin/otelgin/config.go +++ b/instrumentation/github.com/gin-gonic/gin/otelgin/config.go @@ -21,6 +21,7 @@ import ( type config struct { TracerProvider oteltrace.TracerProvider Propagators propagation.TextMapPropagator + SpanStartOptions []oteltrace.SpanStartOption Filters []Filter GinFilters []GinFilter SpanNameFormatter SpanNameFormatter @@ -89,6 +90,14 @@ func WithPropagators(propagators propagation.TextMapPropagator) Option { }) } +// WithSpanStartOptions configures an additional set of +// trace.SpanStartOptions, which are applied to each new span. +func WithSpanStartOptions(opts ...oteltrace.SpanStartOption) Option { + return optionFunc(func(c *config) { + c.SpanStartOptions = append(c.SpanStartOptions, opts...) + }) +} + // WithTracerProvider specifies a tracer provider to use for creating a tracer. // If none is specified, the global provider is used. func WithTracerProvider(provider oteltrace.TracerProvider) Option { diff --git a/instrumentation/github.com/gin-gonic/gin/otelgin/gin.go b/instrumentation/github.com/gin-gonic/gin/otelgin/gin.go index 3243f7df1f0..a157d5d6c54 100644 --- a/instrumentation/github.com/gin-gonic/gin/otelgin/gin.go +++ b/instrumentation/github.com/gin-gonic/gin/otelgin/gin.go @@ -31,6 +31,7 @@ const ( // server handling the request. func Middleware(service string, opts ...Option) gin.HandlerFunc { cfg := config{} + for _, opt := range opts { opt.apply(&cfg) } @@ -95,6 +96,8 @@ func Middleware(service string, opts ...Option) gin.HandlerFunc { oteltrace.WithSpanKind(oteltrace.SpanKindServer), } + opts = append(opts, cfg.SpanStartOptions...) + spanName := cfg.SpanNameFormatter(c) if spanName == "" { spanName = fmt.Sprintf("HTTP %s route not found", c.Request.Method) diff --git a/instrumentation/github.com/gin-gonic/gin/otelgin/test/gin_test.go b/instrumentation/github.com/gin-gonic/gin/otelgin/test/gin_test.go index 58e9c9b97b6..2b55912bfb3 100644 --- a/instrumentation/github.com/gin-gonic/gin/otelgin/test/gin_test.go +++ b/instrumentation/github.com/gin-gonic/gin/otelgin/test/gin_test.go @@ -268,6 +268,31 @@ func TestSpanStatus(t *testing.T) { }) } +func TestWithSpanOptions_CustomAttributesAndSpanKind(t *testing.T) { + sr := tracetest.NewSpanRecorder() + provider := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + + customAttr := attribute.String("custom.key", "custom.value") + + router := gin.New() + router.Use(otelgin.Middleware("foobar", + otelgin.WithTracerProvider(provider), + otelgin.WithSpanStartOptions(trace.WithAttributes(customAttr)), + )) + router.GET("/test", func(c *gin.Context) {}) + + r := httptest.NewRequest("GET", "/test", nil) + w := httptest.NewRecorder() + router.ServeHTTP(w, r) + + spans := sr.Ended() + require.Len(t, spans, 1) + + span := spans[0] + assert.Contains(t, span.Attributes(), customAttr) + assert.Equal(t, trace.SpanKindServer, span.SpanKind()) +} + func TestSpanName(t *testing.T) { sr := tracetest.NewSpanRecorder() provider := sdktrace.NewTracerProvider( From d84cea4b710fbd8625a74a6c4c3a6c0663839f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 12 May 2025 13:06:24 +0200 Subject: [PATCH 2/2] Update CHANGELOG.md Co-authored-by: Damien Mathieu <42@dmathieu.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 947b7f893e6..8738754ba84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Allow configuring samplers in `go.opentelemetry.io/contrib/otelconf`. (#7148) - Slog log bridge now sets `SeverityText` attribute using source value in `go.opentelemetry.io/contrib/bridges/otelslog`. (#7198) - Add `http.route` metric attribute in `go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin`. (#7275) -- Add the `WithSpanStartOptions` option to add extra attributes, links, etc. to the spans it generates in `go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin`. (#7261) +- Add the `WithSpanStartOptions` option to add custom options to new spans `go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin`. (#7261) ### Changed