Skip to content

Commit

Permalink
feat: Add *gin.Context Filter parameter (#5743)
Browse files Browse the repository at this point in the history
Issue:
#3070
last PR status:
#4444

---------

Signed-off-by: Rehan Pasha <[email protected]>
Signed-off-by: Brian Warner <[email protected]>
Signed-off-by: rehanpfmr <[email protected]>
Co-authored-by: Damien Mathieu <[email protected]>
  • Loading branch information
rehanpfmr and dmathieu authored Aug 19, 2024
1 parent a32ef13 commit 35d271f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Support for the `OTEL_HTTP_CLIENT_COMPATIBILITY_MODE=http/dup` environment variable in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` to emit attributes for both the v1.20.0 and v1.26.0 semantic conventions. (#5401)
- The `go.opentelemetry.io/contrib/bridges/otelzerolog` module.
This module provides an OpenTelemetry logging bridge for `github.com/rs/zerolog`. (#5405)
- Add `WithGinFilter` filter parameter in `go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin` to allow filtering requests with `*gin.Context`. (#5743)

### Removed

Expand Down
8 changes: 8 additions & 0 deletions instrumentation/github.com/gin-gonic/gin/otelgin/gintrace.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ func Middleware(service string, opts ...Option) gin.HandlerFunc {
return
}
}
for _, f := range cfg.GinFilters {
if !f(c) {
// Serve the request to the next middleware
// if a filter rejects the request.
c.Next()
return
}
}
c.Set(tracerKey, tracer)
savedCtx := c.Request.Context()
defer func() {
Expand Down
16 changes: 15 additions & 1 deletion instrumentation/github.com/gin-gonic/gin/otelgin/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package otelgin // import "go.opentelemetry.io/contrib/instrumentation/github.co
import (
"net/http"

"github.com/gin-gonic/gin"

"go.opentelemetry.io/otel/propagation"
oteltrace "go.opentelemetry.io/otel/trace"
)
Expand All @@ -16,13 +18,18 @@ type config struct {
TracerProvider oteltrace.TracerProvider
Propagators propagation.TextMapPropagator
Filters []Filter
GinFilters []GinFilter
SpanNameFormatter SpanNameFormatter
}

// Filter is a predicate used to determine whether a given http.request should
// be traced. A Filter must return true if the request should be traced.
type Filter func(*http.Request) bool

// Adding new Filter parameter (*gin.Context)
// gin.Context has FullPath() method, which returns a matched route full path.
type GinFilter func(*gin.Context) bool

// SpanNameFormatter is used to set span name by http.request.
type SpanNameFormatter func(r *http.Request) string

Expand Down Expand Up @@ -60,7 +67,7 @@ func WithTracerProvider(provider oteltrace.TracerProvider) Option {

// WithFilter adds a filter to the list of filters used by the handler.
// If any filter indicates to exclude a request then the request will not be
// traced. All filters must allow a request to be traced for a Span to be created.
// traced. All gin and net/http filters must allow a request to be traced for a Span to be created.
// If no filters are provided then all requests are traced.
// Filters will be invoked for each processed request, it is advised to make them
// simple and fast.
Expand All @@ -70,6 +77,13 @@ func WithFilter(f ...Filter) Option {
})
}

// WithGinFilter adds a gin filter to the list of filters used by the handler.
func WithGinFilter(f ...GinFilter) Option {
return optionFunc(func(c *config) {
c.GinFilters = append(c.GinFilters, f...)
})
}

// WithSpanNameFormatter takes a function that will be called on every
// request and the returned string will become the Span Name.
func WithSpanNameFormatter(f func(r *http.Request) string) Option {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,37 @@ func TestWithFilter(t *testing.T) {
assert.Len(t, sr.Ended(), 1)
})
}

func TestWithGinFilter(t *testing.T) {
t.Run("custom filter filtering route", func(t *testing.T) {
sr := tracetest.NewSpanRecorder()
otel.SetTracerProvider(sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)))

router := gin.New()
f := func(c *gin.Context) bool { return c.Request.URL.Path != "/healthcheck" }
router.Use(otelgin.Middleware("foobar", otelgin.WithGinFilter(f)))
router.GET("/healthcheck", func(c *gin.Context) {})

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

router.ServeHTTP(w, r)
assert.Len(t, sr.Ended(), 0)
})

t.Run("custom filter not filtering route", func(t *testing.T) {
sr := tracetest.NewSpanRecorder()
otel.SetTracerProvider(sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)))

router := gin.New()
f := func(c *gin.Context) bool { return c.Request.URL.Path != "/user/:id" }
router.Use(otelgin.Middleware("foobar", otelgin.WithGinFilter(f)))
router.GET("/user/:id", func(c *gin.Context) {})

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

router.ServeHTTP(w, r)
assert.Len(t, sr.Ended(), 1)
})
}

0 comments on commit 35d271f

Please sign in to comment.