Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

otlptracehttp, otlpmetrichttp: Add WithProxy option #4906

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c8d11cd
add support for passing a custom proxy function to otlp metric export…
MickaelAlliel Feb 11, 2024
a337029
update otlp http exporter options template to include new proxy func …
MickaelAlliel Feb 11, 2024
a38fbad
update missing import in template for net http
MickaelAlliel Feb 11, 2024
9c8288e
Update otlp trace grpc http transport configuration to support custom…
MickaelAlliel Feb 11, 2024
147b4eb
add tests for new proxy configuration
MickaelAlliel Feb 11, 2024
f754cef
options tests for proxy configuration
MickaelAlliel Feb 11, 2024
fd4bf04
rename WithProxyFunc to WithProxy to adhere to naming convention of t…
MickaelAlliel Feb 11, 2024
8e8da1e
update changelog with PR id and expand description
MickaelAlliel Feb 12, 2024
da4a533
Merge remote-tracking branch 'origin/main' into feat/add-custom-proxy…
MickaelAlliel Feb 14, 2024
8b96a0c
add test and withproxy config to trace client
MickaelAlliel Feb 14, 2024
fced1c5
only clone transport if needed
MickaelAlliel Feb 15, 2024
8919bbf
lint
MickaelAlliel Feb 15, 2024
4d0f620
Merge branch 'main' into feat/add-custom-proxy-to-http-transport
MickaelAlliel Feb 19, 2024
f8b4909
Merge remote-tracking branch 'origin/main' into feat/add-custom-proxy…
MickaelAlliel Feb 25, 2024
b6d75e5
rewrite changes for WithProxy option
MickaelAlliel Feb 25, 2024
26e48c4
update documentation for default of WithProxy option
MickaelAlliel Feb 25, 2024
acf4fa1
add documentation to type
MickaelAlliel Feb 25, 2024
e5a82c6
generate options
MickaelAlliel Feb 25, 2024
3bc0bde
Merge branch 'feat/add-custom-proxy-to-http-transport' of github.com:…
MickaelAlliel Feb 25, 2024
1a0f67d
Merge branch 'main' into feat/add-custom-proxy-to-http-transport
MickaelAlliel Mar 4, 2024
40b99e3
Merge branch 'main' of ssh://github.com/open-telemetry/opentelemetry-…
MickaelAlliel Mar 6, 2024
274dd8c
add public type for HTTPTransportProxyFunc
MickaelAlliel Mar 6, 2024
4b8fd69
Merge branch 'feat/add-custom-proxy-to-http-transport' of github.com:…
MickaelAlliel Mar 6, 2024
a1320f5
add public type for HTTPTransportProxyFunc
MickaelAlliel Mar 6, 2024
00e596c
fix changelog due to bad merge, move WithProxy additions to Unrelease…
MickaelAlliel Mar 6, 2024
9e9459b
Merge branch 'main' into feat/add-custom-proxy-to-http-transport
MickaelAlliel Mar 11, 2024
21eda4b
fix changelog after main branch merge
MickaelAlliel Mar 11, 2024
246aade
Merge branch 'main' into feat/add-custom-proxy-to-http-transport
MickaelAlliel Mar 12, 2024
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Added

