Skip to content

Commit 8dca9cc

Browse files
amanakinXSAMdmathieu
authored
Support OTEL_EXPORTER_OTLP_LOGS_INSECURE and OTEL_EXPORTER_OTLP_INSECURE environments in grpc exporter (#5739)
Closes #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 <[email protected]> Co-authored-by: Damien Mathieu <[email protected]>
1 parent fb7cc02 commit 8dca9cc

File tree

4 files changed

+137
-13
lines changed

4 files changed

+137
-13
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
88

99
## [Unreleased]
1010

11+
### Added
12+
13+
- Support `OTEL_EXPORTER_OTLP_LOGS_INSECURE` and `OTEL_EXPORTER_OTLP_INSECURE` environments in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`. (#5739)
14+
1115
### Fixed
1216

1317
- Fix memory leak in the global `MeterProvider` when identical instruments are repeatedly created. (#5754)

exporters/otlp/otlplog/otlploggrpc/config.go

+50-13
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ var (
3535
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT",
3636
"OTEL_EXPORTER_OTLP_ENDPOINT",
3737
}
38-
envInsecure = envEndpoint
38+
envInsecure = []string{
39+
"OTEL_EXPORTER_OTLP_LOGS_INSECURE",
40+
"OTEL_EXPORTER_OTLP_INSECURE",
41+
}
3942

4043
envHeaders = []string{
4144
"OTEL_EXPORTER_OTLP_LOGS_HEADERS",
@@ -109,6 +112,7 @@ func newConfig(options []Option) config {
109112
fallback[string](defaultEndpoint),
110113
)
111114
c.insecure = c.insecure.Resolve(
115+
loadInsecureFromEnvEndpoint(envEndpoint),
112116
getEnv[bool](envInsecure, convInsecure),
113117
)
114118
c.tlsCfg = c.tlsCfg.Resolve(
@@ -204,11 +208,7 @@ func WithEndpointURL(rawURL string) Option {
204208
}
205209
return fnOpt(func(c config) config {
206210
c.endpoint = newSetting(u.Host)
207-
if u.Scheme != "https" {
208-
c.insecure = newSetting(true)
209-
} else {
210-
c.insecure = newSetting(false)
211-
}
211+
c.insecure = insecureFromScheme(c.insecure, u.Scheme)
212212
return c
213213
})
214214
}
@@ -394,15 +394,39 @@ func convEndpoint(s string) (string, error) {
394394
return u.Host, nil
395395
}
396396

397-
// convInsecure parses s as a URL string and returns if the connection should
398-
// use client transport security or not. If s is an invalid URL, false and an
399-
// error are returned.
397+
// convInsecure converts s from string to bool without case sensitivity.
398+
// If s is not valid returns error.
400399
func convInsecure(s string) (bool, error) {
401-
u, err := url.Parse(s)
402-
if err != nil {
403-
return false, err
400+
s = strings.ToLower(s)
401+
if s != "true" && s != "false" {
402+
return false, fmt.Errorf("can't convert %q to bool", s)
403+
}
404+
405+
return s == "true", nil
406+
}
407+
408+
// loadInsecureFromEnvEndpoint returns a resolver that fetches
409+
// insecure setting from envEndpoint is it possible.
410+
func loadInsecureFromEnvEndpoint(envEndpoint []string) resolver[bool] {
411+
return func(s setting[bool]) setting[bool] {
412+
if s.Set {
413+
// Passed, valid, options have precedence.
414+
return s
415+
}
416+
417+
for _, key := range envEndpoint {
418+
if vStr := os.Getenv(key); vStr != "" {
419+
u, err := url.Parse(vStr)
420+
if err != nil {
421+
otel.Handle(fmt.Errorf("invalid %s value %s: %w", key, vStr, err))
422+
continue
423+
}
424+
425+
return insecureFromScheme(s, u.Scheme)
426+
}
427+
}
428+
return s
404429
}
405-
return u.Scheme != "https", nil
406430
}
407431

408432
// convHeaders converts the OTel environment variable header value s into a
@@ -529,6 +553,19 @@ func loadCertificates(certPath, keyPath string) ([]tls.Certificate, error) {
529553
return []tls.Certificate{crt}, nil
530554
}
531555

556+
// insecureFromScheme return setting if the connection should
557+
// use client transport security or not.
558+
// Empty scheme doesn't force insecure setting.
559+
func insecureFromScheme(prev setting[bool], scheme string) setting[bool] {
560+
if scheme == "https" {
561+
return newSetting(false)
562+
} else if len(scheme) > 0 {
563+
return newSetting(true)
564+
}
565+
566+
return prev
567+
}
568+
532569
func compressorToCompression(compressor string) Compression {
533570
c, err := convCompression(compressor)
534571
if err != nil {

exporters/otlp/otlplog/otlploggrpc/config_test.go

+77
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,83 @@ func TestNewConfig(t *testing.T) {
333333
`invalid OTEL_EXPORTER_OTLP_LOGS_TIMEOUT value 100 seconds: strconv.Atoi: parsing "100 seconds": invalid syntax`,
334334
},
335335
},
336+
{
337+
name: "OptionEndpointURLWithoutScheme",
338+
options: []Option{
339+
WithEndpointURL("//env.endpoint:8080/prefix"),
340+
},
341+
want: config{
342+
endpoint: newSetting("env.endpoint:8080"),
343+
retryCfg: newSetting(defaultRetryCfg),
344+
timeout: newSetting(defaultTimeout),
345+
},
346+
},
347+
{
348+
name: "EnvEndpointWithoutScheme",
349+
envars: map[string]string{
350+
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "//env.endpoint:8080/prefix",
351+
},
352+
want: config{
353+
endpoint: newSetting("env.endpoint:8080"),
354+
retryCfg: newSetting(defaultRetryCfg),
355+
timeout: newSetting(defaultTimeout),
356+
},
357+
},
358+
{
359+
name: "DefaultEndpointWithEnvInsecure",
360+
envars: map[string]string{
361+
"OTEL_EXPORTER_OTLP_LOGS_INSECURE": "true",
362+
},
363+
want: config{
364+
endpoint: newSetting(defaultEndpoint),
365+
insecure: newSetting(true),
366+
retryCfg: newSetting(defaultRetryCfg),
367+
timeout: newSetting(defaultTimeout),
368+
},
369+
},
370+
{
371+
name: "EnvEndpointWithoutSchemeWithEnvInsecure",
372+
envars: map[string]string{
373+
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "//env.endpoint:8080/prefix",
374+
"OTEL_EXPORTER_OTLP_LOGS_INSECURE": "true",
375+
},
376+
want: config{
377+
endpoint: newSetting("env.endpoint:8080"),
378+
insecure: newSetting(true),
379+
retryCfg: newSetting(defaultRetryCfg),
380+
timeout: newSetting(defaultTimeout),
381+
},
382+
},
383+
{
384+
name: "OptionEndpointURLWithoutSchemeWithEnvInsecure",
385+
options: []Option{
386+
WithEndpointURL("//env.endpoint:8080/prefix"),
387+
},
388+
envars: map[string]string{
389+
"OTEL_EXPORTER_OTLP_LOGS_INSECURE": "true",
390+
},
391+
want: config{
392+
endpoint: newSetting("env.endpoint:8080"),
393+
insecure: newSetting(true),
394+
retryCfg: newSetting(defaultRetryCfg),
395+
timeout: newSetting(defaultTimeout),
396+
},
397+
},
398+
{
399+
name: "OptionEndpointWithEnvInsecure",
400+
options: []Option{
401+
WithEndpoint("env.endpoint:8080"),
402+
},
403+
envars: map[string]string{
404+
"OTEL_EXPORTER_OTLP_LOGS_INSECURE": "true",
405+
},
406+
want: config{
407+
endpoint: newSetting("env.endpoint:8080"),
408+
insecure: newSetting(true),
409+
retryCfg: newSetting(defaultRetryCfg),
410+
timeout: newSetting(defaultTimeout),
411+
},
412+
},
336413
}
337414

338415
for _, tc := range testcases {

exporters/otlp/otlplog/otlploggrpc/doc.go

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ The value should not contain a query string or fragment.
1818
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT takes precedence over OTEL_EXPORTER_OTLP_ENDPOINT.
1919
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithGRPCConn] options.
2020
21+
OTEL_EXPORTER_OTLP_INSECURE, OTEL_EXPORTER_OTLP_LOGS_INSECURE (default: "false") -
22+
setting "true" disables client transport security for the exporter's gRPC connection.
23+
You can use this only when an endpoint is provided without scheme.
24+
OTEL_EXPORTER_OTLP_LOGS_INSECURE takes precedence over OTEL_EXPORTER_OTLP_INSECURE.
25+
The configuration can be overridden by [WithInsecure], [WithGRPCConn] options.
26+
2127
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_LOGS_HEADERS (default: none) -
2228
key-value pairs used as gRPC metadata associated with gRPC requests.
2329
The value is expected to be represented in a format matching the [W3C Baggage HTTP Header Content Format],

0 commit comments

Comments
 (0)