Skip to content

Commit cf8179a

Browse files
authored
otlploghttp: Add WithHTTPClient option (#6688)
Towards (for OTLP logs exporter): - #4536 - #5129 - #2632 Per https://github.com/open-telemetry/opentelemetry-go/pull/6362/files#r1978191352 Providing `WithHTTPClient` option allows easy interoperability e.g. with https://pkg.go.dev/golang.org/x/oauth2/clientcredentials#Config.Client and also see #2632. The options is also similar to: https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc#WithGRPCConn I favor this over #6686 The option for OTLP span and metrics exporters will be added in separate PRs.
1 parent 4895ae6 commit cf8179a

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1515
The package contains semantic conventions from the `v1.31.0` version of the OpenTelemetry Semantic Conventions.
1616
See the [migration documentation](./semconv/v1.31.0/MIGRATION.md) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/v1.30.0`(#6479)
1717
- Add `Recording`, `Scope`, and `Record` types in `go.opentelemetry.io/otel/log/logtest`. (#6507)
18+
- Add `WithHTTPClient` option to configure the `http.Client` used by `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#6688)
1819

1920
### Removed
2021

exporters/otlp/otlplog/otlploghttp/client.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,23 @@ func newNoopClient() *client {
4444

4545
// newHTTPClient creates a new HTTP log client.
4646
func newHTTPClient(cfg config) (*client, error) {
47-
hc := &http.Client{
48-
Transport: ourTransport,
49-
Timeout: cfg.timeout.Value,
50-
}
47+
hc := cfg.httpClient
48+
if hc == nil {
49+
hc = &http.Client{
50+
Transport: ourTransport,
51+
Timeout: cfg.timeout.Value,
52+
}
5153

52-
if cfg.tlsCfg.Value != nil || cfg.proxy.Value != nil {
53-
clonedTransport := ourTransport.Clone()
54-
hc.Transport = clonedTransport
54+
if cfg.tlsCfg.Value != nil || cfg.proxy.Value != nil {
55+
clonedTransport := ourTransport.Clone()
56+
hc.Transport = clonedTransport
5557

56-
if cfg.tlsCfg.Value != nil {
57-
clonedTransport.TLSClientConfig = cfg.tlsCfg.Value
58-
}
59-
if cfg.proxy.Value != nil {
60-
clonedTransport.Proxy = cfg.proxy.Value
58+
if cfg.tlsCfg.Value != nil {
59+
clonedTransport.TLSClientConfig = cfg.tlsCfg.Value
60+
}
61+
if cfg.proxy.Value != nil {
62+
clonedTransport.Proxy = cfg.proxy.Value
63+
}
6164
}
6265
}
6366

exporters/otlp/otlplog/otlploghttp/client_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,28 @@ func TestConfig(t *testing.T) {
783783
assert.Equal(t, []string{headerValueSetInProxy}, got[headerKeySetInProxy])
784784
})
785785

786+
t.Run("WithHTTPClient", func(t *testing.T) {
787+
headerKeySetInProxy := http.CanonicalHeaderKey("X-Using-Proxy")
788+
headerValueSetInProxy := "true"
789+
exp, coll := factoryFunc("", nil, WithHTTPClient(&http.Client{
790+
Transport: &http.Transport{
791+
Proxy: func(r *http.Request) (*url.URL, error) {
792+
r.Header.Set(headerKeySetInProxy, headerValueSetInProxy)
793+
return r.URL, nil
794+
},
795+
},
796+
}))
797+
ctx := context.Background()
798+
t.Cleanup(func() { require.NoError(t, coll.Shutdown(ctx)) })
799+
require.NoError(t, exp.Export(ctx, make([]log.Record, 1)))
800+
// Ensure everything is flushed.
801+
require.NoError(t, exp.Shutdown(ctx))
802+
803+
got := coll.Headers()
804+
require.Contains(t, got, headerKeySetInProxy)
805+
assert.Equal(t, []string{headerValueSetInProxy}, got[headerKeySetInProxy])
806+
})
807+
786808
t.Run("non-retryable errors are propagated", func(t *testing.T) {
787809
exporterErr := errors.New("missing required attribute aaaa")
788810
rCh := make(chan exportResult, 1)

exporters/otlp/otlplog/otlploghttp/config.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ type config struct {
9595
timeout setting[time.Duration]
9696
proxy setting[HTTPTransportProxyFunc]
9797
retryCfg setting[retry.Config]
98+
httpClient *http.Client
9899
}
99100

100101
func newConfig(options []Option) config {
@@ -344,6 +345,25 @@ func WithProxy(pf HTTPTransportProxyFunc) Option {
344345
})
345346
}
346347

348+
// WithHTTPClient sets the HTTP client to used by the exporter.
349+
//
350+
// This option will take precedence over [WithProxy], [WithTimeout],
351+
// [WithTLSClientConfig] options as well as OTEL_EXPORTER_OTLP_CERTIFICATE,
352+
// OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE, OTEL_EXPORTER_OTLP_TIMEOUT,
353+
// OTEL_EXPORTER_OTLP_LOGS_TIMEOUT environment variables.
354+
//
355+
// Timeout and all other fields of the passed [http.Client] are left intact.
356+
//
357+
// Be aware that passing an HTTP client with transport like
358+
// [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp.NewTransport] can
359+
// cause the client to be instrumented twice and cause infinite recursion.
360+
func WithHTTPClient(c *http.Client) Option {
361+
return fnOpt(func(cfg config) config {
362+
cfg.httpClient = c
363+
return cfg
364+
})
365+
}
366+
347367
// setting is a configuration setting value.
348368
type setting[T any] struct {
349369
Value T

0 commit comments

Comments
 (0)