Skip to content

Commit

Permalink
Add WithEndpointURL option to OTLP over HTTP exporters (open-telemetr…
Browse files Browse the repository at this point in the history
…y#4808)

Co-authored-by: Robert Pająk <pellared@hotmail.com>
  • Loading branch information
2 people authored and m-posluszny committed Jan 19, 2024
1 parent 2682b8c commit 39443e6
Show file tree
Hide file tree
Showing 25 changed files with 516 additions and 19 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Added

- Add `WithEndpointURL` option to the `exporters/otlp/otlpmetric/otlpmetricgrpc`, `exporters/otlp/otlpmetric/otlpmetrichttp`, `exporters/otlp/otlptrace/otlptracegrpc` and `exporters/otlp/otlptrace/otlptracehttp` packages. (#4808)

### Fixed

- Fixed missing Mix and Max values for `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` by introducing `MarshalText` and `MarshalJSON` for type `Extrema` in `go.opentelemetry.io/sdk/metric/metricdata`. (#4826)
Expand Down
14 changes: 14 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetricgrpc/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,20 @@ func TestConfig(t *testing.T) {
return exp, coll
}

t.Run("WithEndpointURL", func(t *testing.T) {
coll, err := otest.NewGRPCCollector("", nil)
require.NoError(t, err)
t.Cleanup(coll.Shutdown)

ctx := context.Background()
exp, err := New(ctx, WithEndpointURL("http://"+coll.Addr().String()))
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, exp.Shutdown(ctx)) })

assert.NoError(t, exp.Export(ctx, &metricdata.ResourceMetrics{}))
assert.Len(t, coll.Collect().Dump(), 1)
})

t.Run("WithHeaders", func(t *testing.T) {
key := "my-custom-header"
headers := map[string]string{key: "custom-value"}
Expand Down
23 changes: 23 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetricgrpc/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ func WithInsecure() Option {
// value will be used. If both are set, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
// will take precedence.
//
// If both this option and WithEndpointURL are used, the last used option will
// take precedence.
//
// By default, if an environment variable is not set, and this option is not
// passed, "localhost:4317" will be used.
//
Expand All @@ -88,6 +91,26 @@ func WithEndpoint(endpoint string) Option {
return wrappedOption{oconf.WithEndpoint(endpoint)}
}

// WithEndpointURL sets the target endpoint URL the Exporter will connect to.
//
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
// environment variable is set, and this option is not passed, that variable
// value will be used. If both are set, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
// will take precedence.
//
// If both this option and WithEndpoint are used, the last used option will
// take precedence.
//
// If an invalid URL is provided, the default value will be kept.
//
// By default, if an environment variable is not set, and this option is not
// passed, "localhost:4317" will be used.
//
// This option has no effect if WithGRPCConn is used.
func WithEndpointURL(u string) Option {
return wrappedOption{oconf.WithEndpointURL(u)}
}

// WithReconnectionPeriod set the minimum amount of time between connection
// attempts to the target endpoint.
//
Expand Down
2 changes: 1 addition & 1 deletion exporters/otlp/otlpmetric/otlpmetricgrpc/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The value may additionally a port, a scheme, and a path.
The value accepts "http" and "https" scheme.
The value should not contain a query string or fragment.
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT takes precedence over OTEL_EXPORTER_OTLP_ENDPOINT.
The configuration can be overridden by [WithEndpoint], [WithInsecure], [WithGRPCConn] options.
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithGRPCConn] options.
OTEL_EXPORTER_OTLP_INSECURE, OTEL_EXPORTER_OTLP_METRICS_INSECURE (default: "false") -
setting "true" disables client transport security for the exporter's gRPC connection.
Expand Down
20 changes: 20 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlp
import (
"crypto/tls"
"fmt"
"net/url"
"path"
"strings"
"time"
Expand All @@ -31,6 +32,7 @@ import (
"google.golang.org/grpc/encoding/gzip"

"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/retry"
"go.opentelemetry.io/otel/internal/global"
"go.opentelemetry.io/otel/sdk/metric"
)

Expand Down Expand Up @@ -279,6 +281,24 @@ func WithEndpoint(endpoint string) GenericOption {
})
}

func WithEndpointURL(v string) GenericOption {
return newGenericOption(func(cfg Config) Config {
u, err := url.Parse(v)
if err != nil {
global.Error(err, "otlpmetric: parse endpoint url", "url", v)
return cfg
}

cfg.Metrics.Endpoint = u.Host
cfg.Metrics.URLPath = u.Path
if u.Scheme != "https" {
cfg.Metrics.Insecure = true
}

return cfg
})
}

func WithCompression(compression Compression) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Metrics.Compression = compression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,42 @@ func TestConfigs(t *testing.T) {
assert.Equal(t, "someendpoint", c.Metrics.Endpoint)
},
},
{
name: "Test With Endpoint URL",
opts: []GenericOption{
WithEndpointURL("http://someendpoint/somepath"),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Equal(t, "someendpoint", c.Metrics.Endpoint)
assert.Equal(t, "/somepath", c.Metrics.URLPath)
assert.Equal(t, true, c.Metrics.Insecure)
},
},
{
name: "Test With Secure Endpoint URL",
opts: []GenericOption{
WithEndpointURL("https://someendpoint/somepath"),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Equal(t, "someendpoint", c.Metrics.Endpoint)
assert.Equal(t, "/somepath", c.Metrics.URLPath)
assert.Equal(t, false, c.Metrics.Insecure)
},
},
{
name: "Test With Invalid Endpoint URL",
opts: []GenericOption{
WithEndpointURL("%invalid"),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
if grpcOption {
assert.Equal(t, "localhost:4317", c.Metrics.Endpoint)
} else {
assert.Equal(t, "localhost:4318", c.Metrics.Endpoint)
}
assert.Equal(t, "/v1/metrics", c.Metrics.URLPath)
},
},
{
name: "Test Environment Endpoint",
env: map[string]string{
Expand Down
14 changes: 14 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ func TestConfig(t *testing.T) {
return exp, coll
}

t.Run("WithEndpointURL", func(t *testing.T) {
coll, err := otest.NewHTTPCollector("", nil)
require.NoError(t, err)
ctx := context.Background()

exp, err := New(ctx, WithEndpointURL("http://"+coll.Addr().String()))
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, coll.Shutdown(ctx)) })
t.Cleanup(func() { require.NoError(t, exp.Shutdown(ctx)) })

assert.NoError(t, exp.Export(ctx, &metricdata.ResourceMetrics{}))
assert.Len(t, coll.Collect().Dump(), 1)
})