- Add `WithProxy` option in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#4906)
- Add `WithProxy` option in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlptracehttp`. (#4906)

### Changed

- `SpanFromContext` and `SpanContextFromContext` in `go.opentelemetry.io/otel/trace` no longer make a heap allocation when the passed context has no span. (#5049)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlp
import (
"crypto/tls"
"fmt"
"net/http"
"net/url"
"path"
"strings"
Expand Down Expand Up @@ -42,6 +43,10 @@ const (
)

type (
// HTTPTransportProxyFunc is a function that resolves which URL to use as proxy for a given request.
// This type is compatible with `http.Transport.Proxy` and can be used to set a custom proxy function to the OTLP HTTP client.
HTTPTransportProxyFunc func(*http.Request) (*url.URL, error)

SignalConfig struct {
Endpoint string
Insecure bool
Expand All @@ -56,6 +61,8 @@ type (

TemporalitySelector metric.TemporalitySelector
AggregationSelector metric.AggregationSelector

Proxy HTTPTransportProxyFunc
}

Config struct {
Expand Down Expand Up @@ -360,3 +367,10 @@ func WithAggregationSelector(selector metric.AggregationSelector) GenericOption
return cfg
})
}

func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Metrics.Proxy = pf
return cfg
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package oconf

import (
"errors"
"net/http"
"net/url"
"testing"
"time"

Expand Down Expand Up @@ -444,6 +446,29 @@ func TestConfigs(t *testing.T) {
assert.Equal(t, metric.AggregationDrop{}, got(undefinedKind))
},
},

// Proxy Tests
{
name: "Test With Proxy",
opts: []GenericOption{
WithProxy(func(r *http.Request) (*url.URL, error) {
return url.Parse("http://proxy.com")
}),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.NotNil(t, c.Metrics.Proxy)
proxyURL, err := c.Metrics.Proxy(&http.Request{})
assert.NoError(t, err)
assert.Equal(t, "http://proxy.com", proxyURL.String())
},
},
{
name: "Test Without Proxy",
opts: []GenericOption{},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Nil(t, c.Metrics.Proxy)
},
},
}

for _, tt := range tests {
Expand Down
15 changes: 11 additions & 4 deletions exporters/otlp/otlpmetric/otlpmetrichttp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,17 @@ func newClient(cfg oconf.Config) (*client, error) {
Transport: ourTransport,
Timeout: cfg.Metrics.Timeout,
}
if cfg.Metrics.TLSCfg != nil {
transport := ourTransport.Clone()
transport.TLSClientConfig = cfg.Metrics.TLSCfg
httpClient.Transport = transport

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
}
}

u := &url.URL{
Expand Down
19 changes: 19 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -227,4 +228,22 @@ func TestConfig(t *testing.T) {
require.Contains(t, got, key)
assert.Equal(t, got[key], []string{headers[key]})
})

t.Run("WithProxy", func(t *testing.T) {
headerKeySetInProxy := http.CanonicalHeaderKey("X-Using-Proxy")
headerValueSetInProxy := "true"
exp, coll := factoryFunc("", nil, WithProxy(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, got[headerKeySetInProxy], []string{headerValueSetInProxy})
})
}
14 changes: 14 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpme

import (
"crypto/tls"
"net/http"
"net/url"
"time"

"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/oconf"
Expand All @@ -16,6 +18,11 @@ import (
// collector.
type Compression oconf.Compression

// HTTPTransportProxyFunc is a function that resolves which URL to use as proxy for a given request.
// This type is compatible with http.Transport.Proxy and can be used to set a custom proxy function
// to the OTLP HTTP client.
type HTTPTransportProxyFunc func(*http.Request) (*url.URL, error)

const (
// NoCompression tells the driver to send payloads without
// compression.
Expand Down Expand Up @@ -206,3 +213,10 @@ func WithTemporalitySelector(selector metric.TemporalitySelector) Option {
func WithAggregationSelector(selector metric.AggregationSelector) Option {
return wrappedOption{oconf.WithAggregationSelector(selector)}
}

// WithProxy sets the Proxy function the client will use to determine the
// proxy to use for an HTTP request. If this option is not used, the client
// will use [http.ProxyFromEnvironment].
func WithProxy(pf HTTPTransportProxyFunc) Option {
return wrappedOption{oconf.WithProxy(oconf.HTTPTransportProxyFunc(pf))}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlp
import (
"crypto/tls"
"fmt"
"net/http"
"net/url"
"path"
"strings"
Expand Down Expand Up @@ -42,6 +43,10 @@ const (
)

type (
// HTTPTransportProxyFunc is a function that resolves which URL to use as proxy for a given request.
// This type is compatible with `http.Transport.Proxy` and can be used to set a custom proxy function to the OTLP HTTP client.
HTTPTransportProxyFunc func(*http.Request) (*url.URL, error)

SignalConfig struct {
Endpoint string
Insecure bool
Expand All @@ -56,6 +61,8 @@ type (

TemporalitySelector metric.TemporalitySelector
AggregationSelector metric.AggregationSelector

Proxy HTTPTransportProxyFunc
}

Config struct {
Expand Down Expand Up @@ -360,3 +367,10 @@ func WithAggregationSelector(selector metric.AggregationSelector) GenericOption
return cfg
})
}

func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Metrics.Proxy = pf
return cfg
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package oconf

import (
"errors"
"net/http"
"net/url"
"testing"
"time"

Expand Down Expand Up @@ -444,6 +446,29 @@ func TestConfigs(t *testing.T) {
assert.Equal(t, metric.AggregationDrop{}, got(undefinedKind))
},
},

// Proxy Tests
{
name: "Test With Proxy",
opts: []GenericOption{
WithProxy(func(r *http.Request) (*url.URL, error) {
return url.Parse("http://proxy.com")
}),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.NotNil(t, c.Metrics.Proxy)
proxyURL, err := c.Metrics.Proxy(&http.Request{})
assert.NoError(t, err)
assert.Equal(t, "http://proxy.com", proxyURL.String())
},
},
{
name: "Test Without Proxy",
opts: []GenericOption{},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Nil(t, c.Metrics.Proxy)
},
},
}

for _, tt := range tests {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/
import (
"crypto/tls"
"fmt"
"net/http"
"net/url"
"path"
"strings"
Expand All @@ -35,6 +36,10 @@ const (
)

type (
// HTTPTransportProxyFunc is a function that resolves which URL to use as proxy for a given request.
// This type is compatible with `http.Transport.Proxy` and can be used to set a custom proxy function to the OTLP HTTP client.
HTTPTransportProxyFunc func(*http.Request) (*url.URL, error)

SignalConfig struct {
Endpoint string
Insecure bool
Expand All @@ -46,6 +51,8 @@ type (

// gRPC configurations
GRPCCredentials credentials.TransportCredentials

Proxy HTTPTransportProxyFunc
}

Config struct {
Expand Down Expand Up @@ -332,3 +339,10 @@ func WithTimeout(duration time.Duration) GenericOption {
return cfg
})
}

func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Traces.Proxy = pf
return cfg
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package otlpconfig

import (
"errors"
"net/http"
"net/url"
"testing"
"time"

Expand Down Expand Up @@ -408,6 +410,29 @@ func TestConfigs(t *testing.T) {
assert.Equal(t, c.Traces.Timeout, 5*time.Second)
},
},

// Proxy Tests
{
name: "Test With Proxy",
opts: []GenericOption{
WithProxy(func(r *http.Request) (*url.URL, error) {
return url.Parse("http://proxy.com")
}),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.NotNil(t, c.Traces.Proxy)
proxyURL, err := c.Traces.Proxy(&http.Request{})
assert.NoError(t, err)
assert.Equal(t, "http://proxy.com", proxyURL.String())
},
},
{
name: "Test Without Proxy",
opts: []GenericOption{},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Nil(t, c.Traces.Proxy)
},
},
}

for _, tt := range tests {
Expand Down
15 changes: 11 additions & 4 deletions exporters/otlp/otlptrace/otlptracehttp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,17 @@ func NewClient(opts ...Option) otlptrace.Client {
Transport: ourTransport,
Timeout: cfg.Traces.Timeout,
}
if cfg.Traces.TLSCfg != nil {
transport := ourTransport.Clone()
transport.TLSClientConfig = cfg.Traces.TLSCfg
httpClient.Transport = transport

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

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

stopCh := make(chan struct{})
Expand Down
19 changes: 19 additions & 0 deletions exporters/otlp/otlptrace/otlptracehttp/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -36,6 +37,10 @@ var (
customUserAgentHeader = map[string]string{
"user-agent": "custome-user-agent",
}

customProxyHeader = map[string]string{
"header-added-via-proxy": "proxy-value",
}
)

func TestEndToEnd(t *testing.T) {
Expand Down Expand Up @@ -150,6 +155,20 @@ func TestEndToEnd(t *testing.T) {
ExpectedHeaders: customUserAgentHeader,
},
},
{
name: "with custom proxy",
opts: []otlptracehttp.Option{
otlptracehttp.WithProxy(func(r *http.Request) (*url.URL, error) {
for k, v := range customProxyHeader {
r.Header.Set(k, v)
}
return r.URL, nil
}),
},
mcCfg: mockCollectorConfig{
ExpectedHeaders: customProxyHeader,
},
},
}

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