feat: support standard OTEL env vars via autoexport (#11864)

This commit is contained in:
Mridang Agarwalla
2026-04-01 06:14:21 +00:00
committed by GitHub
parent 7a15a06d69
commit 330548e13c
11 changed files with 590 additions and 7 deletions
@@ -7,11 +7,11 @@ import (
"strings"
)
const _ExporterTypeName = "NoneStdOutStdErrGRPCHTTPGooglePrometheus"
const _ExporterTypeName = "NoneStdOutStdErrGRPCHTTPGooglePrometheusAuto"
var _ExporterTypeIndex = [...]uint8{0, 0, 4, 10, 16, 20, 24, 30, 40}
var _ExporterTypeIndex = [...]uint8{0, 0, 4, 10, 16, 20, 24, 30, 40, 44}
const _ExporterTypeLowerName = "nonestdoutstderrgrpchttpgoogleprometheus"
const _ExporterTypeLowerName = "nonestdoutstderrgrpchttpgoogleprometheusauto"
func (i ExporterType) String() string {
if i < 0 || i >= ExporterType(len(_ExporterTypeIndex)-1) {
@@ -32,9 +32,10 @@ func _ExporterTypeNoOp() {
_ = x[ExporterTypeHTTP-(5)]
_ = x[ExporterTypeGoogle-(6)]
_ = x[ExporterTypePrometheus-(7)]
_ = x[ExporterTypeAuto-(8)]
}
var _ExporterTypeValues = []ExporterType{ExporterTypeUnspecified, ExporterTypeNone, ExporterTypeStdOut, ExporterTypeStdErr, ExporterTypeGRPC, ExporterTypeHTTP, ExporterTypeGoogle, ExporterTypePrometheus}
var _ExporterTypeValues = []ExporterType{ExporterTypeUnspecified, ExporterTypeNone, ExporterTypeStdOut, ExporterTypeStdErr, ExporterTypeGRPC, ExporterTypeHTTP, ExporterTypeGoogle, ExporterTypePrometheus, ExporterTypeAuto}
var _ExporterTypeNameToValueMap = map[string]ExporterType{
_ExporterTypeName[0:0]: ExporterTypeUnspecified,
@@ -53,6 +54,8 @@ var _ExporterTypeNameToValueMap = map[string]ExporterType{
_ExporterTypeLowerName[24:30]: ExporterTypeGoogle,
_ExporterTypeName[30:40]: ExporterTypePrometheus,
_ExporterTypeLowerName[30:40]: ExporterTypePrometheus,
_ExporterTypeName[40:44]: ExporterTypeAuto,
_ExporterTypeLowerName[40:44]: ExporterTypeAuto,
}
var _ExporterTypeNames = []string{
@@ -64,6 +67,7 @@ var _ExporterTypeNames = []string{
_ExporterTypeName[20:24],
_ExporterTypeName[24:30],
_ExporterTypeName[30:40],
_ExporterTypeName[40:44],
}
// ExporterTypeString retrieves an enum value from the enum constants string name.
+25
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"go.opentelemetry.io/contrib/exporters/autoexport"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
"go.opentelemetry.io/otel/exporters/stdout/stdoutlog"
@@ -15,6 +16,30 @@ import (
func newLoggerProvider(ctx context.Context, cfg ExporterConfig, resource *resource.Resource) (_ *sdk_log.LoggerProvider, err error) {
var exporter sdk_log.Exporter
switch cfg.Type {
case ExporterTypeAuto:
// autoexport delegates exporter selection to the standard OTEL env vars.
// We can't just call autoexport.NewLogExporter unconditionally because
// autoexport defaults to "otlp" when OTEL_LOGS_EXPORTER is unset, and
// the OTLP exporter silently points at localhost:4318 even with no env
// vars configured. That would cause every ZITADEL instance to start
// attempting OTLP connections after upgrading, spamming logs with
// connection errors.
//
// This guard is a heuristic: we check the env vars that realistically
// indicate someone has intentionally configured OTEL export. It does not
// cover every possible OTLP env var (e.g. OTEL_EXPORTER_OTLP_HEADERS or
// OTEL_EXPORTER_OTLP_CERTIFICATE on their own), but those vars are
// meaningless without an endpoint or exporter type being set too.
if os.Getenv("OTEL_LOGS_EXPORTER") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_PROTOCOL") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_LOGS_PROTOCOL") != "" {
exporter, err = autoexport.NewLogExporter(ctx)
if err == nil && autoexport.IsNoneLogExporter(exporter) {
exporter = nil
}
}
case ExporterTypeUnspecified, ExporterTypeNone:
// no exporter
case ExporterTypeStdOut, ExporterTypeStdErr:
+137
View File
@@ -79,3 +79,140 @@ func Test_newLoggerProvider(t *testing.T) {
})
}
}
func Test_newLoggerProvider_autoexport(t *testing.T) {
resource, err := resource.New(t.Context())
require.NoError(t, err)
tests := []struct {
name string
cfg ExporterConfig
envVars map[string]string
wantErr bool
}{
{
name: "auto type with OTEL_LOGS_EXPORTER=console creates provider",
cfg: ExporterConfig{
Type: ExporterTypeAuto,
},
envVars: map[string]string{
"OTEL_LOGS_EXPORTER": "console",
},
},
{
name: "auto type with no OTEL env vars creates provider (noop fallback)",
cfg: ExporterConfig{
Type: ExporterTypeAuto,
},
},
{
name: "auto type with OTEL_LOGS_EXPORTER=none creates provider (autoexport none)",
cfg: ExporterConfig{
Type: ExporterTypeAuto,
},
envVars: map[string]string{
"OTEL_LOGS_EXPORTER": "none",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_ENDPOINT uses OTLP default",
cfg: ExporterConfig{
Type: ExporterTypeAuto,
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_LOGS_ENDPOINT uses OTLP default",
cfg: ExporterConfig{
Type: ExporterTypeAuto,
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "http://localhost:4318",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_PROTOCOL uses OTLP default",
cfg: ExporterConfig{
Type: ExporterTypeAuto,
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_LOGS_PROTOCOL uses OTLP default",
cfg: ExporterConfig{
Type: ExporterTypeAuto,
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": "http/protobuf",
},
},
{
name: "none type ignores OTEL env vars (explicit disable)",
cfg: ExporterConfig{
Type: ExporterTypeNone,
},
envVars: map[string]string{
"OTEL_LOGS_EXPORTER": "invalid_exporter",
},
},
// Backward compatibility: ExporterTypeNone ignores global OTEL endpoint
{
name: "none type ignores OTEL_EXPORTER_OTLP_ENDPOINT",
cfg: ExporterConfig{
Type: ExporterTypeNone,
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
},
},
// Backward compatibility: ExporterTypeNone ignores per-signal OTEL var
{
name: "none type ignores OTEL_LOGS_EXPORTER=console",
cfg: ExporterConfig{
Type: ExporterTypeNone,
},
envVars: map[string]string{
"OTEL_LOGS_EXPORTER": "console",
},
},
// Backward compatibility: explicit ZITADEL types take priority over OTEL env vars
{
name: "stdout type ignores OTEL_LOGS_EXPORTER",
cfg: ExporterConfig{
Type: ExporterTypeStdOut,
},
envVars: map[string]string{
"OTEL_LOGS_EXPORTER": "grpc",
},
},
{
name: "grpc type ignores OTEL_EXPORTER_OTLP_ENDPOINT",
cfg: ExporterConfig{
Type: ExporterTypeGRPC,
Endpoint: "localhost:4317",
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://some-other-host:4318",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for k, v := range tt.envVars {
t.Setenv(k, v)
}
got, gotErr := newLoggerProvider(t.Context(), tt.cfg, resource)
if tt.wantErr {
assert.Error(t, gotErr)
assert.Nil(t, got)
} else {
assert.NoError(t, gotErr)
assert.NotNil(t, got)
}
})
}
}
+26
View File
@@ -9,6 +9,7 @@ import (
google_metric "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.opentelemetry.io/contrib/exporters/autoexport"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
@@ -160,6 +161,31 @@ func labelsToAttributes(labels map[string]attribute.Value) []attribute.KeyValue
func newMeterProvider(ctx context.Context, cfg MetricConfig, resource *resource.Resource) (_ *sdk_metric.MeterProvider, err error) {
var readerOption sdk_metric.Option
switch cfg.Exporter.Type {
case ExporterTypeAuto:
// autoexport delegates reader selection to the standard OTEL env vars.
// We can't just call autoexport.NewMetricReader unconditionally because
// autoexport defaults to "otlp" when OTEL_METRICS_EXPORTER is unset, and
// the OTLP exporter silently points at localhost:4318 even with no env
// vars configured. That would cause every ZITADEL instance to start
// attempting OTLP connections after upgrading, spamming logs with
// connection errors.
//
// This guard is a heuristic: we check the env vars that realistically
// indicate someone has intentionally configured OTEL export. It does not
// cover every possible OTLP env var (e.g. OTEL_EXPORTER_OTLP_HEADERS or
// OTEL_EXPORTER_OTLP_CERTIFICATE on their own), but those vars are
// meaningless without an endpoint or exporter type being set too.
if os.Getenv("OTEL_METRICS_EXPORTER") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_METRICS_ENDPOINT") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_PROTOCOL") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_METRICS_PROTOCOL") != "" {
var reader sdk_metric.Reader
reader, err = autoexport.NewMetricReader(ctx)
if err == nil && !autoexport.IsNoneMetricReader(reader) {
readerOption = sdk_metric.WithReader(reader)
}
}
case ExporterTypeUnspecified, ExporterTypeNone:
// no reader option
case ExporterTypeStdOut, ExporterTypeStdErr:
+177
View File
@@ -77,6 +77,22 @@ func TestMetricConfig_SetLegacyConfig(t *testing.T) {
},
},
},
{
name: "auto type is not overridden by legacy config",
target: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
lc: &LegacyMetricConfig{
Type: "otel",
},
want: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -184,3 +200,164 @@ func Test_newMeterProvider(t *testing.T) {
})
}
}
func Test_newMeterProvider_autoexport(t *testing.T) {
resource, err := resource.New(t.Context())
require.NoError(t, err)
tests := []struct {
name string
cfg MetricConfig
envVars map[string]string
wantErr bool
}{
{
name: "auto type with OTEL_METRICS_EXPORTER=console creates provider",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_METRICS_EXPORTER": "console",
},
},
{
name: "auto type with no OTEL env vars creates provider (noop fallback)",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
},
{
name: "auto type with OTEL_METRICS_EXPORTER=none creates provider (autoexport none)",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_METRICS_EXPORTER": "none",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_ENDPOINT uses OTLP default",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_METRICS_ENDPOINT uses OTLP default",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "http://localhost:4318",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_PROTOCOL uses OTLP default",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_METRICS_PROTOCOL uses OTLP default",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": "http/protobuf",
},
},
{
name: "none type ignores OTEL env vars (explicit disable)",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeNone,
},
},
envVars: map[string]string{
"OTEL_METRICS_EXPORTER": "invalid_exporter",
},
},
// Backward compatibility: ExporterTypeNone ignores global OTEL endpoint
{
name: "none type ignores OTEL_EXPORTER_OTLP_ENDPOINT",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeNone,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
},
},
// Backward compatibility: ExporterTypeNone ignores per-signal OTEL var
{
name: "none type ignores OTEL_METRICS_EXPORTER=console",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeNone,
},
},
envVars: map[string]string{
"OTEL_METRICS_EXPORTER": "console",
},
},
// Backward compatibility: explicit ZITADEL types take priority over OTEL env vars
{
name: "stdout type ignores OTEL_METRICS_EXPORTER",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeStdOut,
},
},
envVars: map[string]string{
"OTEL_METRICS_EXPORTER": "grpc",
},
},
{
name: "grpc type ignores OTEL_EXPORTER_OTLP_ENDPOINT",
cfg: MetricConfig{
Exporter: ExporterConfig{
Type: ExporterTypeGRPC,
Endpoint: "localhost:4317",
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://some-other-host:4318",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for k, v := range tt.envVars {
t.Setenv(k, v)
}
got, gotErr := newMeterProvider(t.Context(), tt.cfg, resource)
if tt.wantErr {
assert.Error(t, gotErr)
assert.Nil(t, got)
} else {
assert.NoError(t, gotErr)
assert.NotNil(t, got)
}
})
}
}
+1
View File
@@ -36,6 +36,7 @@ const (
ExporterTypeHTTP
ExporterTypeGoogle
ExporterTypePrometheus
ExporterTypeAuto
)
// isNone returns true if the ExporterType is either Unspecified or None.
+27 -2
View File
@@ -9,6 +9,7 @@ import (
"slices"
google_trace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
"go.opentelemetry.io/contrib/exporters/autoexport"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
@@ -136,6 +137,30 @@ func (s *Span) SetStatusByError(err error) {
func newTracerProvider(ctx context.Context, cfg TraceConfig, resource *resource.Resource) (_ *sdk_trace.TracerProvider, err error) {
var exporter sdk_trace.SpanExporter
switch cfg.Exporter.Type {
case ExporterTypeAuto:
// autoexport delegates exporter selection to the standard OTEL env vars.
// We can't just call autoexport.NewSpanExporter unconditionally because
// autoexport defaults to "otlp" when OTEL_TRACES_EXPORTER is unset, and
// the OTLP exporter silently points at localhost:4318 even with no env
// vars configured. That would cause every ZITADEL instance to start
// attempting OTLP connections after upgrading, spamming logs with
// connection errors.
//
// This guard is a heuristic: we check the env vars that realistically
// indicate someone has intentionally configured OTEL export. It does not
// cover every possible OTLP env var (e.g. OTEL_EXPORTER_OTLP_HEADERS or
// OTEL_EXPORTER_OTLP_CERTIFICATE on their own), but those vars are
// meaningless without an endpoint or exporter type being set too.
if os.Getenv("OTEL_TRACES_EXPORTER") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_PROTOCOL") != "" ||
os.Getenv("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL") != "" {
exporter, err = autoexport.NewSpanExporter(ctx)
if err == nil && autoexport.IsNoneSpanExporter(exporter) {
exporter = nil
}
}
case ExporterTypeUnspecified, ExporterTypeNone:
// no exporter
case ExporterTypeStdOut, ExporterTypeStdErr:
@@ -147,7 +172,7 @@ func newTracerProvider(ctx context.Context, cfg TraceConfig, resource *resource.
case ExporterTypeGoogle:
exporter, err = traceGoogleExporter(ctx, cfg.Exporter)
case ExporterTypePrometheus:
fallthrough // prometheus is not supported for logs
fallthrough // prometheus is not supported for traces
default:
err = errExporterType(cfg.Exporter.Type, "tracer")
}
@@ -160,7 +185,7 @@ func newTracerProvider(ctx context.Context, cfg TraceConfig, resource *resource.
sdk_trace.WithSampler(sampler),
}
if exporter != nil {
opts = append(opts, sdk_trace.WithBatcher(exporter))
opts = append(opts, sdk_trace.WithBatcher(exporter, sdk_trace.WithBatchTimeout(cfg.Exporter.BatchDuration)))
}
tracerProvider := sdk_trace.NewTracerProvider(opts...)
return tracerProvider, nil
+179
View File
@@ -87,6 +87,24 @@ func TestTraceConfig_SetLegacyConfig(t *testing.T) {
},
},
},
{
name: "auto type is not overridden by legacy config",
target: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
lc: &LegacyTraceConfig{
Type: "google",
Fraction: 0.5,
Endpoint: "endpoint",
},
want: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -189,3 +207,164 @@ func Test_newTracerProvider(t *testing.T) {
})
}
}
func Test_newTracerProvider_autoexport(t *testing.T) {
resource, err := resource.New(t.Context())
require.NoError(t, err)
tests := []struct {
name string
cfg TraceConfig
envVars map[string]string
wantErr bool
}{
{
name: "auto type with OTEL_TRACES_EXPORTER=console creates provider",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_TRACES_EXPORTER": "console",
},
},
{
name: "auto type with no OTEL env vars creates provider (noop fallback)",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
},
{
name: "auto type with OTEL_TRACES_EXPORTER=none creates provider (autoexport none)",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_TRACES_EXPORTER": "none",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_ENDPOINT uses OTLP default",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_TRACES_ENDPOINT uses OTLP default",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": "http://localhost:4318",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_PROTOCOL uses OTLP default",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
},
},
{
name: "auto type with only OTEL_EXPORTER_OTLP_TRACES_PROTOCOL uses OTLP default",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeAuto,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": "http/protobuf",
},
},
{
name: "none type ignores OTEL env vars (explicit disable)",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeNone,
},
},
envVars: map[string]string{
"OTEL_TRACES_EXPORTER": "invalid_exporter",
},
},
// Backward compatibility: ExporterTypeNone ignores global OTEL endpoint
{
name: "none type ignores OTEL_EXPORTER_OTLP_ENDPOINT",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeNone,
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
},
},
// Backward compatibility: ExporterTypeNone ignores per-signal OTEL var
{
name: "none type ignores OTEL_TRACES_EXPORTER=console",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeNone,
},
},
envVars: map[string]string{
"OTEL_TRACES_EXPORTER": "console",
},
},
// Backward compatibility: explicit ZITADEL types take priority over OTEL env vars
{
name: "stdout type ignores OTEL_TRACES_EXPORTER",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeStdOut,
},
},
envVars: map[string]string{
"OTEL_TRACES_EXPORTER": "grpc",
},
},
{
name: "grpc type ignores OTEL_EXPORTER_OTLP_ENDPOINT",
cfg: TraceConfig{
Exporter: ExporterConfig{
Type: ExporterTypeGRPC,
Endpoint: "localhost:4317",
},
},
envVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://some-other-host:4318",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for k, v := range tt.envVars {
t.Setenv(k, v)
}
got, gotErr := newTracerProvider(t.Context(), tt.cfg, resource)
if tt.wantErr {
assert.Error(t, gotErr)
assert.Nil(t, got)
} else {
assert.NoError(t, gotErr)
assert.NotNil(t, got)
}
})
}
}
+4 -1
View File
@@ -8,6 +8,7 @@ Instrumentation:
Exporter:
# The following exporter types are supported:
# "none": Disables trace exporting
# "auto": Delegates to standard OTEL env vars (OTEL_TRACES_EXPORTER, OTEL_EXPORTER_OTLP_ENDPOINT)
# "stdOut": Exports traces to standard output
# "stdErr": Exports traces to standard error
# "grpc": Exports traces using the OTEL gRPC exporter (recommended)
@@ -26,6 +27,7 @@ Instrumentation:
Exporter:
# The following exporter types are supported:
# "none": Disables metric exporting
# "auto": Delegates to standard OTEL env vars (OTEL_METRICS_EXPORTER, OTEL_EXPORTER_OTLP_ENDPOINT)
# "stdOut": Exports metrics to standard output
# "stdErr": Exports metrics to standard error
# "grpc": Exports metrics using the OTEL gRPC exporter (recommended)
@@ -91,6 +93,7 @@ Instrumentation:
Exporter:
# The following exporter types are supported:
# - "none": Disables OTEL log exporter
# - "auto": Delegates to standard OTEL env vars (OTEL_LOGS_EXPORTER, OTEL_EXPORTER_OTLP_ENDPOINT)
# - "stdOut": Exports OTEL logs to standard output
# - "stdErr": Exports OTEL logs to standard error
# - "grpc": Exports OTEL logs using the OTEL gRPC exporter (recommended)
@@ -100,7 +103,7 @@ Instrumentation:
Endpoint: "" # ZITADEL_INSTRUMENTATION_LOG_EXPORTER_ENDPOINT
# Disable TLS for grpc and http exporters
Insecure: false # ZITADEL_INSTRUMENTATION_LOG_EXPORTER_INSECURE
# Interval at which metrics are exported
# Interval at which logs are batched for export
BatchDuration: 1s # ZITADEL_INSTRUMENTATION_LOG_EXPORTER_BATCHDURATION
Profile:
Exporter:
+2
View File
@@ -106,6 +106,7 @@ require (
github.com/zitadel/schema v1.3.2
github.com/zitadel/sloggcp v0.6.0
go.opentelemetry.io/contrib/bridges/otelslog v0.17.0
go.opentelemetry.io/contrib/exporters/autoexport v0.67.0
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0
go.opentelemetry.io/otel v1.42.0
@@ -257,6 +258,7 @@ require (
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.42.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 // indirect
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
+4
View File
@@ -856,8 +856,12 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/bridges/otelslog v0.17.0 h1:NFIS6x7wyObQ7cR84x7bt1sr8nYBx89s3x3GwRjw40k=
go.opentelemetry.io/contrib/bridges/otelslog v0.17.0/go.mod h1:39SaByOyDMRMe872AE7uelMuQZidIw7LLFAnQi0FWTE=
go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 h1:dkBzNEAIKADEaFnuESzcXvpd09vxvDZsOjx11gjUqLk=
go.opentelemetry.io/contrib/bridges/prometheus v0.67.0/go.mod h1:Z5RIwRkZgauOIfnG5IpidvLpERjhTninpP1dTG2jTl4=
go.opentelemetry.io/contrib/detectors/gcp v1.42.0 h1:kpt2PEJuOuqYkPcktfJqWWDjTEd/FNgrxcniL7kQrXQ=
go.opentelemetry.io/contrib/detectors/gcp v1.42.0/go.mod h1:W9zQ439utxymRrXsUOzZbFX4JhLxXU4+ZnCt8GG7yA8=
go.opentelemetry.io/contrib/exporters/autoexport v0.67.0 h1:4fnRcNpc6YFtG3zsFw9achKn3XgmxPxuMuqIL5rE8e8=
go.opentelemetry.io/contrib/exporters/autoexport v0.67.0/go.mod h1:qTvIHMFKoxW7HXg02gm6/Wofhq5p3Ib/A/NNt1EoBSQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 h1:yI1/OhfEPy7J9eoa6Sj051C7n5dvpj0QX8g4sRchg04=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0/go.mod h1:NoUCKYWK+3ecatC4HjkRktREheMeEtrXoQxrqYFeHSc=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o=