t.Run("WithHeaders", func(t *testing.T) {
key := http.CanonicalHeaderKey("my-custom-header")
headers := map[string]string{key: "custom-value"}
Expand Down
20 changes: 20 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@ func WithEndpoint(endpoint string) Option {
return wrappedOption{oconf.WithEndpoint(endpoint)}
}

// WithEndpointURL sets the target endpoint URL the Exporter will connect to.
//
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
// environment variable is set, and this option is not passed, that variable
// value will be used. If both are set, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
// will take precedence.
//
// If both this option and WithEndpoint are used, the last used option will
// take precedence.
//
// If an invalid URL is provided, the default value will be kept.
//
// By default, if an environment variable is not set, and this option is not
// passed, "localhost:4317" will be used.
//
// This option has no effect if WithGRPCConn is used.
func WithEndpointURL(u string) Option {
return wrappedOption{oconf.WithEndpointURL(u)}
}

// WithCompression sets the compression strategy the Exporter will use to
// compress the HTTP body.
//
Expand Down
4 changes: 2 additions & 2 deletions exporters/otlp/otlpmetric/otlpmetrichttp/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ The value must contain a scheme ("http" or "https") and host.
The value may additionally contain a port and a path.
The value should not contain a query string or fragment.
The configuration can be overridden by OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
environment variable and by [WithEndpoint], [WithInsecure] options.
environment variable and by [WithEndpoint], [WithEndpointURL], and [WithInsecure] options.
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT (default: "https://localhost:4318/v1/metrics") -
target URL to which the exporter sends telemetry.
The value must contain a scheme ("http" or "https") and host.
The value may additionally contain a port and a path.
The value should not contain a query string or fragment.
The configuration can be overridden by [WithEndpoint], [WitnInsecure], [WithURLPath] options.
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WitnInsecure], and [WithURLPath] options.
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_METRICS_HEADERS (default: none) -
key-value pairs used as headers associated with HTTP requests.
Expand Down
20 changes: 20 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/internal/oconf/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlp
import (
"crypto/tls"
"fmt"
"net/url"
"path"
"strings"
"time"
Expand All @@ -31,6 +32,7 @@ import (
"google.golang.org/grpc/encoding/gzip"

"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/retry"
"go.opentelemetry.io/otel/internal/global"
"go.opentelemetry.io/otel/sdk/metric"
)

Expand Down Expand Up @@ -279,6 +281,24 @@ func WithEndpoint(endpoint string) GenericOption {
})
}

