Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
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)
- Add `Recording`, `Scope`, and `Record` types in `go.opentelemetry.io/otel/log/logtest`. (#6507)
- Add `WithHTTPClient` option to configure the `http.Client` used by `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#6688)
- Add `WithHTTPClient` option to configure the `http.Client` used by `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#6752)

### Removed

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 15 additions & 12 deletions exporters/otlp/otlpmetric/otlpmetrichttp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,23 @@ var ourTransport = &http.Transport{

// newClient creates a new HTTP metric client.
func newClient(cfg oconf.Config) (*client, error) {
httpClient := &http.Client{
Transport: ourTransport,
Timeout: cfg.Metrics.Timeout,
}
httpClient := cfg.Metrics.HTTPClient
if httpClient == nil {
httpClient = &http.Client{
Transport: ourTransport,
Timeout: cfg.Metrics.Timeout,
}

if cfg.Metrics.TLSCfg != nil || cfg.Metrics.Proxy != nil {
clonedTransport := ourTransport.Clone()
httpClient.Transport = clonedTransport
if cfg.Metrics.TLSCfg != nil || cfg.Metrics.Proxy != nil {
clonedTransport := ourTransport.Clone()
httpClient.Transport = clonedTransport

if cfg.Metrics.TLSCfg != nil {
clonedTransport.TLSClientConfig = cfg.Metrics.TLSCfg
}
if cfg.Metrics.Proxy != nil {
clonedTransport.Proxy = cfg.Metrics.Proxy
if cfg.Metrics.TLSCfg != nil {
clonedTransport.TLSClientConfig = cfg.Metrics.TLSCfg
}
if cfg.Metrics.Proxy != nil {
clonedTransport.Proxy = cfg.Metrics.Proxy
}
}
}

Expand Down
22 changes: 22 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,28 @@ func TestConfig(t *testing.T) {
})

t.Run("WithProxy", func(t *testing.T) {
headerKeySetInProxy := http.CanonicalHeaderKey("X-Using-Proxy")
headerValueSetInProxy := "true"
exp, coll := factoryFunc("", nil, WithHTTPClient(&http.Client{
Transport: &http.Transport{
Proxy: func(r *http.Request) (*url.URL, error) {
r.Header.Set(headerKeySetInProxy, headerValueSetInProxy)
return r.URL, nil
},
},
}))
ctx := context.Background()
t.Cleanup(func() { require.NoError(t, coll.Shutdown(ctx)) })
require.NoError(t, exp.Export(ctx, &metricdata.ResourceMetrics{}))
// Ensure everything is flushed.
require.NoError(t, exp.Shutdown(ctx))

got := coll.Headers()
require.Contains(t, got, headerKeySetInProxy)
assert.Equal(t, []string{headerValueSetInProxy}, got[headerKeySetInProxy])
})

t.Run("WithHTTPClient", func(t *testing.T) {
headerKeySetInProxy := http.CanonicalHeaderKey("X-Using-Proxy")
headerValueSetInProxy := "true"
exp, coll := factoryFunc("", nil, WithProxy(func(r *http.Request) (*url.URL, error) {
Expand Down
16 changes: 16 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,19 @@ func WithAggregationSelector(selector metric.AggregationSelector) Option {
func WithProxy(pf HTTPTransportProxyFunc) Option {
return wrappedOption{oconf.WithProxy(oconf.HTTPTransportProxyFunc(pf))}
}

// WithHTTPClient sets the HTTP client to used by the exporter.
//
// This option will take precedence over [WithProxy], [WithTimeout],
// [WithTLSClientConfig] options as well as OTEL_EXPORTER_OTLP_CERTIFICATE,
// OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE, OTEL_EXPORTER_OTLP_TIMEOUT,
// OTEL_EXPORTER_OTLP_METRICS_TIMEOUT environment variables.
//
// Timeout and all other fields of the passed [http.Client] are left intact.
//
// Be aware that passing an HTTP client with transport like
// [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp.NewTransport] can
// cause the client to be instrumented twice and cause infinite recursion.
func WithHTTPClient(c *http.Client) Option {
return wrappedOption{oconf.WithHTTPClient(c)}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 13 additions & 4 deletions internal/shared/otlp/otlpmetric/oconf/options.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ type (
Timeout time.Duration
URLPath string

// gRPC configurations
GRPCCredentials credentials.TransportCredentials

TemporalitySelector metric.TemporalitySelector
AggregationSelector metric.AggregationSelector

Proxy HTTPTransportProxyFunc
// gRPC configurations
GRPCCredentials credentials.TransportCredentials

// HTTP configurations
Proxy HTTPTransportProxyFunc
HTTPClient *http.Client
}

Config struct {
Expand Down Expand Up @@ -373,3 +375,10 @@ func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
return cfg
})
}

func WithHTTPClient(c *http.Client) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Metrics.HTTPClient = c
return cfg
})
}
18 changes: 18 additions & 0 deletions internal/shared/otlp/otlpmetric/oconf/options_test.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,24 @@ func TestConfigs(t *testing.T) {
assert.Nil(t, c.Metrics.Proxy)
},
},

// HTTP Client Tests
{
name: "Test With HTTP Client",
opts: []GenericOption{
WithHTTPClient(http.DefaultClient),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Equal(t, http.DefaultClient, c.Metrics.HTTPClient)
},
},
{
name: "Test Without HTTP Client",
opts: []GenericOption{},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Nil(t, c.Metrics.HTTPClient)
},
},
}

for _, tt := range tests {
Expand Down
Loading