Upgrade to OpenTelemetry Semantic Conventions v1.26.0
This commit is contained in:
parent
2f9905061e
commit
8cb1829698
21 changed files with 558 additions and 217 deletions
|
@ -201,6 +201,7 @@ type Tracing struct {
|
|||
GlobalAttributes map[string]string `description:"Defines additional attributes (key:value) on all spans." json:"globalAttributes,omitempty" toml:"globalAttributes,omitempty" yaml:"globalAttributes,omitempty" export:"true"`
|
||||
CapturedRequestHeaders []string `description:"Request headers to add as attributes for server and client spans." json:"capturedRequestHeaders,omitempty" toml:"capturedRequestHeaders,omitempty" yaml:"capturedRequestHeaders,omitempty" export:"true"`
|
||||
CapturedResponseHeaders []string `description:"Response headers to add as attributes for server and client spans." json:"capturedResponseHeaders,omitempty" toml:"capturedResponseHeaders,omitempty" yaml:"capturedResponseHeaders,omitempty" export:"true"`
|
||||
SafeQueryParams []string `description:"Query params to not redact." json:"safeQueryParams,omitempty" toml:"safeQueryParams,omitempty" yaml:"safeQueryParams,omitempty" export:"true"`
|
||||
SampleRate float64 `description:"Sets the rate between 0.0 and 1.0 of requests to trace." json:"sampleRate,omitempty" toml:"sampleRate,omitempty" yaml:"sampleRate,omitempty" export:"true"`
|
||||
AddInternals bool `description:"Enables tracing for internal services (ping, dashboard, etc...)." json:"addInternals,omitempty" toml:"addInternals,omitempty" yaml:"addInternals,omitempty" export:"true"`
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
"go.opentelemetry.io/otel/metric"
|
||||
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/encoding/gzip"
|
||||
)
|
||||
|
@ -58,16 +58,16 @@ func NewSemConvMetricRegistry(ctx context.Context, config *types.OTLP) (*SemConv
|
|||
meter := otel.Meter("github.com/traefik/traefik",
|
||||
metric.WithInstrumentationVersion(version.Version))
|
||||
|
||||
httpServerRequestDuration, err := meter.Float64Histogram("http.server.request.duration",
|
||||
metric.WithDescription("Duration of HTTP server requests."),
|
||||
httpServerRequestDuration, err := meter.Float64Histogram(semconv.HTTPServerRequestDurationName,
|
||||
metric.WithDescription(semconv.HTTPServerRequestDurationDescription),
|
||||
metric.WithUnit("s"),
|
||||
metric.WithExplicitBucketBoundaries(config.ExplicitBoundaries...))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't build httpServerRequestDuration histogram: %w", err)
|
||||
}
|
||||
|
||||
httpClientRequestDuration, err := meter.Float64Histogram("http.client.request.duration",
|
||||
metric.WithDescription("Duration of HTTP client requests."),
|
||||
httpClientRequestDuration, err := meter.Float64Histogram(semconv.HTTPClientRequestDurationName,
|
||||
metric.WithDescription(semconv.HTTPClientRequestDurationDescription),
|
||||
metric.WithUnit("s"),
|
||||
metric.WithExplicitBucketBoundaries(config.ExplicitBoundaries...))
|
||||
if err != nil {
|
||||
|
|
|
@ -513,7 +513,7 @@ func TestForwardAuthTracing(t *testing.T) {
|
|||
attribute.String("url.scheme", "http"),
|
||||
attribute.String("user_agent.original", ""),
|
||||
attribute.String("network.peer.address", "127.0.0.1"),
|
||||
attribute.String("network.peer.port", serverPort),
|
||||
attribute.Int64("network.peer.port", int64(serverPortInt)),
|
||||
attribute.String("server.address", "127.0.0.1"),
|
||||
attribute.Int64("server.port", int64(serverPortInt)),
|
||||
attribute.StringSlice("http.request.header.x-foo", []string{"foo", "bar"}),
|
||||
|
@ -546,7 +546,7 @@ func TestForwardAuthTracing(t *testing.T) {
|
|||
otel.SetTextMapPropagator(autoprop.NewTextMapPropagator())
|
||||
|
||||
mockTracer := &mockTracer{}
|
||||
tracer := tracing.NewTracer(mockTracer, []string{"X-Foo"}, []string{"X-Bar"})
|
||||
tracer := tracing.NewTracer(mockTracer, []string{"X-Foo"}, []string{"X-Bar"}, []string{"q"})
|
||||
initialCtx, initialSpan := tracer.Start(req.Context(), "initial")
|
||||
defer initialSpan.End()
|
||||
req = req.WithContext(initialCtx)
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/traefik/traefik/v3/pkg/tracing"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.opentelemetry.io/otel/trace/noop"
|
||||
)
|
||||
|
@ -35,7 +35,7 @@ type entryPointTracing struct {
|
|||
func WrapEntryPointHandler(ctx context.Context, tracer *tracing.Tracer, semConvMetricRegistry *metrics.SemConvMetricsRegistry, entryPointName string) alice.Constructor {
|
||||
return func(next http.Handler) (http.Handler, error) {
|
||||
if tracer == nil {
|
||||
tracer = tracing.NewTracer(noop.Tracer{}, nil, nil)
|
||||
tracer = tracing.NewTracer(noop.Tracer{}, nil, nil, nil)
|
||||
}
|
||||
|
||||
return newEntryPoint(ctx, tracer, semConvMetricRegistry, entryPointName, next), nil
|
||||
|
@ -47,7 +47,7 @@ func newEntryPoint(ctx context.Context, tracer *tracing.Tracer, semConvMetricReg
|
|||
middlewares.GetLogger(ctx, "tracing", entryPointTypeName).Debug().Msg("Creating middleware")
|
||||
|
||||
if tracer == nil {
|
||||
tracer = tracing.NewTracer(noop.Tracer{}, nil, nil)
|
||||
tracer = tracing.NewTracer(noop.Tracer{}, nil, nil, nil)
|
||||
}
|
||||
|
||||
return &entryPointTracing{
|
||||
|
|
|
@ -42,15 +42,14 @@ func TestEntryPointMiddleware_tracing(t *testing.T) {
|
|||
attribute.String("network.protocol.version", "1.1"),
|
||||
attribute.Int64("http.request.body.size", int64(0)),
|
||||
attribute.String("url.path", "/search"),
|
||||
attribute.String("url.query", "q=Opentelemetry"),
|
||||
attribute.String("url.query", "q=Opentelemetry&token=REDACTED"),
|
||||
attribute.String("url.scheme", "http"),
|
||||
attribute.String("user_agent.original", "entrypoint-test"),
|
||||
attribute.String("server.address", "www.test.com"),
|
||||
attribute.String("network.peer.address", "10.0.0.1"),
|
||||
attribute.String("network.peer.port", "1234"),
|
||||
attribute.String("client.address", "10.0.0.1"),
|
||||
attribute.Int64("client.port", int64(1234)),
|
||||
attribute.String("client.socket.address", ""),
|
||||
attribute.Int64("network.peer.port", int64(1234)),
|
||||
attribute.StringSlice("http.request.header.x-foo", []string{"foo", "bar"}),
|
||||
attribute.Int64("http.response.status_code", int64(404)),
|
||||
attribute.StringSlice("http.response.header.x-bar", []string{"foo", "bar"}),
|
||||
|
@ -61,7 +60,7 @@ func TestEntryPointMiddleware_tracing(t *testing.T) {
|
|||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodGet, "http://www.test.com/search?q=Opentelemetry", nil)
|
||||
req := httptest.NewRequest(http.MethodGet, "http://www.test.com/search?q=Opentelemetry&token=123", nil)
|
||||
rw := httptest.NewRecorder()
|
||||
req.RemoteAddr = "10.0.0.1:1234"
|
||||
req.Header.Set("User-Agent", "entrypoint-test")
|
||||
|
@ -77,7 +76,7 @@ func TestEntryPointMiddleware_tracing(t *testing.T) {
|
|||
|
||||
tracer := &mockTracer{}
|
||||
|
||||
handler := newEntryPoint(context.Background(), tracing.NewTracer(tracer, []string{"X-Foo"}, []string{"X-Bar"}), nil, test.entryPoint, next)
|
||||
handler := newEntryPoint(context.Background(), tracing.NewTracer(tracer, []string{"X-Foo"}, []string{"X-Bar"}, []string{"q"}), nil, test.entryPoint, next)
|
||||
handler.ServeHTTP(rw, req)
|
||||
|
||||
for _, span := range tracer.spans {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/traefik/traefik/v3/pkg/middlewares"
|
||||
"github.com/traefik/traefik/v3/pkg/tracing"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
"github.com/traefik/traefik/v3/pkg/middlewares"
|
||||
"github.com/traefik/traefik/v3/pkg/tracing"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
|
@ -95,7 +95,7 @@ func (r *retry) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||
currentSpan.SetAttributes(attribute.String("traefik.middleware.name", r.name))
|
||||
// Only add the attribute "http.resend_count" defined by semantic conventions starting from second attempt.
|
||||
if attempts > 1 {
|
||||
currentSpan.SetAttributes(semconv.HTTPResendCount(attempts - 1))
|
||||
currentSpan.SetAttributes(semconv.HTTPRequestResendCount(attempts - 1))
|
||||
}
|
||||
|
||||
req = req.WithContext(tracingCtx)
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/traefik/traefik/v3/pkg/tracing"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/encoding/gzip"
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -17,7 +19,7 @@ import (
|
|||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
|
@ -47,7 +49,7 @@ func NewTracing(conf *static.Tracing) (*Tracer, io.Closer, error) {
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
return NewTracer(tr, conf.CapturedRequestHeaders, conf.CapturedResponseHeaders), closer, nil
|
||||
return NewTracer(tr, conf.CapturedRequestHeaders, conf.CapturedResponseHeaders, conf.SafeQueryParams), closer, nil
|
||||
}
|
||||
|
||||
// TracerFromContext extracts the trace.Tracer from the given context.
|
||||
|
@ -122,14 +124,16 @@ func (t TracerProvider) Tracer(name string, options ...trace.TracerOption) trace
|
|||
type Tracer struct {
|
||||
trace.Tracer
|
||||
|
||||
safeQueryParams []string
|
||||
capturedRequestHeaders []string
|
||||
capturedResponseHeaders []string
|
||||
}
|
||||
|
||||
// NewTracer builds and configures a new Tracer.
|
||||
func NewTracer(tracer trace.Tracer, capturedRequestHeaders, capturedResponseHeaders []string) *Tracer {
|
||||
func NewTracer(tracer trace.Tracer, capturedRequestHeaders, capturedResponseHeaders, safeQueryParams []string) *Tracer {
|
||||
return &Tracer{
|
||||
Tracer: tracer,
|
||||
safeQueryParams: safeQueryParams,
|
||||
capturedRequestHeaders: capturedRequestHeaders,
|
||||
capturedResponseHeaders: capturedResponseHeaders,
|
||||
}
|
||||
|
@ -153,37 +157,37 @@ func (t *Tracer) Start(ctx context.Context, spanName string, opts ...trace.SpanS
|
|||
}
|
||||
|
||||
// CaptureClientRequest used to add span attributes from the request as a Client.
|
||||
// TODO: need to update the semconv package as it does not implement fully Semantic Convention v1.23.0.
|
||||
func (t *Tracer) CaptureClientRequest(span trace.Span, r *http.Request) {
|
||||
if t == nil || span == nil || r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Common attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#common-attributes
|
||||
// Common attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.26.0/docs/http/http-spans.md#common-attributes
|
||||
span.SetAttributes(semconv.HTTPRequestMethodKey.String(r.Method))
|
||||
span.SetAttributes(semconv.NetworkProtocolVersion(proto(r.Proto)))
|
||||
|
||||
// Client attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#http-client
|
||||
span.SetAttributes(semconv.URLFull(r.URL.String()))
|
||||
span.SetAttributes(semconv.URLScheme(r.URL.Scheme))
|
||||
// Client attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.26.0/docs/http/http-spans.md#http-client
|
||||
sURL := t.safeURL(r.URL)
|
||||
span.SetAttributes(semconv.URLFull(sURL.String()))
|
||||
span.SetAttributes(semconv.URLScheme(sURL.Scheme))
|
||||
span.SetAttributes(semconv.UserAgentOriginal(r.UserAgent()))
|
||||
|
||||
host, port, err := net.SplitHostPort(r.URL.Host)
|
||||
host, port, err := net.SplitHostPort(sURL.Host)
|
||||
if err != nil {
|
||||
span.SetAttributes(attribute.String("network.peer.address", host))
|
||||
span.SetAttributes(semconv.ServerAddress(r.URL.Host))
|
||||
switch r.URL.Scheme {
|
||||
span.SetAttributes(semconv.NetworkPeerAddress(host))
|
||||
span.SetAttributes(semconv.ServerAddress(sURL.Host))
|
||||
switch sURL.Scheme {
|
||||
case "http":
|
||||
span.SetAttributes(attribute.String("network.peer.port", "80"))
|
||||
span.SetAttributes(semconv.NetworkPeerPort(80))
|
||||
span.SetAttributes(semconv.ServerPort(80))
|
||||
case "https":
|
||||
span.SetAttributes(attribute.String("network.peer.port", "443"))
|
||||
span.SetAttributes(semconv.NetworkPeerPort(443))
|
||||
span.SetAttributes(semconv.ServerPort(443))
|
||||
}
|
||||
} else {
|
||||
span.SetAttributes(attribute.String("network.peer.address", host))
|
||||
span.SetAttributes(attribute.String("network.peer.port", port))
|
||||
span.SetAttributes(semconv.NetworkPeerAddress(host))
|
||||
intPort, _ := strconv.Atoi(port)
|
||||
span.SetAttributes(semconv.NetworkPeerPort(intPort))
|
||||
span.SetAttributes(semconv.ServerAddress(host))
|
||||
span.SetAttributes(semconv.ServerPort(intPort))
|
||||
}
|
||||
|
@ -201,20 +205,20 @@ func (t *Tracer) CaptureClientRequest(span trace.Span, r *http.Request) {
|
|||
}
|
||||
|
||||
// CaptureServerRequest used to add span attributes from the request as a Server.
|
||||
// TODO: need to update the semconv package as it does not implement fully Semantic Convention v1.23.0.
|
||||
func (t *Tracer) CaptureServerRequest(span trace.Span, r *http.Request) {
|
||||
if t == nil || span == nil || r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Common attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#common-attributes
|
||||
// Common attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.26.0/docs/http/http-spans.md#common-attributes
|
||||
span.SetAttributes(semconv.HTTPRequestMethodKey.String(r.Method))
|
||||
span.SetAttributes(semconv.NetworkProtocolVersion(proto(r.Proto)))
|
||||
|
||||
// Server attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#http-server-semantic-conventions
|
||||
sURL := t.safeURL(r.URL)
|
||||
// Server attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.26.0/docs/http/http-spans.md#http-server-semantic-conventions
|
||||
span.SetAttributes(semconv.HTTPRequestBodySize(int(r.ContentLength)))
|
||||
span.SetAttributes(semconv.URLPath(r.URL.Path))
|
||||
span.SetAttributes(semconv.URLQuery(r.URL.RawQuery))
|
||||
span.SetAttributes(semconv.URLPath(sURL.Path))
|
||||
span.SetAttributes(semconv.URLQuery(sURL.RawQuery))
|
||||
span.SetAttributes(semconv.URLScheme(r.Header.Get("X-Forwarded-Proto")))
|
||||
span.SetAttributes(semconv.UserAgentOriginal(r.UserAgent()))
|
||||
span.SetAttributes(semconv.ServerAddress(r.Host))
|
||||
|
@ -222,17 +226,15 @@ func (t *Tracer) CaptureServerRequest(span trace.Span, r *http.Request) {
|
|||
host, port, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
span.SetAttributes(semconv.ClientAddress(r.RemoteAddr))
|
||||
span.SetAttributes(attribute.String("network.peer.address", r.RemoteAddr))
|
||||
span.SetAttributes(semconv.NetworkPeerAddress(r.Host))
|
||||
} else {
|
||||
span.SetAttributes(attribute.String("network.peer.address", host))
|
||||
span.SetAttributes(attribute.String("network.peer.port", port))
|
||||
span.SetAttributes(semconv.NetworkPeerAddress(host))
|
||||
span.SetAttributes(semconv.ClientAddress(host))
|
||||
intPort, _ := strconv.Atoi(port)
|
||||
span.SetAttributes(semconv.ClientPort(intPort))
|
||||
span.SetAttributes(semconv.NetworkPeerPort(intPort))
|
||||
}
|
||||
|
||||
span.SetAttributes(semconv.ClientSocketAddress(r.Header.Get("X-Forwarded-For")))
|
||||
|
||||
for _, header := range t.capturedRequestHeaders {
|
||||
// User-agent is already part of the semantic convention as a recommended attribute.
|
||||
if strings.EqualFold(header, "User-Agent") {
|
||||
|
@ -273,6 +275,32 @@ func (t *Tracer) CaptureResponse(span trace.Span, responseHeaders http.Header, c
|
|||
}
|
||||
}
|
||||
|
||||
func (t *Tracer) safeURL(originalURL *url.URL) *url.URL {
|
||||
if originalURL == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
redactedURL := *originalURL
|
||||
|
||||
// Redact password if exists.
|
||||
if redactedURL.User != nil {
|
||||
redactedURL.User = url.UserPassword("REDACTED", "REDACTED")
|
||||
}
|
||||
|
||||
// Redact query parameters.
|
||||
query := redactedURL.Query()
|
||||
for k := range query {
|
||||
if slices.Contains(t.safeQueryParams, k) {
|
||||
continue
|
||||
}
|
||||
|
||||
query.Set(k, "REDACTED")
|
||||
}
|
||||
redactedURL.RawQuery = query.Encode()
|
||||
|
||||
return &redactedURL
|
||||
}
|
||||
|
||||
func proto(proto string) string {
|
||||
switch proto {
|
||||
case "HTTP/1.0":
|
||||
|
|
57
pkg/tracing/tracing_test.go
Normal file
57
pkg/tracing/tracing_test.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package tracing
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_safeFullURL(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
safeQueryParams []string
|
||||
originalURL *url.URL
|
||||
expectedURL *url.URL
|
||||
}{
|
||||
{
|
||||
desc: "Nil URL",
|
||||
originalURL: nil,
|
||||
expectedURL: nil,
|
||||
},
|
||||
{
|
||||
desc: "No query parameters",
|
||||
originalURL: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
expectedURL: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
},
|
||||
{
|
||||
desc: "All query parameters redacted",
|
||||
originalURL: &url.URL{Scheme: "https", Host: "example.com", RawQuery: "foo=bar&baz=qux"},
|
||||
expectedURL: &url.URL{Scheme: "https", Host: "example.com", RawQuery: "baz=REDACTED&foo=REDACTED"},
|
||||
},
|
||||
{
|
||||
desc: "Some query parameters unredacted",
|
||||
safeQueryParams: []string{"foo"},
|
||||
originalURL: &url.URL{Scheme: "https", Host: "example.com", RawQuery: "foo=bar&baz=qux"},
|
||||
expectedURL: &url.URL{Scheme: "https", Host: "example.com", RawQuery: "baz=REDACTED&foo=bar"},
|
||||
},
|
||||
{
|
||||
desc: "User info and some query parameters redacted",
|
||||
safeQueryParams: []string{"foo"},
|
||||
originalURL: &url.URL{Scheme: "https", Host: "example.com", User: url.UserPassword("username", "password"), RawQuery: "foo=bar&baz=qux"},
|
||||
expectedURL: &url.URL{Scheme: "https", Host: "example.com", User: url.UserPassword("REDACTED", "REDACTED"), RawQuery: "baz=REDACTED&foo=bar"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tr := NewTracer(nil, nil, nil, test.safeQueryParams)
|
||||
|
||||
gotURL := tr.safeURL(test.originalURL)
|
||||
|
||||
assert.Equal(t, test.expectedURL, gotURL)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue