diff --git a/otelfiber/README.md b/otelfiber/README.md index 2867ee09..5d3a215b 100644 --- a/otelfiber/README.md +++ b/otelfiber/README.md @@ -31,17 +31,20 @@ otelfiber.Middleware(opts ...otelfiber.Option) fiber.Handler ``` ## Config +You can configure the middleware using functional parameters -| Property | Type | Description | Default | + +| Function | Argument Type | Description | Default | | :------------------ | :-------------------------------- | :--------------------------------------------------------------------------------- | :-------------------------------------------------------------------- | -| Next | `func(*fiber.Ctx) bool` | Define a function to skip this middleware when returned trueRequired - Rego quer | nil | -| TracerProvider | `oteltrace.TracerProvider` | Specifies a tracer provider to use for creating a tracer | nil - the global tracer provider is used | -| MeterProvider | `otelmetric.MeterProvider` | Specifies a meter provider to use for reporting | nil - the global meter provider is used | -| Port | `*int` | Specifies the value to use when setting the `net.host.port` attribute on metrics/spans | Required: If not default (`80` for `http`, `443` for `https`) | -| Propagators | `propagation.TextMapPropagator` | Specifies propagators to use for extracting information from the HTTP requests | If none are specified, global ones will be used | -| ServerName | `*string` | specifies the value to use when setting the `http.server_name` attribute on metrics/spans | - | -| SpanNameFormatter | `func(*fiber.Ctx) string` | Takes a function that will be called on every request and the returned string will become the Span Name | default formatter returns the route pathRaw | -| CustomAttributes | `func(*fiber.Ctx) []attribute.KeyValue` | Define a function to add custom attributes to the span | nil | +| `WithNext` | `func(*fiber.Ctx) bool` | Define a function to skip this middleware when returned true .| nil | +| `WithTracerProvider` | `oteltrace.TracerProvider` | Specifies a tracer provider to use for creating a tracer. | nil - the global tracer provider is used | +| `WithMeterProvider` | `otelmetric.MeterProvider` | Specifies a meter provider to use for reporting. | nil - the global meter provider is used | +| `WithPort` | `int` | Specifies the value to use when setting the `net.host.port` attribute on metrics/spans. | Defaults to (`80` for `http`, `443` for `https`) | +| `WithPropagators` | `propagation.TextMapPropagator` | Specifies propagators to use for extracting information from the HTTP requests. | If none are specified, global ones will be used | +| `WithServerName` | `string` | Specifies the value to use when setting the `http.server_name` attribute on metrics/spans. | - | +| `WithSpanNameFormatter` | `func(*fiber.Ctx) string` | Takes a function that will be called on every request and the returned string will become the span Name. | Default formatter returns the route pathRaw | +| `WithCustomAttributes` | `func(*fiber.Ctx) []attribute.KeyValue` | Define a function to add custom attributes to the span. | nil | +| `WithCollectClientIP` | `bool` | Specifies whether to collect the client's IP address from the request. | true | ## Usage diff --git a/otelfiber/config.go b/otelfiber/config.go index 70373128..bc8aec92 100644 --- a/otelfiber/config.go +++ b/otelfiber/config.go @@ -18,6 +18,7 @@ type config struct { ServerName *string SpanNameFormatter func(*fiber.Ctx) string CustomAttributes func(*fiber.Ctx) []attribute.KeyValue + collectClientIP bool } // Option specifies instrumentation configuration options. @@ -96,3 +97,11 @@ func WithCustomAttributes(f func(ctx *fiber.Ctx) []attribute.KeyValue) Option { cfg.CustomAttributes = f }) } + +// WithCollectClientIP specifies whether to collect the client's IP address +// from the request. This is enabled by default. +func WithCollectClientIP(collect bool) Option { + return optionFunc(func(cfg *config) { + cfg.collectClientIP = collect + }) +} diff --git a/otelfiber/fiber.go b/otelfiber/fiber.go index a5dfd521..9ec13cd2 100644 --- a/otelfiber/fiber.go +++ b/otelfiber/fiber.go @@ -33,7 +33,9 @@ const ( // Middleware returns fiber handler which will trace incoming requests. func Middleware(opts ...Option) fiber.Handler { - cfg := config{} + cfg := config{ + collectClientIP: true, + } for _, opt := range opts { opt.apply(&cfg) } diff --git a/otelfiber/otelfiber_test/fiber_test.go b/otelfiber/otelfiber_test/fiber_test.go index 130802b4..e3499a1c 100644 --- a/otelfiber/otelfiber_test/fiber_test.go +++ b/otelfiber/otelfiber_test/fiber_test.go @@ -496,3 +496,41 @@ func TestOutboundTracingPropagationWithInboundContext(t *testing.T) { assert.Equal(t, traceId, resp.Header.Get("X-B3-TraceId")) assert.Equal(t, "1", resp.Header.Get("X-B3-Sampled")) } + +func TestCollectClientIP(t *testing.T) { + t.Parallel() + + for _, enabled := range []bool{true, false} { + enabled := enabled + t.Run(fmt.Sprintf("enabled=%t", enabled), func(t *testing.T) { + t.Parallel() + + sr := tracetest.NewSpanRecorder() + provider := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + otel.SetTracerProvider(provider) + + app := fiber.New() + app.Use(otelfiber.Middleware( + otelfiber.WithTracerProvider(provider), + otelfiber.WithCollectClientIP(enabled), + )) + app.Get("/foo", func(ctx *fiber.Ctx) error { + return ctx.SendStatus(http.StatusNoContent) + }) + + req := httptest.NewRequest("GET", "/foo", nil) + _, _ = app.Test(req) + + spans := sr.Ended() + require.Len(t, spans, 1) + + span := spans[0] + attrs := span.Attributes() + if enabled { + assert.Contains(t, attrs, attribute.String("http.client_ip", "0.0.0.0")) + } else { + assert.NotContains(t, attrs, attribute.String("http.client_ip", "0.0.0.0")) + } + }) + } +} diff --git a/otelfiber/semconv.go b/otelfiber/semconv.go index c560aa07..c5ed04bb 100644 --- a/otelfiber/semconv.go +++ b/otelfiber/semconv.go @@ -56,9 +56,11 @@ func httpServerTraceAttributesFromRequest(c *fiber.Ctx, cfg config) []attribute. if username, ok := HasBasicAuth(c.Get(fiber.HeaderAuthorization)); ok { attrs = append(attrs, semconv.EnduserIDKey.String(utils.CopyString(username))) } - clientIP := c.IP() - if len(clientIP) > 0 { - attrs = append(attrs, semconv.HTTPClientIPKey.String(utils.CopyString(clientIP))) + if cfg.collectClientIP { + clientIP := c.IP() + if len(clientIP) > 0 { + attrs = append(attrs, semconv.HTTPClientIPKey.String(utils.CopyString(clientIP))) + } } if cfg.CustomAttributes != nil {