func WithEndpointURL(v string) GenericOption {
return newGenericOption(func(cfg Config) Config {
u, err := url.Parse(v)
if err != nil {
global.Error(err, "otlpmetric: parse endpoint url", "url", v)
return cfg
}

cfg.Metrics.Endpoint = u.Host
cfg.Metrics.URLPath = u.Path
if u.Scheme != "https" {
cfg.Metrics.Insecure = true
}

return cfg
})
}

func WithCompression(compression Compression) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Metrics.Compression = compression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,42 @@ func TestConfigs(t *testing.T) {
assert.Equal(t, "someendpoint", c.Metrics.Endpoint)
},
},
{
name: "Test With Endpoint URL",
opts: []GenericOption{
WithEndpointURL("http://someendpoint/somepath"),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Equal(t, "someendpoint", c.Metrics.Endpoint)
assert.Equal(t, "/somepath", c.Metrics.URLPath)
assert.Equal(t, true, c.Metrics.Insecure)
},
},
{
name: "Test With Secure Endpoint URL",
opts: []GenericOption{
WithEndpointURL("https://someendpoint/somepath"),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
assert.Equal(t, "someendpoint", c.Metrics.Endpoint)
assert.Equal(t, "/somepath", c.Metrics.URLPath)
assert.Equal(t, false, c.Metrics.Insecure)
},
},
{
name: "Test With Invalid Endpoint URL",
opts: []GenericOption{
WithEndpointURL("%invalid"),
},
asserts: func(t *testing.T, c *Config, grpcOption bool) {
if grpcOption {
assert.Equal(t, "localhost:4317", c.Metrics.Endpoint)
} else {
assert.Equal(t, "localhost:4318", c.Metrics.Endpoint)
}
assert.Equal(t, "/v1/metrics", c.Metrics.URLPath)
},
},
{
name: "Test Environment Endpoint",
env: map[string]string{
Expand Down
18 changes: 18 additions & 0 deletions exporters/otlp/otlptrace/otlptracegrpc/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,24 @@ func TestNewEndToEnd(t *testing.T) {
}
}

func TestWithEndpointURL(t *testing.T) {
mc := runMockCollector(t)

ctx := context.Background()
exp := newGRPCExporter(t, ctx, "", []otlptracegrpc.Option{
otlptracegrpc.WithEndpointURL("http://" + mc.endpoint),
}...)
t.Cleanup(func() {
ctx, cancel := contextWithTimeout(ctx, t, 10*time.Second)
defer cancel()

require.NoError(t, exp.Shutdown(ctx))
})

// RunEndToEndTest closes mc.
otlptracetest.RunEndToEndTest(ctx, t, exp, mc)
}

func newGRPCExporter(t *testing.T, ctx context.Context, endpoint string, additionalOpts ...otlptracegrpc.Option) *otlptrace.Exporter {
opts := []otlptracegrpc.Option{
otlptracegrpc.WithInsecure(),
Expand Down
2 changes: 1 addition & 1 deletion exporters/otlp/otlptrace/otlptracegrpc/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The value may additionally a port, a scheme, and a path.
The value accepts "http" and "https" scheme.
The value should not contain a query string or fragment.
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT takes precedence over OTEL_EXPORTER_OTLP_ENDPOINT.
The configuration can be overridden by [WithEndpoint], [WithInsecure], [WithGRPCConn] options.
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithGRPCConn] options.
OTEL_EXPORTER_OTLP_INSECURE, OTEL_EXPORTER_OTLP_TRACES_INSECURE (default: "false") -
setting "true" disables client transport security for the exporter's gRPC connection.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/
import (
"crypto/tls"
"fmt"
"net/url"
"path"
"strings"
"time"
Expand All @@ -32,6 +33,7 @@ import (

"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry"
"go.opentelemetry.io/otel/internal/global"
)

const (
Expand Down Expand Up @@ -265,6 +267,24 @@ func WithEndpoint(endpoint string) GenericOption {
})
}

func WithEndpointURL(v string) GenericOption {
return newGenericOption(func(cfg Config) Config {
u, err := url.Parse(v)
if err != nil {
global.Error(err, "otlptrace: parse endpoint url", "url", v)
return cfg
}

cfg.Traces.Endpoint = u.Host
cfg.Traces.URLPath = u.Path
if u.Scheme != "https" {
cfg.Traces.Insecure = true
}

return cfg
})
}

func WithCompression(compression Compression) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Traces.Compression = compression
Expand Down

0 comments on commit 39443e6

Please sign in to comment.