diff --git a/CHANGELOG.md b/CHANGELOG.md index 2591358863c..a24bb930a7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ The next release will require at least [Go 1.22]. It replaces the existing `Enabled` method that is removed from the `Processor` interface itself. It does not fall within the scope of the OpenTelemetry Go versioning and stability [policy](./VERSIONING.md) and it may be changed in backwards incompatible ways or removed in feature releases. (#5692) - Support [Go 1.23]. (#5720) +- Option to configure `http.Client` in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5752) ### Changed @@ -1681,15 +1682,15 @@ with major version 0. - Adds `otlpgrpc.WithRetry`option for configuring the retry policy for transient errors on the otlp/gRPC exporter. (#1832) - The following status codes are defined as transient errors: - | gRPC Status Code | Description | - | ---------------- | ----------- | - | 1 | Cancelled | - | 4 | Deadline Exceeded | - | 8 | Resource Exhausted | - | 10 | Aborted | - | 10 | Out of Range | - | 14 | Unavailable | - | 15 | Data Loss | + | gRPC Status Code | Description | + | ---------------- | ------------------ | + | 1 | Cancelled | + | 4 | Deadline Exceeded | + | 8 | Resource Exhausted | + | 10 | Aborted | + | 10 | Out of Range | + | 14 | Unavailable | + | 15 | Data Loss | - Added `Status` type to the `go.opentelemetry.io/otel/sdk/trace` package to represent the status of a span. (#1874) - Added `SpanStub` type and its associated functions to the `go.opentelemetry.io/otel/sdk/trace/tracetest` package. This type can be used as a testing replacement for the `SpanSnapshot` that was removed from the `go.opentelemetry.io/otel/sdk/trace` package. (#1873) diff --git a/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go b/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go index 8f84a799632..c528437b97c 100644 --- a/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go +++ b/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go @@ -52,7 +52,8 @@ type ( // gRPC configurations GRPCCredentials credentials.TransportCredentials - Proxy HTTPTransportProxyFunc + Proxy HTTPTransportProxyFunc + Client *http.Client } Config struct { @@ -351,3 +352,10 @@ func WithProxy(pf HTTPTransportProxyFunc) GenericOption { return cfg }) } + +func WithHTTPClient(c *http.Client) GenericOption { + return newGenericOption(func(cfg Config) Config { + cfg.Traces.Client = c + return cfg + }) +} diff --git a/exporters/otlp/otlptrace/otlptracehttp/client.go b/exporters/otlp/otlptrace/otlptracehttp/client.go index bb2f3ffd1d8..dc9f09e04e1 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/client.go +++ b/exporters/otlp/otlptrace/otlptracehttp/client.go @@ -76,7 +76,9 @@ func NewClient(opts ...Option) otlptrace.Client { Timeout: cfg.Traces.Timeout, } - if cfg.Traces.TLSCfg != nil || cfg.Traces.Proxy != nil { + if cfg.Traces.Client != nil { + httpClient = cfg.Traces.Client + } else if cfg.Traces.TLSCfg != nil || cfg.Traces.Proxy != nil { clonedTransport := ourTransport.Clone() httpClient.Transport = clonedTransport diff --git a/exporters/otlp/otlptrace/otlptracehttp/client_test.go b/exporters/otlp/otlptrace/otlptracehttp/client_test.go index 876d7584d49..8ab0547022b 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/client_test.go +++ b/exporters/otlp/otlptrace/otlptracehttp/client_test.go @@ -43,6 +43,18 @@ var ( } ) +type rtWrapper struct { + base http.RoundTripper +} + +func (rt rtWrapper) RoundTrip(req *http.Request) (*http.Response, error) { + for k, v := range customProxyHeader { + req.Header.Set(k, v) + } + + return rt.base.RoundTrip(req) +} + func TestEndToEnd(t *testing.T) { tests := []struct { name string @@ -169,6 +181,17 @@ func TestEndToEnd(t *testing.T) { ExpectedHeaders: customProxyHeader, }, }, + { + name: "with custom http client", + opts: []otlptracehttp.Option{ + otlptracehttp.WithHTTPClient(&http.Client{ + Transport: &rtWrapper{base: http.DefaultTransport}, + }), + }, + mcCfg: mockCollectorConfig{ + ExpectedHeaders: customProxyHeader, + }, + }, } for _, tc := range tests { diff --git a/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go b/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go index 2ebbc752f4b..458fb8170e3 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go +++ b/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go @@ -52,7 +52,8 @@ type ( // gRPC configurations GRPCCredentials credentials.TransportCredentials - Proxy HTTPTransportProxyFunc + Proxy HTTPTransportProxyFunc + Client *http.Client } Config struct { @@ -351,3 +352,10 @@ func WithProxy(pf HTTPTransportProxyFunc) GenericOption { return cfg }) } + +func WithHTTPClient(c *http.Client) GenericOption { + return newGenericOption(func(cfg Config) Config { + cfg.Traces.Client = c + return cfg + }) +} diff --git a/exporters/otlp/otlptrace/otlptracehttp/options.go b/exporters/otlp/otlptrace/otlptracehttp/options.go index 3559c5664f4..332b04efe3f 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/options.go +++ b/exporters/otlp/otlptrace/otlptracehttp/options.go @@ -153,3 +153,11 @@ func WithRetry(rc RetryConfig) Option { func WithProxy(pf HTTPTransportProxyFunc) Option { return wrappedOption{otlpconfig.WithProxy(otlpconfig.HTTPTransportProxyFunc(pf))} } + +// WithHTTPClient sets the HTTP client the exporter will use to send +// traces to the collector. If this option is not used, the exporter will +// create a new HTTP client. If the client is configured, WithProxy and WithTLSClientConfig +// will have no effect. +func WithHTTPClient(client *http.Client) Option { + return wrappedOption{otlpconfig.WithHTTPClient(client)} +} diff --git a/internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl b/internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl index a867b707e89..66da2afb906 100644 --- a/internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl +++ b/internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl @@ -53,6 +53,7 @@ type ( GRPCCredentials credentials.TransportCredentials Proxy HTTPTransportProxyFunc + Client *http.Client } Config struct { @@ -351,3 +352,10 @@ func WithProxy(pf HTTPTransportProxyFunc) GenericOption { return cfg }) } + +func WithHTTPClient(c *http.Client) GenericOption { + return newGenericOption(func(cfg Config) Config { + cfg.Traces.Client = c + return cfg + }) +} \ No newline at end of file