mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2024-12-26 21:05:00 +02:00
Support OTEL_EXPORTER_OTLP_LOGS_INSECURE and OTEL_EXPORTER_OTLP_INSECURE environments in grpc exporter (#5739)
Closes https://github.com/open-telemetry/opentelemetry-go/issues/5719 In this commit I add OTEL_EXPORTER_OTLP_LOGS_INSECURE and OTEL_EXPORTER_OTLP_INSECURE env options to `otlploggrpc.Exporter`. Now insecure option is fetched from env endpoint value (OTEL_EXPORTER_OTLP_LOGS_ENDPOINT/OTEL_EXPORTER_OTLP_ENDPOINT). According to [spec](https://opentelemetry.io/docs/specs/otel/protocol/exporter/): > Insecure: Whether to enable client transport security for the exporter’s gRPC connection. This option only applies to OTLP/gRPC when an endpoint is provided without the http or https scheme - OTLP/HTTP always uses the scheme provided for the endpoint. So with current behavior we have several problems: - If default endpoint is used, we can't use insecure connection (with setting OTEL_EXPORTER_OTLP_INSECURE). - If endpoint provided with option without scheme (e.g. `WithEndpoint`) we can't use insecure connection with env settings. - If endpoint provided with env variable without scheme (e.g. `//env.endpoint:8080/`) we can't use insecure connection. This commit fixes this. The same problem with `otlploghttp.Exporter`, and probably it should be fixed there too. I'm open to suggestions on how to fix the current behavior in a more elegant way. --------- Co-authored-by: Sam Xie <sam@samxie.me> Co-authored-by: Damien Mathieu <42@dmathieu.com>
This commit is contained in:
parent
fb7cc020f2
commit
8dca9cc0fa
@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Support `OTEL_EXPORTER_OTLP_LOGS_INSECURE` and `OTEL_EXPORTER_OTLP_INSECURE` environments in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`. (#5739)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix memory leak in the global `MeterProvider` when identical instruments are repeatedly created. (#5754)
|
||||
|
@ -35,7 +35,10 @@ var (
|
||||
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT",
|
||||
"OTEL_EXPORTER_OTLP_ENDPOINT",
|
||||
}
|
||||
envInsecure = envEndpoint
|
||||
envInsecure = []string{
|
||||
"OTEL_EXPORTER_OTLP_LOGS_INSECURE",
|
||||
"OTEL_EXPORTER_OTLP_INSECURE",
|
||||
}
|
||||
|
||||
envHeaders = []string{
|
||||
"OTEL_EXPORTER_OTLP_LOGS_HEADERS",
|
||||
@ -109,6 +112,7 @@ func newConfig(options []Option) config {
|
||||
fallback[string](defaultEndpoint),
|
||||
)
|
||||
c.insecure = c.insecure.Resolve(
|
||||
loadInsecureFromEnvEndpoint(envEndpoint),
|
||||
getEnv[bool](envInsecure, convInsecure),
|
||||
)
|
||||
c.tlsCfg = c.tlsCfg.Resolve(
|
||||
@ -204,11 +208,7 @@ func WithEndpointURL(rawURL string) Option {
|
||||
}
|
||||
return fnOpt(func(c config) config {
|
||||
c.endpoint = newSetting(u.Host)
|
||||
if u.Scheme != "https" {
|
||||
c.insecure = newSetting(true)
|
||||
} else {
|
||||
c.insecure = newSetting(false)
|
||||
}
|
||||
c.insecure = insecureFromScheme(c.insecure, u.Scheme)
|
||||
return c
|
||||
})
|
||||
}
|
||||
@ -394,15 +394,39 @@ func convEndpoint(s string) (string, error) {
|
||||
return u.Host, nil
|
||||
}
|
||||
|
||||
// convInsecure parses s as a URL string and returns if the connection should
|
||||
// use client transport security or not. If s is an invalid URL, false and an
|
||||
// error are returned.
|
||||
// convInsecure converts s from string to bool without case sensitivity.
|
||||
// If s is not valid returns error.
|
||||
func convInsecure(s string) (bool, error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return false, err
|
||||
s = strings.ToLower(s)
|
||||
if s != "true" && s != "false" {
|
||||
return false, fmt.Errorf("can't convert %q to bool", s)
|
||||
}
|
||||
|
||||
return s == "true", nil
|
||||
}
|
||||
|
||||
// loadInsecureFromEnvEndpoint returns a resolver that fetches
|
||||
// insecure setting from envEndpoint is it possible.
|
||||
func loadInsecureFromEnvEndpoint(envEndpoint []string) resolver[bool] {
|
||||
return func(s setting[bool]) setting[bool] {
|
||||
if s.Set {
|
||||
// Passed, valid, options have precedence.
|
||||
return s
|
||||
}
|
||||
|
||||
for _, key := range envEndpoint {
|
||||
if vStr := os.Getenv(key); vStr != "" {
|
||||
u, err := url.Parse(vStr)
|
||||
if err != nil {
|
||||
otel.Handle(fmt.Errorf("invalid %s value %s: %w", key, vStr, err))
|
||||
continue
|
||||
}
|
||||
|
||||
return insecureFromScheme(s, u.Scheme)
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
return u.Scheme != "https", nil
|
||||
}
|
||||
|
||||
// convHeaders converts the OTel environment variable header value s into a
|
||||
@ -529,6 +553,19 @@ func loadCertificates(certPath, keyPath string) ([]tls.Certificate, error) {
|
||||
return []tls.Certificate{crt}, nil
|
||||
}
|
||||
|
||||
// insecureFromScheme return setting if the connection should
|
||||
// use client transport security or not.
|
||||
// Empty scheme doesn't force insecure setting.
|
||||
func insecureFromScheme(prev setting[bool], scheme string) setting[bool] {
|
||||
if scheme == "https" {
|
||||
return newSetting(false)
|
||||
} else if len(scheme) > 0 {
|
||||
return newSetting(true)
|
||||
}
|
||||
|
||||
return prev
|
||||
}
|
||||
|
||||
func compressorToCompression(compressor string) Compression {
|
||||
c, err := convCompression(compressor)
|
||||
if err != nil {
|
||||
|
@ -333,6 +333,83 @@ func TestNewConfig(t *testing.T) {
|
||||
`invalid OTEL_EXPORTER_OTLP_LOGS_TIMEOUT value 100 seconds: strconv.Atoi: parsing "100 seconds": invalid syntax`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OptionEndpointURLWithoutScheme",
|
||||
options: []Option{
|
||||
WithEndpointURL("//env.endpoint:8080/prefix"),
|
||||
},
|
||||
want: config{
|
||||
endpoint: newSetting("env.endpoint:8080"),
|
||||
retryCfg: newSetting(defaultRetryCfg),
|
||||
timeout: newSetting(defaultTimeout),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "EnvEndpointWithoutScheme",
|
||||
envars: map[string]string{
|
||||
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "//env.endpoint:8080/prefix",
|
||||
},
|
||||
want: config{
|
||||
endpoint: newSetting("env.endpoint:8080"),
|
||||
retryCfg: newSetting(defaultRetryCfg),
|
||||
timeout: newSetting(defaultTimeout),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DefaultEndpointWithEnvInsecure",
|
||||
envars: map[string]string{
|
||||
"OTEL_EXPORTER_OTLP_LOGS_INSECURE": "true",
|
||||
},
|
||||
want: config{
|
||||
endpoint: newSetting(defaultEndpoint),
|
||||
insecure: newSetting(true),
|
||||
retryCfg: newSetting(defaultRetryCfg),
|
||||
timeout: newSetting(defaultTimeout),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "EnvEndpointWithoutSchemeWithEnvInsecure",
|
||||
envars: map[string]string{
|
||||
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "//env.endpoint:8080/prefix",
|
||||
"OTEL_EXPORTER_OTLP_LOGS_INSECURE": "true",
|
||||
},
|
||||
want: config{
|
||||
endpoint: newSetting("env.endpoint:8080"),
|
||||
insecure: newSetting(true),
|
||||
retryCfg: newSetting(defaultRetryCfg),
|
||||
timeout: newSetting(defaultTimeout),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OptionEndpointURLWithoutSchemeWithEnvInsecure",
|
||||
options: []Option{
|
||||
WithEndpointURL("//env.endpoint:8080/prefix"),
|
||||
},
|
||||
envars: map[string]string{
|
||||
"OTEL_EXPORTER_OTLP_LOGS_INSECURE": "true",
|
||||
},
|
||||
want: config{
|
||||
endpoint: newSetting("env.endpoint:8080"),
|
||||
insecure: newSetting(true),
|
||||
retryCfg: newSetting(defaultRetryCfg),
|
||||
timeout: newSetting(defaultTimeout),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OptionEndpointWithEnvInsecure",
|
||||
options: []Option{
|
||||
WithEndpoint("env.endpoint:8080"),
|
||||
},
|
||||
envars: map[string]string{
|
||||
"OTEL_EXPORTER_OTLP_LOGS_INSECURE": "true",
|
||||
},
|
||||
want: config{
|
||||
endpoint: newSetting("env.endpoint:8080"),
|
||||
insecure: newSetting(true),
|
||||
retryCfg: newSetting(defaultRetryCfg),
|
||||
timeout: newSetting(defaultTimeout),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
|
@ -18,6 +18,12 @@ The value should not contain a query string or fragment.
|
||||
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT takes precedence over OTEL_EXPORTER_OTLP_ENDPOINT.
|
||||
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithGRPCConn] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_INSECURE, OTEL_EXPORTER_OTLP_LOGS_INSECURE (default: "false") -
|
||||
setting "true" disables client transport security for the exporter's gRPC connection.
|
||||
You can use this only when an endpoint is provided without scheme.
|
||||
OTEL_EXPORTER_OTLP_LOGS_INSECURE takes precedence over OTEL_EXPORTER_OTLP_INSECURE.
|
||||
The configuration can be overridden by [WithInsecure], [WithGRPCConn] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_LOGS_HEADERS (default: none) -
|
||||
key-value pairs used as gRPC metadata associated with gRPC requests.
|
||||
The value is expected to be represented in a format matching the [W3C Baggage HTTP Header Content Format],
|
||||
|
Loading…
Reference in New Issue
Block a user