From 03578c6a5d0d0c5b479054128cfd04bc5518242d Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:03:23 -0700 Subject: [PATCH 01/39] copy v0.3.0 and update import definition Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config.go | 240 +++++++++++++++ otelconf/config_json.go | 266 +++++++++++++++++ otelconf/config_test.go | 648 ++++++++++++++++++++++++++++++++++++++++ otelconf/config_yaml.go | 57 ++++ otelconf/fuzz_test.go | 64 ++++ 5 files changed, 1275 insertions(+) create mode 100644 otelconf/config.go create mode 100644 otelconf/fuzz_test.go diff --git a/otelconf/config.go b/otelconf/config.go new file mode 100644 index 00000000000..2e373e27e47 --- /dev/null +++ b/otelconf/config.go @@ -0,0 +1,240 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package otelconf provides an OpenTelemetry declarative configuration SDK. +package otelconf // import "go.opentelemetry.io/contrib/otelconf/v1.0.0-rc.1" + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "os" + + "go.opentelemetry.io/otel/baggage" + "go.opentelemetry.io/otel/log" + nooplog "go.opentelemetry.io/otel/log/noop" + "go.opentelemetry.io/otel/metric" + noopmetric "go.opentelemetry.io/otel/metric/noop" + sdklog "go.opentelemetry.io/otel/sdk/log" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/trace" + nooptrace "go.opentelemetry.io/otel/trace/noop" + yaml "go.yaml.in/yaml/v3" +) + +const ( + protocolProtobufHTTP = "http/protobuf" + protocolProtobufGRPC = "grpc" + + compressionGzip = "gzip" + compressionNone = "none" +) + +type configOptions struct { + ctx context.Context + opentelemetryConfig OpenTelemetryConfiguration + loggerProviderOptions []sdklog.LoggerProviderOption + meterProviderOptions []sdkmetric.Option + tracerProviderOptions []sdktrace.TracerProviderOption +} + +type shutdownFunc func(context.Context) error + +func noopShutdown(context.Context) error { + return nil +} + +// SDK is a struct that contains all the providers +// configured via the configuration model. +type SDK struct { + meterProvider metric.MeterProvider + tracerProvider trace.TracerProvider + loggerProvider log.LoggerProvider + shutdown shutdownFunc +} + +// TracerProvider returns a configured trace.TracerProvider. +func (s *SDK) TracerProvider() trace.TracerProvider { + return s.tracerProvider +} + +// MeterProvider returns a configured metric.MeterProvider. +func (s *SDK) MeterProvider() metric.MeterProvider { + return s.meterProvider +} + +// LoggerProvider returns a configured log.LoggerProvider. +func (s *SDK) LoggerProvider() log.LoggerProvider { + return s.loggerProvider +} + +// Shutdown calls shutdown on all configured providers. +func (s *SDK) Shutdown(ctx context.Context) error { + return s.shutdown(ctx) +} + +var noopSDK = SDK{ + loggerProvider: nooplog.LoggerProvider{}, + meterProvider: noopmetric.MeterProvider{}, + tracerProvider: nooptrace.TracerProvider{}, + shutdown: func(context.Context) error { return nil }, +} + +// NewSDK creates SDK providers based on the configuration model. +func NewSDK(opts ...ConfigurationOption) (SDK, error) { + o := configOptions{ + ctx: context.Background(), + } + for _, opt := range opts { + o = opt.apply(o) + } + if o.opentelemetryConfig.Disabled != nil && *o.opentelemetryConfig.Disabled { + return noopSDK, nil + } + + r := newResource(o.opentelemetryConfig.Resource) + + mp, mpShutdown, err := meterProvider(o, r) + if err != nil { + return noopSDK, err + } + + tp, tpShutdown, err := tracerProvider(o, r) + if err != nil { + return noopSDK, err + } + + lp, lpShutdown, err := loggerProvider(o, r) + if err != nil { + return noopSDK, err + } + + return SDK{ + meterProvider: mp, + tracerProvider: tp, + loggerProvider: lp, + shutdown: func(ctx context.Context) error { + return errors.Join(mpShutdown(ctx), tpShutdown(ctx), lpShutdown(ctx)) + }, + }, nil +} + +// ConfigurationOption configures options for providers. +type ConfigurationOption interface { + apply(configOptions) configOptions +} + +type configurationOptionFunc func(configOptions) configOptions + +func (fn configurationOptionFunc) apply(cfg configOptions) configOptions { + return fn(cfg) +} + +// WithContext sets the context.Context for the SDK. +func WithContext(ctx context.Context) ConfigurationOption { + return configurationOptionFunc(func(c configOptions) configOptions { + c.ctx = ctx + return c + }) +} + +// WithOpenTelemetryConfiguration sets the OpenTelemetryConfiguration used +// to produce the SDK. +func WithOpenTelemetryConfiguration(cfg OpenTelemetryConfiguration) ConfigurationOption { + return configurationOptionFunc(func(c configOptions) configOptions { + c.opentelemetryConfig = cfg + return c + }) +} + +// WithLoggerProviderOptions appends LoggerProviderOptions used for constructing +// the LoggerProvider. OpenTelemetryConfiguration takes precedence over these options. +func WithLoggerProviderOptions(opts ...sdklog.LoggerProviderOption) ConfigurationOption { + return configurationOptionFunc(func(c configOptions) configOptions { + c.loggerProviderOptions = append(c.loggerProviderOptions, opts...) + return c + }) +} + +// WithMeterProviderOptions appends metric.Options used for constructing the +// MeterProvider. OpenTelemetryConfiguration takes precedence over these options. +func WithMeterProviderOptions(opts ...sdkmetric.Option) ConfigurationOption { + return configurationOptionFunc(func(c configOptions) configOptions { + c.meterProviderOptions = append(c.meterProviderOptions, opts...) + return c + }) +} + +// WithTracerProviderOptions appends TracerProviderOptions used for constructing +// the TracerProvider. OpenTelemetryConfiguration takes precedence over these options. +func WithTracerProviderOptions(opts ...sdktrace.TracerProviderOption) ConfigurationOption { + return configurationOptionFunc(func(c configOptions) configOptions { + c.tracerProviderOptions = append(c.tracerProviderOptions, opts...) + return c + }) +} + +// ParseYAML parses a YAML configuration file into an OpenTelemetryConfiguration. +func ParseYAML(file []byte) (*OpenTelemetryConfiguration, error) { + var cfg OpenTelemetryConfiguration + err := yaml.Unmarshal(file, &cfg) + if err != nil { + return nil, err + } + + return &cfg, nil +} + +// createTLSConfig creates a tls.Config from certificate files. +func createTLSConfig(caCertFile, clientCertFile, clientKeyFile *string) (*tls.Config, error) { + tlsConfig := &tls.Config{} + if caCertFile != nil { + caText, err := os.ReadFile(*caCertFile) + if err != nil { + return nil, err + } + certPool := x509.NewCertPool() + if !certPool.AppendCertsFromPEM(caText) { + return nil, errors.New("could not create certificate authority chain from certificate") + } + tlsConfig.RootCAs = certPool + } + if clientCertFile != nil { + if clientKeyFile == nil { + return nil, errors.New("client certificate was provided but no client key was provided") + } + clientCert, err := tls.LoadX509KeyPair(*clientCertFile, *clientKeyFile) + if err != nil { + return nil, fmt.Errorf("could not use client certificate: %w", err) + } + tlsConfig.Certificates = []tls.Certificate{clientCert} + } + return tlsConfig, nil +} + +// createHeadersConfig combines the two header config fields. Headers take precedence over headersList. +func createHeadersConfig(headers []NameStringValuePair, headersList *string) (map[string]string, error) { + result := make(map[string]string) + if headersList != nil { + // Parsing follows https://github.com/open-telemetry/opentelemetry-configuration/blob/568e5080816d40d75792eb754fc96bde09654159/schema/type_descriptions.yaml#L584. + headerslist, err := baggage.Parse(*headersList) + if err != nil { + return nil, fmt.Errorf("invalid headers list: %w", err) + } + for _, kv := range headerslist.Members() { + result[kv.Key()] = kv.Value() + } + } + // Headers take precedence over HeadersList, so this has to be after HeadersList is processed + if len(headers) > 0 { + for _, kv := range headers { + if kv.Value != nil { + result[kv.Name] = *kv.Value + } + } + } + return result, nil +} diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 3c2de10e15c..c33dd47b1aa 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -191,6 +191,44 @@ func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { sh.Plain.Console = c } *j = LogRecordExporter(sh.Plain) +} + +// MarshalJSON implements json.Marshaler. +func (j *AttributeNameValueType) MarshalJSON() ([]byte, error) { + return json.Marshal(j.Value) +} + +var enumValuesAttributeNameValueType = []any{ + nil, + "string", + "bool", + "int", + "double", + "string_array", + "bool_array", + "int_array", + "double_array", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *AttributeNameValueType) UnmarshalJSON(b []byte) error { + var v struct { + Value any + } + if err := json.Unmarshal(b, &v.Value); err != nil { + return err + } + var ok bool + for _, expected := range enumValuesAttributeNameValueType { + if reflect.DeepEqual(v.Value, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesAttributeNameValueType, v.Value) + } + *j = AttributeNameValueType(v) return nil } @@ -315,6 +353,140 @@ func (j *BatchSpanProcessor) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. +func (j *GeneralInstrumentationPeerServiceMappingElem) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["peer"]; raw != nil && !ok { + return errors.New("field peer in GeneralInstrumentationPeerServiceMappingElem: required") + } + if _, ok := raw["service"]; raw != nil && !ok { + return errors.New("field service in GeneralInstrumentationPeerServiceMappingElem: required") + } + type Plain GeneralInstrumentationPeerServiceMappingElem + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = GeneralInstrumentationPeerServiceMappingElem(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *NameStringValuePair) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["name"]; !ok { + return errors.New("json: cannot unmarshal field name in NameStringValuePair required") + } + if _, ok := raw["value"]; !ok { + return errors.New("json: cannot unmarshal field value in NameStringValuePair required") + } + var name, value string + var ok bool + if name, ok = raw["name"].(string); !ok { + return errors.New("yaml: cannot unmarshal field name in NameStringValuePair must be string") + } + if value, ok = raw["value"].(string); !ok { + return errors.New("yaml: cannot unmarshal field value in NameStringValuePair must be string") + } + + *j = NameStringValuePair{ + Name: name, + Value: &value, + } + return nil +} + +var enumValuesOTLPMetricDefaultHistogramAggregation = []any{ + "explicit_bucket_histogram", + "base2_exponential_bucket_histogram", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *OTLPMetricDefaultHistogramAggregation) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValuesOTLPMetricDefaultHistogramAggregation { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesOTLPMetricDefaultHistogramAggregation, v) + } + *j = OTLPMetricDefaultHistogramAggregation(v) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *OTLPMetric) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["endpoint"]; raw != nil && !ok { + return errors.New("field endpoint in OTLPMetric: required") + } + if _, ok := raw["protocol"]; raw != nil && !ok { + return errors.New("field protocol in OTLPMetric: required") + } + type Plain OTLPMetric + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = OTLPMetric(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *OTLP) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["endpoint"]; raw != nil && !ok { + return errors.New("field endpoint in OTLP: required") + } + if _, ok := raw["protocol"]; raw != nil && !ok { + return errors.New("field protocol in OTLP: required") + } + type Plain OTLP + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = OTLP(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["file_format"]; raw != nil && !ok { + return errors.New("field file_format in OpenTelemetryConfiguration: required") + } + type Plain OpenTelemetryConfiguration + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = OpenTelemetryConfiguration(plain) + return nil +} + // UnmarshalJSON implements json.Unmarshaler. func (j *PeriodicMetricReader) UnmarshalJSON(b []byte) error { type Plain PeriodicMetricReader @@ -354,6 +526,22 @@ func (j *CardinalityLimits) UnmarshalJSON(value []byte) error { *j = CardinalityLimits(plain) return nil } +func (j *PullMetricReader) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["exporter"]; raw != nil && !ok { + return errors.New("field exporter in PullMetricReader: required") + } + type Plain PullMetricReader + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = PullMetricReader(plain) + return nil +} // UnmarshalJSON implements json.Unmarshaler. func (j *SpanLimits) UnmarshalJSON(value []byte) error { @@ -393,6 +581,23 @@ func (j *OTLPHttpMetricExporter) UnmarshalJSON(b []byte) error { return nil } +func (j *SimpleLogRecordProcessor) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["exporter"]; raw != nil && !ok { + return errors.New("field exporter in SimpleLogRecordProcessor: required") + } + type Plain SimpleLogRecordProcessor + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = SimpleLogRecordProcessor(plain) + return nil +} + // UnmarshalJSON implements json.Unmarshaler. func (j *OTLPGrpcMetricExporter) UnmarshalJSON(b []byte) error { type Plain OTLPGrpcMetricExporter @@ -416,6 +621,51 @@ func (j *OTLPGrpcMetricExporter) UnmarshalJSON(b []byte) error { *j = OTLPGrpcMetricExporter(sh.Plain) return nil } +func (j *SimpleSpanProcessor) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["exporter"]; raw != nil && !ok { + return errors.New("field exporter in SimpleSpanProcessor: required") + } + type Plain SimpleSpanProcessor + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = SimpleSpanProcessor(plain) + return nil +} + +var enumValuesViewSelectorInstrumentType = []any{ + "counter", + "histogram", + "observable_counter", + "observable_gauge", + "observable_up_down_counter", + "up_down_counter", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ViewSelectorInstrumentType) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValuesViewSelectorInstrumentType { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesViewSelectorInstrumentType, v) + } + *j = ViewSelectorInstrumentType(v) + return nil +} // UnmarshalJSON implements json.Unmarshaler. func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { @@ -440,6 +690,22 @@ func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { *j = OTLPHttpExporter(sh.Plain) return nil } +func (j *Zipkin) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["endpoint"]; raw != nil && !ok { + return errors.New("field endpoint in Zipkin: required") + } + type Plain Zipkin + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Zipkin(plain) + return nil +} // UnmarshalJSON implements json.Unmarshaler. func (j *OTLPGrpcExporter) UnmarshalJSON(b []byte) error { diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 99c31e76b63..b87b06f7917 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -4,11 +4,24 @@ package otelconf import ( + "crypto/tls" + "encoding/json" + "errors" + "os" + "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.yaml.in/yaml/v3" + + "github.com/stretchr/testify/require" + lognoop "go.opentelemetry.io/otel/log/noop" + metricnoop "go.opentelemetry.io/otel/metric/noop" + sdklog "go.opentelemetry.io/otel/sdk/log" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + tracenoop "go.opentelemetry.io/otel/trace/noop" ) func TestUnmarshalPushMetricExporterInvalidData(t *testing.T) { @@ -339,6 +352,433 @@ func TestUnmarshalBatchLogRecordProcessor(t *testing.T) { } } +func TestNewSDK(t *testing.T) { + tests := []struct { + name string + cfg []ConfigurationOption + wantTracerProvider any + wantMeterProvider any + wantLoggerProvider any + wantErr error + wantShutdownErr error + }{ + { + name: "no-configuration", + wantTracerProvider: tracenoop.NewTracerProvider(), + wantMeterProvider: metricnoop.NewMeterProvider(), + wantLoggerProvider: lognoop.NewLoggerProvider(), + }, + { + name: "with-configuration", + cfg: []ConfigurationOption{ + WithContext(t.Context()), + WithOpenTelemetryConfiguration(OpenTelemetryConfiguration{ + TracerProvider: &TracerProvider{}, + MeterProvider: &MeterProvider{}, + LoggerProvider: &LoggerProvider{}, + }), + }, + wantTracerProvider: &sdktrace.TracerProvider{}, + wantMeterProvider: &sdkmetric.MeterProvider{}, + wantLoggerProvider: &sdklog.LoggerProvider{}, + }, + { + name: "with-sdk-disabled", + cfg: []ConfigurationOption{ + WithContext(t.Context()), + WithOpenTelemetryConfiguration(OpenTelemetryConfiguration{ + Disabled: ptr(true), + TracerProvider: &TracerProvider{}, + MeterProvider: &MeterProvider{}, + LoggerProvider: &LoggerProvider{}, + }), + }, + wantTracerProvider: tracenoop.NewTracerProvider(), + wantMeterProvider: metricnoop.NewMeterProvider(), + wantLoggerProvider: lognoop.NewLoggerProvider(), + }, + } + for _, tt := range tests { + sdk, err := NewSDK(tt.cfg...) + require.Equal(t, tt.wantErr, err) + assert.IsType(t, tt.wantTracerProvider, sdk.TracerProvider()) + assert.IsType(t, tt.wantMeterProvider, sdk.MeterProvider()) + assert.IsType(t, tt.wantLoggerProvider, sdk.LoggerProvider()) + require.Equal(t, tt.wantShutdownErr, sdk.Shutdown(t.Context())) + } +} + +var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ + Disabled: ptr(false), + FileFormat: ptr("0.3"), + AttributeLimits: &AttributeLimits{ + AttributeCountLimit: ptr(128), + AttributeValueLengthLimit: ptr(4096), + }, + Instrumentation: &Instrumentation{ + Cpp: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Dotnet: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Erlang: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + General: &GeneralInstrumentation{ + Http: &GeneralInstrumentationHttp{ + Client: &GeneralInstrumentationHttpClient{ + RequestCapturedHeaders: []string{"Content-Type", "Accept"}, + ResponseCapturedHeaders: []string{"Content-Type", "Content-Encoding"}, + }, + Server: &GeneralInstrumentationHttpServer{ + RequestCapturedHeaders: []string{"Content-Type", "Accept"}, + ResponseCapturedHeaders: []string{"Content-Type", "Content-Encoding"}, + }, + }, + Peer: &GeneralInstrumentationPeer{ + ServiceMapping: []GeneralInstrumentationPeerServiceMappingElem{ + {Peer: "1.2.3.4", Service: "FooService"}, + {Peer: "2.3.4.5", Service: "BarService"}, + }, + }, + }, + Go: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Java: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Js: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Php: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Python: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Ruby: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Rust: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + Swift: LanguageSpecificInstrumentation{ + "example": map[string]any{ + "property": "value", + }, + }, + }, + LoggerProvider: &LoggerProvider{ + Limits: &LogRecordLimits{ + AttributeCountLimit: ptr(128), + AttributeValueLengthLimit: ptr(4096), + }, + Processors: []LogRecordProcessor{ + { + Batch: &BatchLogRecordProcessor{ + ExportTimeout: ptr(30000), + Exporter: LogRecordExporter{ + OTLP: &OTLP{ + Certificate: ptr("/app/cert.pem"), + ClientCertificate: ptr("/app/cert.pem"), + ClientKey: ptr("/app/cert.pem"), + Compression: ptr("gzip"), + Endpoint: ptr("http://localhost:4318/v1/logs"), + Headers: []NameStringValuePair{ + {Name: "api-key", Value: ptr("1234")}, + }, + HeadersList: ptr("api-key=1234"), + Insecure: ptr(false), + Protocol: ptr("http/protobuf"), + Timeout: ptr(10000), + }, + }, + MaxExportBatchSize: ptr(512), + MaxQueueSize: ptr(2048), + ScheduleDelay: ptr(5000), + }, + }, + { + Simple: &SimpleLogRecordProcessor{ + Exporter: LogRecordExporter{ + Console: Console{}, + }, + }, + }, + }, + }, + MeterProvider: &MeterProvider{ + Readers: []MetricReader{ + { + Producers: []MetricProducer{ + {Opencensus: MetricProducerOpencensus{}}, + }, + Pull: &PullMetricReader{ + Exporter: PullMetricExporter{ + Prometheus: &Prometheus{ + Host: ptr("localhost"), + Port: ptr(9464), + WithResourceConstantLabels: &IncludeExclude{ + Excluded: []string{"service.attr1"}, + Included: []string{"service*"}, + }, + WithoutScopeInfo: ptr(false), + WithoutTypeSuffix: ptr(false), + WithoutUnits: ptr(false), + }, + }, + }, + }, + { + Producers: []MetricProducer{ + {}, + }, + Periodic: &PeriodicMetricReader{ + Exporter: PushMetricExporter{ + OTLP: &OTLPMetric{ + Certificate: ptr("/app/cert.pem"), + ClientCertificate: ptr("/app/cert.pem"), + ClientKey: ptr("/app/cert.pem"), + Compression: ptr("gzip"), + DefaultHistogramAggregation: ptr(OTLPMetricDefaultHistogramAggregationBase2ExponentialBucketHistogram), + Endpoint: ptr("http://localhost:4318/v1/metrics"), + Headers: []NameStringValuePair{ + {Name: "api-key", Value: ptr("1234")}, + }, + HeadersList: ptr("api-key=1234"), + Insecure: ptr(false), + Protocol: ptr("http/protobuf"), + TemporalityPreference: ptr("delta"), + Timeout: ptr(10000), + }, + }, + Interval: ptr(5000), + Timeout: ptr(30000), + }, + }, + { + Periodic: &PeriodicMetricReader{ + Exporter: PushMetricExporter{ + Console: Console{}, + }, + }, + }, + }, + Views: []View{ + { + Selector: &ViewSelector{ + InstrumentName: ptr("my-instrument"), + InstrumentType: ptr(ViewSelectorInstrumentTypeHistogram), + MeterName: ptr("my-meter"), + MeterSchemaUrl: ptr("https://opentelemetry.io/schemas/1.16.0"), + MeterVersion: ptr("1.0.0"), + Unit: ptr("ms"), + }, + Stream: &ViewStream{ + Aggregation: &ViewStreamAggregation{ + ExplicitBucketHistogram: &ViewStreamAggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000}, + RecordMinMax: ptr(true), + }, + }, + AttributeKeys: &IncludeExclude{ + Included: []string{"key1", "key2"}, + Excluded: []string{"key3"}, + }, + Description: ptr("new_description"), + Name: ptr("new_instrument_name"), + }, + }, + }, + }, + Propagator: &Propagator{ + Composite: []*string{ptr("tracecontext"), ptr("baggage"), ptr("b3"), ptr("b3multi"), ptr("jaeger"), ptr("xray"), ptr("ottrace")}, + }, + Resource: &Resource{ + Attributes: []AttributeNameValue{ + {Name: "service.name", Value: "unknown_service"}, + {Name: "string_key", Type: &AttributeNameValueType{Value: "string"}, Value: "value"}, + {Name: "bool_key", Type: &AttributeNameValueType{Value: "bool"}, Value: true}, + {Name: "int_key", Type: &AttributeNameValueType{Value: "int"}, Value: 1}, + {Name: "double_key", Type: &AttributeNameValueType{Value: "double"}, Value: 1.1}, + {Name: "string_array_key", Type: &AttributeNameValueType{Value: "string_array"}, Value: []any{"value1", "value2"}}, + {Name: "bool_array_key", Type: &AttributeNameValueType{Value: "bool_array"}, Value: []any{true, false}}, + {Name: "int_array_key", Type: &AttributeNameValueType{Value: "int_array"}, Value: []any{1, 2}}, + {Name: "double_array_key", Type: &AttributeNameValueType{Value: "double_array"}, Value: []any{1.1, 2.2}}, + }, + AttributesList: ptr("service.namespace=my-namespace,service.version=1.0.0"), + Detectors: &Detectors{ + Attributes: &DetectorsAttributes{ + Excluded: []string{"process.command_args"}, + Included: []string{"process.*"}, + }, + }, + SchemaUrl: ptr("https://opentelemetry.io/schemas/1.16.0"), + }, + TracerProvider: &TracerProvider{ + Limits: &SpanLimits{ + AttributeCountLimit: ptr(128), + AttributeValueLengthLimit: ptr(4096), + EventCountLimit: ptr(128), + EventAttributeCountLimit: ptr(128), + LinkCountLimit: ptr(128), + LinkAttributeCountLimit: ptr(128), + }, + Processors: []SpanProcessor{ + { + Batch: &BatchSpanProcessor{ + ExportTimeout: ptr(30000), + Exporter: SpanExporter{ + OTLP: &OTLP{ + Certificate: ptr("/app/cert.pem"), + ClientCertificate: ptr("/app/cert.pem"), + ClientKey: ptr("/app/cert.pem"), + Compression: ptr("gzip"), + Endpoint: ptr("http://localhost:4318/v1/traces"), + Headers: []NameStringValuePair{ + {Name: "api-key", Value: ptr("1234")}, + }, + HeadersList: ptr("api-key=1234"), + Insecure: ptr(false), + Protocol: ptr("http/protobuf"), + Timeout: ptr(10000), + }, + }, + MaxExportBatchSize: ptr(512), + MaxQueueSize: ptr(2048), + ScheduleDelay: ptr(5000), + }, + }, + { + Batch: &BatchSpanProcessor{ + Exporter: SpanExporter{ + Zipkin: &Zipkin{ + Endpoint: ptr("http://localhost:9411/api/v2/spans"), + Timeout: ptr(10000), + }, + }, + }, + }, + { + Simple: &SimpleSpanProcessor{ + Exporter: SpanExporter{ + Console: Console{}, + }, + }, + }, + }, + Sampler: &Sampler{ + ParentBased: &SamplerParentBased{ + LocalParentNotSampled: &Sampler{ + AlwaysOff: SamplerAlwaysOff{}, + }, + LocalParentSampled: &Sampler{ + AlwaysOn: SamplerAlwaysOn{}, + }, + RemoteParentNotSampled: &Sampler{ + AlwaysOff: SamplerAlwaysOff{}, + }, + RemoteParentSampled: &Sampler{ + AlwaysOn: SamplerAlwaysOn{}, + }, + Root: &Sampler{ + TraceIDRatioBased: &SamplerTraceIDRatioBased{ + Ratio: ptr(0.0001), + }, + }, + }, + }, + }, +} + +func TestParseYAML(t *testing.T) { + tests := []struct { + name string + input string + wantErr error + wantType any + }{ + { + name: "valid YAML config", + input: `valid_empty.yaml`, + wantErr: nil, + wantType: &OpenTelemetryConfiguration{ + Disabled: ptr(false), + FileFormat: ptr("0.1"), + }, + }, + { + name: "invalid config", + input: "invalid_bool.yaml", + wantErr: errors.New(`yaml: unmarshal errors: + line 2: cannot unmarshal !!str ` + "`notabool`" + ` into bool`), + }, + { + name: "invalid nil name", + input: "invalid_nil_name.yaml", + wantErr: errors.New(`yaml: cannot unmarshal field name in NameStringValuePair required`), + }, + { + name: "invalid nil value", + input: "invalid_nil_value.yaml", + wantErr: errors.New(`yaml: cannot unmarshal field value in NameStringValuePair required`), + }, + { + name: "valid v0.2 config", + input: "v0.2.yaml", + wantErr: errors.New(`yaml: unmarshal errors: + line 81: cannot unmarshal !!map into []otelconf.NameStringValuePair + line 185: cannot unmarshal !!map into []otelconf.NameStringValuePair + line 244: cannot unmarshal !!seq into otelconf.IncludeExclude + line 305: cannot unmarshal !!map into []otelconf.NameStringValuePair + line 408: cannot unmarshal !!map into []otelconf.AttributeNameValue`), + }, + { + name: "valid v0.3 config", + input: "v0.3.yaml", + wantType: &v03OpenTelemetryConfig, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b, err := os.ReadFile(filepath.Join("..", "testdata", tt.input)) + require.NoError(t, err) + + got, err := ParseYAML(b) + if tt.wantErr != nil { + require.Error(t, err) + require.Equal(t, tt.wantErr.Error(), err.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.wantType, got) + } + }) + } +} + func TestUnmarshalBatchSpanProcessor(t *testing.T) { for _, tt := range []struct { name string @@ -439,6 +879,67 @@ func TestUnmarshalBatchSpanProcessor(t *testing.T) { }) } } +func TestSerializeJSON(t *testing.T) { + tests := []struct { + name string + input string + wantErr error + wantType any + }{ + { + name: "valid JSON config", + input: `valid_empty.json`, + wantErr: nil, + wantType: OpenTelemetryConfiguration{ + Disabled: ptr(false), + FileFormat: ptr("0.1"), + }, + }, + { + name: "invalid config", + input: "invalid_bool.json", + wantErr: errors.New(`json: cannot unmarshal string into Go struct field Plain.disabled of type bool`), + }, + { + name: "invalid nil name", + input: "invalid_nil_name.json", + wantErr: errors.New(`json: cannot unmarshal field name in NameStringValuePair required`), + }, + { + name: "invalid nil value", + input: "invalid_nil_value.json", + wantErr: errors.New(`json: cannot unmarshal field value in NameStringValuePair required`), + }, + { + name: "valid v0.2 config", + input: "v0.2.json", + wantErr: errors.New(`json: cannot unmarshal object into Go struct field LogRecordProcessor.logger_provider.processors.batch`), + }, + { + name: "valid v0.3 config", + input: "v0.3.json", + wantType: v03OpenTelemetryConfig, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b, err := os.ReadFile(filepath.Join("..", "testdata", tt.input)) + require.NoError(t, err) + + var got OpenTelemetryConfiguration + err = json.Unmarshal(b, &got) + + if tt.wantErr != nil { + require.Error(t, err) + require.ErrorContains(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.wantType, got) + } + }) + } +} func TestUnmarshalPeriodicMetricReader(t *testing.T) { for _, tt := range []struct { @@ -516,6 +1017,61 @@ func TestUnmarshalPeriodicMetricReader(t *testing.T) { }) } } +func TestCreateTLSConfig(t *testing.T) { + tests := []struct { + name string + caCertFile *string + clientCertFile *string + clientKeyFile *string + wantErrContains string + want func(*tls.Config, *testing.T) + }{ + { + name: "no-input", + want: func(result *tls.Config, t *testing.T) { + require.Nil(t, result.Certificates) + require.Nil(t, result.RootCAs) + }, + }, + { + name: "only-cacert-provided", + caCertFile: ptr(filepath.Join("..", "testdata", "ca.crt")), + want: func(result *tls.Config, t *testing.T) { + require.Nil(t, result.Certificates) + require.NotNil(t, result.RootCAs) + }, + }, + { + name: "nonexistent-cacert-file", + caCertFile: ptr("nowhere.crt"), + wantErrContains: "open nowhere.crt:", + }, + { + name: "nonexistent-clientcert-file", + clientCertFile: ptr("nowhere.crt"), + clientKeyFile: ptr("nowhere.crt"), + wantErrContains: "could not use client certificate: open nowhere.crt:", + }, + { + name: "bad-cacert-file", + caCertFile: ptr(filepath.Join("..", "testdata", "bad_cert.crt")), + wantErrContains: "could not create certificate authority chain from certificate", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := createTLSConfig(tt.caCertFile, tt.clientCertFile, tt.clientKeyFile) + + if tt.wantErrContains != "" { + require.Contains(t, err.Error(), tt.wantErrContains) + } else { + require.NoError(t, err) + tt.want(got, t) + } + }) + } +} func TestUnmarshalCardinalityLimits(t *testing.T) { for _, tt := range []struct { @@ -653,6 +1209,98 @@ func TestUnmarshalCardinalityLimits(t *testing.T) { }) } } +func TestCreateHeadersConfig(t *testing.T) { + tests := []struct { + name string + headers []NameStringValuePair + headersList *string + wantHeaders map[string]string + wantErr string + }{ + { + name: "no headers", + headers: []NameStringValuePair{}, + headersList: nil, + wantHeaders: map[string]string{}, + }, + { + name: "headerslist only", + headers: []NameStringValuePair{}, + headersList: ptr("a=b,c=d"), + wantHeaders: map[string]string{ + "a": "b", + "c": "d", + }, + }, + { + name: "headers only", + headers: []NameStringValuePair{ + { + Name: "a", + Value: ptr("b"), + }, + { + Name: "c", + Value: ptr("d"), + }, + }, + headersList: nil, + wantHeaders: map[string]string{ + "a": "b", + "c": "d", + }, + }, + { + name: "both headers and headerslist", + headers: []NameStringValuePair{ + { + Name: "a", + Value: ptr("b"), + }, + }, + headersList: ptr("c=d"), + wantHeaders: map[string]string{ + "a": "b", + "c": "d", + }, + }, + { + name: "headers supersedes headerslist", + headers: []NameStringValuePair{ + { + Name: "a", + Value: ptr("b"), + }, + { + Name: "c", + Value: ptr("override"), + }, + }, + headersList: ptr("c=d"), + wantHeaders: map[string]string{ + "a": "b", + "c": "override", + }, + }, + { + name: "invalid headerslist", + headersList: ptr("==="), + wantErr: "invalid headers list: invalid key: \"\"", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + headersMap, err := createHeadersConfig(tt.headers, tt.headersList) + if tt.wantErr != "" { + require.Error(t, err) + require.Equal(t, tt.wantErr, err.Error()) + } else { + require.NoError(t, err) + } + require.Equal(t, tt.wantHeaders, headersMap) + }) + } +} func TestCreateHeadersConfig(t *testing.T) { tests := []struct { diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 4e8bab5b282..3ff8184875a 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -41,6 +41,28 @@ func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. +func (j *AttributeNameValueType) UnmarshalYAML(unmarshal func(any) error) error { + var v struct { + Value any + } + if err := unmarshal(&v.Value); err != nil { + return err + } + var ok bool + for _, expected := range enumValuesAttributeNameValueType { + if reflect.DeepEqual(v.Value, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesAttributeNameValueType, v.Value) + } + *j = AttributeNameValueType(v) + return nil +} + // UnmarshalYAML implements yaml.Unmarshaler. func (j *SpanExporter) UnmarshalYAML(node *yaml.Node) error { type Plain SpanExporter @@ -122,6 +144,31 @@ func (j *BatchLogRecordProcessor) UnmarshalYAML(node *yaml.Node) error { *j = BatchLogRecordProcessor(plain) return nil } +func (j *NameStringValuePair) UnmarshalYAML(unmarshal func(any) error) error { + var raw map[string]any + if err := unmarshal(&raw); err != nil { + return err + } + if _, ok := raw["name"]; !ok { + return errors.New("yaml: cannot unmarshal field name in NameStringValuePair required") + } + if _, ok := raw["value"]; !ok { + return errors.New("yaml: cannot unmarshal field value in NameStringValuePair required") + } + var name, value string + var ok bool + if name, ok = raw["name"].(string); !ok { + return errors.New("yaml: cannot unmarshal field name in NameStringValuePair must be string") + } + if value, ok = raw["value"].(string); !ok { + return errors.New("yaml: cannot unmarshal field value in NameStringValuePair must be string") + } + *j = NameStringValuePair{ + Name: name, + Value: &value, + } + return nil +} // UnmarshalYAML implements yaml.Unmarshaler. func (j *BatchSpanProcessor) UnmarshalYAML(node *yaml.Node) error { @@ -443,3 +490,13 @@ func (j *PullMetricReader) UnmarshalYAML(node *yaml.Node) error { *j = PullMetricReader(plain) return nil } + +func (j *LanguageSpecificInstrumentation) UnmarshalYAML(unmarshal func(any) error) error { + var raw map[string]any + if err := unmarshal(&raw); err != nil { + return err + } + + *j = raw + return nil +} diff --git a/otelconf/fuzz_test.go b/otelconf/fuzz_test.go new file mode 100644 index 00000000000..0fd6289da2a --- /dev/null +++ b/otelconf/fuzz_test.go @@ -0,0 +1,64 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otelconf + +import ( + "context" + "encoding/json" + "os" + "path/filepath" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func FuzzJSON(f *testing.F) { + b, err := os.ReadFile(filepath.Join("..", "testdata", "v0.3.json")) + require.NoError(f, err) + f.Add(b) + + f.Fuzz(func(t *testing.T, data []byte) { + t.Log("JSON:\n" + string(data)) + + var cfg OpenTelemetryConfiguration + err := json.Unmarshal(b, &cfg) + if err != nil { + return + } + + sdk, err := NewSDK(WithOpenTelemetryConfiguration(cfg)) + if err != nil { + return + } + + ctx, cancel := context.WithTimeout(t.Context(), time.Millisecond) + defer cancel() + _ = sdk.Shutdown(ctx) + }) +} + +func FuzzYAML(f *testing.F) { + b, err := os.ReadFile(filepath.Join("..", "testdata", "v0.3.yaml")) + require.NoError(f, err) + f.Add(b) + + f.Fuzz(func(t *testing.T, data []byte) { + t.Log("YAML:\n" + string(data)) + + cfg, err := ParseYAML(data) + if err != nil { + return + } + + sdk, err := NewSDK(WithOpenTelemetryConfiguration(*cfg)) + if err != nil { + return + } + + ctx, cancel := context.WithTimeout(t.Context(), time.Millisecond) + defer cancel() + _ = sdk.Shutdown(ctx) + }) +} From ba8730ba7f41de8985aa145d8669cd6589ce1983 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:08:05 -0700 Subject: [PATCH 02/39] update AttributeNameValueType to AttributeType Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 12 ++++++------ otelconf/config_test.go | 16 ++++++++-------- otelconf/config_yaml.go | 8 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index c33dd47b1aa..6d271c64c3b 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -194,11 +194,11 @@ func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { } // MarshalJSON implements json.Marshaler. -func (j *AttributeNameValueType) MarshalJSON() ([]byte, error) { +func (j *AttributeType) MarshalJSON() ([]byte, error) { return json.Marshal(j.Value) } -var enumValuesAttributeNameValueType = []any{ +var enumValuesAttributeType = []any{ nil, "string", "bool", @@ -211,7 +211,7 @@ var enumValuesAttributeNameValueType = []any{ } // UnmarshalJSON implements json.Unmarshaler. -func (j *AttributeNameValueType) UnmarshalJSON(b []byte) error { +func (j *AttributeType) UnmarshalJSON(b []byte) error { var v struct { Value any } @@ -219,16 +219,16 @@ func (j *AttributeNameValueType) UnmarshalJSON(b []byte) error { return err } var ok bool - for _, expected := range enumValuesAttributeNameValueType { + for _, expected := range enumValuesAttributeType { if reflect.DeepEqual(v.Value, expected) { ok = true break } } if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesAttributeNameValueType, v.Value) + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesAttributeType, v.Value) } - *j = AttributeNameValueType(v) + *j = AttributeType(v) return nil } diff --git a/otelconf/config_test.go b/otelconf/config_test.go index b87b06f7917..33c769750e1 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -619,14 +619,14 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ Resource: &Resource{ Attributes: []AttributeNameValue{ {Name: "service.name", Value: "unknown_service"}, - {Name: "string_key", Type: &AttributeNameValueType{Value: "string"}, Value: "value"}, - {Name: "bool_key", Type: &AttributeNameValueType{Value: "bool"}, Value: true}, - {Name: "int_key", Type: &AttributeNameValueType{Value: "int"}, Value: 1}, - {Name: "double_key", Type: &AttributeNameValueType{Value: "double"}, Value: 1.1}, - {Name: "string_array_key", Type: &AttributeNameValueType{Value: "string_array"}, Value: []any{"value1", "value2"}}, - {Name: "bool_array_key", Type: &AttributeNameValueType{Value: "bool_array"}, Value: []any{true, false}}, - {Name: "int_array_key", Type: &AttributeNameValueType{Value: "int_array"}, Value: []any{1, 2}}, - {Name: "double_array_key", Type: &AttributeNameValueType{Value: "double_array"}, Value: []any{1.1, 2.2}}, + {Name: "string_key", Type: &AttributeType{Value: "string"}, Value: "value"}, + {Name: "bool_key", Type: &AttributeType{Value: "bool"}, Value: true}, + {Name: "int_key", Type: &AttributeType{Value: "int"}, Value: 1}, + {Name: "double_key", Type: &AttributeType{Value: "double"}, Value: 1.1}, + {Name: "string_array_key", Type: &AttributeType{Value: "string_array"}, Value: []any{"value1", "value2"}}, + {Name: "bool_array_key", Type: &AttributeType{Value: "bool_array"}, Value: []any{true, false}}, + {Name: "int_array_key", Type: &AttributeType{Value: "int_array"}, Value: []any{1, 2}}, + {Name: "double_array_key", Type: &AttributeType{Value: "double_array"}, Value: []any{1.1, 2.2}}, }, AttributesList: ptr("service.namespace=my-namespace,service.version=1.0.0"), Detectors: &Detectors{ diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 3ff8184875a..8f5e4917d85 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -42,7 +42,7 @@ func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { } // UnmarshalYAML implements yaml.Unmarshaler. -func (j *AttributeNameValueType) UnmarshalYAML(unmarshal func(any) error) error { +func (j *AttributeType) UnmarshalYAML(unmarshal func(any) error) error { var v struct { Value any } @@ -50,16 +50,16 @@ func (j *AttributeNameValueType) UnmarshalYAML(unmarshal func(any) error) error return err } var ok bool - for _, expected := range enumValuesAttributeNameValueType { + for _, expected := range enumValuesAttributeType { if reflect.DeepEqual(v.Value, expected) { ok = true break } } if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesAttributeNameValueType, v.Value) + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesAttributeType, v.Value) } - *j = AttributeNameValueType(v) + *j = AttributeType(v) return nil } From b21f94b6be9302fd8973de85d3235f35096e22fa Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:12:24 -0700 Subject: [PATCH 03/39] update Zipkin to ZipkinSpanExporter Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 9 +++++---- otelconf/config_test.go | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 6d271c64c3b..367298c3821 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -690,20 +690,21 @@ func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { *j = OTLPHttpExporter(sh.Plain) return nil } -func (j *Zipkin) UnmarshalJSON(b []byte) error { + +func (j *ZipkinSpanExporter) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { return err } if _, ok := raw["endpoint"]; raw != nil && !ok { - return errors.New("field endpoint in Zipkin: required") + return errors.New("field endpoint in ZipkinSpanExporter: required") } - type Plain Zipkin + type Plain ZipkinSpanExporter var plain Plain if err := json.Unmarshal(b, &plain); err != nil { return err } - *j = Zipkin(plain) + *j = ZipkinSpanExporter(plain) return nil } diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 33c769750e1..2efbcd09459 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -674,7 +674,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ { Batch: &BatchSpanProcessor{ Exporter: SpanExporter{ - Zipkin: &Zipkin{ + Zipkin: &ZipkinSpanExporter{ Endpoint: ptr("http://localhost:9411/api/v2/spans"), Timeout: ptr(10000), }, From 6c9e47c89b91e9e0231f8b01066484672ca5201d Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:14:10 -0700 Subject: [PATCH 04/39] rename LanguageSpecificInstrumentation -> ExperimentalLanguageSpecificInstrumentation Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_test.go | 22 +++++++++++----------- otelconf/config_yaml.go | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 2efbcd09459..bf8854a96a7 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -416,17 +416,17 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ AttributeValueLengthLimit: ptr(4096), }, Instrumentation: &Instrumentation{ - Cpp: LanguageSpecificInstrumentation{ + Cpp: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Dotnet: LanguageSpecificInstrumentation{ + Dotnet: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Erlang: LanguageSpecificInstrumentation{ + Erlang: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, @@ -449,42 +449,42 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, }, - Go: LanguageSpecificInstrumentation{ + Go: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Java: LanguageSpecificInstrumentation{ + Java: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Js: LanguageSpecificInstrumentation{ + Js: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Php: LanguageSpecificInstrumentation{ + Php: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Python: LanguageSpecificInstrumentation{ + Python: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Ruby: LanguageSpecificInstrumentation{ + Ruby: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Rust: LanguageSpecificInstrumentation{ + Rust: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, }, - Swift: LanguageSpecificInstrumentation{ + Swift: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", }, diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 8f5e4917d85..7fd045ce40e 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -491,7 +491,7 @@ func (j *PullMetricReader) UnmarshalYAML(node *yaml.Node) error { return nil } -func (j *LanguageSpecificInstrumentation) UnmarshalYAML(unmarshal func(any) error) error { +func (j *ExperimentalLanguageSpecificInstrumentation) UnmarshalYAML(unmarshal func(any) error) error { var raw map[string]any if err := unmarshal(&raw); err != nil { return err From 245cd8c046dde2082f9258bdbfd9b42fa8f60e61 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:17:41 -0700 Subject: [PATCH 05/39] Prometheus -> ExperimentalPrometheusMetricExporter Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/otelconf/config_test.go b/otelconf/config_test.go index bf8854a96a7..4272b1365a2 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -537,7 +537,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, Pull: &PullMetricReader{ Exporter: PullMetricExporter{ - Prometheus: &Prometheus{ + PrometheusDevelopment: &ExperimentalPrometheusMetricExporter{ Host: ptr("localhost"), Port: ptr(9464), WithResourceConstantLabels: &IncludeExclude{ From 1005fcbc0ac0561b3f3aa8888a293c6df7942ad8 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:20:09 -0700 Subject: [PATCH 06/39] Console -> ConsoleExporter Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 4272b1365a2..138123b0e94 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -523,7 +523,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ { Simple: &SimpleLogRecordProcessor{ Exporter: LogRecordExporter{ - Console: Console{}, + Console: ConsoleExporter{}, }, }, }, @@ -581,7 +581,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ { Periodic: &PeriodicMetricReader{ Exporter: PushMetricExporter{ - Console: Console{}, + Console: ConsoleExporter{}, }, }, }, @@ -684,7 +684,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ { Simple: &SimpleSpanProcessor{ Exporter: SpanExporter{ - Console: Console{}, + Console: ConsoleExporter{}, }, }, }, From 967e3c4d892a59903af2630a2c701d45a9e3d397 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:40:15 -0700 Subject: [PATCH 07/39] update OTLP exporter config Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_test.go | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 138123b0e94..1dce08dd9ed 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -500,18 +500,17 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ Batch: &BatchLogRecordProcessor{ ExportTimeout: ptr(30000), Exporter: LogRecordExporter{ - OTLP: &OTLP{ - Certificate: ptr("/app/cert.pem"), - ClientCertificate: ptr("/app/cert.pem"), - ClientKey: ptr("/app/cert.pem"), - Compression: ptr("gzip"), - Endpoint: ptr("http://localhost:4318/v1/logs"), + OTLPHttp: &OTLPHttpExporter{ + CertificateFile: ptr("/app/cert.pem"), + ClientCertificateFile: ptr("/app/cert.pem"), + ClientKeyFile: ptr("/app/cert.pem"), + Compression: ptr("gzip"), + Endpoint: ptr("http://localhost:4318/v1/logs"), Headers: []NameStringValuePair{ {Name: "api-key", Value: ptr("1234")}, }, HeadersList: ptr("api-key=1234"), Insecure: ptr(false), - Protocol: ptr("http/protobuf"), Timeout: ptr(10000), }, }, @@ -557,10 +556,10 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, Periodic: &PeriodicMetricReader{ Exporter: PushMetricExporter{ - OTLP: &OTLPMetric{ - Certificate: ptr("/app/cert.pem"), - ClientCertificate: ptr("/app/cert.pem"), - ClientKey: ptr("/app/cert.pem"), + OTLPHttp: &OTLPHttpMetricExporter{ + CertificateFile: ptr("/app/cert.pem"), + ClientCertificateFile: ptr("/app/cert.pem"), + ClientKeyFile: ptr("/app/cert.pem"), Compression: ptr("gzip"), DefaultHistogramAggregation: ptr(OTLPMetricDefaultHistogramAggregationBase2ExponentialBucketHistogram), Endpoint: ptr("http://localhost:4318/v1/metrics"), @@ -569,7 +568,6 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, HeadersList: ptr("api-key=1234"), Insecure: ptr(false), - Protocol: ptr("http/protobuf"), TemporalityPreference: ptr("delta"), Timeout: ptr(10000), }, @@ -651,18 +649,17 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ Batch: &BatchSpanProcessor{ ExportTimeout: ptr(30000), Exporter: SpanExporter{ - OTLP: &OTLP{ - Certificate: ptr("/app/cert.pem"), - ClientCertificate: ptr("/app/cert.pem"), - ClientKey: ptr("/app/cert.pem"), - Compression: ptr("gzip"), - Endpoint: ptr("http://localhost:4318/v1/traces"), + OTLPHttp: &OTLPHttpExporter{ + CertificateFile: ptr("/app/cert.pem"), + ClientCertificateFile: ptr("/app/cert.pem"), + ClientKeyFile: ptr("/app/cert.pem"), + Compression: ptr("gzip"), + Endpoint: ptr("http://localhost:4318/v1/traces"), Headers: []NameStringValuePair{ {Name: "api-key", Value: ptr("1234")}, }, HeadersList: ptr("api-key=1234"), Insecure: ptr(false), - Protocol: ptr("http/protobuf"), Timeout: ptr(10000), }, }, From 7f63de5dd08ca5d1ba7e028d68f6be17ddc04284 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 14:27:45 -0700 Subject: [PATCH 08/39] add testdata Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/v1.0.0-rc.1/testdata/ca.crt | 22 +++++++++++++++ otelconf/v1.0.0-rc.1/testdata/ca.key | 28 +++++++++++++++++++ .../testdata/client-certs/client.crt | 22 +++++++++++++++ .../testdata/client-certs/client.csr | 18 ++++++++++++ .../testdata/client-certs/client.key | 28 +++++++++++++++++++ .../testdata/server-certs/server.crt | 22 +++++++++++++++ .../testdata/server-certs/server.csr | 18 ++++++++++++ .../testdata/server-certs/server.key | 28 +++++++++++++++++++ 8 files changed, 186 insertions(+) create mode 100644 otelconf/v1.0.0-rc.1/testdata/ca.crt create mode 100644 otelconf/v1.0.0-rc.1/testdata/ca.key create mode 100644 otelconf/v1.0.0-rc.1/testdata/client-certs/client.crt create mode 100644 otelconf/v1.0.0-rc.1/testdata/client-certs/client.csr create mode 100644 otelconf/v1.0.0-rc.1/testdata/client-certs/client.key create mode 100644 otelconf/v1.0.0-rc.1/testdata/server-certs/server.crt create mode 100644 otelconf/v1.0.0-rc.1/testdata/server-certs/server.csr create mode 100644 otelconf/v1.0.0-rc.1/testdata/server-certs/server.key diff --git a/otelconf/v1.0.0-rc.1/testdata/ca.crt b/otelconf/v1.0.0-rc.1/testdata/ca.crt new file mode 100644 index 00000000000..51013bceb5d --- /dev/null +++ b/otelconf/v1.0.0-rc.1/testdata/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIUBxmeJyLb45dq6RmW5bOFIl8VON0wDQYJKoZIhvcNAQEL +BQAwXzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM +DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxDjAMBgNVBAMMBU15 +IENBMB4XDTI1MDQxNTEyMjM0MloXDTI2MDQxNTEyMjM0MlowXzELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x +EzARBgNVBAoMCk15IENvbXBhbnkxDjAMBgNVBAMMBU15IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3ywD9NQpjd2H/PaHnodeX6YWn67OaqODTsUs +mOcJphhfya+/lybNtWScHoiURpB40QhTacDsjQ7J0Trykznm6ynl06uSQZKONVxo +LW+FmCBDRE+BqmFBFdMEMvRBGVxns7IctzY//GaZbX81Ni1pyLrzrRG9B5LuU7Sb +yggByJrut72RC7bRgAz8v2s++JKvDVKRk3hTmSwCiEC30s9QUu1N9BGnib5V09v/ +Sa7wseVp7ICGC0YckCkJMIjvzpaVMFA9/uMHFnloty+gMs/eMWGw0bb391QJb+k8 +WQHRZAlKTaLKVqeXC5G5CvK+u3q6j+4hQG46IclOJ76lRY//MwIDAQABo1MwUTAd +BgNVHQ4EFgQU5QWO+akQtDDflpGrTaXR4zEeah8wHwYDVR0jBBgwFoAU5QWO+akQ +tDDflpGrTaXR4zEeah8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC +AQEAkNcppwcF+zjeZNmzGTccO1lSkPeC2LLlp/oEna0KUEGuKDFCemamxvESmua0 ++bXt9vw1qd+VztDIZ+zB+yAYYWyKYm41Nu1+IweLD8jmKPoQc5UXiWlSdF1Sjeub +9vcuX/G+FPOAGklt6X62y/jnlcumv1SOMB2BftSdD1Co8Yl9NRqFf3/OiEvd10bH +UXttTae4XEOp5p06ZFHW4JAnrHWBeuiLNJoswdKbA3rQO1Z6u5ioakluNHiCJX6T +fcJxbEVmorLNfBOnZTm61rPsC5aVtvFAxXDDb6B00KBW9FrV9m2MEFw71bMmC8X3 +rFaC9Gm5g2bfyX/65YBQyLwXRA== +-----END CERTIFICATE----- diff --git a/otelconf/v1.0.0-rc.1/testdata/ca.key b/otelconf/v1.0.0-rc.1/testdata/ca.key new file mode 100644 index 00000000000..2606228e841 --- /dev/null +++ b/otelconf/v1.0.0-rc.1/testdata/ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDfLAP01CmN3Yf8 +9oeeh15fphafrs5qo4NOxSyY5wmmGF/Jr7+XJs21ZJweiJRGkHjRCFNpwOyNDsnR +OvKTOebrKeXTq5JBko41XGgtb4WYIENET4GqYUEV0wQy9EEZXGezshy3Nj/8Zplt +fzU2LWnIuvOtEb0Hku5TtJvKCAHImu63vZELttGADPy/az74kq8NUpGTeFOZLAKI +QLfSz1BS7U30EaeJvlXT2/9JrvCx5WnsgIYLRhyQKQkwiO/OlpUwUD3+4wcWeWi3 +L6Ayz94xYbDRtvf3VAlv6TxZAdFkCUpNospWp5cLkbkK8r67erqP7iFAbjohyU4n +vqVFj/8zAgMBAAECggEACkVl4TdjZN/brUJRmx5rz4AGChZ5R1QKT7WL3XWmbnpM +s54Jg/h7N6VPTozjFh0zLrgbmVeDfVYGdSS30/9Ap+b1hRwuXQap7i+p5YunTpeB +Fl/6YU/x4clBGcZbnRdqFKLkyox/9rkvcoSoe2YQjdoHgP2ecxsCfzWCTD1kUkoJ +JFynOn/Typ5umABoOxrZASMSZYrGM1jAzlA2k66ntq+cv26gne0cfuT0LHLJHwZE +7OaMfSo0xaovz+G81msTZZJ8uYOX64v7k+DwTxY+8WUA/H38caDHgHGpO7/ZbYax +VSeVAcUARV/wUgS4VZlqy+mnAl4XppHHpqx1vRIhAQKBgQDvzOwKBxb4uHF7I3kd +5+9kaDh7VzD7HdR1UyLFFSJCeMlGplJaUlpNMQiOtzQj2/AEfn3GqIMX00TLcdzA +ztY1pmaHWPxXHYuYq9P+v+a2jn1MrhRChCOB+7awp1aBSQfi5AFxmbCTFyRMUlZo +powvwBL7e5XC2yCbsFwPWr0VcwKBgQDuP4WImU9mH6tScFRprvWqwwJJQkV7O3km +HgBRR+9++sVWga/U2vA/hV/E3/k0h9m2aezAPW76tvttkgd3WvhxlxtK6f/9geMB +E2fMhnD9MSCU+a6DAr/yRd7ZZQoaQPszhSpDevNo2RSAkQcKYmo3v53KPCRcZkfT +yvyDRBD/QQKBgEi0WsRXjfFvCokJIkmc7ooEx0suDl20l5vSzvHuDGsW7/+JoeJc +oaBRw4Rxq09L+aODLmMy6DwrA+qi5QlYLL4ra16R7kADZzWssyPDzxF+diLvjJj2 +M0XPqX453hJosAlsk7t7m3udQpYZSLWF+W7oz1iMCcYAZgyOFftZyYZdAoGBAJP1 +JvyaGVEWwdLEp+eqHC8cREMywOuzF52wbAoOXpHBMuRyTbwm66THM56UabNR2scK +KVmJzW4uTR7S3YgmGryQVwbDI5NQIqX8Yy4FIA5dgBqEpPf/sSzIb4ka0pdTW623 +OXQG2zt19OGTL4gnbkeI3HlHuF0Zt+mz2fW7Q8MBAoGBAK8b40DO5VYks7AP+EhJ +OBOiNx4AC6KpKjF60undjfqO2Rt32h7FlS9YScdrxRaXOafebCC0OrgxpnA/HE5Y +pyHWJ4kPMlGFLR9vb0nuxS72v3xiPdV8dIUDcE+fdr873CtTpvSdyDAIizRCeZKO +Sv03W0utXEnISreIFVOv5DVJ +-----END PRIVATE KEY----- diff --git a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.crt b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.crt new file mode 100644 index 00000000000..9c19e635cd8 --- /dev/null +++ b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIUKlT4T6hHDXsut6dUk9GVedYGsnIwDQYJKoZIhvcNAQEL +BQAwXzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM +DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxDjAMBgNVBAMMBU15 +IENBMB4XDTI1MDQxNTEyMjQwMloXDTI2MDQxNTEyMjQwMlowYzELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x +EzARBgNVBAoMCk15IENvbXBhbnkxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBANOZK2z5lCPc//y3IiLZxSqFs5o6Z/Rk +2AY+jMe7xzEGihxcjtcrSdn5hmmklL536TvOfLqU9D8wINeAMP0XLbAi23AMiAJP +rcgUIvY7XcB3ujUdtOZWOBCbpvOfOdS50nQPh1w6bHl2dJmO9P0WXIr3WDMBmf2m +CeUwggqGhKKMvUjawiTcT3dseZyJyFghnv5sERC7XVQlMZI27qGLi/gcHKpQ63IS +wVOoJf/D+8TCkgkPhre0q9a5VOdtCt6sjFaHLyMj8lnM7ZJwLFLW5aDCqxzBN1Qy +5Utd3RiTXIRUcnWO4T0xYBSKmkdOqr9P5ytLKvQf090LpbAS1MvAqlsCAwEAAaNY +MFYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MB0GA1UdDgQWBBQBWxmwxzxSiV9heDSd +rXfwUQe9xjAfBgNVHSMEGDAWgBTlBY75qRC0MN+WkatNpdHjMR5qHzANBgkqhkiG +9w0BAQsFAAOCAQEA01nQZ/HHFq4g3hXBQUncr/21789F2SEjRUiO9kRXGL1VkGfK +cL7eqQYncpV5cKWMHM9XBs88TypL4CEP+XRSWXp8G/dQeKtwV5RMPxcSS508w+kF +0/hGWm3xkrwEQSs0cn/2uiXoRLIoWX2/2R45nd5YJZdPJ7SGzfxCpNvw81y740+G +6nR3n9Zocbc26Tj6aLhuXqDTA9nFVWqdoYqZ60dyse22oLqF7GNo8Onfrs7kbcBb +qx7QFg+mnAanqHVAIuDDZv/zeHewYQM7hlys/Qig0ZPxyh+MJY013HoFd0CPzndi +XEQxktfA9iRaDVkB+kRoxof4xoUAiWEohkn6HQ== +-----END CERTIFICATE----- diff --git a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.csr b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.csr new file mode 100644 index 00000000000..b2c90a59625 --- /dev/null +++ b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICzzCCAbcCAQAwYzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxEjAQ +BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANOZK2z5lCPc//y3IiLZxSqFs5o6Z/Rk2AY+jMe7xzEGihxcjtcrSdn5hmmklL53 +6TvOfLqU9D8wINeAMP0XLbAi23AMiAJPrcgUIvY7XcB3ujUdtOZWOBCbpvOfOdS5 +0nQPh1w6bHl2dJmO9P0WXIr3WDMBmf2mCeUwggqGhKKMvUjawiTcT3dseZyJyFgh +nv5sERC7XVQlMZI27qGLi/gcHKpQ63ISwVOoJf/D+8TCkgkPhre0q9a5VOdtCt6s +jFaHLyMj8lnM7ZJwLFLW5aDCqxzBN1Qy5Utd3RiTXIRUcnWO4T0xYBSKmkdOqr9P +5ytLKvQf090LpbAS1MvAqlsCAwEAAaAnMCUGCSqGSIb3DQEJDjEYMBYwFAYDVR0R +BA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQCHElfAx2wYlI/cLYTv +QTVVbzkF4EhXNrpg8XNZkEC40IdQ+FbWbmJMjtd/PnyZ4G18PII2L+Pw8a835qsF +0oelcEq1xJnLDik330DRh2GyAOUL0zahLHNIoz1j3rlQZNC7WWWrPKJW4bpJhw/7 +E++Q4xLoqwuhKitRu3DNWY28/JCpzHUhlngLl/FKyo8KQL4ttC357NLF3lnLabkj +V4UUWDyazvZeq/DahnWEQ3M/KD1FpzP/AgqDEur3f1bszdrAGH0aSMfk5zymklbu +y5NrkQzB9EjsF78aATQMxI+moWWJgo5rNFAo8/J/khNPjcFlxcNMICe+hGonH9KK +YWse +-----END CERTIFICATE REQUEST----- diff --git a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.key b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.key new file mode 100644 index 00000000000..0ff9d12afe7 --- /dev/null +++ b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDTmSts+ZQj3P/8 +tyIi2cUqhbOaOmf0ZNgGPozHu8cxBoocXI7XK0nZ+YZppJS+d+k7zny6lPQ/MCDX +gDD9Fy2wIttwDIgCT63IFCL2O13Ad7o1HbTmVjgQm6bznznUudJ0D4dcOmx5dnSZ +jvT9FlyK91gzAZn9pgnlMIIKhoSijL1I2sIk3E93bHmcichYIZ7+bBEQu11UJTGS +Nu6hi4v4HByqUOtyEsFTqCX/w/vEwpIJD4a3tKvWuVTnbQrerIxWhy8jI/JZzO2S +cCxS1uWgwqscwTdUMuVLXd0Yk1yEVHJ1juE9MWAUippHTqq/T+crSyr0H9PdC6Ww +EtTLwKpbAgMBAAECggEAKIlAW3kYmyI8XCKNRJXpgrLobFRiE9y50cBr4dukVk0F +aleE+c2OMVbvHA/ueuqn4NA27tuYSv6iXAZv3BxzoTmcRkPwTlkLVrgc1oUa+cM2 +BfTx8ep0hSH8gtFvF8Sdf6R17wI2Q7KgtcZAQrfk9K5b1DGrWX9Uh/aaAwAwKp9o +S83DpTmef/WMvSuJP5GauSltjRctyvWqSqjXW2bGmeBB/hNF8INmZWbVaKia+Nes +niiqmy1n8dAnGH8YsISZRuuthFO0I+TSlb9s9aLSArUz5eMvGzLICfQ+GpJAL0wv +n50VwQHHkgf+FsWdfrskifOUOzXm6qMC2V0f3fDEsQKBgQD4LYjPAMWlmX5K8dBO +qjTShlDv0iteDf8j8tLV2vNTq7haBMnPoFqpOlfj0QY4mJ7ZRRilAWFo0EWtZ9TR +Qttr+/Ao7ogbUwbw41IxJQUrfGy9R8LRkjOzGVcmUmG2fJJH7qeiVpqausQmHqrZ +Z++4yQzHRNYrMFNmiwNuQvQ1QwKBgQDaRHyjSven0OueiKBYkD1gCdUN52EPpQPq +LXz4+3v6tNobtF3Ra1+U7qcArdAurmZeQaTwHGYUXiX9VAl9QEdvWwoZG3FREgzK +8MYLOZGLs9aPGM9l5IpQa1Eyz+R573IYV8mMyiyl6ahv0gcslK0g7JwZcq9iJ3NG +3XM0zRfZCQKBgHGWDZaIiO1ZCids82T9m717AhIxQ+4BQ/QFECAW3OU/o9l3dZJU +lwn7DPzUzx8aIyHX8QacUiPxpuJNsmawTdLndSyWt66h2nxn3ldl1S7o/K/I506Z +tpXTFEMS02v9KcpIXWr8bjhBIMM9p/5nBp2xTurpA4iyzokRONm/RRwXAoGBAIlr +wUVWN+LSqOZhgwL/nYTP6/IbEYM2E+bmyN5CB+bq4r+6qa7meYFdWIwW4xHg/9as +YdpDJwn/1M9Qj8DqLY+wtATmwEuYn7FOMoJytm5MxfPGXR377BGB39esCF+1IBKv +gtg/mijDmib9B0NMQEyQbB+hk0arK+scFiLSVgdxAoGBAJgPn1ioygEwVm5QqQ1U +7VZXLGxsAaghDlqJNmZPFtoIFuzfdVn2OOioYJBdNhs7xH0vjfDoYXqLh3p3bSJZ +Jb3FtALaK/fGPeJRIF6P9x18sOE5k5jnedbNRlbZir1oJcaVgTd6jFkcVnhBX98t +nLa8Nu24UI0ROy4TKpG5eOZ0 +-----END PRIVATE KEY----- diff --git a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.crt b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.crt new file mode 100644 index 00000000000..8e875ee86a1 --- /dev/null +++ b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIUKlT4T6hHDXsut6dUk9GVedYGsnEwDQYJKoZIhvcNAQEL +BQAwXzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM +DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxDjAMBgNVBAMMBU15 +IENBMB4XDTI1MDQxNTEyMjM1NVoXDTI2MDQxNTEyMjM1NVowYzELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x +EzARBgNVBAoMCk15IENvbXBhbnkxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMZnNX0adWFrF/ZENvDOAj54BWg+UDIj +6xG10GE7IRJ2xwEJ6DI0VYByKXWciOqpcSzy8S09SlhoieSdothhnAHxNoNz3ElE +vUz1wuRhTlxm5Sts31yOg2F4UWTaWM/EdaK10Om5LLJOqeKVVPMVRER9LazMPIry +jgmQEEpVHNjiRgwSdNQSorNlAhHQu8ypzSNSj3oMLZ869RUUUqqoxBkCpp9KpsfU +ttgf4ociwUGn2GxCYKijosbnN0pF7utQOirseROD14LZ1JrHJQ4Ywwemp/8tFrUR +KD7xqwLtN5YfZsjp2DMVAvTzmYn4/+T1b0VDvYGHiRacC9uytYIFJf8CAwEAAaNY +MFYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MB0GA1UdDgQWBBQm7ZfyRLZ9UXzRn7qu +MAtp+HJ/wDAfBgNVHSMEGDAWgBTlBY75qRC0MN+WkatNpdHjMR5qHzANBgkqhkiG +9w0BAQsFAAOCAQEAdEOyjOwve3+nDVUdEzBNILCFOplsMW0fap8ghj3QIN+U2Hjb +zZb/LEMUWSbLxMAOheOo/AF2MFBrG+OhgVtqDIVefpzViCIxFKqgsnHDoDB5jO3X +C6Csl1QmuE76Y/4nprS1H7UNbgK9wOlEkScPxodIZnC+MghGFxczshb1v5YmkbYL +aAXt4Aa2c5zgiF39ZNfDnuhtenIWWT9YaMrCI3xYcXsaWHzZigKwTDCUNDGaAbd5 +cMSQhOYoz5HKzyFsiVYWBY4vk7FPrBu0ZxOLyNBxsS3w4q/YUY+66LyMwbsnFLg6 +s/6hFfJdGic/WMPP+Z87eb33vb2Dqa/845XwBg== +-----END CERTIFICATE----- diff --git a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.csr b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.csr new file mode 100644 index 00000000000..4bfcb7fd3f3 --- /dev/null +++ b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICzzCCAbcCAQAwYzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxEjAQ +BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMZnNX0adWFrF/ZENvDOAj54BWg+UDIj6xG10GE7IRJ2xwEJ6DI0VYByKXWciOqp +cSzy8S09SlhoieSdothhnAHxNoNz3ElEvUz1wuRhTlxm5Sts31yOg2F4UWTaWM/E +daK10Om5LLJOqeKVVPMVRER9LazMPIryjgmQEEpVHNjiRgwSdNQSorNlAhHQu8yp +zSNSj3oMLZ869RUUUqqoxBkCpp9KpsfUttgf4ociwUGn2GxCYKijosbnN0pF7utQ +OirseROD14LZ1JrHJQ4Ywwemp/8tFrURKD7xqwLtN5YfZsjp2DMVAvTzmYn4/+T1 +b0VDvYGHiRacC9uytYIFJf8CAwEAAaAnMCUGCSqGSIb3DQEJDjEYMBYwFAYDVR0R +BA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQBbMTNbsuUXm9FsRKrf +Q3nDMzUr9VUPlQXT0YymwhpnWkpk9iRjc/oljwaPioRdJJ9ZJdcvjAWnWcM9DUFs +n5rGeXMIXN3e5kuGNa5cz16QENCYkbaW7BYRYuRBDSxHdh6vOxv7RpXSLA9xmZ3m +Oy1Oye5sQb1hfXrIfXrSYrZxoSICNqeU8J3ql3ACyayxmQhIgd0PMM1C8wcBOJeA +OeTFMRfiBVBFp2WP192KYzLCth2mi7rUf3jwaHMzPMRNsh2n+yC2w0IU9ZxhXorL +luyMLTZ25qKrvYr9ibJV+NJRzoxeqXYz7JVoYUSJ1N/fGLy/OpR7uHoyJipXXU6E +HVch +-----END CERTIFICATE REQUEST----- diff --git a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.key b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.key new file mode 100644 index 00000000000..4a86c6dd69c --- /dev/null +++ b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDGZzV9GnVhaxf2 +RDbwzgI+eAVoPlAyI+sRtdBhOyESdscBCegyNFWAcil1nIjqqXEs8vEtPUpYaInk +naLYYZwB8TaDc9xJRL1M9cLkYU5cZuUrbN9cjoNheFFk2ljPxHWitdDpuSyyTqni +lVTzFUREfS2szDyK8o4JkBBKVRzY4kYMEnTUEqKzZQIR0LvMqc0jUo96DC2fOvUV +FFKqqMQZAqafSqbH1LbYH+KHIsFBp9hsQmCoo6LG5zdKRe7rUDoq7HkTg9eC2dSa +xyUOGMMHpqf/LRa1ESg+8asC7TeWH2bI6dgzFQL085mJ+P/k9W9FQ72Bh4kWnAvb +srWCBSX/AgMBAAECggEANTYvIVt8SeF4LsOC3LjT3z8/bALybVA21qwltD4wk4wp +uXyXuwdQOz/jILkX+5/wS7boulJq4yU+foNMzq33MoooLb9gQIJgJwju+WOjqaKr +KidsDJ3oXLbxVZQ+J5MwXbBX1Kemdjgk1jFo9D0q7xeHrYWlYzrEn4n05IrJTt1/ +1iVzyOA6TvxBCFlAOANhwyZdvOLOMg8KqpQZEbmwemUGCOPVJLknoG04nDYn/5SR +nSlrmSJeqNVu5PIeAy8DR0hAAvggLHf9os56qoP/bXSyFbryabUIG6DsUT1Py8YP +kLKqS/IQhTWjXgjzaaEQOLFZkIiO3/hkoPg/djqcgQKBgQD0PA+gRItT9Sw6vwqk +TtazoN3lSP9QXJODlc3XTO0AiwClNwqseCwmrpIFT4ylz4Mn737EPfyPOSOclkoJ +WzvaiP721ErrCtv57oLOerhEGixEMmZQYzfDPJwT5Ui8k/ThWd1XwWCspVy5+IlJ ++uD21rue136LlQQSK4kqmCZDwQKBgQDP9fKE41yO4cezHRXAUbbvaRUfl565+PvC +3CRVU4b6rhnEu5q6hnIZ9ol3EfDIW/uDRL+jbbnpSN9pcMEOivtNJVmaJONEk0EC +b9oN4mijYD6UhsdxTBq0VQ9nohjsTesHmaHNaJisIquPoN6+ZaNdY5mbpM3/heLi +52v3CIrZvwKBgQCp6ecNHuK3pEgDDsm+icLA8VeunlxRcjaGQwATm0b/K7VlO6fH +WUuOFcEsxK0a5gVfETVmHaHJmnz2AXC8laZMYSbQXd1JLCLh/FcwgxwS9Qp6331i +y8QNpesHxGoYF+8zoCtnU/eH5PtfvlL1Dv7Xe4jH9y/ot+E/Kt6grX1hgQKBgQCo +1q3HZjBHcNeJfBukwLMdPNuBgr/DjXoZglGdVOtJqwAQ0Z+VwIHywk5o9Y/fm45f +zPkp3nQKCrgYCwsym3Pb9m8AzuIVUth8+gK3MxJxUjp8q9BRE9C6iDSxltFVSQ2A +ZiMPedQ6LQvM2Hb/bdVshOi5jNwSkMjcH7dwIOdaUQKBgQDapokikGG3Suzq6qSy +8XkYLHlqBKo3aPdkqmSleziIJ1yPv64kpZuRd3WREHgJvWwSdy4V2eKU3TW/8cCQ +40kTA49cwgl0cTSOc88NnsBJ34n1ebA8Y50CKPAQP/Jw44+i62KUwJLuUPRCgndy +S6sEyFQNSn6RduzwFIUUx2XjpQ== +-----END PRIVATE KEY----- From c9611d9af058f401b2683b5abcd2e1d066a64bb2 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 14:28:53 -0700 Subject: [PATCH 09/39] update config Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config.go | 9 ++--- otelconf/config_json.go | 68 +++++++++++++++++++++++++---------- otelconf/config_test.go | 79 ++++++++++++++++++----------------------- 3 files changed, 89 insertions(+), 67 deletions(-) diff --git a/otelconf/config.go b/otelconf/config.go index 2e373e27e47..068110e7032 100644 --- a/otelconf/config.go +++ b/otelconf/config.go @@ -26,9 +26,6 @@ import ( ) const ( - protocolProtobufHTTP = "http/protobuf" - protocolProtobufGRPC = "grpc" - compressionGzip = "gzip" compressionNone = "none" ) @@ -95,7 +92,11 @@ func NewSDK(opts ...ConfigurationOption) (SDK, error) { return noopSDK, nil } - r := newResource(o.opentelemetryConfig.Resource) + resource, ok := o.opentelemetryConfig.Resource.(ResourceJson) + if !ok { + return noopSDK, errors.New("invalid resource") + } + r := newResource(&resource) mp, mpShutdown, err := meterProvider(o, r) if err != nil { diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 367298c3821..588f9f20d06 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -354,23 +354,23 @@ func (j *BatchSpanProcessor) UnmarshalJSON(b []byte) error { } // UnmarshalJSON implements json.Unmarshaler. -func (j *GeneralInstrumentationPeerServiceMappingElem) UnmarshalJSON(b []byte) error { +func (j *ExperimentalPeerInstrumentationServiceMappingElem) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { return err } if _, ok := raw["peer"]; raw != nil && !ok { - return errors.New("field peer in GeneralInstrumentationPeerServiceMappingElem: required") + return errors.New("field peer in ExperimentalPeerInstrumentationServiceMappingElem: required") } if _, ok := raw["service"]; raw != nil && !ok { - return errors.New("field service in GeneralInstrumentationPeerServiceMappingElem: required") + return errors.New("field service in ExperimentalPeerInstrumentationServiceMappingElem: required") } - type Plain GeneralInstrumentationPeerServiceMappingElem + type Plain ExperimentalPeerInstrumentationServiceMappingElem var plain Plain if err := json.Unmarshal(b, &plain); err != nil { return err } - *j = GeneralInstrumentationPeerServiceMappingElem(plain) + *j = ExperimentalPeerInstrumentationServiceMappingElem(plain) return nil } @@ -408,7 +408,7 @@ var enumValuesOTLPMetricDefaultHistogramAggregation = []any{ } // UnmarshalJSON implements json.Unmarshaler. -func (j *OTLPMetricDefaultHistogramAggregation) UnmarshalJSON(b []byte) error { +func (j *ExporterDefaultHistogramAggregation) UnmarshalJSON(b []byte) error { var v string if err := json.Unmarshal(b, &v); err != nil { return err @@ -423,12 +423,12 @@ func (j *OTLPMetricDefaultHistogramAggregation) UnmarshalJSON(b []byte) error { if !ok { return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesOTLPMetricDefaultHistogramAggregation, v) } - *j = OTLPMetricDefaultHistogramAggregation(v) + *j = ExporterDefaultHistogramAggregation(v) return nil } // UnmarshalJSON implements json.Unmarshaler. -func (j *OTLPMetric) UnmarshalJSON(b []byte) error { +func (j *OTLPHttpMetricExporter) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { return err @@ -436,20 +436,35 @@ func (j *OTLPMetric) UnmarshalJSON(b []byte) error { if _, ok := raw["endpoint"]; raw != nil && !ok { return errors.New("field endpoint in OTLPMetric: required") } - if _, ok := raw["protocol"]; raw != nil && !ok { - return errors.New("field protocol in OTLPMetric: required") + type Plain OTLPHttpMetricExporter + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = OTLPHttpMetricExporter(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *OTLPGrpcMetricExporter) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["endpoint"]; raw != nil && !ok { + return errors.New("field endpoint in OTLPMetric: required") } - type Plain OTLPMetric + type Plain OTLPGrpcMetricExporter var plain Plain if err := json.Unmarshal(b, &plain); err != nil { return err } - *j = OTLPMetric(plain) + *j = OTLPGrpcMetricExporter(plain) return nil } // UnmarshalJSON implements json.Unmarshaler. -func (j *OTLP) UnmarshalJSON(b []byte) error { +func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { return err @@ -457,15 +472,30 @@ func (j *OTLP) UnmarshalJSON(b []byte) error { if _, ok := raw["endpoint"]; raw != nil && !ok { return errors.New("field endpoint in OTLP: required") } - if _, ok := raw["protocol"]; raw != nil && !ok { - return errors.New("field protocol in OTLP: required") + type Plain OTLPHttpExporter + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err } - type Plain OTLP + *j = OTLPHttpExporter(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *OTLPGrpcExporter) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["endpoint"]; raw != nil && !ok { + return errors.New("field endpoint in OTLP: required") + } + type Plain OTLPGrpcExporter var plain Plain if err := json.Unmarshal(b, &plain); err != nil { return err } - *j = OTLP(plain) + *j = OTLPGrpcExporter(plain) return nil } @@ -648,7 +678,7 @@ var enumValuesViewSelectorInstrumentType = []any{ } // UnmarshalJSON implements json.Unmarshaler. -func (j *ViewSelectorInstrumentType) UnmarshalJSON(b []byte) error { +func (j *InstrumentType) UnmarshalJSON(b []byte) error { var v string if err := json.Unmarshal(b, &v); err != nil { return err @@ -663,7 +693,7 @@ func (j *ViewSelectorInstrumentType) UnmarshalJSON(b []byte) error { if !ok { return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesViewSelectorInstrumentType, v) } - *j = ViewSelectorInstrumentType(v) + *j = InstrumentType(v) return nil } diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 1dce08dd9ed..4f5bbd17383 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -373,9 +373,9 @@ func TestNewSDK(t *testing.T) { cfg: []ConfigurationOption{ WithContext(t.Context()), WithOpenTelemetryConfiguration(OpenTelemetryConfiguration{ - TracerProvider: &TracerProvider{}, - MeterProvider: &MeterProvider{}, - LoggerProvider: &LoggerProvider{}, + TracerProvider: &TracerProviderJson{}, + MeterProvider: &MeterProviderJson{}, + LoggerProvider: &LoggerProviderJson{}, }), }, wantTracerProvider: &sdktrace.TracerProvider{}, @@ -388,9 +388,9 @@ func TestNewSDK(t *testing.T) { WithContext(t.Context()), WithOpenTelemetryConfiguration(OpenTelemetryConfiguration{ Disabled: ptr(true), - TracerProvider: &TracerProvider{}, - MeterProvider: &MeterProvider{}, - LoggerProvider: &LoggerProvider{}, + TracerProvider: &TracerProviderJson{}, + MeterProvider: &MeterProviderJson{}, + LoggerProvider: &LoggerProviderJson{}, }), }, wantTracerProvider: tracenoop.NewTracerProvider(), @@ -410,12 +410,12 @@ func TestNewSDK(t *testing.T) { var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ Disabled: ptr(false), - FileFormat: ptr("0.3"), + FileFormat: "0.3", AttributeLimits: &AttributeLimits{ AttributeCountLimit: ptr(128), AttributeValueLengthLimit: ptr(4096), }, - Instrumentation: &Instrumentation{ + InstrumentationDevelopment: &InstrumentationJson{ Cpp: ExperimentalLanguageSpecificInstrumentation{ "example": map[string]any{ "property": "value", @@ -431,19 +431,19 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ "property": "value", }, }, - General: &GeneralInstrumentation{ - Http: &GeneralInstrumentationHttp{ - Client: &GeneralInstrumentationHttpClient{ + General: &ExperimentalGeneralInstrumentation{ + Http: &ExperimentalHttpInstrumentation{ + Client: &ExperimentalHttpInstrumentationClient{ RequestCapturedHeaders: []string{"Content-Type", "Accept"}, ResponseCapturedHeaders: []string{"Content-Type", "Content-Encoding"}, }, - Server: &GeneralInstrumentationHttpServer{ + Server: &ExperimentalHttpInstrumentationServer{ RequestCapturedHeaders: []string{"Content-Type", "Accept"}, ResponseCapturedHeaders: []string{"Content-Type", "Content-Encoding"}, }, }, - Peer: &GeneralInstrumentationPeer{ - ServiceMapping: []GeneralInstrumentationPeerServiceMappingElem{ + Peer: &ExperimentalPeerInstrumentation{ + ServiceMapping: []ExperimentalPeerInstrumentationServiceMappingElem{ {Peer: "1.2.3.4", Service: "FooService"}, {Peer: "2.3.4.5", Service: "BarService"}, }, @@ -490,7 +490,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, }, - LoggerProvider: &LoggerProvider{ + LoggerProvider: &LoggerProviderJson{ Limits: &LogRecordLimits{ AttributeCountLimit: ptr(128), AttributeValueLengthLimit: ptr(4096), @@ -510,7 +510,6 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ {Name: "api-key", Value: ptr("1234")}, }, HeadersList: ptr("api-key=1234"), - Insecure: ptr(false), Timeout: ptr(10000), }, }, @@ -528,12 +527,9 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, }, - MeterProvider: &MeterProvider{ + MeterProvider: &MeterProviderJson{ Readers: []MetricReader{ { - Producers: []MetricProducer{ - {Opencensus: MetricProducerOpencensus{}}, - }, Pull: &PullMetricReader{ Exporter: PullMetricExporter{ PrometheusDevelopment: &ExperimentalPrometheusMetricExporter{ @@ -551,9 +547,6 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, { - Producers: []MetricProducer{ - {}, - }, Periodic: &PeriodicMetricReader{ Exporter: PushMetricExporter{ OTLPHttp: &OTLPHttpMetricExporter{ @@ -561,14 +554,13 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ ClientCertificateFile: ptr("/app/cert.pem"), ClientKeyFile: ptr("/app/cert.pem"), Compression: ptr("gzip"), - DefaultHistogramAggregation: ptr(OTLPMetricDefaultHistogramAggregationBase2ExponentialBucketHistogram), + DefaultHistogramAggregation: ptr(ExporterDefaultHistogramAggregationBase2ExponentialBucketHistogram), Endpoint: ptr("http://localhost:4318/v1/metrics"), Headers: []NameStringValuePair{ {Name: "api-key", Value: ptr("1234")}, }, HeadersList: ptr("api-key=1234"), - Insecure: ptr(false), - TemporalityPreference: ptr("delta"), + TemporalityPreference: ptr(ExporterTemporalityPreferenceDelta), Timeout: ptr(10000), }, }, @@ -588,15 +580,15 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ { Selector: &ViewSelector{ InstrumentName: ptr("my-instrument"), - InstrumentType: ptr(ViewSelectorInstrumentTypeHistogram), + InstrumentType: ptr(InstrumentTypeHistogram), MeterName: ptr("my-meter"), MeterSchemaUrl: ptr("https://opentelemetry.io/schemas/1.16.0"), MeterVersion: ptr("1.0.0"), Unit: ptr("ms"), }, Stream: &ViewStream{ - Aggregation: &ViewStreamAggregation{ - ExplicitBucketHistogram: &ViewStreamAggregationExplicitBucketHistogram{ + Aggregation: &Aggregation{ + ExplicitBucketHistogram: &ExplicitBucketHistogramAggregation{ Boundaries: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000}, RecordMinMax: ptr(true), }, @@ -611,10 +603,10 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, }, - Propagator: &Propagator{ - Composite: []*string{ptr("tracecontext"), ptr("baggage"), ptr("b3"), ptr("b3multi"), ptr("jaeger"), ptr("xray"), ptr("ottrace")}, + Propagator: &PropagatorJson{ + // Composite: []TextMapPropagator{TraceContextPropagator, ptr("tracecontext"), ptr("baggage"), ptr("b3"), ptr("b3multi"), ptr("jaeger"), ptr("xray"), ptr("ottrace")}, }, - Resource: &Resource{ + Resource: &ResourceJson{ Attributes: []AttributeNameValue{ {Name: "service.name", Value: "unknown_service"}, {Name: "string_key", Type: &AttributeType{Value: "string"}, Value: "value"}, @@ -627,15 +619,15 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ {Name: "double_array_key", Type: &AttributeType{Value: "double_array"}, Value: []any{1.1, 2.2}}, }, AttributesList: ptr("service.namespace=my-namespace,service.version=1.0.0"), - Detectors: &Detectors{ - Attributes: &DetectorsAttributes{ + DetectionDevelopment: &ExperimentalResourceDetection{ + Attributes: &IncludeExclude{ Excluded: []string{"process.command_args"}, Included: []string{"process.*"}, }, }, SchemaUrl: ptr("https://opentelemetry.io/schemas/1.16.0"), }, - TracerProvider: &TracerProvider{ + TracerProvider: &TracerProviderJson{ Limits: &SpanLimits{ AttributeCountLimit: ptr(128), AttributeValueLengthLimit: ptr(4096), @@ -659,7 +651,6 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ {Name: "api-key", Value: ptr("1234")}, }, HeadersList: ptr("api-key=1234"), - Insecure: ptr(false), Timeout: ptr(10000), }, }, @@ -687,21 +678,21 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, Sampler: &Sampler{ - ParentBased: &SamplerParentBased{ + ParentBased: &ParentBasedSampler{ LocalParentNotSampled: &Sampler{ - AlwaysOff: SamplerAlwaysOff{}, + AlwaysOff: AlwaysOffSampler{}, }, LocalParentSampled: &Sampler{ - AlwaysOn: SamplerAlwaysOn{}, + AlwaysOn: AlwaysOnSampler{}, }, RemoteParentNotSampled: &Sampler{ - AlwaysOff: SamplerAlwaysOff{}, + AlwaysOff: AlwaysOffSampler{}, }, RemoteParentSampled: &Sampler{ - AlwaysOn: SamplerAlwaysOn{}, + AlwaysOn: AlwaysOnSampler{}, }, Root: &Sampler{ - TraceIDRatioBased: &SamplerTraceIDRatioBased{ + TraceIDRatioBased: &TraceIDRatioBasedSampler{ Ratio: ptr(0.0001), }, }, @@ -723,7 +714,7 @@ func TestParseYAML(t *testing.T) { wantErr: nil, wantType: &OpenTelemetryConfiguration{ Disabled: ptr(false), - FileFormat: ptr("0.1"), + FileFormat: "0.1", }, }, { @@ -889,7 +880,7 @@ func TestSerializeJSON(t *testing.T) { wantErr: nil, wantType: OpenTelemetryConfiguration{ Disabled: ptr(false), - FileFormat: ptr("0.1"), + FileFormat: "0.1", }, }, { From ca1e391ac831e562fe19cdb54a2fc435fa10ec4f Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 25 Sep 2025 14:30:33 -0700 Subject: [PATCH 10/39] update signals Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/log.go | 3 ++- otelconf/metric.go | 5 +++-- otelconf/trace.go | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/otelconf/log.go b/otelconf/log.go index d5c6a2a9a10..e79e79845c0 100644 --- a/otelconf/log.go +++ b/otelconf/log.go @@ -23,7 +23,8 @@ import ( ) func loggerProvider(cfg configOptions, res *resource.Resource) (log.LoggerProvider, shutdownFunc, error) { - if cfg.opentelemetryConfig.LoggerProvider == nil { + provider, ok := cfg.opentelemetryConfig.LoggerProvider.(*LoggerProviderJson) + if provider == nil { return noop.NewLoggerProvider(), noopShutdown, nil } provider, ok := cfg.opentelemetryConfig.LoggerProvider.(*LoggerProviderJson) diff --git a/otelconf/metric.go b/otelconf/metric.go index b6e12114401..5686a99e0a0 100644 --- a/otelconf/metric.go +++ b/otelconf/metric.go @@ -40,7 +40,8 @@ var zeroScope instrumentation.Scope const instrumentKindUndefined = sdkmetric.InstrumentKind(0) func meterProvider(cfg configOptions, res *resource.Resource) (metric.MeterProvider, shutdownFunc, error) { - if cfg.opentelemetryConfig.MeterProvider == nil { + provider, ok := cfg.opentelemetryConfig.MeterProvider.(*MeterProviderJson) + if provider == nil { return noop.NewMeterProvider(), noopShutdown, nil } provider, ok := cfg.opentelemetryConfig.MeterProvider.(*MeterProviderJson) @@ -173,7 +174,7 @@ func otlpHTTPMetricExporter(ctx context.Context, otlpConfig *OTLPHttpMetricExpor if u.Scheme == "http" { opts = append(opts, otlpmetrichttp.WithInsecure()) } - if u.Path != "" { + if len(u.Path) > 0 { opts = append(opts, otlpmetrichttp.WithURLPath(u.Path)) } } diff --git a/otelconf/trace.go b/otelconf/trace.go index 54638a742be..872b4048941 100644 --- a/otelconf/trace.go +++ b/otelconf/trace.go @@ -25,7 +25,8 @@ import ( var errInvalidSamplerConfiguration = newErrInvalid("sampler configuration") func tracerProvider(cfg configOptions, res *resource.Resource) (trace.TracerProvider, shutdownFunc, error) { - if cfg.opentelemetryConfig.TracerProvider == nil { + provider, ok := cfg.opentelemetryConfig.TracerProvider.(*TracerProviderJson) + if provider == nil { return noop.NewTracerProvider(), noopShutdown, nil } provider, ok := cfg.opentelemetryConfig.TracerProvider.(*TracerProviderJson) From 7d4de9a76835361c7cc4dff578511984f95f9965 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 9 Oct 2025 15:18:21 -0700 Subject: [PATCH 11/39] update resource parsing Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/otelconf/config.go b/otelconf/config.go index 068110e7032..c57d03456c8 100644 --- a/otelconf/config.go +++ b/otelconf/config.go @@ -92,11 +92,10 @@ func NewSDK(opts ...ConfigurationOption) (SDK, error) { return noopSDK, nil } - resource, ok := o.opentelemetryConfig.Resource.(ResourceJson) - if !ok { - return noopSDK, errors.New("invalid resource") + r, err := newResource(o.opentelemetryConfig.Resource) + if err != nil { + return noopSDK, err } - r := newResource(&resource) mp, mpShutdown, err := meterProvider(o, r) if err != nil { From 6192a4284ebb63c1f1e84932de8512c5e7c4257b Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Wed, 15 Oct 2025 08:08:49 -0700 Subject: [PATCH 12/39] incremental improvements * added validation for various JSON unmarshallers * updated tests to ensure expected model matches the test file * add custom unmarshalers to support nil values for certain config options Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 16 +++ otelconf/config_test.go | 262 +++++++++++++++++++++++++++++++++++++--- otelconf/config_yaml.go | 217 ++++++++++++++++++++++++++++++++- 3 files changed, 471 insertions(+), 24 deletions(-) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 588f9f20d06..33581b122c2 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -441,6 +441,9 @@ func (j *OTLPHttpMetricExporter) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Timeout != nil && 0 > *plain.Timeout { + return fmt.Errorf("field %s: must be >= %v", "timeout", 0) + } *j = OTLPHttpMetricExporter(plain) return nil } @@ -459,6 +462,9 @@ func (j *OTLPGrpcMetricExporter) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Timeout != nil && 0 > *plain.Timeout { + return fmt.Errorf("field %s: must be >= %v", "timeout", 0) + } *j = OTLPGrpcMetricExporter(plain) return nil } @@ -477,6 +483,9 @@ func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Timeout != nil && 0 > *plain.Timeout { + return fmt.Errorf("field %s: must be >= %v", "timeout", 0) + } *j = OTLPHttpExporter(plain) return nil } @@ -495,6 +504,9 @@ func (j *OTLPGrpcExporter) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Timeout != nil && 0 > *plain.Timeout { + return fmt.Errorf("field %s: must be >= %v", "timeout", 0) + } *j = OTLPGrpcExporter(plain) return nil } @@ -670,6 +682,7 @@ func (j *SimpleSpanProcessor) UnmarshalJSON(b []byte) error { var enumValuesViewSelectorInstrumentType = []any{ "counter", + "gauge", "histogram", "observable_counter", "observable_gauge", @@ -734,6 +747,9 @@ func (j *ZipkinSpanExporter) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Timeout != nil && 0 > *plain.Timeout { + return fmt.Errorf("field %s: must be >= %v", "timeout", 0) + } *j = ZipkinSpanExporter(plain) return nil } diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 4f5bbd17383..1f879c2ed79 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -408,9 +408,9 @@ func TestNewSDK(t *testing.T) { } } -var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ +var v10OpenTelemetryConfig = OpenTelemetryConfiguration{ Disabled: ptr(false), - FileFormat: "0.3", + FileFormat: "1.0-rc.1", AttributeLimits: &AttributeLimits{ AttributeCountLimit: ptr(128), AttributeValueLengthLimit: ptr(4096), @@ -490,7 +490,21 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, }, + LogLevel: ptr("info"), LoggerProvider: &LoggerProviderJson{ + LoggerConfiguratorDevelopment: &ExperimentalLoggerConfigurator{ + DefaultConfig: &ExperimentalLoggerConfig{ + Disabled: ptr(true), + }, + Loggers: []ExperimentalLoggerMatcherAndConfig{ + { + Config: &ExperimentalLoggerConfig{ + Disabled: ptr(false), + }, + Name: ptr("io.opentelemetry.contrib.*"), + }, + }, + }, Limits: &LogRecordLimits{ AttributeCountLimit: ptr(128), AttributeValueLengthLimit: ptr(4096), @@ -505,6 +519,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ ClientCertificateFile: ptr("/app/cert.pem"), ClientKeyFile: ptr("/app/cert.pem"), Compression: ptr("gzip"), + Encoding: ptr(OTLPHttpEncodingProtobuf), Endpoint: ptr("http://localhost:4318/v1/logs"), Headers: []NameStringValuePair{ {Name: "api-key", Value: ptr("1234")}, @@ -518,6 +533,43 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ ScheduleDelay: ptr(5000), }, }, + { + Batch: &BatchLogRecordProcessor{ + Exporter: LogRecordExporter{ + OTLPGrpc: &OTLPGrpcExporter{ + CertificateFile: ptr("/app/cert.pem"), + ClientCertificateFile: ptr("/app/cert.pem"), + ClientKeyFile: ptr("/app/cert.pem"), + Compression: ptr("gzip"), + Endpoint: ptr("http://localhost:4317"), + Headers: []NameStringValuePair{ + {Name: "api-key", Value: ptr("1234")}, + }, + HeadersList: ptr("api-key=1234"), + Timeout: ptr(10000), + Insecure: ptr(false), + }, + }, + }, + }, + { + Batch: &BatchLogRecordProcessor{ + Exporter: LogRecordExporter{ + OTLPFileDevelopment: &ExperimentalOTLPFileExporter{ + OutputStream: ptr("file:///var/log/logs.jsonl"), + }, + }, + }, + }, + { + Batch: &BatchLogRecordProcessor{ + Exporter: LogRecordExporter{ + OTLPFileDevelopment: &ExperimentalOTLPFileExporter{ + OutputStream: ptr("stdout"), + }, + }, + }, + }, { Simple: &SimpleLogRecordProcessor{ Exporter: LogRecordExporter{ @@ -528,9 +580,38 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, MeterProvider: &MeterProviderJson{ + ExemplarFilter: ptr(ExemplarFilter("trace_based")), + MeterConfiguratorDevelopment: &ExperimentalMeterConfigurator{ + DefaultConfig: &ExperimentalMeterConfig{ + Disabled: ptr(true), + }, + Meters: []ExperimentalMeterMatcherAndConfig{ + { + Config: &ExperimentalMeterConfig{ + Disabled: ptr(false), + }, + Name: ptr("io.opentelemetry.contrib.*"), + }, + }, + }, Readers: []MetricReader{ { Pull: &PullMetricReader{ + Producers: []MetricProducer{ + { + Opencensus: OpenCensusMetricProducer{}, + }, + }, + CardinalityLimits: &CardinalityLimits{ + Default: ptr(2000), + Counter: ptr(2000), + Gauge: ptr(2000), + Histogram: ptr(2000), + ObservableCounter: ptr(2000), + ObservableGauge: ptr(2000), + ObservableUpDownCounter: ptr(2000), + UpDownCounter: ptr(2000), + }, Exporter: PullMetricExporter{ PrometheusDevelopment: &ExperimentalPrometheusMetricExporter{ Host: ptr("localhost"), @@ -539,15 +620,30 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ Excluded: []string{"service.attr1"}, Included: []string{"service*"}, }, - WithoutScopeInfo: ptr(false), - WithoutTypeSuffix: ptr(false), - WithoutUnits: ptr(false), + WithoutScopeInfo: ptr(false), }, }, }, }, { Periodic: &PeriodicMetricReader{ + Producers: []MetricProducer{ + { + AdditionalProperties: map[string]any{ + "prometheus": nil, + }, + }, + }, + CardinalityLimits: &CardinalityLimits{ + Default: ptr(2000), + Counter: ptr(2000), + Gauge: ptr(2000), + Histogram: ptr(2000), + ObservableCounter: ptr(2000), + ObservableGauge: ptr(2000), + ObservableUpDownCounter: ptr(2000), + UpDownCounter: ptr(2000), + }, Exporter: PushMetricExporter{ OTLPHttp: &OTLPHttpMetricExporter{ CertificateFile: ptr("/app/cert.pem"), @@ -556,6 +652,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ Compression: ptr("gzip"), DefaultHistogramAggregation: ptr(ExporterDefaultHistogramAggregationBase2ExponentialBucketHistogram), Endpoint: ptr("http://localhost:4318/v1/metrics"), + Encoding: ptr(OTLPHttpEncodingProtobuf), Headers: []NameStringValuePair{ {Name: "api-key", Value: ptr("1234")}, }, @@ -564,10 +661,53 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ Timeout: ptr(10000), }, }, - Interval: ptr(5000), + Interval: ptr(60000), Timeout: ptr(30000), }, }, + { + Periodic: &PeriodicMetricReader{ + Exporter: PushMetricExporter{ + OTLPGrpc: &OTLPGrpcMetricExporter{ + CertificateFile: ptr("/app/cert.pem"), + ClientCertificateFile: ptr("/app/cert.pem"), + ClientKeyFile: ptr("/app/cert.pem"), + Compression: ptr("gzip"), + DefaultHistogramAggregation: ptr(ExporterDefaultHistogramAggregationBase2ExponentialBucketHistogram), + Endpoint: ptr("http://localhost:4317"), + Headers: []NameStringValuePair{ + {Name: "api-key", Value: ptr("1234")}, + }, + HeadersList: ptr("api-key=1234"), + TemporalityPreference: ptr(ExporterTemporalityPreferenceDelta), + Timeout: ptr(10000), + Insecure: ptr(false), + }, + }, + }, + }, + { + Periodic: &PeriodicMetricReader{ + Exporter: PushMetricExporter{ + OTLPFileDevelopment: &ExperimentalOTLPFileMetricExporter{ + OutputStream: ptr("file:///var/log/metrics.jsonl"), + DefaultHistogramAggregation: ptr(ExporterDefaultHistogramAggregationBase2ExponentialBucketHistogram), + TemporalityPreference: ptr(ExporterTemporalityPreferenceDelta), + }, + }, + }, + }, + { + Periodic: &PeriodicMetricReader{ + Exporter: PushMetricExporter{ + OTLPFileDevelopment: &ExperimentalOTLPFileMetricExporter{ + OutputStream: ptr("stdout"), + DefaultHistogramAggregation: ptr(ExporterDefaultHistogramAggregationBase2ExponentialBucketHistogram), + TemporalityPreference: ptr(ExporterTemporalityPreferenceDelta), + }, + }, + }, + }, { Periodic: &PeriodicMetricReader{ Exporter: PushMetricExporter{ @@ -593,6 +733,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ RecordMinMax: ptr(true), }, }, + AggregationCardinalityLimit: ptr(2000), AttributeKeys: &IncludeExclude{ Included: []string{"key1", "key2"}, Excluded: []string{"key3"}, @@ -604,7 +745,27 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ }, }, Propagator: &PropagatorJson{ - // Composite: []TextMapPropagator{TraceContextPropagator, ptr("tracecontext"), ptr("baggage"), ptr("b3"), ptr("b3multi"), ptr("jaeger"), ptr("xray"), ptr("ottrace")}, + Composite: []TextMapPropagator{ + { + Tracecontext: TraceContextPropagator{}, + }, + { + Baggage: BaggagePropagator{}, + }, + { + B3: B3Propagator{}, + }, + { + B3Multi: B3MultiPropagator{}, + }, + { + Jaeger: JaegerPropagator{}, + }, + { + Ottrace: OpenTracingPropagator{}, + }, + }, + CompositeList: ptr("tracecontext,baggage,b3,b3multi,jaeger,ottrace,xray"), }, Resource: &ResourceJson{ Attributes: []AttributeNameValue{ @@ -624,10 +785,25 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ Excluded: []string{"process.command_args"}, Included: []string{"process.*"}, }, + // TODO: implement resource detectors + // Detectors: []ExperimentalResourceDetector{} + // }, }, SchemaUrl: ptr("https://opentelemetry.io/schemas/1.16.0"), }, TracerProvider: &TracerProviderJson{ + TracerConfiguratorDevelopment: &ExperimentalTracerConfigurator{ + DefaultConfig: &ExperimentalTracerConfig{ + Disabled: true, + }, + Tracers: []ExperimentalTracerMatcherAndConfig{ + { + Config: ExperimentalTracerConfig{}, + Name: "io.opentelemetry.contrib.*", + }, + }, + }, + Limits: &SpanLimits{ AttributeCountLimit: ptr(128), AttributeValueLengthLimit: ptr(4096), @@ -646,6 +822,7 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ ClientCertificateFile: ptr("/app/cert.pem"), ClientKeyFile: ptr("/app/cert.pem"), Compression: ptr("gzip"), + Encoding: ptr(OTLPHttpEncodingProtobuf), Endpoint: ptr("http://localhost:4318/v1/traces"), Headers: []NameStringValuePair{ {Name: "api-key", Value: ptr("1234")}, @@ -659,6 +836,43 @@ var v03OpenTelemetryConfig = OpenTelemetryConfiguration{ ScheduleDelay: ptr(5000), }, }, + { + Batch: &BatchSpanProcessor{ + Exporter: SpanExporter{ + OTLPGrpc: &OTLPGrpcExporter{ + CertificateFile: ptr("/app/cert.pem"), + ClientCertificateFile: ptr("/app/cert.pem"), + ClientKeyFile: ptr("/app/cert.pem"), + Compression: ptr("gzip"), + Endpoint: ptr("http://localhost:4317"), + Headers: []NameStringValuePair{ + {Name: "api-key", Value: ptr("1234")}, + }, + HeadersList: ptr("api-key=1234"), + Timeout: ptr(10000), + Insecure: ptr(false), + }, + }, + }, + }, + { + Batch: &BatchSpanProcessor{ + Exporter: SpanExporter{ + OTLPFileDevelopment: &ExperimentalOTLPFileExporter{ + OutputStream: ptr("file:///var/log/traces.jsonl"), + }, + }, + }, + }, + { + Batch: &BatchSpanProcessor{ + Exporter: SpanExporter{ + OTLPFileDevelopment: &ExperimentalOTLPFileExporter{ + OutputStream: ptr("stdout"), + }, + }, + }, + }, { Batch: &BatchSpanProcessor{ Exporter: SpanExporter{ @@ -725,28 +939,36 @@ func TestParseYAML(t *testing.T) { }, { name: "invalid nil name", - input: "invalid_nil_name.yaml", + input: "v1.0.0_invalid_nil_name.yaml", wantErr: errors.New(`yaml: cannot unmarshal field name in NameStringValuePair required`), }, { name: "invalid nil value", - input: "invalid_nil_value.yaml", + input: "v1.0.0_invalid_nil_value.yaml", wantErr: errors.New(`yaml: cannot unmarshal field value in NameStringValuePair required`), }, { name: "valid v0.2 config", input: "v0.2.yaml", wantErr: errors.New(`yaml: unmarshal errors: - line 81: cannot unmarshal !!map into []otelconf.NameStringValuePair - line 185: cannot unmarshal !!map into []otelconf.NameStringValuePair - line 244: cannot unmarshal !!seq into otelconf.IncludeExclude - line 305: cannot unmarshal !!map into []otelconf.NameStringValuePair - line 408: cannot unmarshal !!map into []otelconf.AttributeNameValue`), + line 64: cannot unmarshal !!seq into otelconf.IncludeExclude`), }, { - name: "valid v0.3 config", - input: "v0.3.yaml", - wantType: &v03OpenTelemetryConfig, + name: "valid v0.3 config", + input: "v0.3.yaml", + wantErr: errors.New(`yaml: unmarshal errors: + line 2: cannot unmarshal !!str` + " `traceco...`" + ` into map[string]interface {} + line 3: cannot unmarshal !!str` + " `baggage`" + ` into map[string]interface {} + line 4: cannot unmarshal !!str` + " `b3`" + ` into map[string]interface {} + line 5: cannot unmarshal !!str` + " `b3multi`" + ` into map[string]interface {} + line 6: cannot unmarshal !!str` + " `jaeger`" + ` into map[string]interface {} + line 7: cannot unmarshal !!str` + " `xray`" + ` into map[string]interface {} + line 8: cannot unmarshal !!str` + " `ottrace`" + ` into map[string]interface {}`), + }, + { + name: "valid v1.0.0 config", + input: "v1.0.0-rc.1.yaml", + wantType: &v10OpenTelemetryConfig, }, } @@ -890,12 +1112,12 @@ func TestSerializeJSON(t *testing.T) { }, { name: "invalid nil name", - input: "invalid_nil_name.json", + input: "v1.0.0_invalid_nil_name.json", wantErr: errors.New(`json: cannot unmarshal field name in NameStringValuePair required`), }, { name: "invalid nil value", - input: "invalid_nil_value.json", + input: "v1.0.0_invalid_nil_value.json", wantErr: errors.New(`json: cannot unmarshal field value in NameStringValuePair required`), }, { @@ -906,7 +1128,7 @@ func TestSerializeJSON(t *testing.T) { { name: "valid v0.3 config", input: "v0.3.json", - wantType: v03OpenTelemetryConfig, + wantType: v10OpenTelemetryConfig, }, } diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 7fd045ce40e..c34f27f2c31 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -41,12 +41,90 @@ func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { return nil } +func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { + type Plain OpenTelemetryConfiguration + var plain Plain + + if err := node.Decode(&plain); err != nil { + return err + } + + marshaled, err := yaml.Marshal(plain.LoggerProvider) + if err != nil { + return err + } + + var lp LoggerProviderJson + if err := yaml.Unmarshal(marshaled, &lp); err != nil { + return err + } + plain.LoggerProvider = &lp + + marshaled, err = yaml.Marshal(plain.MeterProvider) + if err != nil { + return err + } + + var mp MeterProviderJson + if err := yaml.Unmarshal(marshaled, &mp); err != nil { + return err + } + plain.MeterProvider = &mp + + marshaled, err = yaml.Marshal(plain.TracerProvider) + if err != nil { + return err + } + + var tp TracerProviderJson + if err := yaml.Unmarshal(marshaled, &tp); err != nil { + return err + } + plain.TracerProvider = &tp + + marshaled, err = yaml.Marshal(plain.Propagator) + if err != nil { + return err + } + + var p PropagatorJson + if err := yaml.Unmarshal(marshaled, &p); err != nil { + return err + } + plain.Propagator = &p + + marshaled, err = yaml.Marshal(plain.Resource) + if err != nil { + return err + } + + var r ResourceJson + if err := yaml.Unmarshal(marshaled, &r); err != nil { + return err + } + plain.Resource = &r + + marshaled, err = yaml.Marshal(plain.InstrumentationDevelopment) + if err != nil { + return err + } + + var i InstrumentationJson + if err := yaml.Unmarshal(marshaled, &i); err != nil { + return err + } + plain.InstrumentationDevelopment = &i + + *j = OpenTelemetryConfiguration(plain) + return nil +} + // UnmarshalYAML implements yaml.Unmarshaler. -func (j *AttributeType) UnmarshalYAML(unmarshal func(any) error) error { +func (j *AttributeType) UnmarshalYAML(node *yaml.Node) error { var v struct { Value any } - if err := unmarshal(&v.Value); err != nil { + if err := node.Decode(&v.Value); err != nil { return err } var ok bool @@ -144,9 +222,9 @@ func (j *BatchLogRecordProcessor) UnmarshalYAML(node *yaml.Node) error { *j = BatchLogRecordProcessor(plain) return nil } -func (j *NameStringValuePair) UnmarshalYAML(unmarshal func(any) error) error { +func (j *NameStringValuePair) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any - if err := unmarshal(&raw); err != nil { + if err := node.Decode(&raw); err != nil { return err } if _, ok := raw["name"]; !ok { @@ -170,6 +248,137 @@ func (j *NameStringValuePair) UnmarshalYAML(unmarshal func(any) error) error { return nil } +func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { + var raw map[string]any + if err := node.Decode(&raw); err != nil { + return err + } + type Plain PushMetricExporter + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + // console can be nil, must check and set here + if _, ok := raw["console"]; ok { + plain.Console = ConsoleExporter{} + } + *j = PushMetricExporter(plain) + return nil +} + +func (j *SpanExporter) UnmarshalYAML(node *yaml.Node) error { + var raw map[string]any + if err := node.Decode(&raw); err != nil { + return err + } + type Plain SpanExporter + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + // console can be nil, must check and set here + if _, ok := raw["console"]; ok { + plain.Console = ConsoleExporter{} + } + *j = SpanExporter(plain) + return nil +} + +func (j *LogRecordExporter) UnmarshalYAML(node *yaml.Node) error { + var raw map[string]any + if err := node.Decode(&raw); err != nil { + return err + } + type Plain LogRecordExporter + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + // console can be nil, must check and set here + if _, ok := raw["console"]; ok { + plain.Console = ConsoleExporter{} + } + *j = LogRecordExporter(plain) + return nil +} + +func (j *Sampler) UnmarshalYAML(node *yaml.Node) error { + var raw map[string]any + if err := node.Decode(&raw); err != nil { + return err + } + type Plain Sampler + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + // console can be nil, must check and set here + if _, ok := raw["always_on"]; ok { + plain.AlwaysOn = AlwaysOnSampler{} + } + if _, ok := raw["always_off"]; ok { + plain.AlwaysOff = AlwaysOffSampler{} + } + *j = Sampler(plain) + return nil +} + +func (j *MetricProducer) UnmarshalYAML(node *yaml.Node) error { + var raw map[string]any + if err := node.Decode(&raw); err != nil { + return err + } + type Plain MetricProducer + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + // opencensus can be nil, must check and set here + if v, ok := raw["opencensus"]; ok && v == nil { + delete(raw, "opencensus") + plain.Opencensus = OpenCensusMetricProducer{} + } + if len(raw) > 0 { + plain.AdditionalProperties = raw + } + + *j = MetricProducer(plain) + return nil +} + +func (j *TextMapPropagator) UnmarshalYAML(node *yaml.Node) error { + var raw map[string]any + if err := node.Decode(&raw); err != nil { + return err + } + type Plain TextMapPropagator + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + // b3 can be nil, must check and set here + if v, ok := raw["b3"]; ok && v == nil { + plain.B3 = B3Propagator{} + } + if v, ok := raw["b3multi"]; ok && v == nil { + plain.B3Multi = B3MultiPropagator{} + } + if v, ok := raw["baggage"]; ok && v == nil { + plain.Baggage = BaggagePropagator{} + } + if v, ok := raw["jaeger"]; ok && v == nil { + plain.Jaeger = JaegerPropagator{} + } + if v, ok := raw["ottrace"]; ok && v == nil { + plain.Ottrace = OpenTracingPropagator{} + } + if v, ok := raw["tracecontext"]; ok && v == nil { + plain.Tracecontext = TraceContextPropagator{} + } + *j = TextMapPropagator(plain) + return nil +} + // UnmarshalYAML implements yaml.Unmarshaler. func (j *BatchSpanProcessor) UnmarshalYAML(node *yaml.Node) error { if !hasYAMLMapKey(node, "exporter") { From 1840b0a831b162a92cec034dfefaded63ac17e41 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Wed, 15 Oct 2025 08:17:51 -0700 Subject: [PATCH 13/39] add 1.0.0-rc1 test file Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/testdata/v1.0.0-rc.1.yaml | 952 +++++++++++++++++++++++++++++ 1 file changed, 952 insertions(+) create mode 100644 otelconf/testdata/v1.0.0-rc.1.yaml diff --git a/otelconf/testdata/v1.0.0-rc.1.yaml b/otelconf/testdata/v1.0.0-rc.1.yaml new file mode 100644 index 00000000000..d870ef331a9 --- /dev/null +++ b/otelconf/testdata/v1.0.0-rc.1.yaml @@ -0,0 +1,952 @@ +# kitchen-sink.yaml demonstrates all configurable surface area, including explanatory comments. +# +# It DOES NOT represent expected real world configuration, as it makes strange configuration +# choices in an effort to exercise the full surface area. +# +# Configuration values are set to their defaults when default values are defined. + +# The file format version. +# The yaml format is documented at +# https://github.com/open-telemetry/opentelemetry-configuration/tree/main/schema +file_format: "1.0-rc.1" +# Configure if the SDK is disabled or not. +# If omitted or null, false is used. +disabled: false +# Configure the log level of the internal logger used by the SDK. +# If omitted, info is used. +log_level: info +# Configure general attribute limits. See also tracer_provider.limits, logger_provider.limits. +attribute_limits: + # Configure max attribute value size. + # Value must be non-negative. + # If omitted or null, there is no limit. + attribute_value_length_limit: 4096 + # Configure max attribute count. + # Value must be non-negative. + # If omitted or null, 128 is used. + attribute_count_limit: 128 +# Configure logger provider. +# If omitted, a noop logger provider is used. +logger_provider: + # Configure log record processors. + processors: + - # Configure a batch log record processor. + batch: + # Configure delay interval (in milliseconds) between two consecutive exports. + # Value must be non-negative. + # If omitted or null, 1000 is used. + schedule_delay: 5000 + # Configure maximum allowed time (in milliseconds) to export data. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 30000 is used. + export_timeout: 30000 + # Configure maximum queue size. Value must be positive. + # If omitted or null, 2048 is used. + max_queue_size: 2048 + # Configure maximum batch size. Value must be positive. + # If omitted or null, 512 is used. + max_export_batch_size: 512 + # Configure exporter. + exporter: + # Configure exporter to be OTLP with HTTP transport. + otlp_http: + endpoint: http://localhost:4318/v1/logs + # Configure certificate used to verify a server's TLS credentials. + # Absolute path to certificate file in PEM format. + # If omitted or null, system default certificate verification is used for secure connections. + certificate_file: /app/cert.pem + # Configure mTLS private client key. + # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key_file: /app/cert.pem + # Configure mTLS client certificate. + # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate_file: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. + # Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure the encoding used for messages. + # Values include: protobuf, json. Implementations may not support json. + # If omitted or null, protobuf is used. + encoding: protobuf + - # Configure a batch log record processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with gRPC transport. + otlp_grpc: + # Configure endpoint. + # If omitted or null, http://localhost:4317 is used. + endpoint: http://localhost:4317 + # Configure certificate used to verify a server's TLS credentials. + # Absolute path to certificate file in PEM format. + # If omitted or null, system default certificate verification is used for secure connections. + certificate_file: /app/cert.pem + # Configure mTLS private client key. + # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key_file: /app/cert.pem + # Configure mTLS client certificate. + # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate_file: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. + # Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. + # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # If omitted or null, false is used. + insecure: false + - # Configure a batch log record processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with file transport. + # This type is in development and subject to breaking changes in minor versions. + otlp_file/development: + # Configure output stream. + # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + # If omitted or null, stdout is used. + output_stream: file:///var/log/logs.jsonl + - # Configure a batch log record processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with file transport. + # This type is in development and subject to breaking changes in minor versions. + otlp_file/development: + # Configure output stream. + # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + # If omitted or null, stdout is used. + output_stream: stdout + - # Configure a simple log record processor. + simple: + # Configure exporter. + exporter: + # Configure exporter to be console. + console: + # Configure log record limits. See also attribute_limits. + limits: + # Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. + # Value must be non-negative. + # If omitted or null, there is no limit. + attribute_value_length_limit: 4096 + # Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. + # Value must be non-negative. + # If omitted or null, 128 is used. + attribute_count_limit: 128 + # Configure loggers. + # This type is in development and subject to breaking changes in minor versions. + logger_configurator/development: + # Configure the default logger config used there is no matching entry in .logger_configurator/development.loggers. + default_config: + # Configure if the logger is enabled or not. + disabled: true + # Configure loggers. + loggers: + - # Configure logger names to match, evaluated as follows: + # + # * If the logger name exactly matches. + # * If the logger name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + name: io.opentelemetry.contrib.* + # The logger config. + config: + # Configure if the logger is enabled or not. + disabled: false +# Configure meter provider. +# If omitted, a noop meter provider is used. +meter_provider: + # Configure metric readers. + readers: + - # Configure a pull based metric reader. + pull: + # Configure exporter. + exporter: + # Configure exporter to be prometheus. + # This type is in development and subject to breaking changes in minor versions. + prometheus/development: + # Configure host. + # If omitted or null, localhost is used. + host: localhost + # Configure port. + # If omitted or null, 9464 is used. + port: 9464 + # Configure Prometheus Exporter to produce metrics without a scope info metric. + # If omitted or null, false is used. + without_scope_info: false + # Configure Prometheus Exporter to add resource attributes as metrics attributes. + with_resource_constant_labels: + # Configure resource attributes to be included. + # Attribute keys from resources are evaluated to match as follows: + # * If the value of the attribute key exactly matches. + # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + # If omitted, no resource attributes are included. + included: + - "service*" + # Configure resource attributes to be excluded. Applies after .with_resource_constant_labels.included (i.e. excluded has higher priority than included). + # Attribute keys from resources are evaluated to match as follows: + # * If the value of the attribute key exactly matches. + # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + # If omitted, .included resource attributes are included. + excluded: + - "service.attr1" + # Configure how Prometheus metrics are exposed. Values include: + # + # * UnderscoreEscapingWithSuffixes, the default. This fully escapes metric names for classic Prometheus metric name compatibility, and includes appending type and unit suffixes. + # * UnderscoreEscapingWithoutSuffixes, metric names will continue to escape special characters to _, but suffixes won't be attached. + # * NoUTF8EscapingWithSuffixes will disable changing special characters to _. Special suffixes like units and _total for counters will be attached. + # * NoTranslation. This strategy bypasses all metric and label name translation, passing them through unaltered. + # + # If omitted or null, UnderscoreEscapingWithSuffixes is used. + translation_strategy: UnderscoreEscapingWithSuffixes + # Configure metric producers. + producers: + - # Configure metric producer to be opencensus. + opencensus: + # Configure cardinality limits. + cardinality_limits: + # Configure default cardinality limit for all instrument types. + # Instrument-specific cardinality limits take priority. + # If omitted or null, 2000 is used. + default: 2000 + # Configure default cardinality limit for counter instruments. + # If omitted or null, the value from .default is used. + counter: 2000 + # Configure default cardinality limit for gauge instruments. + # If omitted or null, the value from .default is used. + gauge: 2000 + # Configure default cardinality limit for histogram instruments. + # If omitted or null, the value from .default is used. + histogram: 2000 + # Configure default cardinality limit for observable_counter instruments. + # If omitted or null, the value from .default is used. + observable_counter: 2000 + # Configure default cardinality limit for observable_gauge instruments. + # If omitted or null, the value from .default is used. + observable_gauge: 2000 + # Configure default cardinality limit for observable_up_down_counter instruments. + # If omitted or null, the value from .default is used. + observable_up_down_counter: 2000 + # Configure default cardinality limit for up_down_counter instruments. + # If omitted or null, the value from .default is used. + up_down_counter: 2000 + - # Configure a periodic metric reader. + periodic: + # Configure delay interval (in milliseconds) between start of two consecutive exports. + # Value must be non-negative. + # If omitted or null, 60000 is used. + interval: 60000 + # Configure maximum allowed time (in milliseconds) to export data. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 30000 is used. + timeout: 30000 + # Configure exporter. + exporter: + # Configure exporter to be OTLP with HTTP transport. + otlp_http: + # Configure endpoint, including the metric specific path. + # If omitted or null, http://localhost:4318/v1/metrics is used. + endpoint: http://localhost:4318/v1/metrics + # Configure certificate used to verify a server's TLS credentials. + # Absolute path to certificate file in PEM format. + # If omitted or null, system default certificate verification is used for secure connections. + certificate_file: /app/cert.pem + # Configure mTLS private client key. + # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key_file: /app/cert.pem + # Configure mTLS client certificate. + # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate_file: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. + # Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure the encoding used for messages. + # Values include: protobuf, json. Implementations may not support json. + # If omitted or null, protobuf is used. + encoding: protobuf + # Configure temporality preference. + # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, cumulative is used. + temporality_preference: delta + # Configure default histogram aggregation. + # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, explicit_bucket_histogram is used. + default_histogram_aggregation: base2_exponential_bucket_histogram + # Configure metric producers. + producers: + - # Configure metric producer to be prometheus. + prometheus: + # Configure cardinality limits. + cardinality_limits: + # Configure default cardinality limit for all instrument types. + # Instrument-specific cardinality limits take priority. + # If omitted or null, 2000 is used. + default: 2000 + # Configure default cardinality limit for counter instruments. + # If omitted or null, the value from .default is used. + counter: 2000 + # Configure default cardinality limit for gauge instruments. + # If omitted or null, the value from .default is used. + gauge: 2000 + # Configure default cardinality limit for histogram instruments. + # If omitted or null, the value from .default is used. + histogram: 2000 + # Configure default cardinality limit for observable_counter instruments. + # If omitted or null, the value from .default is used. + observable_counter: 2000 + # Configure default cardinality limit for observable_gauge instruments. + # If omitted or null, the value from .default is used. + observable_gauge: 2000 + # Configure default cardinality limit for observable_up_down_counter instruments. + # If omitted or null, the value from .default is used. + observable_up_down_counter: 2000 + # Configure default cardinality limit for up_down_counter instruments. + # If omitted or null, the value from .default is used. + up_down_counter: 2000 + - # Configure a periodic metric reader. + periodic: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with gRPC transport. + otlp_grpc: + # Configure endpoint. + # If omitted or null, http://localhost:4317 is used. + endpoint: http://localhost:4317 + # Configure certificate used to verify a server's TLS credentials. + # Absolute path to certificate file in PEM format. + # If omitted or null, system default certificate verification is used for secure connections. + certificate_file: /app/cert.pem + # Configure mTLS private client key. + # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key_file: /app/cert.pem + # Configure mTLS client certificate. + # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate_file: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. + # Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. + # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # If omitted or null, false is used. + insecure: false + # Configure temporality preference. + # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, cumulative is used. + temporality_preference: delta + # Configure default histogram aggregation. + # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, explicit_bucket_histogram is used. + default_histogram_aggregation: base2_exponential_bucket_histogram + - # Configure a periodic metric reader. + periodic: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with file transport. + # This type is in development and subject to breaking changes in minor versions. + otlp_file/development: + # Configure output stream. + # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + # If omitted or null, stdout is used. + output_stream: file:///var/log/metrics.jsonl + # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, cumulative is used. + temporality_preference: delta + # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, explicit_bucket_histogram is used. + default_histogram_aggregation: base2_exponential_bucket_histogram + - # Configure a periodic metric reader. + periodic: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with file transport. + # This type is in development and subject to breaking changes in minor versions. + otlp_file/development: + # Configure output stream. + # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + # If omitted or null, stdout is used. + output_stream: stdout + # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, cumulative is used. + temporality_preference: delta + # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. + # If omitted or null, explicit_bucket_histogram is used. + default_histogram_aggregation: base2_exponential_bucket_histogram + - # Configure a periodic metric reader. + periodic: + # Configure exporter. + exporter: + # Configure exporter to be console. + console: + # Configure views. + # Each view has a selector which determines the instrument(s) it applies to, and a configuration for the resulting stream(s). + views: + - # Configure view selector. + # Selection criteria is additive as described in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#instrument-selection-criteria. + selector: + # Configure instrument name selection criteria. + # If omitted or null, all instrument names match. + instrument_name: my-instrument + # Configure instrument type selection criteria. + # Values include: counter, gauge, histogram, observable_counter, observable_gauge, observable_up_down_counter, up_down_counter. + # If omitted or null, all instrument types match. + instrument_type: histogram + # Configure the instrument unit selection criteria. + # If omitted or null, all instrument units match. + unit: ms + # Configure meter name selection criteria. + # If omitted or null, all meter names match. + meter_name: my-meter + # Configure meter version selection criteria. + # If omitted or null, all meter versions match. + meter_version: 1.0.0 + # Configure meter schema url selection criteria. + # If omitted or null, all meter schema URLs match. + meter_schema_url: https://opentelemetry.io/schemas/1.16.0 + # Configure view stream. + stream: + # Configure metric name of the resulting stream(s). + # If omitted or null, the instrument's original name is used. + name: new_instrument_name + # Configure metric description of the resulting stream(s). + # If omitted or null, the instrument's origin description is used. + description: new_description + # Configure aggregation of the resulting stream(s). + # Values include: default, drop, explicit_bucket_histogram, base2_exponential_bucket_histogram, last_value, sum. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#aggregation. + # If omitted, default is used. + aggregation: + # Configure aggregation to be explicit_bucket_histogram. + explicit_bucket_histogram: + # Configure bucket boundaries. + # If omitted, [0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000] is used. + boundaries: + [ + 0.0, + 5.0, + 10.0, + 25.0, + 50.0, + 75.0, + 100.0, + 250.0, + 500.0, + 750.0, + 1000.0, + 2500.0, + 5000.0, + 7500.0, + 10000.0 + ] + # Configure record min and max. + # If omitted or null, true is used. + record_min_max: true + # Configure the aggregation cardinality limit. + # If omitted or null, the metric reader's default cardinality limit is used. + aggregation_cardinality_limit: 2000 + # Configure attribute keys retained in the resulting stream(s). + attribute_keys: + # Configure list of attribute keys to include in the resulting stream(s). All other attributes are dropped. + # If omitted, all attributes are included. + included: + - key1 + - key2 + # Configure list of attribute keys to exclude from the resulting stream(s). Applies after .attribute_keys.included (i.e. excluded has higher priority than included). + # If omitted, .attribute_keys.included are included. + excluded: + - key3 + # Configure the exemplar filter. + # Values include: trace_based, always_on, always_off. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration. + # If omitted or null, trace_based is used. + exemplar_filter: trace_based + # Configure meters. + # This type is in development and subject to breaking changes in minor versions. + meter_configurator/development: + # Configure the default meter config used there is no matching entry in .meter_configurator/development.meters. + default_config: + # Configure if the meter is enabled or not. + disabled: true + # Configure meters. + meters: + - # Configure meter names to match, evaluated as follows: + # + # * If the meter name exactly matches. + # * If the meter name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + name: io.opentelemetry.contrib.* + # The meter config. + config: + # Configure if the meter is enabled or not. + disabled: false +# Configure text map context propagators. +# If omitted, a noop propagator is used. +propagator: + # Configure the propagators in the composite text map propagator. Entries from .composite_list are appended to the list here with duplicates filtered out. + # Built-in propagator keys include: tracecontext, baggage, b3, b3multi, jaeger, ottrace. Known third party keys include: xray. + # If the resolved list of propagators (from .composite and .composite_list) is empty, a noop propagator is used. + composite: + - # Include the w3c trace context propagator. + tracecontext: + - # Include the w3c baggage propagator. + baggage: + - # Include the zipkin b3 propagator. + b3: + - # Include the zipkin b3 multi propagator. + b3multi: + - # Include the jaeger propagator. + jaeger: + - # Include the opentracing propagator. + ottrace: + # Configure the propagators in the composite text map propagator. Entries are appended to .composite with duplicates filtered out. + # The value is a comma separated list of propagator identifiers matching the format of OTEL_PROPAGATORS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration for details. + # Built-in propagator identifiers include: tracecontext, baggage, b3, b3multi, jaeger, ottrace. Known third party identifiers include: xray. + # If the resolved list of propagators (from .composite and .composite_list) is empty, a noop propagator is used. + composite_list: "tracecontext,baggage,b3,b3multi,jaeger,ottrace,xray" +# Configure tracer provider. +# If omitted, a noop tracer provider is used. +tracer_provider: + # Configure span processors. + processors: + - # Configure a batch span processor. + batch: + # Configure delay interval (in milliseconds) between two consecutive exports. + # Value must be non-negative. + # If omitted or null, 5000 is used. + schedule_delay: 5000 + # Configure maximum allowed time (in milliseconds) to export data. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 30000 is used. + export_timeout: 30000 + # Configure maximum queue size. Value must be positive. + # If omitted or null, 2048 is used. + max_queue_size: 2048 + # Configure maximum batch size. Value must be positive. + # If omitted or null, 512 is used. + max_export_batch_size: 512 + # Configure exporter. + exporter: + # Configure exporter to be OTLP with HTTP transport. + otlp_http: + # Configure endpoint, including the trace specific path. + # If omitted or null, http://localhost:4318/v1/traces is used. + endpoint: http://localhost:4318/v1/traces + # Configure certificate used to verify a server's TLS credentials. + # Absolute path to certificate file in PEM format. + # If omitted or null, system default certificate verification is used for secure connections. + certificate_file: /app/cert.pem + # Configure mTLS private client key. + # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key_file: /app/cert.pem + # Configure mTLS client certificate. + # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate_file: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. + # Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure the encoding used for messages. + # Values include: protobuf, json. Implementations may not support json. + # If omitted or null, protobuf is used. + encoding: protobuf + - # Configure a batch span processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with gRPC transport. + otlp_grpc: + # Configure endpoint. + # If omitted or null, http://localhost:4317 is used. + endpoint: http://localhost:4317 + # Configure certificate used to verify a server's TLS credentials. + # Absolute path to certificate file in PEM format. + # If omitted or null, system default certificate verification is used for secure connections. + certificate_file: /app/cert.pem + # Configure mTLS private client key. + # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + # If omitted or null, mTLS is not used. + client_key_file: /app/cert.pem + # Configure mTLS client certificate. + # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + # If omitted or null, mTLS is not used. + client_certificate_file: /app/cert.pem + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. + # If omitted or null, no headers are added. + headers_list: "api-key=1234" + # Configure compression. + # Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 10000 is used. + timeout: 10000 + # Configure client transport security for the exporter's connection. + # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + # If omitted or null, false is used. + insecure: false + - # Configure a batch span processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with file transport. + # This type is in development and subject to breaking changes in minor versions. + otlp_file/development: + # Configure output stream. + # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + # If omitted or null, stdout is used. + output_stream: file:///var/log/traces.jsonl + - # Configure a batch span processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be OTLP with file transport. + # This type is in development and subject to breaking changes in minor versions. + otlp_file/development: + # Configure output stream. + # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + # If omitted or null, stdout is used. + output_stream: stdout + - # Configure a batch span processor. + batch: + # Configure exporter. + exporter: + # Configure exporter to be zipkin. + zipkin: + # Configure endpoint. + # If omitted or null, http://localhost:9411/api/v2/spans is used. + endpoint: http://localhost:9411/api/v2/spans + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates indefinite. + # If omitted or null, 10000 is used. + timeout: 10000 + - # Configure a simple span processor. + simple: + # Configure exporter. + exporter: + # Configure exporter to be console. + console: + # Configure span limits. See also attribute_limits. + limits: + # Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. + # Value must be non-negative. + # If omitted or null, there is no limit. + attribute_value_length_limit: 4096 + # Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. + # Value must be non-negative. + # If omitted or null, 128 is used. + attribute_count_limit: 128 + # Configure max span event count. + # Value must be non-negative. + # If omitted or null, 128 is used. + event_count_limit: 128 + # Configure max span link count. + # Value must be non-negative. + # If omitted or null, 128 is used. + link_count_limit: 128 + # Configure max attributes per span event. + # Value must be non-negative. + # If omitted or null, 128 is used. + event_attribute_count_limit: 128 + # Configure max attributes per span link. + # Value must be non-negative. + # If omitted or null, 128 is used. + link_attribute_count_limit: 128 + # Configure the sampler. + # If omitted, parent based sampler with a root of always_on is used. + sampler: + # Configure sampler to be parent_based. + parent_based: + # Configure root sampler. + # If omitted or null, always_on is used. + root: + # Configure sampler to be trace_id_ratio_based. + trace_id_ratio_based: + # Configure trace_id_ratio. + # If omitted or null, 1.0 is used. + ratio: 0.0001 + # Configure remote_parent_sampled sampler. + # If omitted or null, always_on is used. + remote_parent_sampled: + # Configure sampler to be always_on. + always_on: + # Configure remote_parent_not_sampled sampler. + # If omitted or null, always_off is used. + remote_parent_not_sampled: + # Configure sampler to be always_off. + always_off: + # Configure local_parent_sampled sampler. + # If omitted or null, always_on is used. + local_parent_sampled: + # Configure sampler to be always_on. + always_on: + # Configure local_parent_not_sampled sampler. + # If omitted or null, always_off is used. + local_parent_not_sampled: + # Configure sampler to be always_off. + always_off: + # Configure tracers. + # This type is in development and subject to breaking changes in minor versions. + tracer_configurator/development: + # Configure the default tracer config used there is no matching entry in .tracer_configurator/development.tracers. + default_config: + # Configure if the tracer is enabled or not. + disabled: true + # Configure tracers. + tracers: + - # Configure tracer names to match, evaluated as follows: + # + # * If the tracer name exactly matches. + # * If the tracer name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + name: io.opentelemetry.contrib.* + # The tracer config. + config: + # Configure if the tracer is enabled or not. + disabled: false +# Configure resource for all signals. +# If omitted, the default resource is used. +resource: + # Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list. + # Entries must contain .name and .value, and may optionally include .type. If an entry's .type omitted or null, string is used. + # The .value's type must match the .type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array. + attributes: + - name: service.name + value: unknown_service + - name: string_key + value: value + type: string + - name: bool_key + value: true + type: bool + - name: int_key + value: 1 + type: int + - name: double_key + value: 1.1 + type: double + - name: string_array_key + value: [ "value1", "value2" ] + type: string_array + - name: bool_array_key + value: [ true, false ] + type: bool_array + - name: int_array_key + value: [ 1, 2 ] + type: int_array + - name: double_array_key + value: [ 1.1, 2.2 ] + type: double_array + # Configure resource attributes. Entries have lower priority than entries from .resource.attributes. + # The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration for details. + # If omitted or null, no resource attributes are added. + attributes_list: "service.namespace=my-namespace,service.version=1.0.0" + # Configure resource detection. + # This type is in development and subject to breaking changes in minor versions. + # If omitted or null, resource detection is disabled. + detection/development: + # Configure attributes provided by resource detectors. + attributes: + # Configure list of attribute key patterns to include from resource detectors. + # Attribute keys from resource detectors are evaluated to match as follows: + # * If the value of the attribute key exactly matches. + # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + # If omitted, all attributes are included. + included: + - process.* + # Configure list of attribute key patterns to exclude from resource detectors. Applies after .resource.detectors.attributes.included (i.e. excluded has higher priority than included). + # Attribute keys from resource detectors are evaluated to match as follows: + # * If the value of the attribute key exactly matches. + # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + # If omitted, .included attributes are included. + excluded: + - process.command_args + # Configure resource detectors. + # Resource detector names are dependent on the SDK language ecosystem. Please consult documentation for each respective language. + # If omitted or null, no resource detectors are enabled. + # TODO: implement resource detectors + # detectors: + # - # Enable the container resource detector, which populates container.* attributes. + # container: + # - # Enable the host resource detector, which populates host.* and os.* attributes. + # host: + # - # Enable the process resource detector, which populates process.* attributes. + # process: + # - # Enable the service detector, which populates service.name based on the OTEL_SERVICE_NAME environment variable and service.instance.id. + # service: + # Configure resource schema URL. + # If omitted or null, no schema URL is used. + schema_url: https://opentelemetry.io/schemas/1.16.0 +# Configure instrumentation. +# This type is in development and subject to breaking changes in minor versions. +instrumentation/development: + # Configure general SemConv options that may apply to multiple languages and instrumentations. + # Instrumenation may merge general config options with the language specific configuration at .instrumentation.. + general: + # Configure instrumentations following the peer semantic conventions. + # See peer semantic conventions: https://opentelemetry.io/docs/specs/semconv/attributes-registry/peer/ + peer: + # Configure the service mapping for instrumentations following peer.service semantic conventions. + # Each entry is a key value pair where "peer" defines the IP address and "service" defines the corresponding logical name of the service. + # See peer.service semantic conventions: https://opentelemetry.io/docs/specs/semconv/general/attributes/#general-remote-service-attributes + service_mapping: + - peer: 1.2.3.4 + service: FooService + - peer: 2.3.4.5 + service: BarService + # Configure instrumentations following the http semantic conventions. + # See http semantic conventions: https://opentelemetry.io/docs/specs/semconv/http/ + http: + # Configure instrumentations following the http client semantic conventions. + client: + # Configure headers to capture for outbound http requests. + request_captured_headers: + - Content-Type + - Accept + # Configure headers to capture for outbound http responses. + response_captured_headers: + - Content-Type + - Content-Encoding + # Configure instrumentations following the http server semantic conventions. + server: + # Configure headers to capture for inbound http requests. + request_captured_headers: + - Content-Type + - Accept + # Configure headers to capture for outbound http responses. + response_captured_headers: + - Content-Type + - Content-Encoding + # Configure C++ language-specific instrumentation libraries. + cpp: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure .NET language-specific instrumentation libraries. + dotnet: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure Erlang language-specific instrumentation libraries. + erlang: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure Go language-specific instrumentation libraries. + go: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure Java language-specific instrumentation libraries. + java: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure JavaScript language-specific instrumentation libraries. + js: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure PHP language-specific instrumentation libraries. + php: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure Python language-specific instrumentation libraries. + python: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure Ruby language-specific instrumentation libraries. + ruby: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure Rust language-specific instrumentation libraries. + rust: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + # Configure Swift language-specific instrumentation libraries. + swift: + # Configure the instrumentation corresponding to key "example". + example: + property: "value" + From 45598a1bde89d5ede0f6d210aaa40d2ddbc683c3 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Wed, 15 Oct 2025 11:51:58 -0700 Subject: [PATCH 14/39] set defaults for disabled/log_level Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_test.go | 3 +- otelconf/config_yaml.go | 159 ++++++++++++++++++-------- otelconf/v1.0.0-rc.1/config_common.go | 5 + 3 files changed, 117 insertions(+), 50 deletions(-) create mode 100644 otelconf/v1.0.0-rc.1/config_common.go diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 1f879c2ed79..3af4fe14889 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -929,13 +929,14 @@ func TestParseYAML(t *testing.T) { wantType: &OpenTelemetryConfiguration{ Disabled: ptr(false), FileFormat: "0.1", + LogLevel: ptr("info"), }, }, { name: "invalid config", input: "invalid_bool.yaml", wantErr: errors.New(`yaml: unmarshal errors: - line 2: cannot unmarshal !!str ` + "`notabool`" + ` into bool`), + line 1: cannot unmarshal !!str ` + "`notabool`" + ` into bool`), }, { name: "invalid nil name", diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index c34f27f2c31..b64877457bf 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -42,78 +42,138 @@ func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { } func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { - type Plain OpenTelemetryConfiguration - var plain Plain + var raw map[string]any - if err := node.Decode(&plain); err != nil { + if err := node.Decode(&raw); err != nil { return err } - marshaled, err := yaml.Marshal(plain.LoggerProvider) - if err != nil { - return err - } + type Plain OpenTelemetryConfiguration + var plain Plain - var lp LoggerProviderJson - if err := yaml.Unmarshal(marshaled, &lp); err != nil { - return err + if v, ok := raw["logger_provider"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } + var lp LoggerProviderJson + if err := yaml.Unmarshal(marshaled, &lp); err != nil { + return err + } + plain.LoggerProvider = &lp } - plain.LoggerProvider = &lp - marshaled, err = yaml.Marshal(plain.MeterProvider) - if err != nil { - return err - } + if v, ok := raw["meter_provider"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } - var mp MeterProviderJson - if err := yaml.Unmarshal(marshaled, &mp); err != nil { - return err + var mp MeterProviderJson + if err := yaml.Unmarshal(marshaled, &mp); err != nil { + return err + } + plain.MeterProvider = &mp } - plain.MeterProvider = &mp - marshaled, err = yaml.Marshal(plain.TracerProvider) - if err != nil { - return err - } + if v, ok := raw["tracer_provider"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } - var tp TracerProviderJson - if err := yaml.Unmarshal(marshaled, &tp); err != nil { - return err + var tp TracerProviderJson + if err := yaml.Unmarshal(marshaled, &tp); err != nil { + return err + } + plain.TracerProvider = &tp } - plain.TracerProvider = &tp - marshaled, err = yaml.Marshal(plain.Propagator) - if err != nil { - return err + if v, ok := raw["propagator"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } + + var p PropagatorJson + if err := yaml.Unmarshal(marshaled, &p); err != nil { + return err + } + plain.Propagator = &p } - var p PropagatorJson - if err := yaml.Unmarshal(marshaled, &p); err != nil { - return err + if v, ok := raw["resource"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } + + var r ResourceJson + if err := yaml.Unmarshal(marshaled, &r); err != nil { + return err + } + plain.Resource = &r } - plain.Propagator = &p - marshaled, err = yaml.Marshal(plain.Resource) - if err != nil { - return err + if v, ok := raw["instrumentation/development"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } + + var i InstrumentationJson + if err := yaml.Unmarshal(marshaled, &i); err != nil { + return err + } + plain.InstrumentationDevelopment = &i } - var r ResourceJson - if err := yaml.Unmarshal(marshaled, &r); err != nil { - return err + if v, ok := raw["attribute_limits"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } + + var a AttributeLimits + if err := yaml.Unmarshal(marshaled, &a); err != nil { + return err + } + plain.AttributeLimits = &a } - plain.Resource = &r - marshaled, err = yaml.Marshal(plain.InstrumentationDevelopment) - if err != nil { - return err + // Configure if the SDK is disabled or not. + // If omitted or null, false is used. + plain.Disabled = ptr(false) + if v, ok := raw["disabled"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } + + var disabled bool + if err := yaml.Unmarshal(marshaled, &disabled); err != nil { + return err + } + plain.Disabled = &disabled } - var i InstrumentationJson - if err := yaml.Unmarshal(marshaled, &i); err != nil { - return err + // Configure the log level of the internal logger used by the SDK. + // If omitted, info is used. + plain.LogLevel = ptr("info") + if v, ok := raw["log_level"]; ok && v != nil { + marshaled, err := yaml.Marshal(v) + if err != nil { + return err + } + + var logLevel string + if err := yaml.Unmarshal(marshaled, &logLevel); err != nil { + return err + } + plain.LogLevel = &logLevel } - plain.InstrumentationDevelopment = &i + + plain.FileFormat = fmt.Sprintf("%v", raw["file_format"]) *j = OpenTelemetryConfiguration(plain) return nil @@ -312,10 +372,11 @@ func (j *Sampler) UnmarshalYAML(node *yaml.Node) error { if err := node.Decode(&plain); err != nil { return err } - // console can be nil, must check and set here + // always_on can be nil, must check and set here if _, ok := raw["always_on"]; ok { plain.AlwaysOn = AlwaysOnSampler{} } + // always_off can be nil, must check and set here if _, ok := raw["always_off"]; ok { plain.AlwaysOff = AlwaysOffSampler{} } diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go new file mode 100644 index 00000000000..b15a3a65037 --- /dev/null +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -0,0 +1,5 @@ +package otelconf + +func ptr[T any](v T) *T { + return &v +} From 625f8051bbe3a60335c10a1309459e026ff2a768 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Wed, 15 Oct 2025 13:31:02 -0700 Subject: [PATCH 15/39] add json parsing/tests Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 262 +++++++++++- otelconf/config_test.go | 14 +- otelconf/testdata/v1.0.0-rc.1.json | 615 +++++++++++++++++++++++++++++ 3 files changed, 883 insertions(+), 8 deletions(-) create mode 100644 otelconf/testdata/v1.0.0-rc.1.json diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 33581b122c2..f61abd5af53 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -389,10 +389,10 @@ func (j *NameStringValuePair) UnmarshalJSON(b []byte) error { var name, value string var ok bool if name, ok = raw["name"].(string); !ok { - return errors.New("yaml: cannot unmarshal field name in NameStringValuePair must be string") + return errors.New("json: cannot unmarshal field name in NameStringValuePair must be string") } if value, ok = raw["value"].(string); !ok { - return errors.New("yaml: cannot unmarshal field value in NameStringValuePair must be string") + return errors.New("json: cannot unmarshal field value in NameStringValuePair must be string") } *j = NameStringValuePair{ @@ -522,9 +522,131 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { } type Plain OpenTelemetryConfiguration var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err + + if v, ok := raw["logger_provider"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + var lp LoggerProviderJson + if err := json.Unmarshal(marshaled, &lp); err != nil { + return err + } + plain.LoggerProvider = &lp + } + + if v, ok := raw["meter_provider"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + + var mp MeterProviderJson + if err := json.Unmarshal(marshaled, &mp); err != nil { + return err + } + plain.MeterProvider = &mp } + + if v, ok := raw["tracer_provider"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + + var tp TracerProviderJson + if err := json.Unmarshal(marshaled, &tp); err != nil { + return err + } + plain.TracerProvider = &tp + } + + if v, ok := raw["propagator"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + + var p PropagatorJson + if err := json.Unmarshal(marshaled, &p); err != nil { + return err + } + plain.Propagator = &p + } + + if v, ok := raw["resource"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + + var r ResourceJson + if err := json.Unmarshal(marshaled, &r); err != nil { + return err + } + plain.Resource = &r + } + + if v, ok := raw["instrumentation/development"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + + var i InstrumentationJson + if err := json.Unmarshal(marshaled, &i); err != nil { + return err + } + plain.InstrumentationDevelopment = &i + } + + if v, ok := raw["attribute_limits"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + + var a AttributeLimits + if err := json.Unmarshal(marshaled, &a); err != nil { + return err + } + plain.AttributeLimits = &a + } + + // Configure if the SDK is disabled or not. + // If omitted or null, false is used. + plain.Disabled = ptr(false) + if v, ok := raw["disabled"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + + var disabled bool + if err := json.Unmarshal(marshaled, &disabled); err != nil { + return err + } + plain.Disabled = &disabled + } + + // Configure the log level of the internal logger used by the SDK. + // If omitted, info is used. + plain.LogLevel = ptr("info") + if v, ok := raw["log_level"]; ok && v != nil { + marshaled, err := json.Marshal(v) + if err != nil { + return err + } + + var logLevel string + if err := json.Unmarshal(marshaled, &logLevel); err != nil { + return err + } + plain.LogLevel = &logLevel + } + + plain.FileFormat = fmt.Sprintf("%v", raw["file_format"]) + *j = OpenTelemetryConfiguration(plain) return nil } @@ -1027,3 +1149,135 @@ func (j *PullMetricReader) UnmarshalJSON(b []byte) error { *j = PullMetricReader(sh.Plain) return nil } + +func (j *PushMetricExporter) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain PushMetricExporter + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + // console can be nil, must check and set here + if _, ok := raw["console"]; ok { + plain.Console = ConsoleExporter{} + } + *j = PushMetricExporter(plain) + return nil +} + +func (j *SpanExporter) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain SpanExporter + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + // console can be nil, must check and set here + if _, ok := raw["console"]; ok { + plain.Console = ConsoleExporter{} + } + *j = SpanExporter(plain) + return nil +} + +func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain LogRecordExporter + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + // console can be nil, must check and set here + if _, ok := raw["console"]; ok { + plain.Console = ConsoleExporter{} + } + *j = LogRecordExporter(plain) + return nil +} + +func (j *Sampler) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain Sampler + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + // always_on can be nil, must check and set here + if _, ok := raw["always_on"]; ok { + plain.AlwaysOn = AlwaysOnSampler{} + } + // always_off can be nil, must check and set here + if _, ok := raw["always_off"]; ok { + plain.AlwaysOff = AlwaysOffSampler{} + } + *j = Sampler(plain) + return nil +} + +func (j *MetricProducer) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain MetricProducer + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + // opencensus can be nil, must check and set here + if v, ok := raw["opencensus"]; ok && v == nil { + delete(raw, "opencensus") + plain.Opencensus = OpenCensusMetricProducer{} + } + if len(raw) > 0 { + plain.AdditionalProperties = raw + } + + *j = MetricProducer(plain) + return nil +} + +func (j *TextMapPropagator) UnmarshalJSON(b []byte) error { + var raw map[string]any + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain TextMapPropagator + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + // b3 can be nil, must check and set here + if v, ok := raw["b3"]; ok && v == nil { + plain.B3 = B3Propagator{} + } + if v, ok := raw["b3multi"]; ok && v == nil { + plain.B3Multi = B3MultiPropagator{} + } + if v, ok := raw["baggage"]; ok && v == nil { + plain.Baggage = BaggagePropagator{} + } + if v, ok := raw["jaeger"]; ok && v == nil { + plain.Jaeger = JaegerPropagator{} + } + if v, ok := raw["ottrace"]; ok && v == nil { + plain.Ottrace = OpenTracingPropagator{} + } + if v, ok := raw["tracecontext"]; ok && v == nil { + plain.Tracecontext = TraceContextPropagator{} + } + *j = TextMapPropagator(plain) + return nil +} diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 3af4fe14889..116c832ea85 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -1104,12 +1104,13 @@ func TestSerializeJSON(t *testing.T) { wantType: OpenTelemetryConfiguration{ Disabled: ptr(false), FileFormat: "0.1", + LogLevel: ptr("info"), }, }, { name: "invalid config", input: "invalid_bool.json", - wantErr: errors.New(`json: cannot unmarshal string into Go struct field Plain.disabled of type bool`), + wantErr: errors.New(`json: cannot unmarshal string into Go value of type bool`), }, { name: "invalid nil name", @@ -1124,11 +1125,16 @@ func TestSerializeJSON(t *testing.T) { { name: "valid v0.2 config", input: "v0.2.json", - wantErr: errors.New(`json: cannot unmarshal object into Go struct field LogRecordProcessor.logger_provider.processors.batch`), + wantErr: errors.New(`json: cannot unmarshal array into Go struct field View.views.stream.attribute_keys of type otelconf.IncludeExclude`), + }, + { + name: "valid v0.3 config", + input: "v0.3.json", + wantErr: errors.New(`json: cannot unmarshal string into Go struct field PropagatorJson.composite of type map[string]interface {}`), }, { - name: "valid v0.3 config", - input: "v0.3.json", + name: "valid v1.0.0 config", + input: "v1.0.0-rc.1.json", wantType: v10OpenTelemetryConfig, }, } diff --git a/otelconf/testdata/v1.0.0-rc.1.json b/otelconf/testdata/v1.0.0-rc.1.json new file mode 100644 index 00000000000..635de1b9cc6 --- /dev/null +++ b/otelconf/testdata/v1.0.0-rc.1.json @@ -0,0 +1,615 @@ +{ + "file_format": "1.0-rc.1", + "disabled": false, + "log_level": "info", + "attribute_limits": { + "attribute_value_length_limit": 4096, + "attribute_count_limit": 128 + }, + "logger_provider": { + "processors": [ + { + "batch": { + "schedule_delay": 5000, + "export_timeout": 30000, + "max_queue_size": 2048, + "max_export_batch_size": 512, + "exporter": { + "otlp_http": { + "endpoint": "http://localhost:4318/v1/logs", + "certificate_file": "/app/cert.pem", + "client_key_file": "/app/cert.pem", + "client_certificate_file": "/app/cert.pem", + "headers": [ + { + "name": "api-key", + "value": "1234" + } + ], + "headers_list": "api-key=1234", + "compression": "gzip", + "timeout": 10000, + "encoding": "protobuf" + } + } + } + }, + { + "batch": { + "exporter": { + "otlp_grpc": { + "endpoint": "http://localhost:4317", + "certificate_file": "/app/cert.pem", + "client_key_file": "/app/cert.pem", + "client_certificate_file": "/app/cert.pem", + "headers": [ + { + "name": "api-key", + "value": "1234" + } + ], + "headers_list": "api-key=1234", + "compression": "gzip", + "timeout": 10000, + "insecure": false + } + } + } + }, + { + "batch": { + "exporter": { + "otlp_file/development": { + "output_stream": "file:///var/log/logs.jsonl" + } + } + } + }, + { + "batch": { + "exporter": { + "otlp_file/development": { + "output_stream": "stdout" + } + } + } + }, + { + "simple": { + "exporter": { + "console": null + } + } + } + ], + "limits": { + "attribute_value_length_limit": 4096, + "attribute_count_limit": 128 + }, + "logger_configurator/development": { + "default_config": { + "disabled": true + }, + "loggers": [ + { + "name": "io.opentelemetry.contrib.*", + "config": { + "disabled": false + } + } + ] + } + }, + "meter_provider": { + "readers": [ + { + "pull": { + "exporter": { + "prometheus/development": { + "host": "localhost", + "port": 9464, + "without_scope_info": false, + "with_resource_constant_labels": { + "included": [ + "service*" + ], + "excluded": [ + "service.attr1" + ] + }, + "translation_strategy": "UnderscoreEscapingWithSuffixes" + } + }, + "producers": [ + { + "opencensus": null + } + ], + "cardinality_limits": { + "default": 2000, + "counter": 2000, + "gauge": 2000, + "histogram": 2000, + "observable_counter": 2000, + "observable_gauge": 2000, + "observable_up_down_counter": 2000, + "up_down_counter": 2000 + } + } + }, + { + "periodic": { + "interval": 60000, + "timeout": 30000, + "exporter": { + "otlp_http": { + "endpoint": "http://localhost:4318/v1/metrics", + "certificate_file": "/app/cert.pem", + "client_key_file": "/app/cert.pem", + "client_certificate_file": "/app/cert.pem", + "headers": [ + { + "name": "api-key", + "value": "1234" + } + ], + "headers_list": "api-key=1234", + "compression": "gzip", + "timeout": 10000, + "encoding": "protobuf", + "temporality_preference": "delta", + "default_histogram_aggregation": "base2_exponential_bucket_histogram" + } + }, + "producers": [ + { + "prometheus": null + } + ], + "cardinality_limits": { + "default": 2000, + "counter": 2000, + "gauge": 2000, + "histogram": 2000, + "observable_counter": 2000, + "observable_gauge": 2000, + "observable_up_down_counter": 2000, + "up_down_counter": 2000 + } + } + }, + { + "periodic": { + "exporter": { + "otlp_grpc": { + "endpoint": "http://localhost:4317", + "certificate_file": "/app/cert.pem", + "client_key_file": "/app/cert.pem", + "client_certificate_file": "/app/cert.pem", + "headers": [ + { + "name": "api-key", + "value": "1234" + } + ], + "headers_list": "api-key=1234", + "compression": "gzip", + "timeout": 10000, + "insecure": false, + "temporality_preference": "delta", + "default_histogram_aggregation": "base2_exponential_bucket_histogram" + } + } + } + }, + { + "periodic": { + "exporter": { + "otlp_file/development": { + "output_stream": "file:///var/log/metrics.jsonl", + "temporality_preference": "delta", + "default_histogram_aggregation": "base2_exponential_bucket_histogram" + } + } + } + }, + { + "periodic": { + "exporter": { + "otlp_file/development": { + "output_stream": "stdout", + "temporality_preference": "delta", + "default_histogram_aggregation": "base2_exponential_bucket_histogram" + } + } + } + }, + { + "periodic": { + "exporter": { + "console": null + } + } + } + ], + "views": [ + { + "selector": { + "instrument_name": "my-instrument", + "instrument_type": "histogram", + "unit": "ms", + "meter_name": "my-meter", + "meter_version": "1.0.0", + "meter_schema_url": "https://opentelemetry.io/schemas/1.16.0" + }, + "stream": { + "name": "new_instrument_name", + "description": "new_description", + "aggregation": { + "explicit_bucket_histogram": { + "boundaries": [ + 0, + 5, + 10, + 25, + 50, + 75, + 100, + 250, + 500, + 750, + 1000, + 2500, + 5000, + 7500, + 10000 + ], + "record_min_max": true + } + }, + "aggregation_cardinality_limit": 2000, + "attribute_keys": { + "included": [ + "key1", + "key2" + ], + "excluded": [ + "key3" + ] + } + } + } + ], + "exemplar_filter": "trace_based", + "meter_configurator/development": { + "default_config": { + "disabled": true + }, + "meters": [ + { + "name": "io.opentelemetry.contrib.*", + "config": { + "disabled": false + } + } + ] + } + }, + "propagator": { + "composite": [ + { + "tracecontext": null + }, + { + "baggage": null + }, + { + "b3": null + }, + { + "b3multi": null + }, + { + "jaeger": null + }, + { + "ottrace": null + } + ], + "composite_list": "tracecontext,baggage,b3,b3multi,jaeger,ottrace,xray" + }, + "tracer_provider": { + "processors": [ + { + "batch": { + "schedule_delay": 5000, + "export_timeout": 30000, + "max_queue_size": 2048, + "max_export_batch_size": 512, + "exporter": { + "otlp_http": { + "endpoint": "http://localhost:4318/v1/traces", + "certificate_file": "/app/cert.pem", + "client_key_file": "/app/cert.pem", + "client_certificate_file": "/app/cert.pem", + "headers": [ + { + "name": "api-key", + "value": "1234" + } + ], + "headers_list": "api-key=1234", + "compression": "gzip", + "timeout": 10000, + "encoding": "protobuf" + } + } + } + }, + { + "batch": { + "exporter": { + "otlp_grpc": { + "endpoint": "http://localhost:4317", + "certificate_file": "/app/cert.pem", + "client_key_file": "/app/cert.pem", + "client_certificate_file": "/app/cert.pem", + "headers": [ + { + "name": "api-key", + "value": "1234" + } + ], + "headers_list": "api-key=1234", + "compression": "gzip", + "timeout": 10000, + "insecure": false + } + } + } + }, + { + "batch": { + "exporter": { + "otlp_file/development": { + "output_stream": "file:///var/log/traces.jsonl" + } + } + } + }, + { + "batch": { + "exporter": { + "otlp_file/development": { + "output_stream": "stdout" + } + } + } + }, + { + "batch": { + "exporter": { + "zipkin": { + "endpoint": "http://localhost:9411/api/v2/spans", + "timeout": 10000 + } + } + } + }, + { + "simple": { + "exporter": { + "console": null + } + } + } + ], + "limits": { + "attribute_value_length_limit": 4096, + "attribute_count_limit": 128, + "event_count_limit": 128, + "link_count_limit": 128, + "event_attribute_count_limit": 128, + "link_attribute_count_limit": 128 + }, + "sampler": { + "parent_based": { + "root": { + "trace_id_ratio_based": { + "ratio": 0.0001 + } + }, + "remote_parent_sampled": { + "always_on": null + }, + "remote_parent_not_sampled": { + "always_off": null + }, + "local_parent_sampled": { + "always_on": null + }, + "local_parent_not_sampled": { + "always_off": null + } + } + }, + "tracer_configurator/development": { + "default_config": { + "disabled": true + }, + "tracers": [ + { + "name": "io.opentelemetry.contrib.*", + "config": { + "disabled": false + } + } + ] + } + }, + "resource": { + "attributes": [ + { + "name": "service.name", + "value": "unknown_service" + }, + { + "name": "string_key", + "value": "value", + "type": "string" + }, + { + "name": "bool_key", + "value": true, + "type": "bool" + }, + { + "name": "int_key", + "value": 1, + "type": "int" + }, + { + "name": "double_key", + "value": 1.1, + "type": "double" + }, + { + "name": "string_array_key", + "value": [ + "value1", + "value2" + ], + "type": "string_array" + }, + { + "name": "bool_array_key", + "value": [ + true, + false + ], + "type": "bool_array" + }, + { + "name": "int_array_key", + "value": [ + 1, + 2 + ], + "type": "int_array" + }, + { + "name": "double_array_key", + "value": [ + 1.1, + 2.2 + ], + "type": "double_array" + } + ], + "attributes_list": "service.namespace=my-namespace,service.version=1.0.0", + "detection/development": { + "attributes": { + "included": [ + "process.*" + ], + "excluded": [ + "process.command_args" + ] + } + }, + "schema_url": "https://opentelemetry.io/schemas/1.16.0" + }, + "instrumentation/development": { + "general": { + "peer": { + "service_mapping": [ + { + "peer": "1.2.3.4", + "service": "FooService" + }, + { + "peer": "2.3.4.5", + "service": "BarService" + } + ] + }, + "http": { + "client": { + "request_captured_headers": [ + "Content-Type", + "Accept" + ], + "response_captured_headers": [ + "Content-Type", + "Content-Encoding" + ] + }, + "server": { + "request_captured_headers": [ + "Content-Type", + "Accept" + ], + "response_captured_headers": [ + "Content-Type", + "Content-Encoding" + ] + } + } + }, + "cpp": { + "example": { + "property": "value" + } + }, + "dotnet": { + "example": { + "property": "value" + } + }, + "erlang": { + "example": { + "property": "value" + } + }, + "go": { + "example": { + "property": "value" + } + }, + "java": { + "example": { + "property": "value" + } + }, + "js": { + "example": { + "property": "value" + } + }, + "php": { + "example": { + "property": "value" + } + }, + "python": { + "example": { + "property": "value" + } + }, + "ruby": { + "example": { + "property": "value" + } + }, + "rust": { + "example": { + "property": "value" + } + }, + "swift": { + "example": { + "property": "value" + } + } + } +} \ No newline at end of file From 472e29b6578d872adeda0ca503b28fac8f55c822 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 09:39:57 -0700 Subject: [PATCH 16/39] refactor common logic Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 98 ++++-------------- otelconf/config_test.go | 8 +- otelconf/config_yaml.go | 103 ++++--------------- otelconf/v1.0.0-rc.1/config_common.go | 137 ++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 169 deletions(-) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index f61abd5af53..1bcbef93fe6 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -380,19 +380,15 @@ func (j *NameStringValuePair) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &raw); err != nil { return err } - if _, ok := raw["name"]; !ok { - return errors.New("json: cannot unmarshal field name in NameStringValuePair required") - } - if _, ok := raw["value"]; !ok { - return errors.New("json: cannot unmarshal field value in NameStringValuePair required") - } - var name, value string - var ok bool - if name, ok = raw["name"].(string); !ok { - return errors.New("json: cannot unmarshal field name in NameStringValuePair must be string") + + name, err := validateStringField(raw, "name") + if err != nil { + return err } - if value, ok = raw["value"].(string); !ok { - return errors.New("json: cannot unmarshal field value in NameStringValuePair must be string") + + value, err := validateStringField(raw, "value") + if err != nil { + return err } *j = NameStringValuePair{ @@ -613,36 +609,9 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { plain.AttributeLimits = &a } - // Configure if the SDK is disabled or not. - // If omitted or null, false is used. - plain.Disabled = ptr(false) - if v, ok := raw["disabled"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { - return err - } - - var disabled bool - if err := json.Unmarshal(marshaled, &disabled); err != nil { - return err - } - plain.Disabled = &disabled - } - - // Configure the log level of the internal logger used by the SDK. - // If omitted, info is used. - plain.LogLevel = ptr("info") - if v, ok := raw["log_level"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { - return err - } - - var logLevel string - if err := json.Unmarshal(marshaled, &logLevel); err != nil { - return err - } - plain.LogLevel = &logLevel + plainConfig := (*OpenTelemetryConfiguration)(&plain) + if err := setConfigDefaults(raw, plainConfig, jsonCodec{}); err != nil { + return err } plain.FileFormat = fmt.Sprintf("%v", raw["file_format"]) @@ -1161,7 +1130,7 @@ func (j *PushMetricExporter) UnmarshalJSON(b []byte) error { return err } // console can be nil, must check and set here - if _, ok := raw["console"]; ok { + if checkConsoleExporter(raw) { plain.Console = ConsoleExporter{} } *j = PushMetricExporter(plain) @@ -1179,7 +1148,7 @@ func (j *SpanExporter) UnmarshalJSON(b []byte) error { return err } // console can be nil, must check and set here - if _, ok := raw["console"]; ok { + if checkConsoleExporter(raw) { plain.Console = ConsoleExporter{} } *j = SpanExporter(plain) @@ -1197,7 +1166,7 @@ func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { return err } // console can be nil, must check and set here - if _, ok := raw["console"]; ok { + if checkConsoleExporter(raw) { plain.Console = ConsoleExporter{} } *j = LogRecordExporter(plain) @@ -1214,14 +1183,7 @@ func (j *Sampler) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &plain); err != nil { return err } - // always_on can be nil, must check and set here - if _, ok := raw["always_on"]; ok { - plain.AlwaysOn = AlwaysOnSampler{} - } - // always_off can be nil, must check and set here - if _, ok := raw["always_off"]; ok { - plain.AlwaysOff = AlwaysOffSampler{} - } + unmarshalSamplerTypes(raw, (*Sampler)(&plain)) *j = Sampler(plain) return nil } @@ -1236,15 +1198,7 @@ func (j *MetricProducer) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &plain); err != nil { return err } - // opencensus can be nil, must check and set here - if v, ok := raw["opencensus"]; ok && v == nil { - delete(raw, "opencensus") - plain.Opencensus = OpenCensusMetricProducer{} - } - if len(raw) > 0 { - plain.AdditionalProperties = raw - } - + unmarshalMetricProducer(raw, (*MetricProducer)(&plain)) *j = MetricProducer(plain) return nil } @@ -1259,25 +1213,7 @@ func (j *TextMapPropagator) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &plain); err != nil { return err } - // b3 can be nil, must check and set here - if v, ok := raw["b3"]; ok && v == nil { - plain.B3 = B3Propagator{} - } - if v, ok := raw["b3multi"]; ok && v == nil { - plain.B3Multi = B3MultiPropagator{} - } - if v, ok := raw["baggage"]; ok && v == nil { - plain.Baggage = BaggagePropagator{} - } - if v, ok := raw["jaeger"]; ok && v == nil { - plain.Jaeger = JaegerPropagator{} - } - if v, ok := raw["ottrace"]; ok && v == nil { - plain.Ottrace = OpenTracingPropagator{} - } - if v, ok := raw["tracecontext"]; ok && v == nil { - plain.Tracecontext = TraceContextPropagator{} - } + unmarshalTextMapPropagatorTypes(raw, (*TextMapPropagator)(&plain)) *j = TextMapPropagator(plain) return nil } diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 116c832ea85..a9a12fbc9fb 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -941,12 +941,12 @@ func TestParseYAML(t *testing.T) { { name: "invalid nil name", input: "v1.0.0_invalid_nil_name.yaml", - wantErr: errors.New(`yaml: cannot unmarshal field name in NameStringValuePair required`), + wantErr: errors.New(`cannot unmarshal field name in NameStringValuePair required`), }, { name: "invalid nil value", input: "v1.0.0_invalid_nil_value.yaml", - wantErr: errors.New(`yaml: cannot unmarshal field value in NameStringValuePair required`), + wantErr: errors.New(`cannot unmarshal field value in NameStringValuePair required`), }, { name: "valid v0.2 config", @@ -1115,12 +1115,12 @@ func TestSerializeJSON(t *testing.T) { { name: "invalid nil name", input: "v1.0.0_invalid_nil_name.json", - wantErr: errors.New(`json: cannot unmarshal field name in NameStringValuePair required`), + wantErr: errors.New(`cannot unmarshal field name in NameStringValuePair required`), }, { name: "invalid nil value", input: "v1.0.0_invalid_nil_value.json", - wantErr: errors.New(`json: cannot unmarshal field value in NameStringValuePair required`), + wantErr: errors.New(`cannot unmarshal field value in NameStringValuePair required`), }, { name: "valid v0.2 config", diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index b64877457bf..afa923b1f1d 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -4,7 +4,6 @@ package otelconf // import "go.opentelemetry.io/contrib/otelconf" import ( - "errors" "fmt" "reflect" @@ -141,41 +140,13 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { plain.AttributeLimits = &a } - // Configure if the SDK is disabled or not. - // If omitted or null, false is used. - plain.Disabled = ptr(false) - if v, ok := raw["disabled"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return err - } - - var disabled bool - if err := yaml.Unmarshal(marshaled, &disabled); err != nil { - return err - } - plain.Disabled = &disabled - } - - // Configure the log level of the internal logger used by the SDK. - // If omitted, info is used. - plain.LogLevel = ptr("info") - if v, ok := raw["log_level"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return err - } - - var logLevel string - if err := yaml.Unmarshal(marshaled, &logLevel); err != nil { - return err - } - plain.LogLevel = &logLevel + plainConfig := (*OpenTelemetryConfiguration)(&plain) + if err := setConfigDefaults(raw, plainConfig, yamlCodec{}); err != nil { + return err } plain.FileFormat = fmt.Sprintf("%v", raw["file_format"]) - - *j = OpenTelemetryConfiguration(plain) + *j = *plainConfig return nil } @@ -287,20 +258,17 @@ func (j *NameStringValuePair) UnmarshalYAML(node *yaml.Node) error { if err := node.Decode(&raw); err != nil { return err } - if _, ok := raw["name"]; !ok { - return errors.New("yaml: cannot unmarshal field name in NameStringValuePair required") - } - if _, ok := raw["value"]; !ok { - return errors.New("yaml: cannot unmarshal field value in NameStringValuePair required") - } - var name, value string - var ok bool - if name, ok = raw["name"].(string); !ok { - return errors.New("yaml: cannot unmarshal field name in NameStringValuePair must be string") + + name, err := validateStringField(raw, "name") + if err != nil { + return err } - if value, ok = raw["value"].(string); !ok { - return errors.New("yaml: cannot unmarshal field value in NameStringValuePair must be string") + + value, err := validateStringField(raw, "value") + if err != nil { + return err } + *j = NameStringValuePair{ Name: name, Value: &value, @@ -319,7 +287,7 @@ func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { return err } // console can be nil, must check and set here - if _, ok := raw["console"]; ok { + if checkConsoleExporter(raw) { plain.Console = ConsoleExporter{} } *j = PushMetricExporter(plain) @@ -337,7 +305,7 @@ func (j *SpanExporter) UnmarshalYAML(node *yaml.Node) error { return err } // console can be nil, must check and set here - if _, ok := raw["console"]; ok { + if checkConsoleExporter(raw) { plain.Console = ConsoleExporter{} } *j = SpanExporter(plain) @@ -355,7 +323,7 @@ func (j *LogRecordExporter) UnmarshalYAML(node *yaml.Node) error { return err } // console can be nil, must check and set here - if _, ok := raw["console"]; ok { + if checkConsoleExporter(raw) { plain.Console = ConsoleExporter{} } *j = LogRecordExporter(plain) @@ -372,14 +340,7 @@ func (j *Sampler) UnmarshalYAML(node *yaml.Node) error { if err := node.Decode(&plain); err != nil { return err } - // always_on can be nil, must check and set here - if _, ok := raw["always_on"]; ok { - plain.AlwaysOn = AlwaysOnSampler{} - } - // always_off can be nil, must check and set here - if _, ok := raw["always_off"]; ok { - plain.AlwaysOff = AlwaysOffSampler{} - } + unmarshalSamplerTypes(raw, (*Sampler)(&plain)) *j = Sampler(plain) return nil } @@ -394,15 +355,7 @@ func (j *MetricProducer) UnmarshalYAML(node *yaml.Node) error { if err := node.Decode(&plain); err != nil { return err } - // opencensus can be nil, must check and set here - if v, ok := raw["opencensus"]; ok && v == nil { - delete(raw, "opencensus") - plain.Opencensus = OpenCensusMetricProducer{} - } - if len(raw) > 0 { - plain.AdditionalProperties = raw - } - + unmarshalMetricProducer(raw, (*MetricProducer)(&plain)) *j = MetricProducer(plain) return nil } @@ -417,25 +370,7 @@ func (j *TextMapPropagator) UnmarshalYAML(node *yaml.Node) error { if err := node.Decode(&plain); err != nil { return err } - // b3 can be nil, must check and set here - if v, ok := raw["b3"]; ok && v == nil { - plain.B3 = B3Propagator{} - } - if v, ok := raw["b3multi"]; ok && v == nil { - plain.B3Multi = B3MultiPropagator{} - } - if v, ok := raw["baggage"]; ok && v == nil { - plain.Baggage = BaggagePropagator{} - } - if v, ok := raw["jaeger"]; ok && v == nil { - plain.Jaeger = JaegerPropagator{} - } - if v, ok := raw["ottrace"]; ok && v == nil { - plain.Ottrace = OpenTracingPropagator{} - } - if v, ok := raw["tracecontext"]; ok && v == nil { - plain.Tracecontext = TraceContextPropagator{} - } + unmarshalTextMapPropagatorTypes(raw, (*TextMapPropagator)(&plain)) *j = TextMapPropagator(plain) return nil } diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go index b15a3a65037..820ef07c6cc 100644 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -1,5 +1,142 @@ package otelconf +import ( + "encoding/json" + "fmt" + + yaml "go.yaml.in/yaml/v3" +) + func ptr[T any](v T) *T { return &v } + +// MarshalUnmarshaler combines marshal and unmarshal operations +type MarshalUnmarshaler interface { + Marshal(v any) ([]byte, error) + Unmarshal(data []byte, v any) error +} + +// jsonCodec implements MarshalUnmarshaler for JSON +type jsonCodec struct{} + +func (jsonCodec) Marshal(v any) ([]byte, error) { + return json.Marshal(v) +} + +func (jsonCodec) Unmarshal(data []byte, v any) error { + return json.Unmarshal(data, v) +} + +// yamlCodec implements MarshalUnmarshaler for YAML +type yamlCodec struct{} + +func (yamlCodec) Marshal(v any) ([]byte, error) { + return yaml.Marshal(v) +} + +func (yamlCodec) Unmarshal(data []byte, v any) error { + return yaml.Unmarshal(data, v) +} + +// setConfigDefaults sets default values for disabled and log_level +func setConfigDefaults(raw map[string]any, plain *OpenTelemetryConfiguration, codec MarshalUnmarshaler) error { + // Configure if the SDK is disabled or not. + // If omitted or null, false is used. + plain.Disabled = ptr(false) + if v, ok := raw["disabled"]; ok && v != nil { + marshaled, err := codec.Marshal(v) + if err != nil { + return err + } + var disabled bool + if err := codec.Unmarshal(marshaled, &disabled); err != nil { + return err + } + plain.Disabled = &disabled + } + + // Configure the log level of the internal logger used by the SDK. + // If omitted, info is used. + plain.LogLevel = ptr("info") + if v, ok := raw["log_level"]; ok && v != nil { + marshaled, err := codec.Marshal(v) + if err != nil { + return err + } + var logLevel string + if err := codec.Unmarshal(marshaled, &logLevel); err != nil { + return err + } + plain.LogLevel = &logLevel + } + + return nil +} + +// validateStringField validates a string field is present and correct type +func validateStringField(raw map[string]any, fieldName string) (string, error) { + v, ok := raw[fieldName] + if !ok { + return "", fmt.Errorf("cannot unmarshal field %s in NameStringValuePair required", fieldName) + } + str, ok := v.(string) + if !ok { + return "", fmt.Errorf("cannot unmarshal field %s in NameStringValuePair must be string", fieldName) + } + return str, nil +} + +// unmarshalExporterWithConsole handles the console exporter unmarshaling pattern +// Returns true if console field was present in raw +func checkConsoleExporter(raw map[string]any) bool { + _, ok := raw["console"] + return ok +} + +// unmarshalSamplerTypes handles always_on and always_off sampler unmarshaling +func unmarshalSamplerTypes(raw map[string]any, plain *Sampler) { + // always_on can be nil, must check and set here + if _, ok := raw["always_on"]; ok { + plain.AlwaysOn = AlwaysOnSampler{} + } + // always_off can be nil, must check and set here + if _, ok := raw["always_off"]; ok { + plain.AlwaysOff = AlwaysOffSampler{} + } +} + +// unmarshalTextMapPropagatorTypes handles all propagator type unmarshaling +func unmarshalTextMapPropagatorTypes(raw map[string]any, plain *TextMapPropagator) { + // b3 can be nil, must check and set here + if v, ok := raw["b3"]; ok && v == nil { + plain.B3 = B3Propagator{} + } + if v, ok := raw["b3multi"]; ok && v == nil { + plain.B3Multi = B3MultiPropagator{} + } + if v, ok := raw["baggage"]; ok && v == nil { + plain.Baggage = BaggagePropagator{} + } + if v, ok := raw["jaeger"]; ok && v == nil { + plain.Jaeger = JaegerPropagator{} + } + if v, ok := raw["ottrace"]; ok && v == nil { + plain.Ottrace = OpenTracingPropagator{} + } + if v, ok := raw["tracecontext"]; ok && v == nil { + plain.Tracecontext = TraceContextPropagator{} + } +} + +// unmarshalMetricProducer handles opencensus metric producer unmarshaling +func unmarshalMetricProducer(raw map[string]any, plain *MetricProducer) { + // opencensus can be nil, must check and set here + if v, ok := raw["opencensus"]; ok && v == nil { + delete(raw, "opencensus") + plain.Opencensus = OpenCensusMetricProducer{} + } + if len(raw) > 0 { + plain.AdditionalProperties = raw + } +} From 8ad1d98987b2a07ef5ceffaceab6a2fc8d54e240 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:39:45 -0700 Subject: [PATCH 17/39] add env parsing test Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config.go | 7 +- otelconf/config_test.go | 102 +++++++++++++++++++++ otelconf/testdata/v1.0.0-env-var.yaml | 123 ++++++++++++++++++++++++++ 3 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 otelconf/testdata/v1.0.0-env-var.yaml diff --git a/otelconf/config.go b/otelconf/config.go index c57d03456c8..7d803213ac3 100644 --- a/otelconf/config.go +++ b/otelconf/config.go @@ -12,6 +12,7 @@ import ( "fmt" "os" + "go.opentelemetry.io/contrib/otelconf/internal/provider" "go.opentelemetry.io/otel/baggage" "go.opentelemetry.io/otel/log" nooplog "go.opentelemetry.io/otel/log/noop" @@ -179,8 +180,12 @@ func WithTracerProviderOptions(opts ...sdktrace.TracerProviderOption) Configurat // ParseYAML parses a YAML configuration file into an OpenTelemetryConfiguration. func ParseYAML(file []byte) (*OpenTelemetryConfiguration, error) { + file, err := provider.ReplaceEnvVars(file) + if err != nil { + return nil, err + } var cfg OpenTelemetryConfiguration - err := yaml.Unmarshal(file, &cfg) + err = yaml.Unmarshal(file, &cfg) if err != nil { return nil, err } diff --git a/otelconf/config_test.go b/otelconf/config_test.go index a9a12fbc9fb..216d81150ca 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -915,6 +915,64 @@ var v10OpenTelemetryConfig = OpenTelemetryConfiguration{ }, } +var v100OpenTelemetryConfigEnvParsing = OpenTelemetryConfiguration{ + Disabled: ptr(false), + FileFormat: "1.0", + LogLevel: ptr("info"), + AttributeLimits: &AttributeLimits{ + AttributeCountLimit: ptr(128), + AttributeValueLengthLimit: ptr(4096), + }, + Resource: &ResourceJson{ + Attributes: []AttributeNameValue{ + {Name: "service.name", Value: "unknown_service"}, + {Name: "string_key", Type: &AttributeType{Value: "string"}, Value: "value"}, + {Name: "bool_key", Type: &AttributeType{Value: "bool"}, Value: true}, + {Name: "int_key", Type: &AttributeType{Value: "int"}, Value: 1}, + {Name: "double_key", Type: &AttributeType{Value: "double"}, Value: 1.1}, + {Name: "string_array_key", Type: &AttributeType{Value: "string_array"}, Value: []any{"value1", "value2"}}, + {Name: "bool_array_key", Type: &AttributeType{Value: "bool_array"}, Value: []any{true, false}}, + {Name: "int_array_key", Type: &AttributeType{Value: "int_array"}, Value: []any{1, 2}}, + {Name: "double_array_key", Type: &AttributeType{Value: "double_array"}, Value: []any{1.1, 2.2}}, + {Name: "string_value", Type: &AttributeType{Value: "string"}, Value: "value"}, + {Name: "bool_value", Type: &AttributeType{Value: "bool"}, Value: true}, + {Name: "int_value", Type: &AttributeType{Value: "int"}, Value: 1}, + {Name: "float_value", Type: &AttributeType{Value: "double"}, Value: 1.1}, + {Name: "hex_value", Type: &AttributeType{Value: "int"}, Value: int(48879)}, + {Name: "quoted_string_value", Type: &AttributeType{Value: "string"}, Value: "value"}, + {Name: "quoted_bool_value", Type: &AttributeType{Value: "string"}, Value: "true"}, + {Name: "quoted_int_value", Type: &AttributeType{Value: "string"}, Value: "1"}, + {Name: "quoted_float_value", Type: &AttributeType{Value: "string"}, Value: "1.1"}, + {Name: "quoted_hex_value", Type: &AttributeType{Value: "string"}, Value: "0xbeef"}, + {Name: "alternative_env_syntax", Type: &AttributeType{Value: "string"}, Value: "value"}, + {Name: "invalid_map_value", Type: &AttributeType{Value: "string"}, Value: "value\nkey:value"}, + {Name: "multiple_references_inject", Type: &AttributeType{Value: "string"}, Value: "foo value 1.1"}, + {Name: "undefined_key", Type: &AttributeType{Value: "string"}, Value: nil}, + {Name: "undefined_key_fallback", Type: &AttributeType{Value: "string"}, Value: "fallback"}, + {Name: "env_var_in_key", Type: &AttributeType{Value: "string"}, Value: "value"}, + {Name: "replace_me", Type: &AttributeType{Value: "string"}, Value: "${DO_NOT_REPLACE_ME}"}, + {Name: "undefined_defaults_to_var", Type: &AttributeType{Value: "string"}, Value: "${STRING_VALUE}"}, + {Name: "escaped_does_not_substitute", Type: &AttributeType{Value: "string"}, Value: "${STRING_VALUE}"}, + {Name: "escaped_does_not_substitute_fallback", Type: &AttributeType{Value: "string"}, Value: "${STRING_VALUE:-fallback}"}, + {Name: "escaped_and_substituted_fallback", Type: &AttributeType{Value: "string"}, Value: "${STRING_VALUE:-value}"}, + {Name: "escaped_and_substituted", Type: &AttributeType{Value: "string"}, Value: "$value"}, + {Name: "multiple_escaped_and_not_substituted", Type: &AttributeType{Value: "string"}, Value: "$${STRING_VALUE}"}, + {Name: "undefined_key_with_escape_sequence_in_fallback", Type: &AttributeType{Value: "string"}, Value: "${UNDEFINED_KEY}"}, + {Name: "value_with_escape", Type: &AttributeType{Value: "string"}, Value: "value$$"}, + {Name: "escape_sequence", Type: &AttributeType{Value: "string"}, Value: "a $ b"}, + {Name: "no_escape_sequence", Type: &AttributeType{Value: "string"}, Value: "a $ b"}, + }, + AttributesList: ptr("service.namespace=my-namespace,service.version=1.0.0"), + // Detectors: &Detectors{ + // Attributes: &DetectorsAttributes{ + // Excluded: []string{"process.command_args"}, + // Included: []string{"process.*"}, + // }, + // }, + SchemaUrl: ptr("https://opentelemetry.io/schemas/1.16.0"), + }, +} + func TestParseYAML(t *testing.T) { tests := []struct { name string @@ -1090,6 +1148,50 @@ func TestUnmarshalBatchSpanProcessor(t *testing.T) { }) } } + +func TestParseYAMLWithEnvironmentVariables(t *testing.T) { + tests := []struct { + name string + input string + wantErr error + wantType any + }{ + { + name: "valid v1.0.0 config with env vars", + input: "v1.0.0-env-var.yaml", + wantType: &v100OpenTelemetryConfigEnvParsing, + }, + } + + t.Setenv("OTEL_SDK_DISABLED", "false") + t.Setenv("OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", "4096") + t.Setenv("OTEL_EXPORTER_OTLP_PROTOCOL", "http/protobuf") + t.Setenv("STRING_VALUE", "value") + t.Setenv("BOOL_VALUE", "true") + t.Setenv("INT_VALUE", "1") + t.Setenv("FLOAT_VALUE", "1.1") + t.Setenv("HEX_VALUE", "0xbeef") // A valid integer value (i.e. 3735928559) written in hexadecimal + t.Setenv("INVALID_MAP_VALUE", "value\\nkey:value") // An invalid attempt to inject a map key into the YAML + t.Setenv("ENV_VAR_IN_KEY", "env_var_in_key") // An env var in key + t.Setenv("DO_NOT_REPLACE_ME", "Never use this value") // An unused environment variable + t.Setenv("REPLACE_ME", "${DO_NOT_REPLACE_ME}") // A valid replacement text, used verbatim, not replaced with "Never use this value" + t.Setenv("VALUE_WITH_ESCAPE", "value$$") // A valid replacement text, used verbatim, not replaced with "Never use this value" + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b, err := os.ReadFile(filepath.Join("..", "testdata", tt.input)) + require.NoError(t, err) + + got, err := ParseYAML(b) + if tt.wantErr != nil { + require.Equal(t, tt.wantErr.Error(), err.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.wantType, got) + } + }) + } +} + func TestSerializeJSON(t *testing.T) { tests := []struct { name string diff --git a/otelconf/testdata/v1.0.0-env-var.yaml b/otelconf/testdata/v1.0.0-env-var.yaml new file mode 100644 index 00000000000..2f520a2c6db --- /dev/null +++ b/otelconf/testdata/v1.0.0-env-var.yaml @@ -0,0 +1,123 @@ +file_format: "1.0" +disabled: ${OTEL_SDK_DISABLED} +attribute_limits: + attribute_value_length_limit: ${OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT} + attribute_count_limit: 128 + +resource: + attributes: + - name: service.name + value: unknown_service + - name: string_key + value: value + type: string + - name: bool_key + value: true + type: bool + - name: int_key + value: 1 + type: int + - name: double_key + value: 1.1 + type: double + - name: string_array_key + value: [ "value1", "value2" ] + type: string_array + - name: bool_array_key + value: [ true, false ] + type: bool_array + - name: int_array_key + value: [ 1, 2 ] + type: int_array + - name: double_array_key + value: [ 1.1, 2.2 ] + type: double_array + - name: string_value + value: ${STRING_VALUE} + type: string + - name: bool_value + value: ${BOOL_VALUE} + type: bool + - name: int_value + value: ${INT_VALUE} + type: int + - name: float_value + value: ${FLOAT_VALUE} + type: double + - name: hex_value + value: ${HEX_VALUE} + type: int + - name: quoted_string_value + value: "${STRING_VALUE}" + type: string + - name: quoted_bool_value + value: "${BOOL_VALUE}" + type: string + - name: quoted_int_value + value: "${INT_VALUE}" + type: string + - name: quoted_float_value + value: "${FLOAT_VALUE}" + type: string + - name: quoted_hex_value + value: "${HEX_VALUE}" + type: string + - name: alternative_env_syntax + value: "${env:STRING_VALUE}" + type: string + - name: invalid_map_value + value: "${INVALID_MAP_VALUE}" + type: string + - name: multiple_references_inject + value: foo ${STRING_VALUE} ${FLOAT_VALUE} + type: string + - name: undefined_key + value: ${UNDEFINED_KEY} + type: string + - name: undefined_key_fallback + value: ${UNDEFINED_KEY:-fallback} + type: string + - name: ${ENV_VAR_IN_KEY} + value: "value" + type: string + - name: replace_me + value: ${REPLACE_ME} + type: string + - name: undefined_defaults_to_var + value: ${UNDEFINED_KEY:-${STRING_VALUE}} + type: string + - name: escaped_does_not_substitute + value: $${STRING_VALUE} + type: string + - name: escaped_does_not_substitute_fallback + value: $${STRING_VALUE:-fallback} + type: string + - name: escaped_and_substituted_fallback + value: $${STRING_VALUE:-${STRING_VALUE}} + type: string + - name: escaped_and_substituted + value: $$${STRING_VALUE} + type: string + - name: multiple_escaped_and_not_substituted + value: $$$${STRING_VALUE} + type: string + - name: undefined_key_with_escape_sequence_in_fallback + value: ${UNDEFINED_KEY:-$${UNDEFINED_KEY}} + type: string + - name: value_with_escape + value: ${VALUE_WITH_ESCAPE} + type: string + - name: escape_sequence + value: a $$ b + type: string + - name: no_escape_sequence + value: a $ b + type: string + attributes_list: "service.namespace=my-namespace,service.version=1.0.0" + detectors: + attributes: + included: + - process.* + excluded: + - process.command_args + schema_url: https://opentelemetry.io/schemas/1.16.0 From 115b92526991dc595dcf634b84ecc91a938b9b3f Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:52:06 -0700 Subject: [PATCH 18/39] fix test Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 216d81150ca..f6ea45a0f69 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -1227,7 +1227,7 @@ func TestSerializeJSON(t *testing.T) { { name: "valid v0.2 config", input: "v0.2.json", - wantErr: errors.New(`json: cannot unmarshal array into Go struct field View.views.stream.attribute_keys of type otelconf.IncludeExclude`), + wantErr: errors.New(`json: cannot unmarshal array into Go struct field`), }, { name: "valid v0.3 config", From 24718b15eb21493b358778fed135563ba385cf46 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:53:18 -0700 Subject: [PATCH 19/39] fix license check Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/v1.0.0-rc.1/config_common.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go index 820ef07c6cc..c44058cfe9e 100644 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -1,3 +1,6 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + package otelconf import ( From e252a4cc04f7bd9ec5eebae526a3e4dd9737926b Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:57:11 -0700 Subject: [PATCH 20/39] add changelog Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- CHANGELOG.md | 1 + otelconf/config.go | 3 ++- otelconf/config_json.go | 6 ++++++ otelconf/config_yaml.go | 8 ++++++++ otelconf/metric.go | 2 +- otelconf/v1.0.0-rc.1/config_common.go | 20 ++++++++++---------- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20d56c0b70e..4e951c6eec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add unmarshaling and validation for `OTLPHttpExporter`, `OTLPGrpcExporter`, `OTLPGrpcMetricExporter` and `OTLPHttpMetricExporter` to v1.0.0 model in `go.opentelemetry.io/contrib/otelconf`. (#8112) - Add a `WithSpanNameFormatter` option to `go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo`. (#7986) - Add unmarshaling and validation for `AttributeType`, `AttributeNameValue`, `SimpleSpanProcessor`, `SimpleLogRecordProcessor`, `ZipkinSpanExporter`, `NameStringValuePair`, `InstrumentType`, `ExperimentalPeerInstrumentationServiceMappingElem`, `ExporterDefaultHistogramAggregation`, `PullMetricReader` to v1.0.0 model in `go.opentelemetry.io/contrib/otelconf`. (#8127) +- Updated `go.opentelemetry.io/contrib/otelconf` to include the [v1.0.0-rc2](https://github.com/open-telemetry/opentelemetry-configuration/releases/tag/v1.0.0-rc.2) release candidate of schema which includes backwards incompatible changes. (#8026) ### Changed diff --git a/otelconf/config.go b/otelconf/config.go index 7d803213ac3..fc6c6f5d3dd 100644 --- a/otelconf/config.go +++ b/otelconf/config.go @@ -12,7 +12,6 @@ import ( "fmt" "os" - "go.opentelemetry.io/contrib/otelconf/internal/provider" "go.opentelemetry.io/otel/baggage" "go.opentelemetry.io/otel/log" nooplog "go.opentelemetry.io/otel/log/noop" @@ -24,6 +23,8 @@ import ( "go.opentelemetry.io/otel/trace" nooptrace "go.opentelemetry.io/otel/trace/noop" yaml "go.yaml.in/yaml/v3" + + "go.opentelemetry.io/contrib/otelconf/internal/provider" ) const ( diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 1bcbef93fe6..d8dd9ad150c 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -1119,6 +1119,7 @@ func (j *PullMetricReader) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *PushMetricExporter) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { @@ -1137,6 +1138,7 @@ func (j *PushMetricExporter) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *SpanExporter) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { @@ -1155,6 +1157,7 @@ func (j *SpanExporter) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { @@ -1173,6 +1176,7 @@ func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *Sampler) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { @@ -1188,6 +1192,7 @@ func (j *Sampler) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *MetricProducer) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { @@ -1203,6 +1208,7 @@ func (j *MetricProducer) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *TextMapPropagator) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index afa923b1f1d..5b87ccd73a1 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -4,6 +4,7 @@ package otelconf // import "go.opentelemetry.io/contrib/otelconf" import ( + "errors" "fmt" "reflect" @@ -40,6 +41,7 @@ func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any @@ -276,6 +278,7 @@ func (j *NameStringValuePair) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any if err := node.Decode(&raw); err != nil { @@ -294,6 +297,7 @@ func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *SpanExporter) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any if err := node.Decode(&raw); err != nil { @@ -312,6 +316,7 @@ func (j *SpanExporter) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *LogRecordExporter) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any if err := node.Decode(&raw); err != nil { @@ -330,6 +335,7 @@ func (j *LogRecordExporter) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *Sampler) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any if err := node.Decode(&raw); err != nil { @@ -345,6 +351,7 @@ func (j *Sampler) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *MetricProducer) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any if err := node.Decode(&raw); err != nil { @@ -360,6 +367,7 @@ func (j *MetricProducer) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *TextMapPropagator) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any if err := node.Decode(&raw); err != nil { diff --git a/otelconf/metric.go b/otelconf/metric.go index 5686a99e0a0..2a685c4a0a3 100644 --- a/otelconf/metric.go +++ b/otelconf/metric.go @@ -174,7 +174,7 @@ func otlpHTTPMetricExporter(ctx context.Context, otlpConfig *OTLPHttpMetricExpor if u.Scheme == "http" { opts = append(opts, otlpmetrichttp.WithInsecure()) } - if len(u.Path) > 0 { + if u.Path != "" { opts = append(opts, otlpmetrichttp.WithURLPath(u.Path)) } } diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go index c44058cfe9e..831d7246e33 100644 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -14,13 +14,13 @@ func ptr[T any](v T) *T { return &v } -// MarshalUnmarshaler combines marshal and unmarshal operations +// MarshalUnmarshaler combines marshal and unmarshal operations. type MarshalUnmarshaler interface { Marshal(v any) ([]byte, error) Unmarshal(data []byte, v any) error } -// jsonCodec implements MarshalUnmarshaler for JSON +// jsonCodec implements MarshalUnmarshaler for JSON. type jsonCodec struct{} func (jsonCodec) Marshal(v any) ([]byte, error) { @@ -31,7 +31,7 @@ func (jsonCodec) Unmarshal(data []byte, v any) error { return json.Unmarshal(data, v) } -// yamlCodec implements MarshalUnmarshaler for YAML +// yamlCodec implements MarshalUnmarshaler for YAML. type yamlCodec struct{} func (yamlCodec) Marshal(v any) ([]byte, error) { @@ -42,7 +42,7 @@ func (yamlCodec) Unmarshal(data []byte, v any) error { return yaml.Unmarshal(data, v) } -// setConfigDefaults sets default values for disabled and log_level +// setConfigDefaults sets default values for disabled and log_level. func setConfigDefaults(raw map[string]any, plain *OpenTelemetryConfiguration, codec MarshalUnmarshaler) error { // Configure if the SDK is disabled or not. // If omitted or null, false is used. @@ -77,7 +77,7 @@ func setConfigDefaults(raw map[string]any, plain *OpenTelemetryConfiguration, co return nil } -// validateStringField validates a string field is present and correct type +// validateStringField validates a string field is present and correct type. func validateStringField(raw map[string]any, fieldName string) (string, error) { v, ok := raw[fieldName] if !ok { @@ -90,14 +90,14 @@ func validateStringField(raw map[string]any, fieldName string) (string, error) { return str, nil } -// unmarshalExporterWithConsole handles the console exporter unmarshaling pattern -// Returns true if console field was present in raw +// unmarshalExporterWithConsole handles the console exporter unmarshaling pattern. +// Returns true if console field was present in raw. func checkConsoleExporter(raw map[string]any) bool { _, ok := raw["console"] return ok } -// unmarshalSamplerTypes handles always_on and always_off sampler unmarshaling +// unmarshalSamplerTypes handles always_on and always_off sampler unmarshaling. func unmarshalSamplerTypes(raw map[string]any, plain *Sampler) { // always_on can be nil, must check and set here if _, ok := raw["always_on"]; ok { @@ -109,7 +109,7 @@ func unmarshalSamplerTypes(raw map[string]any, plain *Sampler) { } } -// unmarshalTextMapPropagatorTypes handles all propagator type unmarshaling +// unmarshalTextMapPropagatorTypes handles all propagator type unmarshaling. func unmarshalTextMapPropagatorTypes(raw map[string]any, plain *TextMapPropagator) { // b3 can be nil, must check and set here if v, ok := raw["b3"]; ok && v == nil { @@ -132,7 +132,7 @@ func unmarshalTextMapPropagatorTypes(raw map[string]any, plain *TextMapPropagato } } -// unmarshalMetricProducer handles opencensus metric producer unmarshaling +// unmarshalMetricProducer handles opencensus metric producer unmarshaling. func unmarshalMetricProducer(raw map[string]any, plain *MetricProducer) { // opencensus can be nil, must check and set here if v, ok := raw["opencensus"]; ok && v == nil { From 4f8330fcd2e51949d7c320f95426dd4dd2adb619 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:37:57 -0700 Subject: [PATCH 21/39] move common code Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 12 ------------ otelconf/v1.0.0-rc.1/config_common.go | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index d8dd9ad150c..58342c88ce2 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -198,18 +198,6 @@ func (j *AttributeType) MarshalJSON() ([]byte, error) { return json.Marshal(j.Value) } -var enumValuesAttributeType = []any{ - nil, - "string", - "bool", - "int", - "double", - "string_array", - "bool_array", - "int_array", - "double_array", -} - // UnmarshalJSON implements json.Unmarshaler. func (j *AttributeType) UnmarshalJSON(b []byte) error { var v struct { diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go index 831d7246e33..7c111e9cd3b 100644 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -14,6 +14,18 @@ func ptr[T any](v T) *T { return &v } +var enumValuesAttributeType = []any{ + nil, + "string", + "bool", + "int", + "double", + "string_array", + "bool_array", + "int_array", + "double_array", +} + // MarshalUnmarshaler combines marshal and unmarshal operations. type MarshalUnmarshaler interface { Marshal(v any) ([]byte, error) From 63b3719735867c4caaba716bf589889232501412 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:12:12 -0700 Subject: [PATCH 22/39] add validation tests for BatchLogRecordProcessor Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 3 +-- otelconf/config_test.go | 1 + otelconf/config_yaml.go | 21 +++++++++++++++++++++ otelconf/v1.0.0-rc.1/config_common.go | 17 +++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 58342c88ce2..933f0786361 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -307,8 +307,7 @@ func (j *BatchLogRecordProcessor) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(sh.Exporter, &sh.Plain.Exporter); err != nil { return err } - err := validateBatchLogRecordProcessor((*BatchLogRecordProcessor)(&sh.Plain)) - if err != nil { + if err := validateBatchLogRecordProcessor((*BatchLogRecordProcessor)(&sh.Plain)); err != nil { return err } *j = BatchLogRecordProcessor(sh.Plain) diff --git a/otelconf/config_test.go b/otelconf/config_test.go index f6ea45a0f69..fac11e8d2e5 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -22,6 +22,7 @@ import ( sdkmetric "go.opentelemetry.io/otel/sdk/metric" sdktrace "go.opentelemetry.io/otel/sdk/trace" tracenoop "go.opentelemetry.io/otel/trace/noop" + yaml "go.yaml.in/yaml/v3" ) func TestUnmarshalPushMetricExporterInvalidData(t *testing.T) { diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 5b87ccd73a1..433425bfa8a 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -713,3 +713,24 @@ func (j *ExperimentalLanguageSpecificInstrumentation) UnmarshalYAML(unmarshal fu *j = raw return nil } + +// UnmarshalYAML implements yaml.Unmarshaler. +func (j *BatchLogRecordProcessor) UnmarshalYAML(node *yaml.Node) error { + var raw map[string]any + if err := node.Decode(&raw); err != nil { + return err + } + if _, ok := raw["exporter"]; raw != nil && !ok { + return errors.New("field exporter in BatchLogRecordProcessor: required") + } + type Plain BatchLogRecordProcessor + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + if err := validateBatchLogRecordProcessor((*BatchLogRecordProcessor)(&plain)); err != nil { + return err + } + *j = BatchLogRecordProcessor(plain) + return nil +} diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go index 7c111e9cd3b..18665c486d7 100644 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -155,3 +155,20 @@ func unmarshalMetricProducer(raw map[string]any, plain *MetricProducer) { plain.AdditionalProperties = raw } } + +// validateBatchLogRecordProcessor handles validation for BatchLogRecordProcessor. +func validateBatchLogRecordProcessor(plain *BatchLogRecordProcessor) error { + if plain.ExportTimeout != nil && 0 > *plain.ExportTimeout { + return fmt.Errorf("field %s: must be >= %v", "export_timeout", 0) + } + if plain.MaxExportBatchSize != nil && 0 >= *plain.MaxExportBatchSize { + return fmt.Errorf("field %s: must be > %v", "max_export_batch_size", 0) + } + if plain.MaxQueueSize != nil && 0 >= *plain.MaxQueueSize { + return fmt.Errorf("field %s: must be > %v", "max_queue_size", 0) + } + if plain.ScheduleDelay != nil && 0 > *plain.ScheduleDelay { + return fmt.Errorf("field %s: must be >= %v", "schedule_delay", 0) + } + return nil +} From 3e754835f65429b1ef4354ef9bf28a270ee1e22e Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:18:12 -0700 Subject: [PATCH 23/39] add validation tests for BatchSpanProcessor Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 3 +-- otelconf/config_yaml.go | 21 +++++++++++++++++++++ otelconf/v1.0.0-rc.1/config_common.go | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 933f0786361..93365a602ef 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -332,8 +332,7 @@ func (j *BatchSpanProcessor) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(sh.Exporter, &sh.Plain.Exporter); err != nil { return err } - err := validateBatchSpanProcessor((*BatchSpanProcessor)(&sh.Plain)) - if err != nil { + if err := validateBatchSpanProcessor((*BatchSpanProcessor)(&sh.Plain)); err != nil { return err } *j = BatchSpanProcessor(sh.Plain) diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 433425bfa8a..9cdf8189cec 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -734,3 +734,24 @@ func (j *BatchLogRecordProcessor) UnmarshalYAML(node *yaml.Node) error { *j = BatchLogRecordProcessor(plain) return nil } + +// UnmarshalYAML implements yaml.Unmarshaler. +func (j *BatchSpanProcessor) UnmarshalYAML(node *yaml.Node) error { + var raw map[string]any + if err := node.Decode(&raw); err != nil { + return err + } + if _, ok := raw["exporter"]; raw != nil && !ok { + return errors.New("field exporter in BatchSpanProcessor: required") + } + type Plain BatchSpanProcessor + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + if err := validateBatchSpanProcessor((*BatchSpanProcessor)(&plain)); err != nil { + return err + } + *j = BatchSpanProcessor(plain) + return nil +} diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go index 18665c486d7..10393283bee 100644 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -172,3 +172,20 @@ func validateBatchLogRecordProcessor(plain *BatchLogRecordProcessor) error { } return nil } + +// validateBatchSpanProcessor handles validation for BatchSpanProcessor. +func validateBatchSpanProcessor(plain *BatchSpanProcessor) error { + if plain.ExportTimeout != nil && 0 > *plain.ExportTimeout { + return fmt.Errorf("field %s: must be >= %v", "export_timeout", 0) + } + if plain.MaxExportBatchSize != nil && 0 >= *plain.MaxExportBatchSize { + return fmt.Errorf("field %s: must be > %v", "max_export_batch_size", 0) + } + if plain.MaxQueueSize != nil && 0 >= *plain.MaxQueueSize { + return fmt.Errorf("field %s: must be > %v", "max_queue_size", 0) + } + if plain.ScheduleDelay != nil && 0 > *plain.ScheduleDelay { + return fmt.Errorf("field %s: must be >= %v", "schedule_delay", 0) + } + return nil +} From 2948c97609c519a06c9104a8c5a29b69a83c303f Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:30:26 -0700 Subject: [PATCH 24/39] add validation/tests for CardinalityLimits Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 13 ++++++++++++ otelconf/config_yaml.go | 13 ++++++++++++ otelconf/v1.0.0-rc.1/config_common.go | 29 +++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 93365a602ef..925ab477ef3 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -1209,3 +1209,16 @@ func (j *TextMapPropagator) UnmarshalJSON(b []byte) error { *j = TextMapPropagator(plain) return nil } + +func (j *CardinalityLimits) UnmarshalJSON(value []byte) error { + type Plain CardinalityLimits + var plain Plain + if err := json.Unmarshal(value, &plain); err != nil { + return err + } + if err := validateCardinalityLimits((*CardinalityLimits)(&plain)); err != nil { + return err + } + *j = CardinalityLimits(plain) + return nil +} diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 9cdf8189cec..8e5abe2b4ec 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -755,3 +755,16 @@ func (j *BatchSpanProcessor) UnmarshalYAML(node *yaml.Node) error { *j = BatchSpanProcessor(plain) return nil } + +func (j *CardinalityLimits) UnmarshalYAML(node *yaml.Node) error { + type Plain CardinalityLimits + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + if err := validateCardinalityLimits((*CardinalityLimits)(&plain)); err != nil { + return err + } + *j = CardinalityLimits(plain) + return nil +} diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go index 10393283bee..681ecc4ca5e 100644 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -189,3 +189,32 @@ func validateBatchSpanProcessor(plain *BatchSpanProcessor) error { } return nil } + +// validateCardinalityLimits handles validation for CardinalityLimits. +func validateCardinalityLimits(plain *CardinalityLimits) error { + if plain.Counter != nil && 0 >= *plain.Counter { + return fmt.Errorf("field %s: must be > %v", "counter", 0) + } + if plain.Default != nil && 0 >= *plain.Default { + return fmt.Errorf("field %s: must be > %v", "default", 0) + } + if plain.Gauge != nil && 0 >= *plain.Gauge { + return fmt.Errorf("field %s: must be > %v", "gauge", 0) + } + if plain.Histogram != nil && 0 >= *plain.Histogram { + return fmt.Errorf("field %s: must be > %v", "histogram", 0) + } + if plain.ObservableCounter != nil && 0 >= *plain.ObservableCounter { + return fmt.Errorf("field %s: must be > %v", "observable_counter", 0) + } + if plain.ObservableGauge != nil && 0 >= *plain.ObservableGauge { + return fmt.Errorf("field %s: must be > %v", "observable_gauge", 0) + } + if plain.ObservableUpDownCounter != nil && 0 >= *plain.ObservableUpDownCounter { + return fmt.Errorf("field %s: must be > %v", "observable_up_down_counter", 0) + } + if plain.UpDownCounter != nil && 0 >= *plain.UpDownCounter { + return fmt.Errorf("field %s: must be > %v", "up_down_counter", 0) + } + return nil +} From 5bb32a3e02c95a5ad94095af1f3478b3d530efb5 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:42:09 -0700 Subject: [PATCH 25/39] add validation/tests for SpanLimits Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 15 +++++ otelconf/config_test.go | 80 +++++++++++++++++++++++++++ otelconf/config_yaml.go | 15 +++++ otelconf/v1.0.0-rc.1/config_common.go | 23 ++++++++ 4 files changed, 133 insertions(+) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 925ab477ef3..e3f21a20047 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -1210,6 +1210,7 @@ func (j *TextMapPropagator) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *CardinalityLimits) UnmarshalJSON(value []byte) error { type Plain CardinalityLimits var plain Plain @@ -1222,3 +1223,17 @@ func (j *CardinalityLimits) UnmarshalJSON(value []byte) error { *j = CardinalityLimits(plain) return nil } + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SpanLimits) UnmarshalJSON(value []byte) error { + type Plain SpanLimits + var plain Plain + if err := json.Unmarshal(value, &plain); err != nil { + return err + } + if err := validateSpanLimits((*SpanLimits)(&plain)); err != nil { + return err + } + *j = SpanLimits(plain) + return nil +} diff --git a/otelconf/config_test.go b/otelconf/config_test.go index fac11e8d2e5..4db86ed9a93 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -2427,3 +2427,83 @@ func TestUnmarshalPullMetricReader(t *testing.T) { }) } } + +func TestUnmarshalSpanLimits(t *testing.T) { + for _, tt := range []struct { + name string + yamlConfig []byte + jsonConfig []byte + wantErr string + }{ + { + name: "valid with all fields positive", + jsonConfig: []byte(`{"attribute_count_limit":100,"attribute_value_length_limit":200,"event_attribute_count_limit":300,"event_count_limit":400,"link_attribute_count_limit":500,"link_count_limit":600}`), + yamlConfig: []byte("attribute_count_limit: 100\nattribute_value_length_limit: 200\nevent_attribute_count_limit: 300\nevent_count_limit: 400\nlink_attribute_count_limit: 500\nlink_count_limit: 600"), + }, + { + name: "valid with single field", + jsonConfig: []byte(`{"attribute_value_length_limit":2000}`), + yamlConfig: []byte("attribute_value_length_limit: 2000"), + }, + { + name: "valid empty", + jsonConfig: []byte(`{}`), + yamlConfig: []byte("{}"), + }, + { + name: "invalid attribute_count_limit negative", + jsonConfig: []byte(`{"attribute_count_limit":-1}`), + yamlConfig: []byte("attribute_count_limit: -1"), + wantErr: "field attribute_count_limit: must be >= 0", + }, + { + name: "invalid attribute_value_length_limit negative", + jsonConfig: []byte(`{"attribute_value_length_limit":-1}`), + yamlConfig: []byte("attribute_value_length_limit: -1"), + wantErr: "field attribute_value_length_limit: must be >= 0", + }, + { + name: "invalid event_attribute_count_limit negative", + jsonConfig: []byte(`{"event_attribute_count_limit":-1}`), + yamlConfig: []byte("event_attribute_count_limit: -1"), + wantErr: "field event_attribute_count_limit: must be >= 0", + }, + { + name: "invalid event_count_limit negative", + jsonConfig: []byte(`{"event_count_limit":-1}`), + yamlConfig: []byte("event_count_limit: -1"), + wantErr: "field event_count_limit: must be >= 0", + }, + { + name: "invalid link_attribute_count_limit negative", + jsonConfig: []byte(`{"link_attribute_count_limit":-1}`), + yamlConfig: []byte("link_attribute_count_limit: -1"), + wantErr: "field link_attribute_count_limit: must be >= 0", + }, + { + name: "invalid link_count_limit negative", + jsonConfig: []byte(`{"link_count_limit":-1}`), + yamlConfig: []byte("link_count_limit: -1"), + wantErr: "field link_count_limit: must be >= 0", + }, + } { + t.Run(tt.name, func(t *testing.T) { + cl := SpanLimits{} + err := cl.UnmarshalJSON(tt.jsonConfig) + if tt.wantErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tt.wantErr) + } else { + require.NoError(t, err) + } + cl = SpanLimits{} + err = yaml.Unmarshal(tt.yamlConfig, &cl) + if tt.wantErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tt.wantErr) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 8e5abe2b4ec..b9cd0257aa7 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -756,6 +756,7 @@ func (j *BatchSpanProcessor) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *CardinalityLimits) UnmarshalYAML(node *yaml.Node) error { type Plain CardinalityLimits var plain Plain @@ -768,3 +769,17 @@ func (j *CardinalityLimits) UnmarshalYAML(node *yaml.Node) error { *j = CardinalityLimits(plain) return nil } + +// UnmarshalYAML implements yaml.Unmarshaler. +func (j *SpanLimits) UnmarshalYAML(node *yaml.Node) error { + type Plain SpanLimits + var plain Plain + if err := node.Decode(&plain); err != nil { + return err + } + if err := validateSpanLimits((*SpanLimits)(&plain)); err != nil { + return err + } + *j = SpanLimits(plain) + return nil +} diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go index 681ecc4ca5e..25fd2effa00 100644 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ b/otelconf/v1.0.0-rc.1/config_common.go @@ -218,3 +218,26 @@ func validateCardinalityLimits(plain *CardinalityLimits) error { } return nil } + +// validateSpanLimits handles validation for SpanLimits. +func validateSpanLimits(plain *SpanLimits) error { + if plain.AttributeCountLimit != nil && 0 > *plain.AttributeCountLimit { + return fmt.Errorf("field %s: must be >= %v", "attribute_count_limit", 0) + } + if plain.AttributeValueLengthLimit != nil && 0 > *plain.AttributeValueLengthLimit { + return fmt.Errorf("field %s: must be >= %v", "attribute_value_length_limit", 0) + } + if plain.EventAttributeCountLimit != nil && 0 > *plain.EventAttributeCountLimit { + return fmt.Errorf("field %s: must be >= %v", "event_attribute_count_limit", 0) + } + if plain.EventCountLimit != nil && 0 > *plain.EventCountLimit { + return fmt.Errorf("field %s: must be >= %v", "event_count_limit", 0) + } + if plain.LinkAttributeCountLimit != nil && 0 > *plain.LinkAttributeCountLimit { + return fmt.Errorf("field %s: must be >= %v", "link_attribute_count_limit", 0) + } + if plain.LinkCountLimit != nil && 0 > *plain.LinkCountLimit { + return fmt.Errorf("field %s: must be >= %v", "link_count_limit", 0) + } + return nil +} From f7684931138e2db87077008a06979620c882933c Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Tue, 21 Oct 2025 08:14:22 -0700 Subject: [PATCH 26/39] these have been moved Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/v1.0.0-rc.1/testdata/ca.crt | 22 --------------- otelconf/v1.0.0-rc.1/testdata/ca.key | 28 ------------------- .../testdata/client-certs/client.crt | 22 --------------- .../testdata/client-certs/client.csr | 18 ------------ .../testdata/client-certs/client.key | 28 ------------------- .../testdata/server-certs/server.crt | 22 --------------- .../testdata/server-certs/server.csr | 18 ------------ .../testdata/server-certs/server.key | 28 ------------------- 8 files changed, 186 deletions(-) delete mode 100644 otelconf/v1.0.0-rc.1/testdata/ca.crt delete mode 100644 otelconf/v1.0.0-rc.1/testdata/ca.key delete mode 100644 otelconf/v1.0.0-rc.1/testdata/client-certs/client.crt delete mode 100644 otelconf/v1.0.0-rc.1/testdata/client-certs/client.csr delete mode 100644 otelconf/v1.0.0-rc.1/testdata/client-certs/client.key delete mode 100644 otelconf/v1.0.0-rc.1/testdata/server-certs/server.crt delete mode 100644 otelconf/v1.0.0-rc.1/testdata/server-certs/server.csr delete mode 100644 otelconf/v1.0.0-rc.1/testdata/server-certs/server.key diff --git a/otelconf/v1.0.0-rc.1/testdata/ca.crt b/otelconf/v1.0.0-rc.1/testdata/ca.crt deleted file mode 100644 index 51013bceb5d..00000000000 --- a/otelconf/v1.0.0-rc.1/testdata/ca.crt +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIUBxmeJyLb45dq6RmW5bOFIl8VON0wDQYJKoZIhvcNAQEL -BQAwXzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM -DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxDjAMBgNVBAMMBU15 -IENBMB4XDTI1MDQxNTEyMjM0MloXDTI2MDQxNTEyMjM0MlowXzELMAkGA1UEBhMC -VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x -EzARBgNVBAoMCk15IENvbXBhbnkxDjAMBgNVBAMMBU15IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3ywD9NQpjd2H/PaHnodeX6YWn67OaqODTsUs -mOcJphhfya+/lybNtWScHoiURpB40QhTacDsjQ7J0Trykznm6ynl06uSQZKONVxo -LW+FmCBDRE+BqmFBFdMEMvRBGVxns7IctzY//GaZbX81Ni1pyLrzrRG9B5LuU7Sb -yggByJrut72RC7bRgAz8v2s++JKvDVKRk3hTmSwCiEC30s9QUu1N9BGnib5V09v/ -Sa7wseVp7ICGC0YckCkJMIjvzpaVMFA9/uMHFnloty+gMs/eMWGw0bb391QJb+k8 -WQHRZAlKTaLKVqeXC5G5CvK+u3q6j+4hQG46IclOJ76lRY//MwIDAQABo1MwUTAd -BgNVHQ4EFgQU5QWO+akQtDDflpGrTaXR4zEeah8wHwYDVR0jBBgwFoAU5QWO+akQ -tDDflpGrTaXR4zEeah8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAkNcppwcF+zjeZNmzGTccO1lSkPeC2LLlp/oEna0KUEGuKDFCemamxvESmua0 -+bXt9vw1qd+VztDIZ+zB+yAYYWyKYm41Nu1+IweLD8jmKPoQc5UXiWlSdF1Sjeub -9vcuX/G+FPOAGklt6X62y/jnlcumv1SOMB2BftSdD1Co8Yl9NRqFf3/OiEvd10bH -UXttTae4XEOp5p06ZFHW4JAnrHWBeuiLNJoswdKbA3rQO1Z6u5ioakluNHiCJX6T -fcJxbEVmorLNfBOnZTm61rPsC5aVtvFAxXDDb6B00KBW9FrV9m2MEFw71bMmC8X3 -rFaC9Gm5g2bfyX/65YBQyLwXRA== ------END CERTIFICATE----- diff --git a/otelconf/v1.0.0-rc.1/testdata/ca.key b/otelconf/v1.0.0-rc.1/testdata/ca.key deleted file mode 100644 index 2606228e841..00000000000 --- a/otelconf/v1.0.0-rc.1/testdata/ca.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDfLAP01CmN3Yf8 -9oeeh15fphafrs5qo4NOxSyY5wmmGF/Jr7+XJs21ZJweiJRGkHjRCFNpwOyNDsnR -OvKTOebrKeXTq5JBko41XGgtb4WYIENET4GqYUEV0wQy9EEZXGezshy3Nj/8Zplt -fzU2LWnIuvOtEb0Hku5TtJvKCAHImu63vZELttGADPy/az74kq8NUpGTeFOZLAKI -QLfSz1BS7U30EaeJvlXT2/9JrvCx5WnsgIYLRhyQKQkwiO/OlpUwUD3+4wcWeWi3 -L6Ayz94xYbDRtvf3VAlv6TxZAdFkCUpNospWp5cLkbkK8r67erqP7iFAbjohyU4n -vqVFj/8zAgMBAAECggEACkVl4TdjZN/brUJRmx5rz4AGChZ5R1QKT7WL3XWmbnpM -s54Jg/h7N6VPTozjFh0zLrgbmVeDfVYGdSS30/9Ap+b1hRwuXQap7i+p5YunTpeB -Fl/6YU/x4clBGcZbnRdqFKLkyox/9rkvcoSoe2YQjdoHgP2ecxsCfzWCTD1kUkoJ -JFynOn/Typ5umABoOxrZASMSZYrGM1jAzlA2k66ntq+cv26gne0cfuT0LHLJHwZE -7OaMfSo0xaovz+G81msTZZJ8uYOX64v7k+DwTxY+8WUA/H38caDHgHGpO7/ZbYax -VSeVAcUARV/wUgS4VZlqy+mnAl4XppHHpqx1vRIhAQKBgQDvzOwKBxb4uHF7I3kd -5+9kaDh7VzD7HdR1UyLFFSJCeMlGplJaUlpNMQiOtzQj2/AEfn3GqIMX00TLcdzA -ztY1pmaHWPxXHYuYq9P+v+a2jn1MrhRChCOB+7awp1aBSQfi5AFxmbCTFyRMUlZo -powvwBL7e5XC2yCbsFwPWr0VcwKBgQDuP4WImU9mH6tScFRprvWqwwJJQkV7O3km -HgBRR+9++sVWga/U2vA/hV/E3/k0h9m2aezAPW76tvttkgd3WvhxlxtK6f/9geMB -E2fMhnD9MSCU+a6DAr/yRd7ZZQoaQPszhSpDevNo2RSAkQcKYmo3v53KPCRcZkfT -yvyDRBD/QQKBgEi0WsRXjfFvCokJIkmc7ooEx0suDl20l5vSzvHuDGsW7/+JoeJc -oaBRw4Rxq09L+aODLmMy6DwrA+qi5QlYLL4ra16R7kADZzWssyPDzxF+diLvjJj2 -M0XPqX453hJosAlsk7t7m3udQpYZSLWF+W7oz1iMCcYAZgyOFftZyYZdAoGBAJP1 -JvyaGVEWwdLEp+eqHC8cREMywOuzF52wbAoOXpHBMuRyTbwm66THM56UabNR2scK -KVmJzW4uTR7S3YgmGryQVwbDI5NQIqX8Yy4FIA5dgBqEpPf/sSzIb4ka0pdTW623 -OXQG2zt19OGTL4gnbkeI3HlHuF0Zt+mz2fW7Q8MBAoGBAK8b40DO5VYks7AP+EhJ -OBOiNx4AC6KpKjF60undjfqO2Rt32h7FlS9YScdrxRaXOafebCC0OrgxpnA/HE5Y -pyHWJ4kPMlGFLR9vb0nuxS72v3xiPdV8dIUDcE+fdr873CtTpvSdyDAIizRCeZKO -Sv03W0utXEnISreIFVOv5DVJ ------END PRIVATE KEY----- diff --git a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.crt b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.crt deleted file mode 100644 index 9c19e635cd8..00000000000 --- a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.crt +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIUKlT4T6hHDXsut6dUk9GVedYGsnIwDQYJKoZIhvcNAQEL -BQAwXzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM -DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxDjAMBgNVBAMMBU15 -IENBMB4XDTI1MDQxNTEyMjQwMloXDTI2MDQxNTEyMjQwMlowYzELMAkGA1UEBhMC -VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x -EzARBgNVBAoMCk15IENvbXBhbnkxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBANOZK2z5lCPc//y3IiLZxSqFs5o6Z/Rk -2AY+jMe7xzEGihxcjtcrSdn5hmmklL536TvOfLqU9D8wINeAMP0XLbAi23AMiAJP -rcgUIvY7XcB3ujUdtOZWOBCbpvOfOdS50nQPh1w6bHl2dJmO9P0WXIr3WDMBmf2m -CeUwggqGhKKMvUjawiTcT3dseZyJyFghnv5sERC7XVQlMZI27qGLi/gcHKpQ63IS -wVOoJf/D+8TCkgkPhre0q9a5VOdtCt6sjFaHLyMj8lnM7ZJwLFLW5aDCqxzBN1Qy -5Utd3RiTXIRUcnWO4T0xYBSKmkdOqr9P5ytLKvQf090LpbAS1MvAqlsCAwEAAaNY -MFYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MB0GA1UdDgQWBBQBWxmwxzxSiV9heDSd -rXfwUQe9xjAfBgNVHSMEGDAWgBTlBY75qRC0MN+WkatNpdHjMR5qHzANBgkqhkiG -9w0BAQsFAAOCAQEA01nQZ/HHFq4g3hXBQUncr/21789F2SEjRUiO9kRXGL1VkGfK -cL7eqQYncpV5cKWMHM9XBs88TypL4CEP+XRSWXp8G/dQeKtwV5RMPxcSS508w+kF -0/hGWm3xkrwEQSs0cn/2uiXoRLIoWX2/2R45nd5YJZdPJ7SGzfxCpNvw81y740+G -6nR3n9Zocbc26Tj6aLhuXqDTA9nFVWqdoYqZ60dyse22oLqF7GNo8Onfrs7kbcBb -qx7QFg+mnAanqHVAIuDDZv/zeHewYQM7hlys/Qig0ZPxyh+MJY013HoFd0CPzndi -XEQxktfA9iRaDVkB+kRoxof4xoUAiWEohkn6HQ== ------END CERTIFICATE----- diff --git a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.csr b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.csr deleted file mode 100644 index b2c90a59625..00000000000 --- a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.csr +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIICzzCCAbcCAQAwYzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx -FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxEjAQ -BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ANOZK2z5lCPc//y3IiLZxSqFs5o6Z/Rk2AY+jMe7xzEGihxcjtcrSdn5hmmklL53 -6TvOfLqU9D8wINeAMP0XLbAi23AMiAJPrcgUIvY7XcB3ujUdtOZWOBCbpvOfOdS5 -0nQPh1w6bHl2dJmO9P0WXIr3WDMBmf2mCeUwggqGhKKMvUjawiTcT3dseZyJyFgh -nv5sERC7XVQlMZI27qGLi/gcHKpQ63ISwVOoJf/D+8TCkgkPhre0q9a5VOdtCt6s -jFaHLyMj8lnM7ZJwLFLW5aDCqxzBN1Qy5Utd3RiTXIRUcnWO4T0xYBSKmkdOqr9P -5ytLKvQf090LpbAS1MvAqlsCAwEAAaAnMCUGCSqGSIb3DQEJDjEYMBYwFAYDVR0R -BA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQCHElfAx2wYlI/cLYTv -QTVVbzkF4EhXNrpg8XNZkEC40IdQ+FbWbmJMjtd/PnyZ4G18PII2L+Pw8a835qsF -0oelcEq1xJnLDik330DRh2GyAOUL0zahLHNIoz1j3rlQZNC7WWWrPKJW4bpJhw/7 -E++Q4xLoqwuhKitRu3DNWY28/JCpzHUhlngLl/FKyo8KQL4ttC357NLF3lnLabkj -V4UUWDyazvZeq/DahnWEQ3M/KD1FpzP/AgqDEur3f1bszdrAGH0aSMfk5zymklbu -y5NrkQzB9EjsF78aATQMxI+moWWJgo5rNFAo8/J/khNPjcFlxcNMICe+hGonH9KK -YWse ------END CERTIFICATE REQUEST----- diff --git a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.key b/otelconf/v1.0.0-rc.1/testdata/client-certs/client.key deleted file mode 100644 index 0ff9d12afe7..00000000000 --- a/otelconf/v1.0.0-rc.1/testdata/client-certs/client.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDTmSts+ZQj3P/8 -tyIi2cUqhbOaOmf0ZNgGPozHu8cxBoocXI7XK0nZ+YZppJS+d+k7zny6lPQ/MCDX -gDD9Fy2wIttwDIgCT63IFCL2O13Ad7o1HbTmVjgQm6bznznUudJ0D4dcOmx5dnSZ -jvT9FlyK91gzAZn9pgnlMIIKhoSijL1I2sIk3E93bHmcichYIZ7+bBEQu11UJTGS -Nu6hi4v4HByqUOtyEsFTqCX/w/vEwpIJD4a3tKvWuVTnbQrerIxWhy8jI/JZzO2S -cCxS1uWgwqscwTdUMuVLXd0Yk1yEVHJ1juE9MWAUippHTqq/T+crSyr0H9PdC6Ww -EtTLwKpbAgMBAAECggEAKIlAW3kYmyI8XCKNRJXpgrLobFRiE9y50cBr4dukVk0F -aleE+c2OMVbvHA/ueuqn4NA27tuYSv6iXAZv3BxzoTmcRkPwTlkLVrgc1oUa+cM2 -BfTx8ep0hSH8gtFvF8Sdf6R17wI2Q7KgtcZAQrfk9K5b1DGrWX9Uh/aaAwAwKp9o -S83DpTmef/WMvSuJP5GauSltjRctyvWqSqjXW2bGmeBB/hNF8INmZWbVaKia+Nes -niiqmy1n8dAnGH8YsISZRuuthFO0I+TSlb9s9aLSArUz5eMvGzLICfQ+GpJAL0wv -n50VwQHHkgf+FsWdfrskifOUOzXm6qMC2V0f3fDEsQKBgQD4LYjPAMWlmX5K8dBO -qjTShlDv0iteDf8j8tLV2vNTq7haBMnPoFqpOlfj0QY4mJ7ZRRilAWFo0EWtZ9TR -Qttr+/Ao7ogbUwbw41IxJQUrfGy9R8LRkjOzGVcmUmG2fJJH7qeiVpqausQmHqrZ -Z++4yQzHRNYrMFNmiwNuQvQ1QwKBgQDaRHyjSven0OueiKBYkD1gCdUN52EPpQPq -LXz4+3v6tNobtF3Ra1+U7qcArdAurmZeQaTwHGYUXiX9VAl9QEdvWwoZG3FREgzK -8MYLOZGLs9aPGM9l5IpQa1Eyz+R573IYV8mMyiyl6ahv0gcslK0g7JwZcq9iJ3NG -3XM0zRfZCQKBgHGWDZaIiO1ZCids82T9m717AhIxQ+4BQ/QFECAW3OU/o9l3dZJU -lwn7DPzUzx8aIyHX8QacUiPxpuJNsmawTdLndSyWt66h2nxn3ldl1S7o/K/I506Z -tpXTFEMS02v9KcpIXWr8bjhBIMM9p/5nBp2xTurpA4iyzokRONm/RRwXAoGBAIlr -wUVWN+LSqOZhgwL/nYTP6/IbEYM2E+bmyN5CB+bq4r+6qa7meYFdWIwW4xHg/9as -YdpDJwn/1M9Qj8DqLY+wtATmwEuYn7FOMoJytm5MxfPGXR377BGB39esCF+1IBKv -gtg/mijDmib9B0NMQEyQbB+hk0arK+scFiLSVgdxAoGBAJgPn1ioygEwVm5QqQ1U -7VZXLGxsAaghDlqJNmZPFtoIFuzfdVn2OOioYJBdNhs7xH0vjfDoYXqLh3p3bSJZ -Jb3FtALaK/fGPeJRIF6P9x18sOE5k5jnedbNRlbZir1oJcaVgTd6jFkcVnhBX98t -nLa8Nu24UI0ROy4TKpG5eOZ0 ------END PRIVATE KEY----- diff --git a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.crt b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.crt deleted file mode 100644 index 8e875ee86a1..00000000000 --- a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.crt +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIUKlT4T6hHDXsut6dUk9GVedYGsnEwDQYJKoZIhvcNAQEL -BQAwXzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM -DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxDjAMBgNVBAMMBU15 -IENBMB4XDTI1MDQxNTEyMjM1NVoXDTI2MDQxNTEyMjM1NVowYzELMAkGA1UEBhMC -VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x -EzARBgNVBAoMCk15IENvbXBhbnkxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMZnNX0adWFrF/ZENvDOAj54BWg+UDIj -6xG10GE7IRJ2xwEJ6DI0VYByKXWciOqpcSzy8S09SlhoieSdothhnAHxNoNz3ElE -vUz1wuRhTlxm5Sts31yOg2F4UWTaWM/EdaK10Om5LLJOqeKVVPMVRER9LazMPIry -jgmQEEpVHNjiRgwSdNQSorNlAhHQu8ypzSNSj3oMLZ869RUUUqqoxBkCpp9KpsfU -ttgf4ociwUGn2GxCYKijosbnN0pF7utQOirseROD14LZ1JrHJQ4Ywwemp/8tFrUR -KD7xqwLtN5YfZsjp2DMVAvTzmYn4/+T1b0VDvYGHiRacC9uytYIFJf8CAwEAAaNY -MFYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MB0GA1UdDgQWBBQm7ZfyRLZ9UXzRn7qu -MAtp+HJ/wDAfBgNVHSMEGDAWgBTlBY75qRC0MN+WkatNpdHjMR5qHzANBgkqhkiG -9w0BAQsFAAOCAQEAdEOyjOwve3+nDVUdEzBNILCFOplsMW0fap8ghj3QIN+U2Hjb -zZb/LEMUWSbLxMAOheOo/AF2MFBrG+OhgVtqDIVefpzViCIxFKqgsnHDoDB5jO3X -C6Csl1QmuE76Y/4nprS1H7UNbgK9wOlEkScPxodIZnC+MghGFxczshb1v5YmkbYL -aAXt4Aa2c5zgiF39ZNfDnuhtenIWWT9YaMrCI3xYcXsaWHzZigKwTDCUNDGaAbd5 -cMSQhOYoz5HKzyFsiVYWBY4vk7FPrBu0ZxOLyNBxsS3w4q/YUY+66LyMwbsnFLg6 -s/6hFfJdGic/WMPP+Z87eb33vb2Dqa/845XwBg== ------END CERTIFICATE----- diff --git a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.csr b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.csr deleted file mode 100644 index 4bfcb7fd3f3..00000000000 --- a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.csr +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIICzzCCAbcCAQAwYzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx -FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxEjAQ -BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AMZnNX0adWFrF/ZENvDOAj54BWg+UDIj6xG10GE7IRJ2xwEJ6DI0VYByKXWciOqp -cSzy8S09SlhoieSdothhnAHxNoNz3ElEvUz1wuRhTlxm5Sts31yOg2F4UWTaWM/E -daK10Om5LLJOqeKVVPMVRER9LazMPIryjgmQEEpVHNjiRgwSdNQSorNlAhHQu8yp -zSNSj3oMLZ869RUUUqqoxBkCpp9KpsfUttgf4ociwUGn2GxCYKijosbnN0pF7utQ -OirseROD14LZ1JrHJQ4Ywwemp/8tFrURKD7xqwLtN5YfZsjp2DMVAvTzmYn4/+T1 -b0VDvYGHiRacC9uytYIFJf8CAwEAAaAnMCUGCSqGSIb3DQEJDjEYMBYwFAYDVR0R -BA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQBbMTNbsuUXm9FsRKrf -Q3nDMzUr9VUPlQXT0YymwhpnWkpk9iRjc/oljwaPioRdJJ9ZJdcvjAWnWcM9DUFs -n5rGeXMIXN3e5kuGNa5cz16QENCYkbaW7BYRYuRBDSxHdh6vOxv7RpXSLA9xmZ3m -Oy1Oye5sQb1hfXrIfXrSYrZxoSICNqeU8J3ql3ACyayxmQhIgd0PMM1C8wcBOJeA -OeTFMRfiBVBFp2WP192KYzLCth2mi7rUf3jwaHMzPMRNsh2n+yC2w0IU9ZxhXorL -luyMLTZ25qKrvYr9ibJV+NJRzoxeqXYz7JVoYUSJ1N/fGLy/OpR7uHoyJipXXU6E -HVch ------END CERTIFICATE REQUEST----- diff --git a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.key b/otelconf/v1.0.0-rc.1/testdata/server-certs/server.key deleted file mode 100644 index 4a86c6dd69c..00000000000 --- a/otelconf/v1.0.0-rc.1/testdata/server-certs/server.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDGZzV9GnVhaxf2 -RDbwzgI+eAVoPlAyI+sRtdBhOyESdscBCegyNFWAcil1nIjqqXEs8vEtPUpYaInk -naLYYZwB8TaDc9xJRL1M9cLkYU5cZuUrbN9cjoNheFFk2ljPxHWitdDpuSyyTqni -lVTzFUREfS2szDyK8o4JkBBKVRzY4kYMEnTUEqKzZQIR0LvMqc0jUo96DC2fOvUV -FFKqqMQZAqafSqbH1LbYH+KHIsFBp9hsQmCoo6LG5zdKRe7rUDoq7HkTg9eC2dSa -xyUOGMMHpqf/LRa1ESg+8asC7TeWH2bI6dgzFQL085mJ+P/k9W9FQ72Bh4kWnAvb -srWCBSX/AgMBAAECggEANTYvIVt8SeF4LsOC3LjT3z8/bALybVA21qwltD4wk4wp -uXyXuwdQOz/jILkX+5/wS7boulJq4yU+foNMzq33MoooLb9gQIJgJwju+WOjqaKr -KidsDJ3oXLbxVZQ+J5MwXbBX1Kemdjgk1jFo9D0q7xeHrYWlYzrEn4n05IrJTt1/ -1iVzyOA6TvxBCFlAOANhwyZdvOLOMg8KqpQZEbmwemUGCOPVJLknoG04nDYn/5SR -nSlrmSJeqNVu5PIeAy8DR0hAAvggLHf9os56qoP/bXSyFbryabUIG6DsUT1Py8YP -kLKqS/IQhTWjXgjzaaEQOLFZkIiO3/hkoPg/djqcgQKBgQD0PA+gRItT9Sw6vwqk -TtazoN3lSP9QXJODlc3XTO0AiwClNwqseCwmrpIFT4ylz4Mn737EPfyPOSOclkoJ -WzvaiP721ErrCtv57oLOerhEGixEMmZQYzfDPJwT5Ui8k/ThWd1XwWCspVy5+IlJ -+uD21rue136LlQQSK4kqmCZDwQKBgQDP9fKE41yO4cezHRXAUbbvaRUfl565+PvC -3CRVU4b6rhnEu5q6hnIZ9ol3EfDIW/uDRL+jbbnpSN9pcMEOivtNJVmaJONEk0EC -b9oN4mijYD6UhsdxTBq0VQ9nohjsTesHmaHNaJisIquPoN6+ZaNdY5mbpM3/heLi -52v3CIrZvwKBgQCp6ecNHuK3pEgDDsm+icLA8VeunlxRcjaGQwATm0b/K7VlO6fH -WUuOFcEsxK0a5gVfETVmHaHJmnz2AXC8laZMYSbQXd1JLCLh/FcwgxwS9Qp6331i -y8QNpesHxGoYF+8zoCtnU/eH5PtfvlL1Dv7Xe4jH9y/ot+E/Kt6grX1hgQKBgQCo -1q3HZjBHcNeJfBukwLMdPNuBgr/DjXoZglGdVOtJqwAQ0Z+VwIHywk5o9Y/fm45f -zPkp3nQKCrgYCwsym3Pb9m8AzuIVUth8+gK3MxJxUjp8q9BRE9C6iDSxltFVSQ2A -ZiMPedQ6LQvM2Hb/bdVshOi5jNwSkMjcH7dwIOdaUQKBgQDapokikGG3Suzq6qSy -8XkYLHlqBKo3aPdkqmSleziIJ1yPv64kpZuRd3WREHgJvWwSdy4V2eKU3TW/8cCQ -40kTA49cwgl0cTSOc88NnsBJ34n1ebA8Y50CKPAQP/Jw44+i62KUwJLuUPRCgndy -S6sEyFQNSn6RduzwFIUUx2XjpQ== ------END PRIVATE KEY----- From 9b5fc2c6c155dfd4920458e6eb0d9b0385759407 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Wed, 22 Oct 2025 08:42:36 -0700 Subject: [PATCH 27/39] remove dupe files, update test data to add detectors TODO Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/testdata/v1.0.0-rc.1.json | 615 ------------------- otelconf/testdata/v1.0.0-rc.1.yaml | 952 ----------------------------- otelconf/testdata/v1.0.0.json | 16 +- otelconf/testdata/v1.0.0.yaml | 19 +- 4 files changed, 11 insertions(+), 1591 deletions(-) delete mode 100644 otelconf/testdata/v1.0.0-rc.1.json delete mode 100644 otelconf/testdata/v1.0.0-rc.1.yaml diff --git a/otelconf/testdata/v1.0.0-rc.1.json b/otelconf/testdata/v1.0.0-rc.1.json deleted file mode 100644 index 635de1b9cc6..00000000000 --- a/otelconf/testdata/v1.0.0-rc.1.json +++ /dev/null @@ -1,615 +0,0 @@ -{ - "file_format": "1.0-rc.1", - "disabled": false, - "log_level": "info", - "attribute_limits": { - "attribute_value_length_limit": 4096, - "attribute_count_limit": 128 - }, - "logger_provider": { - "processors": [ - { - "batch": { - "schedule_delay": 5000, - "export_timeout": 30000, - "max_queue_size": 2048, - "max_export_batch_size": 512, - "exporter": { - "otlp_http": { - "endpoint": "http://localhost:4318/v1/logs", - "certificate_file": "/app/cert.pem", - "client_key_file": "/app/cert.pem", - "client_certificate_file": "/app/cert.pem", - "headers": [ - { - "name": "api-key", - "value": "1234" - } - ], - "headers_list": "api-key=1234", - "compression": "gzip", - "timeout": 10000, - "encoding": "protobuf" - } - } - } - }, - { - "batch": { - "exporter": { - "otlp_grpc": { - "endpoint": "http://localhost:4317", - "certificate_file": "/app/cert.pem", - "client_key_file": "/app/cert.pem", - "client_certificate_file": "/app/cert.pem", - "headers": [ - { - "name": "api-key", - "value": "1234" - } - ], - "headers_list": "api-key=1234", - "compression": "gzip", - "timeout": 10000, - "insecure": false - } - } - } - }, - { - "batch": { - "exporter": { - "otlp_file/development": { - "output_stream": "file:///var/log/logs.jsonl" - } - } - } - }, - { - "batch": { - "exporter": { - "otlp_file/development": { - "output_stream": "stdout" - } - } - } - }, - { - "simple": { - "exporter": { - "console": null - } - } - } - ], - "limits": { - "attribute_value_length_limit": 4096, - "attribute_count_limit": 128 - }, - "logger_configurator/development": { - "default_config": { - "disabled": true - }, - "loggers": [ - { - "name": "io.opentelemetry.contrib.*", - "config": { - "disabled": false - } - } - ] - } - }, - "meter_provider": { - "readers": [ - { - "pull": { - "exporter": { - "prometheus/development": { - "host": "localhost", - "port": 9464, - "without_scope_info": false, - "with_resource_constant_labels": { - "included": [ - "service*" - ], - "excluded": [ - "service.attr1" - ] - }, - "translation_strategy": "UnderscoreEscapingWithSuffixes" - } - }, - "producers": [ - { - "opencensus": null - } - ], - "cardinality_limits": { - "default": 2000, - "counter": 2000, - "gauge": 2000, - "histogram": 2000, - "observable_counter": 2000, - "observable_gauge": 2000, - "observable_up_down_counter": 2000, - "up_down_counter": 2000 - } - } - }, - { - "periodic": { - "interval": 60000, - "timeout": 30000, - "exporter": { - "otlp_http": { - "endpoint": "http://localhost:4318/v1/metrics", - "certificate_file": "/app/cert.pem", - "client_key_file": "/app/cert.pem", - "client_certificate_file": "/app/cert.pem", - "headers": [ - { - "name": "api-key", - "value": "1234" - } - ], - "headers_list": "api-key=1234", - "compression": "gzip", - "timeout": 10000, - "encoding": "protobuf", - "temporality_preference": "delta", - "default_histogram_aggregation": "base2_exponential_bucket_histogram" - } - }, - "producers": [ - { - "prometheus": null - } - ], - "cardinality_limits": { - "default": 2000, - "counter": 2000, - "gauge": 2000, - "histogram": 2000, - "observable_counter": 2000, - "observable_gauge": 2000, - "observable_up_down_counter": 2000, - "up_down_counter": 2000 - } - } - }, - { - "periodic": { - "exporter": { - "otlp_grpc": { - "endpoint": "http://localhost:4317", - "certificate_file": "/app/cert.pem", - "client_key_file": "/app/cert.pem", - "client_certificate_file": "/app/cert.pem", - "headers": [ - { - "name": "api-key", - "value": "1234" - } - ], - "headers_list": "api-key=1234", - "compression": "gzip", - "timeout": 10000, - "insecure": false, - "temporality_preference": "delta", - "default_histogram_aggregation": "base2_exponential_bucket_histogram" - } - } - } - }, - { - "periodic": { - "exporter": { - "otlp_file/development": { - "output_stream": "file:///var/log/metrics.jsonl", - "temporality_preference": "delta", - "default_histogram_aggregation": "base2_exponential_bucket_histogram" - } - } - } - }, - { - "periodic": { - "exporter": { - "otlp_file/development": { - "output_stream": "stdout", - "temporality_preference": "delta", - "default_histogram_aggregation": "base2_exponential_bucket_histogram" - } - } - } - }, - { - "periodic": { - "exporter": { - "console": null - } - } - } - ], - "views": [ - { - "selector": { - "instrument_name": "my-instrument", - "instrument_type": "histogram", - "unit": "ms", - "meter_name": "my-meter", - "meter_version": "1.0.0", - "meter_schema_url": "https://opentelemetry.io/schemas/1.16.0" - }, - "stream": { - "name": "new_instrument_name", - "description": "new_description", - "aggregation": { - "explicit_bucket_histogram": { - "boundaries": [ - 0, - 5, - 10, - 25, - 50, - 75, - 100, - 250, - 500, - 750, - 1000, - 2500, - 5000, - 7500, - 10000 - ], - "record_min_max": true - } - }, - "aggregation_cardinality_limit": 2000, - "attribute_keys": { - "included": [ - "key1", - "key2" - ], - "excluded": [ - "key3" - ] - } - } - } - ], - "exemplar_filter": "trace_based", - "meter_configurator/development": { - "default_config": { - "disabled": true - }, - "meters": [ - { - "name": "io.opentelemetry.contrib.*", - "config": { - "disabled": false - } - } - ] - } - }, - "propagator": { - "composite": [ - { - "tracecontext": null - }, - { - "baggage": null - }, - { - "b3": null - }, - { - "b3multi": null - }, - { - "jaeger": null - }, - { - "ottrace": null - } - ], - "composite_list": "tracecontext,baggage,b3,b3multi,jaeger,ottrace,xray" - }, - "tracer_provider": { - "processors": [ - { - "batch": { - "schedule_delay": 5000, - "export_timeout": 30000, - "max_queue_size": 2048, - "max_export_batch_size": 512, - "exporter": { - "otlp_http": { - "endpoint": "http://localhost:4318/v1/traces", - "certificate_file": "/app/cert.pem", - "client_key_file": "/app/cert.pem", - "client_certificate_file": "/app/cert.pem", - "headers": [ - { - "name": "api-key", - "value": "1234" - } - ], - "headers_list": "api-key=1234", - "compression": "gzip", - "timeout": 10000, - "encoding": "protobuf" - } - } - } - }, - { - "batch": { - "exporter": { - "otlp_grpc": { - "endpoint": "http://localhost:4317", - "certificate_file": "/app/cert.pem", - "client_key_file": "/app/cert.pem", - "client_certificate_file": "/app/cert.pem", - "headers": [ - { - "name": "api-key", - "value": "1234" - } - ], - "headers_list": "api-key=1234", - "compression": "gzip", - "timeout": 10000, - "insecure": false - } - } - } - }, - { - "batch": { - "exporter": { - "otlp_file/development": { - "output_stream": "file:///var/log/traces.jsonl" - } - } - } - }, - { - "batch": { - "exporter": { - "otlp_file/development": { - "output_stream": "stdout" - } - } - } - }, - { - "batch": { - "exporter": { - "zipkin": { - "endpoint": "http://localhost:9411/api/v2/spans", - "timeout": 10000 - } - } - } - }, - { - "simple": { - "exporter": { - "console": null - } - } - } - ], - "limits": { - "attribute_value_length_limit": 4096, - "attribute_count_limit": 128, - "event_count_limit": 128, - "link_count_limit": 128, - "event_attribute_count_limit": 128, - "link_attribute_count_limit": 128 - }, - "sampler": { - "parent_based": { - "root": { - "trace_id_ratio_based": { - "ratio": 0.0001 - } - }, - "remote_parent_sampled": { - "always_on": null - }, - "remote_parent_not_sampled": { - "always_off": null - }, - "local_parent_sampled": { - "always_on": null - }, - "local_parent_not_sampled": { - "always_off": null - } - } - }, - "tracer_configurator/development": { - "default_config": { - "disabled": true - }, - "tracers": [ - { - "name": "io.opentelemetry.contrib.*", - "config": { - "disabled": false - } - } - ] - } - }, - "resource": { - "attributes": [ - { - "name": "service.name", - "value": "unknown_service" - }, - { - "name": "string_key", - "value": "value", - "type": "string" - }, - { - "name": "bool_key", - "value": true, - "type": "bool" - }, - { - "name": "int_key", - "value": 1, - "type": "int" - }, - { - "name": "double_key", - "value": 1.1, - "type": "double" - }, - { - "name": "string_array_key", - "value": [ - "value1", - "value2" - ], - "type": "string_array" - }, - { - "name": "bool_array_key", - "value": [ - true, - false - ], - "type": "bool_array" - }, - { - "name": "int_array_key", - "value": [ - 1, - 2 - ], - "type": "int_array" - }, - { - "name": "double_array_key", - "value": [ - 1.1, - 2.2 - ], - "type": "double_array" - } - ], - "attributes_list": "service.namespace=my-namespace,service.version=1.0.0", - "detection/development": { - "attributes": { - "included": [ - "process.*" - ], - "excluded": [ - "process.command_args" - ] - } - }, - "schema_url": "https://opentelemetry.io/schemas/1.16.0" - }, - "instrumentation/development": { - "general": { - "peer": { - "service_mapping": [ - { - "peer": "1.2.3.4", - "service": "FooService" - }, - { - "peer": "2.3.4.5", - "service": "BarService" - } - ] - }, - "http": { - "client": { - "request_captured_headers": [ - "Content-Type", - "Accept" - ], - "response_captured_headers": [ - "Content-Type", - "Content-Encoding" - ] - }, - "server": { - "request_captured_headers": [ - "Content-Type", - "Accept" - ], - "response_captured_headers": [ - "Content-Type", - "Content-Encoding" - ] - } - } - }, - "cpp": { - "example": { - "property": "value" - } - }, - "dotnet": { - "example": { - "property": "value" - } - }, - "erlang": { - "example": { - "property": "value" - } - }, - "go": { - "example": { - "property": "value" - } - }, - "java": { - "example": { - "property": "value" - } - }, - "js": { - "example": { - "property": "value" - } - }, - "php": { - "example": { - "property": "value" - } - }, - "python": { - "example": { - "property": "value" - } - }, - "ruby": { - "example": { - "property": "value" - } - }, - "rust": { - "example": { - "property": "value" - } - }, - "swift": { - "example": { - "property": "value" - } - } - } -} \ No newline at end of file diff --git a/otelconf/testdata/v1.0.0-rc.1.yaml b/otelconf/testdata/v1.0.0-rc.1.yaml deleted file mode 100644 index d870ef331a9..00000000000 --- a/otelconf/testdata/v1.0.0-rc.1.yaml +++ /dev/null @@ -1,952 +0,0 @@ -# kitchen-sink.yaml demonstrates all configurable surface area, including explanatory comments. -# -# It DOES NOT represent expected real world configuration, as it makes strange configuration -# choices in an effort to exercise the full surface area. -# -# Configuration values are set to their defaults when default values are defined. - -# The file format version. -# The yaml format is documented at -# https://github.com/open-telemetry/opentelemetry-configuration/tree/main/schema -file_format: "1.0-rc.1" -# Configure if the SDK is disabled or not. -# If omitted or null, false is used. -disabled: false -# Configure the log level of the internal logger used by the SDK. -# If omitted, info is used. -log_level: info -# Configure general attribute limits. See also tracer_provider.limits, logger_provider.limits. -attribute_limits: - # Configure max attribute value size. - # Value must be non-negative. - # If omitted or null, there is no limit. - attribute_value_length_limit: 4096 - # Configure max attribute count. - # Value must be non-negative. - # If omitted or null, 128 is used. - attribute_count_limit: 128 -# Configure logger provider. -# If omitted, a noop logger provider is used. -logger_provider: - # Configure log record processors. - processors: - - # Configure a batch log record processor. - batch: - # Configure delay interval (in milliseconds) between two consecutive exports. - # Value must be non-negative. - # If omitted or null, 1000 is used. - schedule_delay: 5000 - # Configure maximum allowed time (in milliseconds) to export data. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 30000 is used. - export_timeout: 30000 - # Configure maximum queue size. Value must be positive. - # If omitted or null, 2048 is used. - max_queue_size: 2048 - # Configure maximum batch size. Value must be positive. - # If omitted or null, 512 is used. - max_export_batch_size: 512 - # Configure exporter. - exporter: - # Configure exporter to be OTLP with HTTP transport. - otlp_http: - endpoint: http://localhost:4318/v1/logs - # Configure certificate used to verify a server's TLS credentials. - # Absolute path to certificate file in PEM format. - # If omitted or null, system default certificate verification is used for secure connections. - certificate_file: /app/cert.pem - # Configure mTLS private client key. - # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - # If omitted or null, mTLS is not used. - client_key_file: /app/cert.pem - # Configure mTLS client certificate. - # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - # If omitted or null, mTLS is not used. - client_certificate_file: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - # If an entry's .value is null, the entry is ignored. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - # If omitted or null, no headers are added. - headers_list: "api-key=1234" - # Configure compression. - # Values include: gzip, none. Implementations may support other compression algorithms. - # If omitted or null, none is used. - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 10000 is used. - timeout: 10000 - # Configure the encoding used for messages. - # Values include: protobuf, json. Implementations may not support json. - # If omitted or null, protobuf is used. - encoding: protobuf - - # Configure a batch log record processor. - batch: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with gRPC transport. - otlp_grpc: - # Configure endpoint. - # If omitted or null, http://localhost:4317 is used. - endpoint: http://localhost:4317 - # Configure certificate used to verify a server's TLS credentials. - # Absolute path to certificate file in PEM format. - # If omitted or null, system default certificate verification is used for secure connections. - certificate_file: /app/cert.pem - # Configure mTLS private client key. - # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - # If omitted or null, mTLS is not used. - client_key_file: /app/cert.pem - # Configure mTLS client certificate. - # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - # If omitted or null, mTLS is not used. - client_certificate_file: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - # If an entry's .value is null, the entry is ignored. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - # If omitted or null, no headers are added. - headers_list: "api-key=1234" - # Configure compression. - # Values include: gzip, none. Implementations may support other compression algorithms. - # If omitted or null, none is used. - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 10000 is used. - timeout: 10000 - # Configure client transport security for the exporter's connection. - # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. - # If omitted or null, false is used. - insecure: false - - # Configure a batch log record processor. - batch: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with file transport. - # This type is in development and subject to breaking changes in minor versions. - otlp_file/development: - # Configure output stream. - # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. - # If omitted or null, stdout is used. - output_stream: file:///var/log/logs.jsonl - - # Configure a batch log record processor. - batch: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with file transport. - # This type is in development and subject to breaking changes in minor versions. - otlp_file/development: - # Configure output stream. - # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. - # If omitted or null, stdout is used. - output_stream: stdout - - # Configure a simple log record processor. - simple: - # Configure exporter. - exporter: - # Configure exporter to be console. - console: - # Configure log record limits. See also attribute_limits. - limits: - # Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. - # Value must be non-negative. - # If omitted or null, there is no limit. - attribute_value_length_limit: 4096 - # Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. - # Value must be non-negative. - # If omitted or null, 128 is used. - attribute_count_limit: 128 - # Configure loggers. - # This type is in development and subject to breaking changes in minor versions. - logger_configurator/development: - # Configure the default logger config used there is no matching entry in .logger_configurator/development.loggers. - default_config: - # Configure if the logger is enabled or not. - disabled: true - # Configure loggers. - loggers: - - # Configure logger names to match, evaluated as follows: - # - # * If the logger name exactly matches. - # * If the logger name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. - name: io.opentelemetry.contrib.* - # The logger config. - config: - # Configure if the logger is enabled or not. - disabled: false -# Configure meter provider. -# If omitted, a noop meter provider is used. -meter_provider: - # Configure metric readers. - readers: - - # Configure a pull based metric reader. - pull: - # Configure exporter. - exporter: - # Configure exporter to be prometheus. - # This type is in development and subject to breaking changes in minor versions. - prometheus/development: - # Configure host. - # If omitted or null, localhost is used. - host: localhost - # Configure port. - # If omitted or null, 9464 is used. - port: 9464 - # Configure Prometheus Exporter to produce metrics without a scope info metric. - # If omitted or null, false is used. - without_scope_info: false - # Configure Prometheus Exporter to add resource attributes as metrics attributes. - with_resource_constant_labels: - # Configure resource attributes to be included. - # Attribute keys from resources are evaluated to match as follows: - # * If the value of the attribute key exactly matches. - # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. - # If omitted, no resource attributes are included. - included: - - "service*" - # Configure resource attributes to be excluded. Applies after .with_resource_constant_labels.included (i.e. excluded has higher priority than included). - # Attribute keys from resources are evaluated to match as follows: - # * If the value of the attribute key exactly matches. - # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. - # If omitted, .included resource attributes are included. - excluded: - - "service.attr1" - # Configure how Prometheus metrics are exposed. Values include: - # - # * UnderscoreEscapingWithSuffixes, the default. This fully escapes metric names for classic Prometheus metric name compatibility, and includes appending type and unit suffixes. - # * UnderscoreEscapingWithoutSuffixes, metric names will continue to escape special characters to _, but suffixes won't be attached. - # * NoUTF8EscapingWithSuffixes will disable changing special characters to _. Special suffixes like units and _total for counters will be attached. - # * NoTranslation. This strategy bypasses all metric and label name translation, passing them through unaltered. - # - # If omitted or null, UnderscoreEscapingWithSuffixes is used. - translation_strategy: UnderscoreEscapingWithSuffixes - # Configure metric producers. - producers: - - # Configure metric producer to be opencensus. - opencensus: - # Configure cardinality limits. - cardinality_limits: - # Configure default cardinality limit for all instrument types. - # Instrument-specific cardinality limits take priority. - # If omitted or null, 2000 is used. - default: 2000 - # Configure default cardinality limit for counter instruments. - # If omitted or null, the value from .default is used. - counter: 2000 - # Configure default cardinality limit for gauge instruments. - # If omitted or null, the value from .default is used. - gauge: 2000 - # Configure default cardinality limit for histogram instruments. - # If omitted or null, the value from .default is used. - histogram: 2000 - # Configure default cardinality limit for observable_counter instruments. - # If omitted or null, the value from .default is used. - observable_counter: 2000 - # Configure default cardinality limit for observable_gauge instruments. - # If omitted or null, the value from .default is used. - observable_gauge: 2000 - # Configure default cardinality limit for observable_up_down_counter instruments. - # If omitted or null, the value from .default is used. - observable_up_down_counter: 2000 - # Configure default cardinality limit for up_down_counter instruments. - # If omitted or null, the value from .default is used. - up_down_counter: 2000 - - # Configure a periodic metric reader. - periodic: - # Configure delay interval (in milliseconds) between start of two consecutive exports. - # Value must be non-negative. - # If omitted or null, 60000 is used. - interval: 60000 - # Configure maximum allowed time (in milliseconds) to export data. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 30000 is used. - timeout: 30000 - # Configure exporter. - exporter: - # Configure exporter to be OTLP with HTTP transport. - otlp_http: - # Configure endpoint, including the metric specific path. - # If omitted or null, http://localhost:4318/v1/metrics is used. - endpoint: http://localhost:4318/v1/metrics - # Configure certificate used to verify a server's TLS credentials. - # Absolute path to certificate file in PEM format. - # If omitted or null, system default certificate verification is used for secure connections. - certificate_file: /app/cert.pem - # Configure mTLS private client key. - # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - # If omitted or null, mTLS is not used. - client_key_file: /app/cert.pem - # Configure mTLS client certificate. - # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - # If omitted or null, mTLS is not used. - client_certificate_file: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - # If an entry's .value is null, the entry is ignored. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - # If omitted or null, no headers are added. - headers_list: "api-key=1234" - # Configure compression. - # Values include: gzip, none. Implementations may support other compression algorithms. - # If omitted or null, none is used. - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 10000 is used. - timeout: 10000 - # Configure the encoding used for messages. - # Values include: protobuf, json. Implementations may not support json. - # If omitted or null, protobuf is used. - encoding: protobuf - # Configure temporality preference. - # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. - # If omitted or null, cumulative is used. - temporality_preference: delta - # Configure default histogram aggregation. - # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. - # If omitted or null, explicit_bucket_histogram is used. - default_histogram_aggregation: base2_exponential_bucket_histogram - # Configure metric producers. - producers: - - # Configure metric producer to be prometheus. - prometheus: - # Configure cardinality limits. - cardinality_limits: - # Configure default cardinality limit for all instrument types. - # Instrument-specific cardinality limits take priority. - # If omitted or null, 2000 is used. - default: 2000 - # Configure default cardinality limit for counter instruments. - # If omitted or null, the value from .default is used. - counter: 2000 - # Configure default cardinality limit for gauge instruments. - # If omitted or null, the value from .default is used. - gauge: 2000 - # Configure default cardinality limit for histogram instruments. - # If omitted or null, the value from .default is used. - histogram: 2000 - # Configure default cardinality limit for observable_counter instruments. - # If omitted or null, the value from .default is used. - observable_counter: 2000 - # Configure default cardinality limit for observable_gauge instruments. - # If omitted or null, the value from .default is used. - observable_gauge: 2000 - # Configure default cardinality limit for observable_up_down_counter instruments. - # If omitted or null, the value from .default is used. - observable_up_down_counter: 2000 - # Configure default cardinality limit for up_down_counter instruments. - # If omitted or null, the value from .default is used. - up_down_counter: 2000 - - # Configure a periodic metric reader. - periodic: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with gRPC transport. - otlp_grpc: - # Configure endpoint. - # If omitted or null, http://localhost:4317 is used. - endpoint: http://localhost:4317 - # Configure certificate used to verify a server's TLS credentials. - # Absolute path to certificate file in PEM format. - # If omitted or null, system default certificate verification is used for secure connections. - certificate_file: /app/cert.pem - # Configure mTLS private client key. - # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - # If omitted or null, mTLS is not used. - client_key_file: /app/cert.pem - # Configure mTLS client certificate. - # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - # If omitted or null, mTLS is not used. - client_certificate_file: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - # If an entry's .value is null, the entry is ignored. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - # If omitted or null, no headers are added. - headers_list: "api-key=1234" - # Configure compression. - # Values include: gzip, none. Implementations may support other compression algorithms. - # If omitted or null, none is used. - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 10000 is used. - timeout: 10000 - # Configure client transport security for the exporter's connection. - # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. - # If omitted or null, false is used. - insecure: false - # Configure temporality preference. - # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. - # If omitted or null, cumulative is used. - temporality_preference: delta - # Configure default histogram aggregation. - # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. - # If omitted or null, explicit_bucket_histogram is used. - default_histogram_aggregation: base2_exponential_bucket_histogram - - # Configure a periodic metric reader. - periodic: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with file transport. - # This type is in development and subject to breaking changes in minor versions. - otlp_file/development: - # Configure output stream. - # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. - # If omitted or null, stdout is used. - output_stream: file:///var/log/metrics.jsonl - # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. - # If omitted or null, cumulative is used. - temporality_preference: delta - # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. - # If omitted or null, explicit_bucket_histogram is used. - default_histogram_aggregation: base2_exponential_bucket_histogram - - # Configure a periodic metric reader. - periodic: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with file transport. - # This type is in development and subject to breaking changes in minor versions. - otlp_file/development: - # Configure output stream. - # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. - # If omitted or null, stdout is used. - output_stream: stdout - # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. - # If omitted or null, cumulative is used. - temporality_preference: delta - # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. - # If omitted or null, explicit_bucket_histogram is used. - default_histogram_aggregation: base2_exponential_bucket_histogram - - # Configure a periodic metric reader. - periodic: - # Configure exporter. - exporter: - # Configure exporter to be console. - console: - # Configure views. - # Each view has a selector which determines the instrument(s) it applies to, and a configuration for the resulting stream(s). - views: - - # Configure view selector. - # Selection criteria is additive as described in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#instrument-selection-criteria. - selector: - # Configure instrument name selection criteria. - # If omitted or null, all instrument names match. - instrument_name: my-instrument - # Configure instrument type selection criteria. - # Values include: counter, gauge, histogram, observable_counter, observable_gauge, observable_up_down_counter, up_down_counter. - # If omitted or null, all instrument types match. - instrument_type: histogram - # Configure the instrument unit selection criteria. - # If omitted or null, all instrument units match. - unit: ms - # Configure meter name selection criteria. - # If omitted or null, all meter names match. - meter_name: my-meter - # Configure meter version selection criteria. - # If omitted or null, all meter versions match. - meter_version: 1.0.0 - # Configure meter schema url selection criteria. - # If omitted or null, all meter schema URLs match. - meter_schema_url: https://opentelemetry.io/schemas/1.16.0 - # Configure view stream. - stream: - # Configure metric name of the resulting stream(s). - # If omitted or null, the instrument's original name is used. - name: new_instrument_name - # Configure metric description of the resulting stream(s). - # If omitted or null, the instrument's origin description is used. - description: new_description - # Configure aggregation of the resulting stream(s). - # Values include: default, drop, explicit_bucket_histogram, base2_exponential_bucket_histogram, last_value, sum. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#aggregation. - # If omitted, default is used. - aggregation: - # Configure aggregation to be explicit_bucket_histogram. - explicit_bucket_histogram: - # Configure bucket boundaries. - # If omitted, [0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000] is used. - boundaries: - [ - 0.0, - 5.0, - 10.0, - 25.0, - 50.0, - 75.0, - 100.0, - 250.0, - 500.0, - 750.0, - 1000.0, - 2500.0, - 5000.0, - 7500.0, - 10000.0 - ] - # Configure record min and max. - # If omitted or null, true is used. - record_min_max: true - # Configure the aggregation cardinality limit. - # If omitted or null, the metric reader's default cardinality limit is used. - aggregation_cardinality_limit: 2000 - # Configure attribute keys retained in the resulting stream(s). - attribute_keys: - # Configure list of attribute keys to include in the resulting stream(s). All other attributes are dropped. - # If omitted, all attributes are included. - included: - - key1 - - key2 - # Configure list of attribute keys to exclude from the resulting stream(s). Applies after .attribute_keys.included (i.e. excluded has higher priority than included). - # If omitted, .attribute_keys.included are included. - excluded: - - key3 - # Configure the exemplar filter. - # Values include: trace_based, always_on, always_off. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration. - # If omitted or null, trace_based is used. - exemplar_filter: trace_based - # Configure meters. - # This type is in development and subject to breaking changes in minor versions. - meter_configurator/development: - # Configure the default meter config used there is no matching entry in .meter_configurator/development.meters. - default_config: - # Configure if the meter is enabled or not. - disabled: true - # Configure meters. - meters: - - # Configure meter names to match, evaluated as follows: - # - # * If the meter name exactly matches. - # * If the meter name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. - name: io.opentelemetry.contrib.* - # The meter config. - config: - # Configure if the meter is enabled or not. - disabled: false -# Configure text map context propagators. -# If omitted, a noop propagator is used. -propagator: - # Configure the propagators in the composite text map propagator. Entries from .composite_list are appended to the list here with duplicates filtered out. - # Built-in propagator keys include: tracecontext, baggage, b3, b3multi, jaeger, ottrace. Known third party keys include: xray. - # If the resolved list of propagators (from .composite and .composite_list) is empty, a noop propagator is used. - composite: - - # Include the w3c trace context propagator. - tracecontext: - - # Include the w3c baggage propagator. - baggage: - - # Include the zipkin b3 propagator. - b3: - - # Include the zipkin b3 multi propagator. - b3multi: - - # Include the jaeger propagator. - jaeger: - - # Include the opentracing propagator. - ottrace: - # Configure the propagators in the composite text map propagator. Entries are appended to .composite with duplicates filtered out. - # The value is a comma separated list of propagator identifiers matching the format of OTEL_PROPAGATORS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration for details. - # Built-in propagator identifiers include: tracecontext, baggage, b3, b3multi, jaeger, ottrace. Known third party identifiers include: xray. - # If the resolved list of propagators (from .composite and .composite_list) is empty, a noop propagator is used. - composite_list: "tracecontext,baggage,b3,b3multi,jaeger,ottrace,xray" -# Configure tracer provider. -# If omitted, a noop tracer provider is used. -tracer_provider: - # Configure span processors. - processors: - - # Configure a batch span processor. - batch: - # Configure delay interval (in milliseconds) between two consecutive exports. - # Value must be non-negative. - # If omitted or null, 5000 is used. - schedule_delay: 5000 - # Configure maximum allowed time (in milliseconds) to export data. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 30000 is used. - export_timeout: 30000 - # Configure maximum queue size. Value must be positive. - # If omitted or null, 2048 is used. - max_queue_size: 2048 - # Configure maximum batch size. Value must be positive. - # If omitted or null, 512 is used. - max_export_batch_size: 512 - # Configure exporter. - exporter: - # Configure exporter to be OTLP with HTTP transport. - otlp_http: - # Configure endpoint, including the trace specific path. - # If omitted or null, http://localhost:4318/v1/traces is used. - endpoint: http://localhost:4318/v1/traces - # Configure certificate used to verify a server's TLS credentials. - # Absolute path to certificate file in PEM format. - # If omitted or null, system default certificate verification is used for secure connections. - certificate_file: /app/cert.pem - # Configure mTLS private client key. - # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - # If omitted or null, mTLS is not used. - client_key_file: /app/cert.pem - # Configure mTLS client certificate. - # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - # If omitted or null, mTLS is not used. - client_certificate_file: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - # If an entry's .value is null, the entry is ignored. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - # If omitted or null, no headers are added. - headers_list: "api-key=1234" - # Configure compression. - # Values include: gzip, none. Implementations may support other compression algorithms. - # If omitted or null, none is used. - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 10000 is used. - timeout: 10000 - # Configure the encoding used for messages. - # Values include: protobuf, json. Implementations may not support json. - # If omitted or null, protobuf is used. - encoding: protobuf - - # Configure a batch span processor. - batch: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with gRPC transport. - otlp_grpc: - # Configure endpoint. - # If omitted or null, http://localhost:4317 is used. - endpoint: http://localhost:4317 - # Configure certificate used to verify a server's TLS credentials. - # Absolute path to certificate file in PEM format. - # If omitted or null, system default certificate verification is used for secure connections. - certificate_file: /app/cert.pem - # Configure mTLS private client key. - # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - # If omitted or null, mTLS is not used. - client_key_file: /app/cert.pem - # Configure mTLS client certificate. - # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - # If omitted or null, mTLS is not used. - client_certificate_file: /app/cert.pem - # Configure headers. Entries have higher priority than entries from .headers_list. - # If an entry's .value is null, the entry is ignored. - headers: - - name: api-key - value: "1234" - # Configure headers. Entries have lower priority than entries from .headers. - # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. - # If omitted or null, no headers are added. - headers_list: "api-key=1234" - # Configure compression. - # Values include: gzip, none. Implementations may support other compression algorithms. - # If omitted or null, none is used. - compression: gzip - # Configure max time (in milliseconds) to wait for each export. - # Value must be non-negative. A value of 0 indicates no limit (infinity). - # If omitted or null, 10000 is used. - timeout: 10000 - # Configure client transport security for the exporter's connection. - # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. - # If omitted or null, false is used. - insecure: false - - # Configure a batch span processor. - batch: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with file transport. - # This type is in development and subject to breaking changes in minor versions. - otlp_file/development: - # Configure output stream. - # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. - # If omitted or null, stdout is used. - output_stream: file:///var/log/traces.jsonl - - # Configure a batch span processor. - batch: - # Configure exporter. - exporter: - # Configure exporter to be OTLP with file transport. - # This type is in development and subject to breaking changes in minor versions. - otlp_file/development: - # Configure output stream. - # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. - # If omitted or null, stdout is used. - output_stream: stdout - - # Configure a batch span processor. - batch: - # Configure exporter. - exporter: - # Configure exporter to be zipkin. - zipkin: - # Configure endpoint. - # If omitted or null, http://localhost:9411/api/v2/spans is used. - endpoint: http://localhost:9411/api/v2/spans - # Configure max time (in milliseconds) to wait for each export. - # Value must be non-negative. A value of 0 indicates indefinite. - # If omitted or null, 10000 is used. - timeout: 10000 - - # Configure a simple span processor. - simple: - # Configure exporter. - exporter: - # Configure exporter to be console. - console: - # Configure span limits. See also attribute_limits. - limits: - # Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. - # Value must be non-negative. - # If omitted or null, there is no limit. - attribute_value_length_limit: 4096 - # Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. - # Value must be non-negative. - # If omitted or null, 128 is used. - attribute_count_limit: 128 - # Configure max span event count. - # Value must be non-negative. - # If omitted or null, 128 is used. - event_count_limit: 128 - # Configure max span link count. - # Value must be non-negative. - # If omitted or null, 128 is used. - link_count_limit: 128 - # Configure max attributes per span event. - # Value must be non-negative. - # If omitted or null, 128 is used. - event_attribute_count_limit: 128 - # Configure max attributes per span link. - # Value must be non-negative. - # If omitted or null, 128 is used. - link_attribute_count_limit: 128 - # Configure the sampler. - # If omitted, parent based sampler with a root of always_on is used. - sampler: - # Configure sampler to be parent_based. - parent_based: - # Configure root sampler. - # If omitted or null, always_on is used. - root: - # Configure sampler to be trace_id_ratio_based. - trace_id_ratio_based: - # Configure trace_id_ratio. - # If omitted or null, 1.0 is used. - ratio: 0.0001 - # Configure remote_parent_sampled sampler. - # If omitted or null, always_on is used. - remote_parent_sampled: - # Configure sampler to be always_on. - always_on: - # Configure remote_parent_not_sampled sampler. - # If omitted or null, always_off is used. - remote_parent_not_sampled: - # Configure sampler to be always_off. - always_off: - # Configure local_parent_sampled sampler. - # If omitted or null, always_on is used. - local_parent_sampled: - # Configure sampler to be always_on. - always_on: - # Configure local_parent_not_sampled sampler. - # If omitted or null, always_off is used. - local_parent_not_sampled: - # Configure sampler to be always_off. - always_off: - # Configure tracers. - # This type is in development and subject to breaking changes in minor versions. - tracer_configurator/development: - # Configure the default tracer config used there is no matching entry in .tracer_configurator/development.tracers. - default_config: - # Configure if the tracer is enabled or not. - disabled: true - # Configure tracers. - tracers: - - # Configure tracer names to match, evaluated as follows: - # - # * If the tracer name exactly matches. - # * If the tracer name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. - name: io.opentelemetry.contrib.* - # The tracer config. - config: - # Configure if the tracer is enabled or not. - disabled: false -# Configure resource for all signals. -# If omitted, the default resource is used. -resource: - # Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list. - # Entries must contain .name and .value, and may optionally include .type. If an entry's .type omitted or null, string is used. - # The .value's type must match the .type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array. - attributes: - - name: service.name - value: unknown_service - - name: string_key - value: value - type: string - - name: bool_key - value: true - type: bool - - name: int_key - value: 1 - type: int - - name: double_key - value: 1.1 - type: double - - name: string_array_key - value: [ "value1", "value2" ] - type: string_array - - name: bool_array_key - value: [ true, false ] - type: bool_array - - name: int_array_key - value: [ 1, 2 ] - type: int_array - - name: double_array_key - value: [ 1.1, 2.2 ] - type: double_array - # Configure resource attributes. Entries have lower priority than entries from .resource.attributes. - # The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration for details. - # If omitted or null, no resource attributes are added. - attributes_list: "service.namespace=my-namespace,service.version=1.0.0" - # Configure resource detection. - # This type is in development and subject to breaking changes in minor versions. - # If omitted or null, resource detection is disabled. - detection/development: - # Configure attributes provided by resource detectors. - attributes: - # Configure list of attribute key patterns to include from resource detectors. - # Attribute keys from resource detectors are evaluated to match as follows: - # * If the value of the attribute key exactly matches. - # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. - # If omitted, all attributes are included. - included: - - process.* - # Configure list of attribute key patterns to exclude from resource detectors. Applies after .resource.detectors.attributes.included (i.e. excluded has higher priority than included). - # Attribute keys from resource detectors are evaluated to match as follows: - # * If the value of the attribute key exactly matches. - # * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. - # If omitted, .included attributes are included. - excluded: - - process.command_args - # Configure resource detectors. - # Resource detector names are dependent on the SDK language ecosystem. Please consult documentation for each respective language. - # If omitted or null, no resource detectors are enabled. - # TODO: implement resource detectors - # detectors: - # - # Enable the container resource detector, which populates container.* attributes. - # container: - # - # Enable the host resource detector, which populates host.* and os.* attributes. - # host: - # - # Enable the process resource detector, which populates process.* attributes. - # process: - # - # Enable the service detector, which populates service.name based on the OTEL_SERVICE_NAME environment variable and service.instance.id. - # service: - # Configure resource schema URL. - # If omitted or null, no schema URL is used. - schema_url: https://opentelemetry.io/schemas/1.16.0 -# Configure instrumentation. -# This type is in development and subject to breaking changes in minor versions. -instrumentation/development: - # Configure general SemConv options that may apply to multiple languages and instrumentations. - # Instrumenation may merge general config options with the language specific configuration at .instrumentation.. - general: - # Configure instrumentations following the peer semantic conventions. - # See peer semantic conventions: https://opentelemetry.io/docs/specs/semconv/attributes-registry/peer/ - peer: - # Configure the service mapping for instrumentations following peer.service semantic conventions. - # Each entry is a key value pair where "peer" defines the IP address and "service" defines the corresponding logical name of the service. - # See peer.service semantic conventions: https://opentelemetry.io/docs/specs/semconv/general/attributes/#general-remote-service-attributes - service_mapping: - - peer: 1.2.3.4 - service: FooService - - peer: 2.3.4.5 - service: BarService - # Configure instrumentations following the http semantic conventions. - # See http semantic conventions: https://opentelemetry.io/docs/specs/semconv/http/ - http: - # Configure instrumentations following the http client semantic conventions. - client: - # Configure headers to capture for outbound http requests. - request_captured_headers: - - Content-Type - - Accept - # Configure headers to capture for outbound http responses. - response_captured_headers: - - Content-Type - - Content-Encoding - # Configure instrumentations following the http server semantic conventions. - server: - # Configure headers to capture for inbound http requests. - request_captured_headers: - - Content-Type - - Accept - # Configure headers to capture for outbound http responses. - response_captured_headers: - - Content-Type - - Content-Encoding - # Configure C++ language-specific instrumentation libraries. - cpp: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure .NET language-specific instrumentation libraries. - dotnet: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure Erlang language-specific instrumentation libraries. - erlang: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure Go language-specific instrumentation libraries. - go: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure Java language-specific instrumentation libraries. - java: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure JavaScript language-specific instrumentation libraries. - js: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure PHP language-specific instrumentation libraries. - php: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure Python language-specific instrumentation libraries. - python: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure Ruby language-specific instrumentation libraries. - ruby: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure Rust language-specific instrumentation libraries. - rust: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - # Configure Swift language-specific instrumentation libraries. - swift: - # Configure the instrumentation corresponding to key "example". - example: - property: "value" - diff --git a/otelconf/testdata/v1.0.0.json b/otelconf/testdata/v1.0.0.json index f85579dd4b3..fe6a130b3f4 100644 --- a/otelconf/testdata/v1.0.0.json +++ b/otelconf/testdata/v1.0.0.json @@ -515,21 +515,7 @@ "excluded": [ "process.command_args" ] - }, - "detectors": [ - { - "container": null - }, - { - "host": null - }, - { - "process": null - }, - { - "service": null - } - ] + } }, "schema_url": "https://opentelemetry.io/schemas/1.16.0" }, diff --git a/otelconf/testdata/v1.0.0.yaml b/otelconf/testdata/v1.0.0.yaml index 2447b8a71e9..2ebbfd0ee38 100644 --- a/otelconf/testdata/v1.0.0.yaml +++ b/otelconf/testdata/v1.0.0.yaml @@ -841,15 +841,16 @@ resource: # Configure resource detectors. # Resource detector names are dependent on the SDK language ecosystem. Please consult documentation for each respective language. # If omitted or null, no resource detectors are enabled. - detectors: - - # Enable the container resource detector, which populates container.* attributes. - container: - - # Enable the host resource detector, which populates host.* and os.* attributes. - host: - - # Enable the process resource detector, which populates process.* attributes. - process: - - # Enable the service detector, which populates service.name based on the OTEL_SERVICE_NAME environment variable and service.instance.id. - service: + # TODO: implement resource detectors + # detectors: + # - # Enable the container resource detector, which populates container.* attributes. + # container: + # - # Enable the host resource detector, which populates host.* and os.* attributes. + # host: + # - # Enable the process resource detector, which populates process.* attributes. + # process: + # - # Enable the service detector, which populates service.name based on the OTEL_SERVICE_NAME environment variable and service.instance.id. + # service: # Configure resource schema URL. # If omitted or null, no schema URL is used. schema_url: https://opentelemetry.io/schemas/1.16.0 From 6237c08a8239ad0ad72587f540b2ac550cf30e68 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 23 Oct 2025 13:10:39 -0700 Subject: [PATCH 28/39] remove createTLSConfig, reuse refactored code Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config.go | 30 ---------------------- otelconf/config_test.go | 56 ----------------------------------------- 2 files changed, 86 deletions(-) diff --git a/otelconf/config.go b/otelconf/config.go index fc6c6f5d3dd..ad1eb356ed9 100644 --- a/otelconf/config.go +++ b/otelconf/config.go @@ -6,11 +6,8 @@ package otelconf // import "go.opentelemetry.io/contrib/otelconf/v1.0.0-rc.1" import ( "context" - "crypto/tls" - "crypto/x509" "errors" "fmt" - "os" "go.opentelemetry.io/otel/baggage" "go.opentelemetry.io/otel/log" @@ -194,33 +191,6 @@ func ParseYAML(file []byte) (*OpenTelemetryConfiguration, error) { return &cfg, nil } -// createTLSConfig creates a tls.Config from certificate files. -func createTLSConfig(caCertFile, clientCertFile, clientKeyFile *string) (*tls.Config, error) { - tlsConfig := &tls.Config{} - if caCertFile != nil { - caText, err := os.ReadFile(*caCertFile) - if err != nil { - return nil, err - } - certPool := x509.NewCertPool() - if !certPool.AppendCertsFromPEM(caText) { - return nil, errors.New("could not create certificate authority chain from certificate") - } - tlsConfig.RootCAs = certPool - } - if clientCertFile != nil { - if clientKeyFile == nil { - return nil, errors.New("client certificate was provided but no client key was provided") - } - clientCert, err := tls.LoadX509KeyPair(*clientCertFile, *clientKeyFile) - if err != nil { - return nil, fmt.Errorf("could not use client certificate: %w", err) - } - tlsConfig.Certificates = []tls.Certificate{clientCert} - } - return tlsConfig, nil -} - // createHeadersConfig combines the two header config fields. Headers take precedence over headersList. func createHeadersConfig(headers []NameStringValuePair, headersList *string) (map[string]string, error) { result := make(map[string]string) diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 4db86ed9a93..6a13aaeef76 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -4,7 +4,6 @@ package otelconf import ( - "crypto/tls" "encoding/json" "errors" "os" @@ -1337,61 +1336,6 @@ func TestUnmarshalPeriodicMetricReader(t *testing.T) { }) } } -func TestCreateTLSConfig(t *testing.T) { - tests := []struct { - name string - caCertFile *string - clientCertFile *string - clientKeyFile *string - wantErrContains string - want func(*tls.Config, *testing.T) - }{ - { - name: "no-input", - want: func(result *tls.Config, t *testing.T) { - require.Nil(t, result.Certificates) - require.Nil(t, result.RootCAs) - }, - }, - { - name: "only-cacert-provided", - caCertFile: ptr(filepath.Join("..", "testdata", "ca.crt")), - want: func(result *tls.Config, t *testing.T) { - require.Nil(t, result.Certificates) - require.NotNil(t, result.RootCAs) - }, - }, - { - name: "nonexistent-cacert-file", - caCertFile: ptr("nowhere.crt"), - wantErrContains: "open nowhere.crt:", - }, - { - name: "nonexistent-clientcert-file", - clientCertFile: ptr("nowhere.crt"), - clientKeyFile: ptr("nowhere.crt"), - wantErrContains: "could not use client certificate: open nowhere.crt:", - }, - { - name: "bad-cacert-file", - caCertFile: ptr(filepath.Join("..", "testdata", "bad_cert.crt")), - wantErrContains: "could not create certificate authority chain from certificate", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := createTLSConfig(tt.caCertFile, tt.clientCertFile, tt.clientKeyFile) - - if tt.wantErrContains != "" { - require.Contains(t, err.Error(), tt.wantErrContains) - } else { - require.NoError(t, err) - tt.want(got, t) - } - }) - } -} func TestUnmarshalCardinalityLimits(t *testing.T) { for _, tt := range []struct { From 64211b59c4d2230fb19a98b09a88915ada0adf0b Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Mon, 27 Oct 2025 11:42:48 -0700 Subject: [PATCH 29/39] clean up Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_common.go | 137 +++++++++++++++ otelconf/config_json.go | 102 +---------- otelconf/config_test.go | 59 +++---- otelconf/config_yaml.go | 143 --------------- otelconf/fuzz_test.go | 4 +- otelconf/v1.0.0-rc.1/config_common.go | 243 -------------------------- 6 files changed, 169 insertions(+), 519 deletions(-) delete mode 100644 otelconf/v1.0.0-rc.1/config_common.go diff --git a/otelconf/config_common.go b/otelconf/config_common.go index 246d29e33b4..14bc8620503 100644 --- a/otelconf/config_common.go +++ b/otelconf/config_common.go @@ -5,6 +5,7 @@ package otelconf // import "go.opentelemetry.io/contrib/otelconf" import ( "context" + "encoding/json" "errors" "fmt" "reflect" @@ -13,6 +14,7 @@ import ( sdklog "go.opentelemetry.io/otel/sdk/log" sdkmetric "go.opentelemetry.io/otel/sdk/metric" sdktrace "go.opentelemetry.io/otel/sdk/trace" + yaml "go.yaml.in/yaml/v3" ) const ( @@ -155,6 +157,53 @@ func newErrInvalid(id string) error { return &errInvalid{Identifier: id} } +// unmarshalSamplerTypes handles always_on and always_off sampler unmarshaling. +func unmarshalSamplerTypes(raw map[string]any, plain *Sampler) { + // always_on can be nil, must check and set here + if _, ok := raw["always_on"]; ok { + plain.AlwaysOn = AlwaysOnSampler{} + } + // always_off can be nil, must check and set here + if _, ok := raw["always_off"]; ok { + plain.AlwaysOff = AlwaysOffSampler{} + } +} + +// unmarshalTextMapPropagatorTypes handles all propagator type unmarshaling. +func unmarshalTextMapPropagatorTypes(raw map[string]any, plain *TextMapPropagator) { + // b3 can be nil, must check and set here + if v, ok := raw["b3"]; ok && v == nil { + plain.B3 = B3Propagator{} + } + if v, ok := raw["b3multi"]; ok && v == nil { + plain.B3Multi = B3MultiPropagator{} + } + if v, ok := raw["baggage"]; ok && v == nil { + plain.Baggage = BaggagePropagator{} + } + if v, ok := raw["jaeger"]; ok && v == nil { + plain.Jaeger = JaegerPropagator{} + } + if v, ok := raw["ottrace"]; ok && v == nil { + plain.Ottrace = OpenTracingPropagator{} + } + if v, ok := raw["tracecontext"]; ok && v == nil { + plain.Tracecontext = TraceContextPropagator{} + } +} + +// unmarshalMetricProducer handles opencensus metric producer unmarshaling. +func unmarshalMetricProducer(raw map[string]any, plain *MetricProducer) { + // opencensus can be nil, must check and set here + if v, ok := raw["opencensus"]; ok && v == nil { + delete(raw, "opencensus") + plain.Opencensus = OpenCensusMetricProducer{} + } + if len(raw) > 0 { + plain.AdditionalProperties = raw + } +} + // validatePeriodicMetricReader handles validation for PeriodicMetricReader. func validatePeriodicMetricReader(plain *PeriodicMetricReader) error { if plain.Timeout != nil && 0 > *plain.Timeout { @@ -297,3 +346,91 @@ func supportedHistogramAggregation(in ExporterDefaultHistogramAggregation) error } return newErrInvalid(fmt.Sprintf("invalid histogram aggregation (expected one of %#v): %#v", enumValuesOTLPMetricDefaultHistogramAggregation, in)) } + +var enumValuesAttributeType = []any{ + nil, + "string", + "bool", + "int", + "double", + "string_array", + "bool_array", + "int_array", + "double_array", +} + +// MarshalUnmarshaler combines marshal and unmarshal operations. +type MarshalUnmarshaler interface { + Marshal(v any) ([]byte, error) + Unmarshal(data []byte, v any) error +} + +// jsonCodec implements MarshalUnmarshaler for JSON. +type jsonCodec struct{} + +func (jsonCodec) Marshal(v any) ([]byte, error) { + return json.Marshal(v) +} + +func (jsonCodec) Unmarshal(data []byte, v any) error { + return json.Unmarshal(data, v) +} + +// yamlCodec implements MarshalUnmarshaler for YAML. +type yamlCodec struct{} + +func (yamlCodec) Marshal(v any) ([]byte, error) { + return yaml.Marshal(v) +} + +func (yamlCodec) Unmarshal(data []byte, v any) error { + return yaml.Unmarshal(data, v) +} + +// setConfigDefaults sets default values for disabled and log_level. +func setConfigDefaults(raw map[string]any, plain *OpenTelemetryConfiguration, codec MarshalUnmarshaler) error { + // Configure if the SDK is disabled or not. + // If omitted or null, false is used. + plain.Disabled = ptr(false) + if v, ok := raw["disabled"]; ok && v != nil { + marshaled, err := codec.Marshal(v) + if err != nil { + return err + } + var disabled bool + if err := codec.Unmarshal(marshaled, &disabled); err != nil { + return err + } + plain.Disabled = &disabled + } + + // Configure the log level of the internal logger used by the SDK. + // If omitted, info is used. + plain.LogLevel = ptr("info") + if v, ok := raw["log_level"]; ok && v != nil { + marshaled, err := codec.Marshal(v) + if err != nil { + return err + } + var logLevel string + if err := codec.Unmarshal(marshaled, &logLevel); err != nil { + return err + } + plain.LogLevel = &logLevel + } + + return nil +} + +// validateStringField validates a string field is present and correct type. +func validateStringField(raw map[string]any, fieldName string) (string, error) { + v, ok := raw[fieldName] + if !ok { + return "", fmt.Errorf("cannot unmarshal field %s in NameStringValuePair required", fieldName) + } + str, ok := v.(string) + if !ok { + return "", fmt.Errorf("cannot unmarshal field %s in NameStringValuePair must be string", fieldName) + } + return str, nil +} diff --git a/otelconf/config_json.go b/otelconf/config_json.go index e3f21a20047..b0ffe7d0f9c 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -191,6 +191,7 @@ func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { sh.Plain.Console = c } *j = LogRecordExporter(sh.Plain) + return nil } // MarshalJSON implements json.Marshaler. @@ -1105,63 +1106,6 @@ func (j *PullMetricReader) UnmarshalJSON(b []byte) error { return nil } -// UnmarshalJSON implements json.Unmarshaler. -func (j *PushMetricExporter) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - type Plain PushMetricExporter - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - // console can be nil, must check and set here - if checkConsoleExporter(raw) { - plain.Console = ConsoleExporter{} - } - *j = PushMetricExporter(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *SpanExporter) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - type Plain SpanExporter - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - // console can be nil, must check and set here - if checkConsoleExporter(raw) { - plain.Console = ConsoleExporter{} - } - *j = SpanExporter(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - type Plain LogRecordExporter - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - // console can be nil, must check and set here - if checkConsoleExporter(raw) { - plain.Console = ConsoleExporter{} - } - *j = LogRecordExporter(plain) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *Sampler) UnmarshalJSON(b []byte) error { var raw map[string]any @@ -1193,47 +1137,3 @@ func (j *MetricProducer) UnmarshalJSON(b []byte) error { *j = MetricProducer(plain) return nil } - -// UnmarshalJSON implements json.Unmarshaler. -func (j *TextMapPropagator) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - type Plain TextMapPropagator - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - unmarshalTextMapPropagatorTypes(raw, (*TextMapPropagator)(&plain)) - *j = TextMapPropagator(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *CardinalityLimits) UnmarshalJSON(value []byte) error { - type Plain CardinalityLimits - var plain Plain - if err := json.Unmarshal(value, &plain); err != nil { - return err - } - if err := validateCardinalityLimits((*CardinalityLimits)(&plain)); err != nil { - return err - } - *j = CardinalityLimits(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *SpanLimits) UnmarshalJSON(value []byte) error { - type Plain SpanLimits - var plain Plain - if err := json.Unmarshal(value, &plain); err != nil { - return err - } - if err := validateSpanLimits((*SpanLimits)(&plain)); err != nil { - return err - } - *j = SpanLimits(plain) - return nil -} diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 6a13aaeef76..45b9d1e0584 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -11,9 +11,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.yaml.in/yaml/v3" - "github.com/stretchr/testify/require" lognoop "go.opentelemetry.io/otel/log/noop" metricnoop "go.opentelemetry.io/otel/metric/noop" @@ -21,7 +18,7 @@ import ( sdkmetric "go.opentelemetry.io/otel/sdk/metric" sdktrace "go.opentelemetry.io/otel/sdk/trace" tracenoop "go.opentelemetry.io/otel/trace/noop" - yaml "go.yaml.in/yaml/v3" + "go.yaml.in/yaml/v3" ) func TestUnmarshalPushMetricExporterInvalidData(t *testing.T) { @@ -410,7 +407,7 @@ func TestNewSDK(t *testing.T) { var v10OpenTelemetryConfig = OpenTelemetryConfiguration{ Disabled: ptr(false), - FileFormat: "1.0-rc.1", + FileFormat: "1.0-rc.2", AttributeLimits: &AttributeLimits{ AttributeCountLimit: ptr(128), AttributeValueLengthLimit: ptr(4096), @@ -614,8 +611,9 @@ var v10OpenTelemetryConfig = OpenTelemetryConfiguration{ }, Exporter: PullMetricExporter{ PrometheusDevelopment: &ExperimentalPrometheusMetricExporter{ - Host: ptr("localhost"), - Port: ptr(9464), + Host: ptr("localhost"), + Port: ptr(9464), + TranslationStrategy: ptr(ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithSuffixes), WithResourceConstantLabels: &IncludeExclude{ Excluded: []string{"service.attr1"}, Included: []string{"service*"}, @@ -794,12 +792,14 @@ var v10OpenTelemetryConfig = OpenTelemetryConfiguration{ TracerProvider: &TracerProviderJson{ TracerConfiguratorDevelopment: &ExperimentalTracerConfigurator{ DefaultConfig: &ExperimentalTracerConfig{ - Disabled: true, + Disabled: ptr(true), }, Tracers: []ExperimentalTracerMatcherAndConfig{ { - Config: ExperimentalTracerConfig{}, - Name: "io.opentelemetry.contrib.*", + Config: ptr(ExperimentalTracerConfig{ + Disabled: ptr(false), + }), + Name: ptr("io.opentelemetry.contrib.*"), }, }, }, @@ -997,14 +997,18 @@ func TestParseYAML(t *testing.T) { line 1: cannot unmarshal !!str ` + "`notabool`" + ` into bool`), }, { - name: "invalid nil name", - input: "v1.0.0_invalid_nil_name.yaml", - wantErr: errors.New(`cannot unmarshal field name in NameStringValuePair required`), + name: "invalid nil name", + input: "v1.0.0_invalid_nil_name.yaml", + wantErr: errors.New(`unmarshal error in *otelconf.BatchSpanProcessor +unmarshal error in *otelconf.SpanExporter +cannot unmarshal field name in NameStringValuePair required`), }, { - name: "invalid nil value", - input: "v1.0.0_invalid_nil_value.yaml", - wantErr: errors.New(`cannot unmarshal field value in NameStringValuePair required`), + name: "invalid nil value", + input: "v1.0.0_invalid_nil_value.yaml", + wantErr: errors.New(`unmarshal error in *otelconf.BatchLogRecordProcessor +unmarshal error in *otelconf.LogRecordExporter +cannot unmarshal field value in NameStringValuePair required`), }, { name: "valid v0.2 config", @@ -1015,25 +1019,20 @@ func TestParseYAML(t *testing.T) { { name: "valid v0.3 config", input: "v0.3.yaml", - wantErr: errors.New(`yaml: unmarshal errors: - line 2: cannot unmarshal !!str` + " `traceco...`" + ` into map[string]interface {} - line 3: cannot unmarshal !!str` + " `baggage`" + ` into map[string]interface {} - line 4: cannot unmarshal !!str` + " `b3`" + ` into map[string]interface {} - line 5: cannot unmarshal !!str` + " `b3multi`" + ` into map[string]interface {} - line 6: cannot unmarshal !!str` + " `jaeger`" + ` into map[string]interface {} - line 7: cannot unmarshal !!str` + " `xray`" + ` into map[string]interface {} - line 8: cannot unmarshal !!str` + " `ottrace`" + ` into map[string]interface {}`), + wantErr: errors.New(`unmarshal error in *otelconf.TextMapPropagator +yaml: unmarshal errors: + line 2: cannot unmarshal !!str` + " `traceco...`" + ` into otelconf.Plain`), }, { name: "valid v1.0.0 config", - input: "v1.0.0-rc.1.yaml", + input: "v1.0.0.yaml", wantType: &v10OpenTelemetryConfig, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - b, err := os.ReadFile(filepath.Join("..", "testdata", tt.input)) + b, err := os.ReadFile(filepath.Join("testdata", tt.input)) require.NoError(t, err) got, err := ParseYAML(b) @@ -1178,7 +1177,7 @@ func TestParseYAMLWithEnvironmentVariables(t *testing.T) { t.Setenv("VALUE_WITH_ESCAPE", "value$$") // A valid replacement text, used verbatim, not replaced with "Never use this value" for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - b, err := os.ReadFile(filepath.Join("..", "testdata", tt.input)) + b, err := os.ReadFile(filepath.Join("testdata", tt.input)) require.NoError(t, err) got, err := ParseYAML(b) @@ -1232,18 +1231,18 @@ func TestSerializeJSON(t *testing.T) { { name: "valid v0.3 config", input: "v0.3.json", - wantErr: errors.New(`json: cannot unmarshal string into Go struct field PropagatorJson.composite of type map[string]interface {}`), + wantErr: errors.New(`unmarshal error in *otelconf.TextMapPropagator`), }, { name: "valid v1.0.0 config", - input: "v1.0.0-rc.1.json", + input: "v1.0.0.json", wantType: v10OpenTelemetryConfig, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - b, err := os.ReadFile(filepath.Join("..", "testdata", tt.input)) + b, err := os.ReadFile(filepath.Join("testdata", tt.input)) require.NoError(t, err) var got OpenTelemetryConfiguration diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index b9cd0257aa7..4b94b7278d1 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -278,63 +278,6 @@ func (j *NameStringValuePair) UnmarshalYAML(node *yaml.Node) error { return nil } -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { - var raw map[string]any - if err := node.Decode(&raw); err != nil { - return err - } - type Plain PushMetricExporter - var plain Plain - if err := node.Decode(&plain); err != nil { - return err - } - // console can be nil, must check and set here - if checkConsoleExporter(raw) { - plain.Console = ConsoleExporter{} - } - *j = PushMetricExporter(plain) - return nil -} - -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *SpanExporter) UnmarshalYAML(node *yaml.Node) error { - var raw map[string]any - if err := node.Decode(&raw); err != nil { - return err - } - type Plain SpanExporter - var plain Plain - if err := node.Decode(&plain); err != nil { - return err - } - // console can be nil, must check and set here - if checkConsoleExporter(raw) { - plain.Console = ConsoleExporter{} - } - *j = SpanExporter(plain) - return nil -} - -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *LogRecordExporter) UnmarshalYAML(node *yaml.Node) error { - var raw map[string]any - if err := node.Decode(&raw); err != nil { - return err - } - type Plain LogRecordExporter - var plain Plain - if err := node.Decode(&plain); err != nil { - return err - } - // console can be nil, must check and set here - if checkConsoleExporter(raw) { - plain.Console = ConsoleExporter{} - } - *j = LogRecordExporter(plain) - return nil -} - // UnmarshalYAML implements yaml.Unmarshaler. func (j *Sampler) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any @@ -367,22 +310,6 @@ func (j *MetricProducer) UnmarshalYAML(node *yaml.Node) error { return nil } -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *TextMapPropagator) UnmarshalYAML(node *yaml.Node) error { - var raw map[string]any - if err := node.Decode(&raw); err != nil { - return err - } - type Plain TextMapPropagator - var plain Plain - if err := node.Decode(&plain); err != nil { - return err - } - unmarshalTextMapPropagatorTypes(raw, (*TextMapPropagator)(&plain)) - *j = TextMapPropagator(plain) - return nil -} - // UnmarshalYAML implements yaml.Unmarshaler. func (j *BatchSpanProcessor) UnmarshalYAML(node *yaml.Node) error { if !hasYAMLMapKey(node, "exporter") { @@ -713,73 +640,3 @@ func (j *ExperimentalLanguageSpecificInstrumentation) UnmarshalYAML(unmarshal fu *j = raw return nil } - -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *BatchLogRecordProcessor) UnmarshalYAML(node *yaml.Node) error { - var raw map[string]any - if err := node.Decode(&raw); err != nil { - return err - } - if _, ok := raw["exporter"]; raw != nil && !ok { - return errors.New("field exporter in BatchLogRecordProcessor: required") - } - type Plain BatchLogRecordProcessor - var plain Plain - if err := node.Decode(&plain); err != nil { - return err - } - if err := validateBatchLogRecordProcessor((*BatchLogRecordProcessor)(&plain)); err != nil { - return err - } - *j = BatchLogRecordProcessor(plain) - return nil -} - -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *BatchSpanProcessor) UnmarshalYAML(node *yaml.Node) error { - var raw map[string]any - if err := node.Decode(&raw); err != nil { - return err - } - if _, ok := raw["exporter"]; raw != nil && !ok { - return errors.New("field exporter in BatchSpanProcessor: required") - } - type Plain BatchSpanProcessor - var plain Plain - if err := node.Decode(&plain); err != nil { - return err - } - if err := validateBatchSpanProcessor((*BatchSpanProcessor)(&plain)); err != nil { - return err - } - *j = BatchSpanProcessor(plain) - return nil -} - -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *CardinalityLimits) UnmarshalYAML(node *yaml.Node) error { - type Plain CardinalityLimits - var plain Plain - if err := node.Decode(&plain); err != nil { - return err - } - if err := validateCardinalityLimits((*CardinalityLimits)(&plain)); err != nil { - return err - } - *j = CardinalityLimits(plain) - return nil -} - -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *SpanLimits) UnmarshalYAML(node *yaml.Node) error { - type Plain SpanLimits - var plain Plain - if err := node.Decode(&plain); err != nil { - return err - } - if err := validateSpanLimits((*SpanLimits)(&plain)); err != nil { - return err - } - *j = SpanLimits(plain) - return nil -} diff --git a/otelconf/fuzz_test.go b/otelconf/fuzz_test.go index 0fd6289da2a..e1c32b48b72 100644 --- a/otelconf/fuzz_test.go +++ b/otelconf/fuzz_test.go @@ -15,7 +15,7 @@ import ( ) func FuzzJSON(f *testing.F) { - b, err := os.ReadFile(filepath.Join("..", "testdata", "v0.3.json")) + b, err := os.ReadFile(filepath.Join("testdata", "v1.0.0.json")) require.NoError(f, err) f.Add(b) @@ -40,7 +40,7 @@ func FuzzJSON(f *testing.F) { } func FuzzYAML(f *testing.F) { - b, err := os.ReadFile(filepath.Join("..", "testdata", "v0.3.yaml")) + b, err := os.ReadFile(filepath.Join("testdata", "v1.0.0.yaml")) require.NoError(f, err) f.Add(b) diff --git a/otelconf/v1.0.0-rc.1/config_common.go b/otelconf/v1.0.0-rc.1/config_common.go deleted file mode 100644 index 25fd2effa00..00000000000 --- a/otelconf/v1.0.0-rc.1/config_common.go +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package otelconf - -import ( - "encoding/json" - "fmt" - - yaml "go.yaml.in/yaml/v3" -) - -func ptr[T any](v T) *T { - return &v -} - -var enumValuesAttributeType = []any{ - nil, - "string", - "bool", - "int", - "double", - "string_array", - "bool_array", - "int_array", - "double_array", -} - -// MarshalUnmarshaler combines marshal and unmarshal operations. -type MarshalUnmarshaler interface { - Marshal(v any) ([]byte, error) - Unmarshal(data []byte, v any) error -} - -// jsonCodec implements MarshalUnmarshaler for JSON. -type jsonCodec struct{} - -func (jsonCodec) Marshal(v any) ([]byte, error) { - return json.Marshal(v) -} - -func (jsonCodec) Unmarshal(data []byte, v any) error { - return json.Unmarshal(data, v) -} - -// yamlCodec implements MarshalUnmarshaler for YAML. -type yamlCodec struct{} - -func (yamlCodec) Marshal(v any) ([]byte, error) { - return yaml.Marshal(v) -} - -func (yamlCodec) Unmarshal(data []byte, v any) error { - return yaml.Unmarshal(data, v) -} - -// setConfigDefaults sets default values for disabled and log_level. -func setConfigDefaults(raw map[string]any, plain *OpenTelemetryConfiguration, codec MarshalUnmarshaler) error { - // Configure if the SDK is disabled or not. - // If omitted or null, false is used. - plain.Disabled = ptr(false) - if v, ok := raw["disabled"]; ok && v != nil { - marshaled, err := codec.Marshal(v) - if err != nil { - return err - } - var disabled bool - if err := codec.Unmarshal(marshaled, &disabled); err != nil { - return err - } - plain.Disabled = &disabled - } - - // Configure the log level of the internal logger used by the SDK. - // If omitted, info is used. - plain.LogLevel = ptr("info") - if v, ok := raw["log_level"]; ok && v != nil { - marshaled, err := codec.Marshal(v) - if err != nil { - return err - } - var logLevel string - if err := codec.Unmarshal(marshaled, &logLevel); err != nil { - return err - } - plain.LogLevel = &logLevel - } - - return nil -} - -// validateStringField validates a string field is present and correct type. -func validateStringField(raw map[string]any, fieldName string) (string, error) { - v, ok := raw[fieldName] - if !ok { - return "", fmt.Errorf("cannot unmarshal field %s in NameStringValuePair required", fieldName) - } - str, ok := v.(string) - if !ok { - return "", fmt.Errorf("cannot unmarshal field %s in NameStringValuePair must be string", fieldName) - } - return str, nil -} - -// unmarshalExporterWithConsole handles the console exporter unmarshaling pattern. -// Returns true if console field was present in raw. -func checkConsoleExporter(raw map[string]any) bool { - _, ok := raw["console"] - return ok -} - -// unmarshalSamplerTypes handles always_on and always_off sampler unmarshaling. -func unmarshalSamplerTypes(raw map[string]any, plain *Sampler) { - // always_on can be nil, must check and set here - if _, ok := raw["always_on"]; ok { - plain.AlwaysOn = AlwaysOnSampler{} - } - // always_off can be nil, must check and set here - if _, ok := raw["always_off"]; ok { - plain.AlwaysOff = AlwaysOffSampler{} - } -} - -// unmarshalTextMapPropagatorTypes handles all propagator type unmarshaling. -func unmarshalTextMapPropagatorTypes(raw map[string]any, plain *TextMapPropagator) { - // b3 can be nil, must check and set here - if v, ok := raw["b3"]; ok && v == nil { - plain.B3 = B3Propagator{} - } - if v, ok := raw["b3multi"]; ok && v == nil { - plain.B3Multi = B3MultiPropagator{} - } - if v, ok := raw["baggage"]; ok && v == nil { - plain.Baggage = BaggagePropagator{} - } - if v, ok := raw["jaeger"]; ok && v == nil { - plain.Jaeger = JaegerPropagator{} - } - if v, ok := raw["ottrace"]; ok && v == nil { - plain.Ottrace = OpenTracingPropagator{} - } - if v, ok := raw["tracecontext"]; ok && v == nil { - plain.Tracecontext = TraceContextPropagator{} - } -} - -// unmarshalMetricProducer handles opencensus metric producer unmarshaling. -func unmarshalMetricProducer(raw map[string]any, plain *MetricProducer) { - // opencensus can be nil, must check and set here - if v, ok := raw["opencensus"]; ok && v == nil { - delete(raw, "opencensus") - plain.Opencensus = OpenCensusMetricProducer{} - } - if len(raw) > 0 { - plain.AdditionalProperties = raw - } -} - -// validateBatchLogRecordProcessor handles validation for BatchLogRecordProcessor. -func validateBatchLogRecordProcessor(plain *BatchLogRecordProcessor) error { - if plain.ExportTimeout != nil && 0 > *plain.ExportTimeout { - return fmt.Errorf("field %s: must be >= %v", "export_timeout", 0) - } - if plain.MaxExportBatchSize != nil && 0 >= *plain.MaxExportBatchSize { - return fmt.Errorf("field %s: must be > %v", "max_export_batch_size", 0) - } - if plain.MaxQueueSize != nil && 0 >= *plain.MaxQueueSize { - return fmt.Errorf("field %s: must be > %v", "max_queue_size", 0) - } - if plain.ScheduleDelay != nil && 0 > *plain.ScheduleDelay { - return fmt.Errorf("field %s: must be >= %v", "schedule_delay", 0) - } - return nil -} - -// validateBatchSpanProcessor handles validation for BatchSpanProcessor. -func validateBatchSpanProcessor(plain *BatchSpanProcessor) error { - if plain.ExportTimeout != nil && 0 > *plain.ExportTimeout { - return fmt.Errorf("field %s: must be >= %v", "export_timeout", 0) - } - if plain.MaxExportBatchSize != nil && 0 >= *plain.MaxExportBatchSize { - return fmt.Errorf("field %s: must be > %v", "max_export_batch_size", 0) - } - if plain.MaxQueueSize != nil && 0 >= *plain.MaxQueueSize { - return fmt.Errorf("field %s: must be > %v", "max_queue_size", 0) - } - if plain.ScheduleDelay != nil && 0 > *plain.ScheduleDelay { - return fmt.Errorf("field %s: must be >= %v", "schedule_delay", 0) - } - return nil -} - -// validateCardinalityLimits handles validation for CardinalityLimits. -func validateCardinalityLimits(plain *CardinalityLimits) error { - if plain.Counter != nil && 0 >= *plain.Counter { - return fmt.Errorf("field %s: must be > %v", "counter", 0) - } - if plain.Default != nil && 0 >= *plain.Default { - return fmt.Errorf("field %s: must be > %v", "default", 0) - } - if plain.Gauge != nil && 0 >= *plain.Gauge { - return fmt.Errorf("field %s: must be > %v", "gauge", 0) - } - if plain.Histogram != nil && 0 >= *plain.Histogram { - return fmt.Errorf("field %s: must be > %v", "histogram", 0) - } - if plain.ObservableCounter != nil && 0 >= *plain.ObservableCounter { - return fmt.Errorf("field %s: must be > %v", "observable_counter", 0) - } - if plain.ObservableGauge != nil && 0 >= *plain.ObservableGauge { - return fmt.Errorf("field %s: must be > %v", "observable_gauge", 0) - } - if plain.ObservableUpDownCounter != nil && 0 >= *plain.ObservableUpDownCounter { - return fmt.Errorf("field %s: must be > %v", "observable_up_down_counter", 0) - } - if plain.UpDownCounter != nil && 0 >= *plain.UpDownCounter { - return fmt.Errorf("field %s: must be > %v", "up_down_counter", 0) - } - return nil -} - -// validateSpanLimits handles validation for SpanLimits. -func validateSpanLimits(plain *SpanLimits) error { - if plain.AttributeCountLimit != nil && 0 > *plain.AttributeCountLimit { - return fmt.Errorf("field %s: must be >= %v", "attribute_count_limit", 0) - } - if plain.AttributeValueLengthLimit != nil && 0 > *plain.AttributeValueLengthLimit { - return fmt.Errorf("field %s: must be >= %v", "attribute_value_length_limit", 0) - } - if plain.EventAttributeCountLimit != nil && 0 > *plain.EventAttributeCountLimit { - return fmt.Errorf("field %s: must be >= %v", "event_attribute_count_limit", 0) - } - if plain.EventCountLimit != nil && 0 > *plain.EventCountLimit { - return fmt.Errorf("field %s: must be >= %v", "event_count_limit", 0) - } - if plain.LinkAttributeCountLimit != nil && 0 > *plain.LinkAttributeCountLimit { - return fmt.Errorf("field %s: must be >= %v", "link_attribute_count_limit", 0) - } - if plain.LinkCountLimit != nil && 0 > *plain.LinkCountLimit { - return fmt.Errorf("field %s: must be >= %v", "link_count_limit", 0) - } - return nil -} From 5e187810a5ad7851c48c0cf7fda0c11ab285326d Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Tue, 28 Oct 2025 12:37:25 -0700 Subject: [PATCH 30/39] test cleanup Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_test.go | 2 +- otelconf/testdata/v1.0.0-env-var.yaml | 123 -------------------------- otelconf/testdata/v1.0.0_env_var.yaml | 1 + 3 files changed, 2 insertions(+), 124 deletions(-) delete mode 100644 otelconf/testdata/v1.0.0-env-var.yaml diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 45b9d1e0584..885e8fec626 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -1157,7 +1157,7 @@ func TestParseYAMLWithEnvironmentVariables(t *testing.T) { }{ { name: "valid v1.0.0 config with env vars", - input: "v1.0.0-env-var.yaml", + input: "v1.0.0_env_var.yaml", wantType: &v100OpenTelemetryConfigEnvParsing, }, } diff --git a/otelconf/testdata/v1.0.0-env-var.yaml b/otelconf/testdata/v1.0.0-env-var.yaml deleted file mode 100644 index 2f520a2c6db..00000000000 --- a/otelconf/testdata/v1.0.0-env-var.yaml +++ /dev/null @@ -1,123 +0,0 @@ -file_format: "1.0" -disabled: ${OTEL_SDK_DISABLED} -attribute_limits: - attribute_value_length_limit: ${OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT} - attribute_count_limit: 128 - -resource: - attributes: - - name: service.name - value: unknown_service - - name: string_key - value: value - type: string - - name: bool_key - value: true - type: bool - - name: int_key - value: 1 - type: int - - name: double_key - value: 1.1 - type: double - - name: string_array_key - value: [ "value1", "value2" ] - type: string_array - - name: bool_array_key - value: [ true, false ] - type: bool_array - - name: int_array_key - value: [ 1, 2 ] - type: int_array - - name: double_array_key - value: [ 1.1, 2.2 ] - type: double_array - - name: string_value - value: ${STRING_VALUE} - type: string - - name: bool_value - value: ${BOOL_VALUE} - type: bool - - name: int_value - value: ${INT_VALUE} - type: int - - name: float_value - value: ${FLOAT_VALUE} - type: double - - name: hex_value - value: ${HEX_VALUE} - type: int - - name: quoted_string_value - value: "${STRING_VALUE}" - type: string - - name: quoted_bool_value - value: "${BOOL_VALUE}" - type: string - - name: quoted_int_value - value: "${INT_VALUE}" - type: string - - name: quoted_float_value - value: "${FLOAT_VALUE}" - type: string - - name: quoted_hex_value - value: "${HEX_VALUE}" - type: string - - name: alternative_env_syntax - value: "${env:STRING_VALUE}" - type: string - - name: invalid_map_value - value: "${INVALID_MAP_VALUE}" - type: string - - name: multiple_references_inject - value: foo ${STRING_VALUE} ${FLOAT_VALUE} - type: string - - name: undefined_key - value: ${UNDEFINED_KEY} - type: string - - name: undefined_key_fallback - value: ${UNDEFINED_KEY:-fallback} - type: string - - name: ${ENV_VAR_IN_KEY} - value: "value" - type: string - - name: replace_me - value: ${REPLACE_ME} - type: string - - name: undefined_defaults_to_var - value: ${UNDEFINED_KEY:-${STRING_VALUE}} - type: string - - name: escaped_does_not_substitute - value: $${STRING_VALUE} - type: string - - name: escaped_does_not_substitute_fallback - value: $${STRING_VALUE:-fallback} - type: string - - name: escaped_and_substituted_fallback - value: $${STRING_VALUE:-${STRING_VALUE}} - type: string - - name: escaped_and_substituted - value: $$${STRING_VALUE} - type: string - - name: multiple_escaped_and_not_substituted - value: $$$${STRING_VALUE} - type: string - - name: undefined_key_with_escape_sequence_in_fallback - value: ${UNDEFINED_KEY:-$${UNDEFINED_KEY}} - type: string - - name: value_with_escape - value: ${VALUE_WITH_ESCAPE} - type: string - - name: escape_sequence - value: a $$ b - type: string - - name: no_escape_sequence - value: a $ b - type: string - attributes_list: "service.namespace=my-namespace,service.version=1.0.0" - detectors: - attributes: - included: - - process.* - excluded: - - process.command_args - schema_url: https://opentelemetry.io/schemas/1.16.0 diff --git a/otelconf/testdata/v1.0.0_env_var.yaml b/otelconf/testdata/v1.0.0_env_var.yaml index f3c24f83e9e..2f520a2c6db 100644 --- a/otelconf/testdata/v1.0.0_env_var.yaml +++ b/otelconf/testdata/v1.0.0_env_var.yaml @@ -1,3 +1,4 @@ +file_format: "1.0" disabled: ${OTEL_SDK_DISABLED} attribute_limits: attribute_value_length_limit: ${OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT} From 49f9e77aaecc69992059f2aec1025d8309d6f7d2 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Tue, 28 Oct 2025 12:39:13 -0700 Subject: [PATCH 31/39] remove dead code Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_common.go | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/otelconf/config_common.go b/otelconf/config_common.go index 14bc8620503..5dd79d2c375 100644 --- a/otelconf/config_common.go +++ b/otelconf/config_common.go @@ -169,29 +169,6 @@ func unmarshalSamplerTypes(raw map[string]any, plain *Sampler) { } } -// unmarshalTextMapPropagatorTypes handles all propagator type unmarshaling. -func unmarshalTextMapPropagatorTypes(raw map[string]any, plain *TextMapPropagator) { - // b3 can be nil, must check and set here - if v, ok := raw["b3"]; ok && v == nil { - plain.B3 = B3Propagator{} - } - if v, ok := raw["b3multi"]; ok && v == nil { - plain.B3Multi = B3MultiPropagator{} - } - if v, ok := raw["baggage"]; ok && v == nil { - plain.Baggage = BaggagePropagator{} - } - if v, ok := raw["jaeger"]; ok && v == nil { - plain.Jaeger = JaegerPropagator{} - } - if v, ok := raw["ottrace"]; ok && v == nil { - plain.Ottrace = OpenTracingPropagator{} - } - if v, ok := raw["tracecontext"]; ok && v == nil { - plain.Tracecontext = TraceContextPropagator{} - } -} - // unmarshalMetricProducer handles opencensus metric producer unmarshaling. func unmarshalMetricProducer(raw map[string]any, plain *MetricProducer) { // opencensus can be nil, must check and set here From 91eda36e5ebd3fc1aa4c41f535be8d1800451df7 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Wed, 29 Oct 2025 09:21:56 -0700 Subject: [PATCH 32/39] lint Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config.go | 47 +-------------------------------------- otelconf/config_common.go | 2 +- otelconf/config_json.go | 44 ++---------------------------------- otelconf/config_test.go | 12 ++++------ otelconf/config_yaml.go | 2 ++ otelconf/log.go | 3 +-- otelconf/metric.go | 3 +-- otelconf/trace.go | 3 +-- 8 files changed, 13 insertions(+), 103 deletions(-) diff --git a/otelconf/config.go b/otelconf/config.go index ad1eb356ed9..db6305803b8 100644 --- a/otelconf/config.go +++ b/otelconf/config.go @@ -2,14 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 // Package otelconf provides an OpenTelemetry declarative configuration SDK. -package otelconf // import "go.opentelemetry.io/contrib/otelconf/v1.0.0-rc.1" +package otelconf // import "go.opentelemetry.io/contrib/otelconf" import ( "context" "errors" - "fmt" - "go.opentelemetry.io/otel/baggage" "go.opentelemetry.io/otel/log" nooplog "go.opentelemetry.io/otel/log/noop" "go.opentelemetry.io/otel/metric" @@ -24,25 +22,6 @@ import ( "go.opentelemetry.io/contrib/otelconf/internal/provider" ) -const ( - compressionGzip = "gzip" - compressionNone = "none" -) - -type configOptions struct { - ctx context.Context - opentelemetryConfig OpenTelemetryConfiguration - loggerProviderOptions []sdklog.LoggerProviderOption - meterProviderOptions []sdkmetric.Option - tracerProviderOptions []sdktrace.TracerProviderOption -} - -type shutdownFunc func(context.Context) error - -func noopShutdown(context.Context) error { - return nil -} - // SDK is a struct that contains all the providers // configured via the configuration model. type SDK struct { @@ -190,27 +169,3 @@ func ParseYAML(file []byte) (*OpenTelemetryConfiguration, error) { return &cfg, nil } - -// createHeadersConfig combines the two header config fields. Headers take precedence over headersList. -func createHeadersConfig(headers []NameStringValuePair, headersList *string) (map[string]string, error) { - result := make(map[string]string) - if headersList != nil { - // Parsing follows https://github.com/open-telemetry/opentelemetry-configuration/blob/568e5080816d40d75792eb754fc96bde09654159/schema/type_descriptions.yaml#L584. - headerslist, err := baggage.Parse(*headersList) - if err != nil { - return nil, fmt.Errorf("invalid headers list: %w", err) - } - for _, kv := range headerslist.Members() { - result[kv.Key()] = kv.Value() - } - } - // Headers take precedence over HeadersList, so this has to be after HeadersList is processed - if len(headers) > 0 { - for _, kv := range headers { - if kv.Value != nil { - result[kv.Name] = *kv.Value - } - } - } - return result, nil -} diff --git a/otelconf/config_common.go b/otelconf/config_common.go index 5dd79d2c375..9d4e90eb259 100644 --- a/otelconf/config_common.go +++ b/otelconf/config_common.go @@ -52,8 +52,8 @@ var enumValuesOTLPMetricDefaultHistogramAggregation = []any{ type configOptions struct { ctx context.Context opentelemetryConfig OpenTelemetryConfiguration - meterProviderOptions []sdkmetric.Option loggerProviderOptions []sdklog.LoggerProviderOption + meterProviderOptions []sdkmetric.Option tracerProviderOptions []sdktrace.TracerProviderOption } diff --git a/otelconf/config_json.go b/otelconf/config_json.go index b0ffe7d0f9c..71b276d0d69 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -410,48 +410,6 @@ func (j *ExporterDefaultHistogramAggregation) UnmarshalJSON(b []byte) error { return nil } -// UnmarshalJSON implements json.Unmarshaler. -func (j *OTLPHttpMetricExporter) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["endpoint"]; raw != nil && !ok { - return errors.New("field endpoint in OTLPMetric: required") - } - type Plain OTLPHttpMetricExporter - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - if plain.Timeout != nil && 0 > *plain.Timeout { - return fmt.Errorf("field %s: must be >= %v", "timeout", 0) - } - *j = OTLPHttpMetricExporter(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *OTLPGrpcMetricExporter) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["endpoint"]; raw != nil && !ok { - return errors.New("field endpoint in OTLPMetric: required") - } - type Plain OTLPGrpcMetricExporter - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - if plain.Timeout != nil && 0 > *plain.Timeout { - return fmt.Errorf("field %s: must be >= %v", "timeout", 0) - } - *j = OTLPGrpcMetricExporter(plain) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { var raw map[string]any @@ -646,6 +604,8 @@ func (j *CardinalityLimits) UnmarshalJSON(value []byte) error { *j = CardinalityLimits(plain) return nil } + +// UnmarshalJSON implements json.Unmarshaler. func (j *PullMetricReader) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 885e8fec626..0c4a3f76b2a 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -1472,13 +1472,14 @@ func TestUnmarshalCardinalityLimits(t *testing.T) { }) } } + func TestCreateHeadersConfig(t *testing.T) { tests := []struct { name string headers []NameStringValuePair headersList *string wantHeaders map[string]string - wantErr string + wantErr error }{ { name: "no headers", @@ -1548,18 +1549,13 @@ func TestCreateHeadersConfig(t *testing.T) { { name: "invalid headerslist", headersList: ptr("==="), - wantErr: "invalid headers list: invalid key: \"\"", + wantErr: newErrInvalid("invalid headers_list"), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { headersMap, err := createHeadersConfig(tt.headers, tt.headersList) - if tt.wantErr != "" { - require.Error(t, err) - require.Equal(t, tt.wantErr, err.Error()) - } else { - require.NoError(t, err) - } + require.ErrorIs(t, err, tt.wantErr) require.Equal(t, tt.wantHeaders, headersMap) }) } diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 4b94b7278d1..c078d915007 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -255,6 +255,8 @@ func (j *BatchLogRecordProcessor) UnmarshalYAML(node *yaml.Node) error { *j = BatchLogRecordProcessor(plain) return nil } + +// UnmarshalYAML implements yaml.Unmarshaler. func (j *NameStringValuePair) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any if err := node.Decode(&raw); err != nil { diff --git a/otelconf/log.go b/otelconf/log.go index e79e79845c0..d5c6a2a9a10 100644 --- a/otelconf/log.go +++ b/otelconf/log.go @@ -23,8 +23,7 @@ import ( ) func loggerProvider(cfg configOptions, res *resource.Resource) (log.LoggerProvider, shutdownFunc, error) { - provider, ok := cfg.opentelemetryConfig.LoggerProvider.(*LoggerProviderJson) - if provider == nil { + if cfg.opentelemetryConfig.LoggerProvider == nil { return noop.NewLoggerProvider(), noopShutdown, nil } provider, ok := cfg.opentelemetryConfig.LoggerProvider.(*LoggerProviderJson) diff --git a/otelconf/metric.go b/otelconf/metric.go index 2a685c4a0a3..b6e12114401 100644 --- a/otelconf/metric.go +++ b/otelconf/metric.go @@ -40,8 +40,7 @@ var zeroScope instrumentation.Scope const instrumentKindUndefined = sdkmetric.InstrumentKind(0) func meterProvider(cfg configOptions, res *resource.Resource) (metric.MeterProvider, shutdownFunc, error) { - provider, ok := cfg.opentelemetryConfig.MeterProvider.(*MeterProviderJson) - if provider == nil { + if cfg.opentelemetryConfig.MeterProvider == nil { return noop.NewMeterProvider(), noopShutdown, nil } provider, ok := cfg.opentelemetryConfig.MeterProvider.(*MeterProviderJson) diff --git a/otelconf/trace.go b/otelconf/trace.go index 872b4048941..54638a742be 100644 --- a/otelconf/trace.go +++ b/otelconf/trace.go @@ -25,8 +25,7 @@ import ( var errInvalidSamplerConfiguration = newErrInvalid("sampler configuration") func tracerProvider(cfg configOptions, res *resource.Resource) (trace.TracerProvider, shutdownFunc, error) { - provider, ok := cfg.opentelemetryConfig.TracerProvider.(*TracerProviderJson) - if provider == nil { + if cfg.opentelemetryConfig.TracerProvider == nil { return noop.NewTracerProvider(), noopShutdown, nil } provider, ok := cfg.opentelemetryConfig.TracerProvider.(*TracerProviderJson) From c14fcc3f449ba5ff630e7c8ca7d4aa8dd63c90b7 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:22:59 -0700 Subject: [PATCH 33/39] re-enable tests with NewSDK Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_json.go | 46 ++------------------- otelconf/config_test.go | 90 +---------------------------------------- otelconf/log_test.go | 22 ++++------ otelconf/metric_test.go | 22 ++++------ otelconf/trace_test.go | 23 ++++------- 5 files changed, 30 insertions(+), 173 deletions(-) diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 71b276d0d69..4f0f02666b4 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -410,48 +410,6 @@ func (j *ExporterDefaultHistogramAggregation) UnmarshalJSON(b []byte) error { return nil } -// UnmarshalJSON implements json.Unmarshaler. -func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["endpoint"]; raw != nil && !ok { - return errors.New("field endpoint in OTLP: required") - } - type Plain OTLPHttpExporter - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - if plain.Timeout != nil && 0 > *plain.Timeout { - return fmt.Errorf("field %s: must be >= %v", "timeout", 0) - } - *j = OTLPHttpExporter(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *OTLPGrpcExporter) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["endpoint"]; raw != nil && !ok { - return errors.New("field endpoint in OTLP: required") - } - type Plain OTLPGrpcExporter - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - if plain.Timeout != nil && 0 > *plain.Timeout { - return fmt.Errorf("field %s: must be >= %v", "timeout", 0) - } - *j = OTLPGrpcExporter(plain) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { var raw map[string]any @@ -661,6 +619,7 @@ func (j *OTLPHttpMetricExporter) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *SimpleLogRecordProcessor) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { @@ -701,6 +660,8 @@ func (j *OTLPGrpcMetricExporter) UnmarshalJSON(b []byte) error { *j = OTLPGrpcMetricExporter(sh.Plain) return nil } + +// UnmarshalJSON implements json.Unmarshaler. func (j *SimpleSpanProcessor) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { @@ -772,6 +733,7 @@ func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON implements json.Unmarshaler. func (j *ZipkinSpanExporter) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 0c4a3f76b2a..f71a4767c23 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -1001,6 +1001,7 @@ func TestParseYAML(t *testing.T) { input: "v1.0.0_invalid_nil_name.yaml", wantErr: errors.New(`unmarshal error in *otelconf.BatchSpanProcessor unmarshal error in *otelconf.SpanExporter +unmarshal error in *otelconf.OTLPHttpExporter cannot unmarshal field name in NameStringValuePair required`), }, { @@ -1008,6 +1009,7 @@ cannot unmarshal field name in NameStringValuePair required`), input: "v1.0.0_invalid_nil_value.yaml", wantErr: errors.New(`unmarshal error in *otelconf.BatchLogRecordProcessor unmarshal error in *otelconf.LogRecordExporter +unmarshal error in *otelconf.OTLPHttpExporter cannot unmarshal field value in NameStringValuePair required`), }, { @@ -1561,94 +1563,6 @@ func TestCreateHeadersConfig(t *testing.T) { } } -func TestCreateHeadersConfig(t *testing.T) { - tests := []struct { - name string - headers []NameStringValuePair - headersList *string - wantHeaders map[string]string - wantErr error - }{ - { - name: "no headers", - headers: []NameStringValuePair{}, - headersList: nil, - wantHeaders: map[string]string{}, - }, - { - name: "headerslist only", - headers: []NameStringValuePair{}, - headersList: ptr("a=b,c=d"), - wantHeaders: map[string]string{ - "a": "b", - "c": "d", - }, - }, - { - name: "headers only", - headers: []NameStringValuePair{ - { - Name: "a", - Value: ptr("b"), - }, - { - Name: "c", - Value: ptr("d"), - }, - }, - headersList: nil, - wantHeaders: map[string]string{ - "a": "b", - "c": "d", - }, - }, - { - name: "both headers and headerslist", - headers: []NameStringValuePair{ - { - Name: "a", - Value: ptr("b"), - }, - }, - headersList: ptr("c=d"), - wantHeaders: map[string]string{ - "a": "b", - "c": "d", - }, - }, - { - name: "headers supersedes headerslist", - headers: []NameStringValuePair{ - { - Name: "a", - Value: ptr("b"), - }, - { - Name: "c", - Value: ptr("override"), - }, - }, - headersList: ptr("c=d"), - wantHeaders: map[string]string{ - "a": "b", - "c": "override", - }, - }, - { - name: "invalid headerslist", - headersList: ptr("==="), - wantErr: newErrInvalid("invalid headers_list"), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - headersMap, err := createHeadersConfig(tt.headers, tt.headersList) - require.ErrorIs(t, err, tt.wantErr) - require.Equal(t, tt.wantHeaders, headersMap) - }) - } -} - func TestUnmarshalSpanLimits(t *testing.T) { for _, tt := range []struct { name string diff --git a/otelconf/log_test.go b/otelconf/log_test.go index 9bb6119ed7a..11f72146c96 100644 --- a/otelconf/log_test.go +++ b/otelconf/log_test.go @@ -713,33 +713,27 @@ func TestLoggerProviderOptions(t *testing.T) { require.NoError(t, err) res := resource.NewSchemaless(attribute.String("foo", "bar")) - // TODO: re-enable this once NewSDK is added - // sdk, err := NewSDK( - // WithOpenTelemetryConfiguration(cfg), - // WithLoggerProviderOptions(sdklog.WithProcessor(sdklog.NewSimpleProcessor(stdoutlogExporter))), - // WithLoggerProviderOptions(sdklog.WithResource(res)), - // ) - lp, shutdown, err := loggerProvider(configOptions{ - opentelemetryConfig: cfg, - loggerProviderOptions: []sdklog.LoggerProviderOption{sdklog.WithProcessor(sdklog.NewSimpleProcessor(stdoutlogExporter))}, - }, res) + sdk, err := NewSDK( + WithOpenTelemetryConfiguration(cfg), + WithLoggerProviderOptions(sdklog.WithProcessor(sdklog.NewSimpleProcessor(stdoutlogExporter))), + WithLoggerProviderOptions(sdklog.WithResource(res)), + ) require.NoError(t, err) defer func() { - assert.NoError(t, shutdown(t.Context())) + assert.NoError(t, sdk.Shutdown(t.Context())) }() // The exporter, which we passed in as an extra option to NewSDK, // should be wired up to the provider in addition to the // configuration-based OTLP exporter. - logger := lp.Logger("test") + logger := sdk.LoggerProvider().Logger("test") logger.Emit(t.Context(), log.Record{}) assert.NotZero(t, buf) assert.Equal(t, 1, calls) // Options provided by WithMeterProviderOptions may be overridden // by configuration, e.g. the resource is always defined via // configuration. - // TODO: re-enable this once NewSDK is added - // assert.NotContains(t, buf.String(), "foo") + assert.NotContains(t, buf.String(), "foo") } func Test_otlpGRPCLogExporter(t *testing.T) { diff --git a/otelconf/metric_test.go b/otelconf/metric_test.go index 0a4b623a2ab..0dd8d0b2315 100644 --- a/otelconf/metric_test.go +++ b/otelconf/metric_test.go @@ -139,19 +139,14 @@ func TestMeterProviderOptions(t *testing.T) { require.NoError(t, err) res := resource.NewSchemaless(attribute.String("foo", "bar")) - // TODO: re-enable this once NewSDK is added - // sdk, err := NewSDK( - // WithOpenTelemetryConfiguration(cfg), - // WithMeterProviderOptions(sdkmetric.WithReader(sdkmetric.NewPeriodicReader(stdoutmetricExporter))), - // WithMeterProviderOptions(sdkmetric.WithResource(res)), - // ) - mp, shutdown, err := meterProvider(configOptions{ - opentelemetryConfig: cfg, - meterProviderOptions: []sdkmetric.Option{sdkmetric.WithReader(sdkmetric.NewPeriodicReader(stdoutmetricExporter))}, - }, res) + sdk, err := NewSDK( + WithOpenTelemetryConfiguration(cfg), + WithMeterProviderOptions(sdkmetric.WithReader(sdkmetric.NewPeriodicReader(stdoutmetricExporter))), + WithMeterProviderOptions(sdkmetric.WithResource(res)), + ) require.NoError(t, err) defer func() { - assert.NoError(t, shutdown(t.Context())) + assert.NoError(t, sdk.Shutdown(t.Context())) // The exporter, which we passed in as an extra option to NewSDK, // should be wired up to the provider in addition to the // configuration-based OTLP exporter. @@ -161,11 +156,10 @@ func TestMeterProviderOptions(t *testing.T) { // Options provided by WithMeterProviderOptions may be overridden // by configuration, e.g. the resource is always defined via // configuration. - // TODO: re-enable this once NewSDK is added - // assert.NotContains(t, buf.String(), "foo") + assert.NotContains(t, buf.String(), "foo") }() - counter, _ := mp.Meter("test").Int64Counter("counter") + counter, _ := sdk.MeterProvider().Meter("test").Int64Counter("counter") counter.Add(t.Context(), 1) } diff --git a/otelconf/trace_test.go b/otelconf/trace_test.go index 760a5d2fe19..5ebd34a76c9 100644 --- a/otelconf/trace_test.go +++ b/otelconf/trace_test.go @@ -157,26 +157,20 @@ func TestTracerProviderOptions(t *testing.T) { require.NoError(t, err) res := resource.NewSchemaless(attribute.String("foo", "bar")) - // TODO: re-enable this once NewSDK is added - // sdk, err := NewSDK( - // WithOpenTelemetryConfiguration(cfg), - // WithTracerProviderOptions(sdktrace.WithSyncer(stdouttraceExporter)), - // WithTracerProviderOptions(sdktrace.WithResource(res)), - // ) - tp, shutdown, err := tracerProvider(configOptions{ - ctx: t.Context(), - opentelemetryConfig: cfg, - tracerProviderOptions: []sdktrace.TracerProviderOption{sdktrace.WithSyncer(stdouttraceExporter)}, - }, res) + sdk, err := NewSDK( + WithOpenTelemetryConfiguration(cfg), + WithTracerProviderOptions(sdktrace.WithSyncer(stdouttraceExporter)), + WithTracerProviderOptions(sdktrace.WithResource(res)), + ) require.NoError(t, err) defer func() { - assert.NoError(t, shutdown(t.Context())) + assert.NoError(t, sdk.Shutdown(t.Context())) }() // The exporter, which we passed in as an extra option to NewSDK, // should be wired up to the provider in addition to the // configuration-based OTLP exporter. - tracer := tp.Tracer("test") + tracer := sdk.TracerProvider().Tracer("test") _, span := tracer.Start(t.Context(), "span") span.End() assert.NotZero(t, buf) @@ -184,8 +178,7 @@ func TestTracerProviderOptions(t *testing.T) { // Options provided by WithMeterProviderOptions may be overridden // by configuration, e.g. the resource is always defined via // configuration. - // TODO: re-enable this once NewSDK is added - // assert.NotContains(t, buf.String(), "foo") + assert.NotContains(t, buf.String(), "foo") } func TestSpanProcessor(t *testing.T) { From 8d05a1209ad378c2d2721a22c1f26733e4b48e4a Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 6 Nov 2025 13:12:07 -0800 Subject: [PATCH 34/39] clean up Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_common.go | 25 ----- otelconf/config_json.go | 229 +++----------------------------------- otelconf/config_test.go | 225 +++++++------------------------------ otelconf/config_yaml.go | 79 +++---------- 4 files changed, 72 insertions(+), 486 deletions(-) diff --git a/otelconf/config_common.go b/otelconf/config_common.go index 9d4e90eb259..c13755d0656 100644 --- a/otelconf/config_common.go +++ b/otelconf/config_common.go @@ -324,18 +324,6 @@ func supportedHistogramAggregation(in ExporterDefaultHistogramAggregation) error return newErrInvalid(fmt.Sprintf("invalid histogram aggregation (expected one of %#v): %#v", enumValuesOTLPMetricDefaultHistogramAggregation, in)) } -var enumValuesAttributeType = []any{ - nil, - "string", - "bool", - "int", - "double", - "string_array", - "bool_array", - "int_array", - "double_array", -} - // MarshalUnmarshaler combines marshal and unmarshal operations. type MarshalUnmarshaler interface { Marshal(v any) ([]byte, error) @@ -398,16 +386,3 @@ func setConfigDefaults(raw map[string]any, plain *OpenTelemetryConfiguration, co return nil } - -// validateStringField validates a string field is present and correct type. -func validateStringField(raw map[string]any, fieldName string) (string, error) { - v, ok := raw[fieldName] - if !ok { - return "", fmt.Errorf("cannot unmarshal field %s in NameStringValuePair required", fieldName) - } - str, ok := v.(string) - if !ok { - return "", fmt.Errorf("cannot unmarshal field %s in NameStringValuePair must be string", fieldName) - } - return str, nil -} diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 4f0f02666b4..11efc7612d1 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -199,28 +199,6 @@ func (j *AttributeType) MarshalJSON() ([]byte, error) { return json.Marshal(j.Value) } -// UnmarshalJSON implements json.Unmarshaler. -func (j *AttributeType) UnmarshalJSON(b []byte) error { - var v struct { - Value any - } - if err := json.Unmarshal(b, &v.Value); err != nil { - return err - } - var ok bool - for _, expected := range enumValuesAttributeType { - if reflect.DeepEqual(v.Value, expected) { - ok = true - break - } - } - if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesAttributeType, v.Value) - } - *j = AttributeType(v) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *TextMapPropagator) UnmarshalJSON(b []byte) error { type Plain TextMapPropagator @@ -340,81 +318,11 @@ func (j *BatchSpanProcessor) UnmarshalJSON(b []byte) error { return nil } -// UnmarshalJSON implements json.Unmarshaler. -func (j *ExperimentalPeerInstrumentationServiceMappingElem) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["peer"]; raw != nil && !ok { - return errors.New("field peer in ExperimentalPeerInstrumentationServiceMappingElem: required") - } - if _, ok := raw["service"]; raw != nil && !ok { - return errors.New("field service in ExperimentalPeerInstrumentationServiceMappingElem: required") - } - type Plain ExperimentalPeerInstrumentationServiceMappingElem - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = ExperimentalPeerInstrumentationServiceMappingElem(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *NameStringValuePair) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - - name, err := validateStringField(raw, "name") - if err != nil { - return err - } - - value, err := validateStringField(raw, "value") - if err != nil { - return err - } - - *j = NameStringValuePair{ - Name: name, - Value: &value, - } - return nil -} - -var enumValuesOTLPMetricDefaultHistogramAggregation = []any{ - "explicit_bucket_histogram", - "base2_exponential_bucket_histogram", -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *ExporterDefaultHistogramAggregation) UnmarshalJSON(b []byte) error { - var v string - if err := json.Unmarshal(b, &v); err != nil { - return err - } - var ok bool - for _, expected := range enumValuesOTLPMetricDefaultHistogramAggregation { - if reflect.DeepEqual(v, expected) { - ok = true - break - } - } - if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesOTLPMetricDefaultHistogramAggregation, v) - } - *j = ExporterDefaultHistogramAggregation(v) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } if _, ok := raw["file_format"]; raw != nil && !ok { return errors.New("field file_format in OpenTelemetryConfiguration: required") @@ -425,11 +333,11 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { if v, ok := raw["logger_provider"]; ok && v != nil { marshaled, err := json.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var lp LoggerProviderJson if err := json.Unmarshal(marshaled, &lp); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.LoggerProvider = &lp } @@ -437,12 +345,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { if v, ok := raw["meter_provider"]; ok && v != nil { marshaled, err := json.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var mp MeterProviderJson if err := json.Unmarshal(marshaled, &mp); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.MeterProvider = &mp } @@ -450,12 +358,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { if v, ok := raw["tracer_provider"]; ok && v != nil { marshaled, err := json.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var tp TracerProviderJson if err := json.Unmarshal(marshaled, &tp); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.TracerProvider = &tp } @@ -463,12 +371,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { if v, ok := raw["propagator"]; ok && v != nil { marshaled, err := json.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var p PropagatorJson if err := json.Unmarshal(marshaled, &p); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.Propagator = &p } @@ -476,12 +384,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { if v, ok := raw["resource"]; ok && v != nil { marshaled, err := json.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var r ResourceJson if err := json.Unmarshal(marshaled, &r); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.Resource = &r } @@ -489,12 +397,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { if v, ok := raw["instrumentation/development"]; ok && v != nil { marshaled, err := json.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var i InstrumentationJson if err := json.Unmarshal(marshaled, &i); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.InstrumentationDevelopment = &i } @@ -502,19 +410,19 @@ func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { if v, ok := raw["attribute_limits"]; ok && v != nil { marshaled, err := json.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var a AttributeLimits if err := json.Unmarshal(marshaled, &a); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.AttributeLimits = &a } plainConfig := (*OpenTelemetryConfiguration)(&plain) if err := setConfigDefaults(raw, plainConfig, jsonCodec{}); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.FileFormat = fmt.Sprintf("%v", raw["file_format"]) @@ -563,24 +471,6 @@ func (j *CardinalityLimits) UnmarshalJSON(value []byte) error { return nil } -// UnmarshalJSON implements json.Unmarshaler. -func (j *PullMetricReader) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["exporter"]; raw != nil && !ok { - return errors.New("field exporter in PullMetricReader: required") - } - type Plain PullMetricReader - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = PullMetricReader(plain) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *SpanLimits) UnmarshalJSON(value []byte) error { type Plain SpanLimits @@ -619,24 +509,6 @@ func (j *OTLPHttpMetricExporter) UnmarshalJSON(b []byte) error { return nil } -// UnmarshalJSON implements json.Unmarshaler. -func (j *SimpleLogRecordProcessor) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["exporter"]; raw != nil && !ok { - return errors.New("field exporter in SimpleLogRecordProcessor: required") - } - type Plain SimpleLogRecordProcessor - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = SimpleLogRecordProcessor(plain) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *OTLPGrpcMetricExporter) UnmarshalJSON(b []byte) error { type Plain OTLPGrpcMetricExporter @@ -661,54 +533,6 @@ func (j *OTLPGrpcMetricExporter) UnmarshalJSON(b []byte) error { return nil } -// UnmarshalJSON implements json.Unmarshaler. -func (j *SimpleSpanProcessor) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["exporter"]; raw != nil && !ok { - return errors.New("field exporter in SimpleSpanProcessor: required") - } - type Plain SimpleSpanProcessor - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = SimpleSpanProcessor(plain) - return nil -} - -var enumValuesViewSelectorInstrumentType = []any{ - "counter", - "gauge", - "histogram", - "observable_counter", - "observable_gauge", - "observable_up_down_counter", - "up_down_counter", -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *InstrumentType) UnmarshalJSON(b []byte) error { - var v string - if err := json.Unmarshal(b, &v); err != nil { - return err - } - var ok bool - for _, expected := range enumValuesViewSelectorInstrumentType { - if reflect.DeepEqual(v, expected) { - ok = true - break - } - } - if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesViewSelectorInstrumentType, v) - } - *j = InstrumentType(v) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { type Plain OTLPHttpExporter @@ -733,27 +557,6 @@ func (j *OTLPHttpExporter) UnmarshalJSON(b []byte) error { return nil } -// UnmarshalJSON implements json.Unmarshaler. -func (j *ZipkinSpanExporter) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if _, ok := raw["endpoint"]; raw != nil && !ok { - return errors.New("field endpoint in ZipkinSpanExporter: required") - } - type Plain ZipkinSpanExporter - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - if plain.Timeout != nil && 0 > *plain.Timeout { - return fmt.Errorf("field %s: must be >= %v", "timeout", 0) - } - *j = ZipkinSpanExporter(plain) - return nil -} - // UnmarshalJSON implements json.Unmarshaler. func (j *OTLPGrpcExporter) UnmarshalJSON(b []byte) error { type Plain OTLPGrpcExporter diff --git a/otelconf/config_test.go b/otelconf/config_test.go index f71a4767c23..8cd3158217b 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -5,7 +5,7 @@ package otelconf import ( "encoding/json" - "errors" + "fmt" "os" "path/filepath" "testing" @@ -973,16 +973,16 @@ var v100OpenTelemetryConfigEnvParsing = OpenTelemetryConfiguration{ }, } -func TestParseYAML(t *testing.T) { +func TestUnmarshalOpenTelemetryConfiguration(t *testing.T) { tests := []struct { name string input string wantErr error - wantType any + wantType *OpenTelemetryConfiguration }{ { - name: "valid YAML config", - input: `valid_empty.yaml`, + name: "valid empty config", + input: `valid_empty`, wantErr: nil, wantType: &OpenTelemetryConfiguration{ Disabled: ptr(false), @@ -991,61 +991,62 @@ func TestParseYAML(t *testing.T) { }, }, { - name: "invalid config", - input: "invalid_bool.yaml", - wantErr: errors.New(`yaml: unmarshal errors: - line 1: cannot unmarshal !!str ` + "`notabool`" + ` into bool`), + name: "invalid config", + input: "invalid_bool", + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + wantType: &OpenTelemetryConfiguration{}, }, { - name: "invalid nil name", - input: "v1.0.0_invalid_nil_name.yaml", - wantErr: errors.New(`unmarshal error in *otelconf.BatchSpanProcessor -unmarshal error in *otelconf.SpanExporter -unmarshal error in *otelconf.OTLPHttpExporter -cannot unmarshal field name in NameStringValuePair required`), + name: "invalid nil name", + input: "v1.0.0_invalid_nil_name", + wantErr: newErrRequired(&NameStringValuePair{}, "name"), + wantType: &OpenTelemetryConfiguration{}, }, { - name: "invalid nil value", - input: "v1.0.0_invalid_nil_value.yaml", - wantErr: errors.New(`unmarshal error in *otelconf.BatchLogRecordProcessor -unmarshal error in *otelconf.LogRecordExporter -unmarshal error in *otelconf.OTLPHttpExporter -cannot unmarshal field value in NameStringValuePair required`), + name: "invalid nil value", + input: "v1.0.0_invalid_nil_value", + wantErr: newErrRequired(&NameStringValuePair{}, "value"), + wantType: &OpenTelemetryConfiguration{}, }, { - name: "valid v0.2 config", - input: "v0.2.yaml", - wantErr: errors.New(`yaml: unmarshal errors: - line 64: cannot unmarshal !!seq into otelconf.IncludeExclude`), + name: "valid v0.2 config", + input: "v0.2", + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + wantType: &OpenTelemetryConfiguration{}, }, { - name: "valid v0.3 config", - input: "v0.3.yaml", - wantErr: errors.New(`unmarshal error in *otelconf.TextMapPropagator -yaml: unmarshal errors: - line 2: cannot unmarshal !!str` + " `traceco...`" + ` into otelconf.Plain`), + name: "valid v0.3 config", + input: "v0.3", + wantErr: newErrUnmarshal(&TextMapPropagator{}), + wantType: &OpenTelemetryConfiguration{}, }, { name: "valid v1.0.0 config", - input: "v1.0.0.yaml", + input: "v1.0.0", wantType: &v10OpenTelemetryConfig, }, } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - b, err := os.ReadFile(filepath.Join("testdata", tt.input)) + t.Run("yaml:"+tt.name, func(t *testing.T) { + b, err := os.ReadFile(filepath.Join("testdata", fmt.Sprintf("%s.yaml", tt.input))) require.NoError(t, err) got, err := ParseYAML(b) - if tt.wantErr != nil { - require.Error(t, err) - require.Equal(t, tt.wantErr.Error(), err.Error()) - } else { - require.NoError(t, err) + require.ErrorIs(t, err, tt.wantErr) + if tt.wantErr == nil { assert.Equal(t, tt.wantType, got) } }) + t.Run("json: "+tt.name, func(t *testing.T) { + b, err := os.ReadFile(filepath.Join("testdata", fmt.Sprintf("%s.json", tt.input))) + require.NoError(t, err) + + var got OpenTelemetryConfiguration + err = json.Unmarshal(b, &got) + require.ErrorIs(t, err, tt.wantErr) + assert.Equal(t, tt.wantType, &got) + }) } } @@ -1193,74 +1194,6 @@ func TestParseYAMLWithEnvironmentVariables(t *testing.T) { } } -func TestSerializeJSON(t *testing.T) { - tests := []struct { - name string - input string - wantErr error - wantType any - }{ - { - name: "valid JSON config", - input: `valid_empty.json`, - wantErr: nil, - wantType: OpenTelemetryConfiguration{ - Disabled: ptr(false), - FileFormat: "0.1", - LogLevel: ptr("info"), - }, - }, - { - name: "invalid config", - input: "invalid_bool.json", - wantErr: errors.New(`json: cannot unmarshal string into Go value of type bool`), - }, - { - name: "invalid nil name", - input: "v1.0.0_invalid_nil_name.json", - wantErr: errors.New(`cannot unmarshal field name in NameStringValuePair required`), - }, - { - name: "invalid nil value", - input: "v1.0.0_invalid_nil_value.json", - wantErr: errors.New(`cannot unmarshal field value in NameStringValuePair required`), - }, - { - name: "valid v0.2 config", - input: "v0.2.json", - wantErr: errors.New(`json: cannot unmarshal array into Go struct field`), - }, - { - name: "valid v0.3 config", - input: "v0.3.json", - wantErr: errors.New(`unmarshal error in *otelconf.TextMapPropagator`), - }, - { - name: "valid v1.0.0 config", - input: "v1.0.0.json", - wantType: v10OpenTelemetryConfig, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - b, err := os.ReadFile(filepath.Join("testdata", tt.input)) - require.NoError(t, err) - - var got OpenTelemetryConfiguration - err = json.Unmarshal(b, &got) - - if tt.wantErr != nil { - require.Error(t, err) - require.ErrorContains(t, err, tt.wantErr.Error()) - } else { - require.NoError(t, err) - assert.Equal(t, tt.wantType, got) - } - }) - } -} - func TestUnmarshalPeriodicMetricReader(t *testing.T) { for _, tt := range []struct { name string @@ -2280,83 +2213,3 @@ func TestUnmarshalPullMetricReader(t *testing.T) { }) } } - -func TestUnmarshalSpanLimits(t *testing.T) { - for _, tt := range []struct { - name string - yamlConfig []byte - jsonConfig []byte - wantErr string - }{ - { - name: "valid with all fields positive", - jsonConfig: []byte(`{"attribute_count_limit":100,"attribute_value_length_limit":200,"event_attribute_count_limit":300,"event_count_limit":400,"link_attribute_count_limit":500,"link_count_limit":600}`), - yamlConfig: []byte("attribute_count_limit: 100\nattribute_value_length_limit: 200\nevent_attribute_count_limit: 300\nevent_count_limit: 400\nlink_attribute_count_limit: 500\nlink_count_limit: 600"), - }, - { - name: "valid with single field", - jsonConfig: []byte(`{"attribute_value_length_limit":2000}`), - yamlConfig: []byte("attribute_value_length_limit: 2000"), - }, - { - name: "valid empty", - jsonConfig: []byte(`{}`), - yamlConfig: []byte("{}"), - }, - { - name: "invalid attribute_count_limit negative", - jsonConfig: []byte(`{"attribute_count_limit":-1}`), - yamlConfig: []byte("attribute_count_limit: -1"), - wantErr: "field attribute_count_limit: must be >= 0", - }, - { - name: "invalid attribute_value_length_limit negative", - jsonConfig: []byte(`{"attribute_value_length_limit":-1}`), - yamlConfig: []byte("attribute_value_length_limit: -1"), - wantErr: "field attribute_value_length_limit: must be >= 0", - }, - { - name: "invalid event_attribute_count_limit negative", - jsonConfig: []byte(`{"event_attribute_count_limit":-1}`), - yamlConfig: []byte("event_attribute_count_limit: -1"), - wantErr: "field event_attribute_count_limit: must be >= 0", - }, - { - name: "invalid event_count_limit negative", - jsonConfig: []byte(`{"event_count_limit":-1}`), - yamlConfig: []byte("event_count_limit: -1"), - wantErr: "field event_count_limit: must be >= 0", - }, - { - name: "invalid link_attribute_count_limit negative", - jsonConfig: []byte(`{"link_attribute_count_limit":-1}`), - yamlConfig: []byte("link_attribute_count_limit: -1"), - wantErr: "field link_attribute_count_limit: must be >= 0", - }, - { - name: "invalid link_count_limit negative", - jsonConfig: []byte(`{"link_count_limit":-1}`), - yamlConfig: []byte("link_count_limit: -1"), - wantErr: "field link_count_limit: must be >= 0", - }, - } { - t.Run(tt.name, func(t *testing.T) { - cl := SpanLimits{} - err := cl.UnmarshalJSON(tt.jsonConfig) - if tt.wantErr != "" { - require.Error(t, err) - require.Contains(t, err.Error(), tt.wantErr) - } else { - require.NoError(t, err) - } - cl = SpanLimits{} - err = yaml.Unmarshal(tt.yamlConfig, &cl) - if tt.wantErr != "" { - require.Error(t, err) - require.Contains(t, err.Error(), tt.wantErr) - } else { - require.NoError(t, err) - } - }) - } -} diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index c078d915007..145b0b3a596 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -46,7 +46,7 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any if err := node.Decode(&raw); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } type Plain OpenTelemetryConfiguration @@ -55,11 +55,11 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { if v, ok := raw["logger_provider"]; ok && v != nil { marshaled, err := yaml.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var lp LoggerProviderJson if err := yaml.Unmarshal(marshaled, &lp); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.LoggerProvider = &lp } @@ -67,12 +67,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { if v, ok := raw["meter_provider"]; ok && v != nil { marshaled, err := yaml.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var mp MeterProviderJson if err := yaml.Unmarshal(marshaled, &mp); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.MeterProvider = &mp } @@ -80,12 +80,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { if v, ok := raw["tracer_provider"]; ok && v != nil { marshaled, err := yaml.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var tp TracerProviderJson if err := yaml.Unmarshal(marshaled, &tp); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.TracerProvider = &tp } @@ -93,12 +93,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { if v, ok := raw["propagator"]; ok && v != nil { marshaled, err := yaml.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var p PropagatorJson if err := yaml.Unmarshal(marshaled, &p); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.Propagator = &p } @@ -106,12 +106,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { if v, ok := raw["resource"]; ok && v != nil { marshaled, err := yaml.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var r ResourceJson if err := yaml.Unmarshal(marshaled, &r); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.Resource = &r } @@ -119,12 +119,12 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { if v, ok := raw["instrumentation/development"]; ok && v != nil { marshaled, err := yaml.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var i InstrumentationJson if err := yaml.Unmarshal(marshaled, &i); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.InstrumentationDevelopment = &i } @@ -132,19 +132,19 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { if v, ok := raw["attribute_limits"]; ok && v != nil { marshaled, err := yaml.Marshal(v) if err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } var a AttributeLimits if err := yaml.Unmarshal(marshaled, &a); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.AttributeLimits = &a } plainConfig := (*OpenTelemetryConfiguration)(&plain) if err := setConfigDefaults(raw, plainConfig, yamlCodec{}); err != nil { - return err + return errors.Join(newErrUnmarshal(j), err) } plain.FileFormat = fmt.Sprintf("%v", raw["file_format"]) @@ -152,28 +152,6 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { return nil } -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *AttributeType) UnmarshalYAML(node *yaml.Node) error { - var v struct { - Value any - } - if err := node.Decode(&v.Value); err != nil { - return err - } - var ok bool - for _, expected := range enumValuesAttributeType { - if reflect.DeepEqual(v.Value, expected) { - ok = true - break - } - } - if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValuesAttributeType, v.Value) - } - *j = AttributeType(v) - return nil -} - // UnmarshalYAML implements yaml.Unmarshaler. func (j *SpanExporter) UnmarshalYAML(node *yaml.Node) error { type Plain SpanExporter @@ -256,30 +234,6 @@ func (j *BatchLogRecordProcessor) UnmarshalYAML(node *yaml.Node) error { return nil } -// UnmarshalYAML implements yaml.Unmarshaler. -func (j *NameStringValuePair) UnmarshalYAML(node *yaml.Node) error { - var raw map[string]any - if err := node.Decode(&raw); err != nil { - return err - } - - name, err := validateStringField(raw, "name") - if err != nil { - return err - } - - value, err := validateStringField(raw, "value") - if err != nil { - return err - } - - *j = NameStringValuePair{ - Name: name, - Value: &value, - } - return nil -} - // UnmarshalYAML implements yaml.Unmarshaler. func (j *Sampler) UnmarshalYAML(node *yaml.Node) error { var raw map[string]any @@ -633,6 +587,7 @@ func (j *PullMetricReader) UnmarshalYAML(node *yaml.Node) error { return nil } +// UnmarshalYAML implements yaml.Unmarshaler. func (j *ExperimentalLanguageSpecificInstrumentation) UnmarshalYAML(unmarshal func(any) error) error { var raw map[string]any if err := unmarshal(&raw); err != nil { From 2714a67bf6965d8206f67e8b05c26979cd704227 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 6 Nov 2025 14:44:55 -0800 Subject: [PATCH 35/39] update tests Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/config_common.go | 65 ---------- otelconf/config_json.go | 130 ++++++++++--------- otelconf/config_test.go | 19 ++- otelconf/config_yaml.go | 138 +++++++-------------- otelconf/testdata/invalid_file_format.json | 1 + otelconf/testdata/invalid_file_format.yaml | 2 + otelconf/testdata/missing_file_format.json | 1 + otelconf/testdata/missing_file_format.yaml | 1 + otelconf/testdata/valid_defaults.json | 1 + otelconf/testdata/valid_defaults.yaml | 1 + 10 files changed, 131 insertions(+), 228 deletions(-) create mode 100644 otelconf/testdata/invalid_file_format.json create mode 100644 otelconf/testdata/invalid_file_format.yaml create mode 100644 otelconf/testdata/missing_file_format.json create mode 100644 otelconf/testdata/missing_file_format.yaml create mode 100644 otelconf/testdata/valid_defaults.json create mode 100644 otelconf/testdata/valid_defaults.yaml diff --git a/otelconf/config_common.go b/otelconf/config_common.go index c13755d0656..bb304e07958 100644 --- a/otelconf/config_common.go +++ b/otelconf/config_common.go @@ -5,7 +5,6 @@ package otelconf // import "go.opentelemetry.io/contrib/otelconf" import ( "context" - "encoding/json" "errors" "fmt" "reflect" @@ -14,7 +13,6 @@ import ( sdklog "go.opentelemetry.io/otel/sdk/log" sdkmetric "go.opentelemetry.io/otel/sdk/metric" sdktrace "go.opentelemetry.io/otel/sdk/trace" - yaml "go.yaml.in/yaml/v3" ) const ( @@ -323,66 +321,3 @@ func supportedHistogramAggregation(in ExporterDefaultHistogramAggregation) error } return newErrInvalid(fmt.Sprintf("invalid histogram aggregation (expected one of %#v): %#v", enumValuesOTLPMetricDefaultHistogramAggregation, in)) } - -// MarshalUnmarshaler combines marshal and unmarshal operations. -type MarshalUnmarshaler interface { - Marshal(v any) ([]byte, error) - Unmarshal(data []byte, v any) error -} - -// jsonCodec implements MarshalUnmarshaler for JSON. -type jsonCodec struct{} - -func (jsonCodec) Marshal(v any) ([]byte, error) { - return json.Marshal(v) -} - -func (jsonCodec) Unmarshal(data []byte, v any) error { - return json.Unmarshal(data, v) -} - -// yamlCodec implements MarshalUnmarshaler for YAML. -type yamlCodec struct{} - -func (yamlCodec) Marshal(v any) ([]byte, error) { - return yaml.Marshal(v) -} - -func (yamlCodec) Unmarshal(data []byte, v any) error { - return yaml.Unmarshal(data, v) -} - -// setConfigDefaults sets default values for disabled and log_level. -func setConfigDefaults(raw map[string]any, plain *OpenTelemetryConfiguration, codec MarshalUnmarshaler) error { - // Configure if the SDK is disabled or not. - // If omitted or null, false is used. - plain.Disabled = ptr(false) - if v, ok := raw["disabled"]; ok && v != nil { - marshaled, err := codec.Marshal(v) - if err != nil { - return err - } - var disabled bool - if err := codec.Unmarshal(marshaled, &disabled); err != nil { - return err - } - plain.Disabled = &disabled - } - - // Configure the log level of the internal logger used by the SDK. - // If omitted, info is used. - plain.LogLevel = ptr("info") - if v, ok := raw["log_level"]; ok && v != nil { - marshaled, err := codec.Marshal(v) - if err != nil { - return err - } - var logLevel string - if err := codec.Unmarshal(marshaled, &logLevel); err != nil { - return err - } - plain.LogLevel = &logLevel - } - - return nil -} diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 11efc7612d1..495cd16e386 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -320,114 +320,110 @@ func (j *BatchSpanProcessor) UnmarshalJSON(b []byte) error { // UnmarshalJSON implements json.Unmarshaler. func (j *OpenTelemetryConfiguration) UnmarshalJSON(b []byte) error { - var raw map[string]any - if err := json.Unmarshal(b, &raw); err != nil { - return errors.Join(newErrUnmarshal(j), err) + type Plain OpenTelemetryConfiguration + type shadow struct { + Plain + FileFormat json.RawMessage `json:"file_format"` + LoggerProvider json.RawMessage `json:"logger_provider"` + MeterProvider json.RawMessage `json:"meter_provider"` + TracerProvider json.RawMessage `json:"tracer_provider"` + Propagator json.RawMessage `json:"propagator"` + Resource json.RawMessage `json:"resource"` + InstrumentationDevelopment json.RawMessage `json:"instrumentation/development"` + AttributeLimits json.RawMessage `json:"attribute_limits"` + Disabled json.RawMessage `json:"disabled"` + LogLevel json.RawMessage `json:"log_level"` } - if _, ok := raw["file_format"]; raw != nil && !ok { - return errors.New("field file_format in OpenTelemetryConfiguration: required") + var sh shadow + if err := json.Unmarshal(b, &sh); err != nil { + return errors.Join(newErrUnmarshal(j), err) } - type Plain OpenTelemetryConfiguration - var plain Plain - if v, ok := raw["logger_provider"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - var lp LoggerProviderJson - if err := json.Unmarshal(marshaled, &lp); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.LoggerProvider = &lp + if len(sh.FileFormat) == 0 { + return newErrRequired(j, "file_format") } - if v, ok := raw["meter_provider"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - - var mp MeterProviderJson - if err := json.Unmarshal(marshaled, &mp); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.MeterProvider = &mp + if err := json.Unmarshal(sh.FileFormat, &sh.Plain.FileFormat); err != nil { + return errors.Join(newErrUnmarshal(j), err) } - if v, ok := raw["tracer_provider"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { + if sh.LoggerProvider != nil { + var l LoggerProviderJson + if err := json.Unmarshal(sh.LoggerProvider, &l); err != nil { return errors.Join(newErrUnmarshal(j), err) } + sh.Plain.LoggerProvider = &l + } - var tp TracerProviderJson - if err := json.Unmarshal(marshaled, &tp); err != nil { + if sh.MeterProvider != nil { + var m MeterProviderJson + if err := json.Unmarshal(sh.MeterProvider, &m); err != nil { return errors.Join(newErrUnmarshal(j), err) } - plain.TracerProvider = &tp + sh.Plain.MeterProvider = &m } - if v, ok := raw["propagator"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { + if sh.TracerProvider != nil { + var t TracerProviderJson + if err := json.Unmarshal(sh.TracerProvider, &t); err != nil { return errors.Join(newErrUnmarshal(j), err) } + sh.Plain.TracerProvider = &t + } + if sh.Propagator != nil { var p PropagatorJson - if err := json.Unmarshal(marshaled, &p); err != nil { + if err := json.Unmarshal(sh.Propagator, &p); err != nil { return errors.Join(newErrUnmarshal(j), err) } - plain.Propagator = &p + sh.Plain.Propagator = &p } - if v, ok := raw["resource"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - + if sh.Resource != nil { var r ResourceJson - if err := json.Unmarshal(marshaled, &r); err != nil { + if err := json.Unmarshal(sh.Resource, &r); err != nil { return errors.Join(newErrUnmarshal(j), err) } - plain.Resource = &r + sh.Plain.Resource = &r } - if v, ok := raw["instrumentation/development"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { + if sh.InstrumentationDevelopment != nil { + var r InstrumentationJson + if err := json.Unmarshal(sh.InstrumentationDevelopment, &r); err != nil { return errors.Join(newErrUnmarshal(j), err) } + sh.Plain.InstrumentationDevelopment = &r + } - var i InstrumentationJson - if err := json.Unmarshal(marshaled, &i); err != nil { + if sh.AttributeLimits != nil { + var r AttributeLimits + if err := json.Unmarshal(sh.AttributeLimits, &r); err != nil { return errors.Join(newErrUnmarshal(j), err) } - plain.InstrumentationDevelopment = &i + sh.Plain.AttributeLimits = &r } - if v, ok := raw["attribute_limits"]; ok && v != nil { - marshaled, err := json.Marshal(v) - if err != nil { + if sh.Disabled != nil { + if err := json.Unmarshal(sh.Disabled, &sh.Plain.Disabled); err != nil { return errors.Join(newErrUnmarshal(j), err) } + } else { + // Configure if the SDK is disabled or not. + // If omitted or null, false is used. + sh.Plain.Disabled = ptr(false) + } - var a AttributeLimits - if err := json.Unmarshal(marshaled, &a); err != nil { + if sh.LogLevel != nil { + if err := json.Unmarshal(sh.LogLevel, &sh.Plain.LogLevel); err != nil { return errors.Join(newErrUnmarshal(j), err) } - plain.AttributeLimits = &a - } - - plainConfig := (*OpenTelemetryConfiguration)(&plain) - if err := setConfigDefaults(raw, plainConfig, jsonCodec{}); err != nil { - return errors.Join(newErrUnmarshal(j), err) + } else { + // Configure the log level of the internal logger used by the SDK. + // If omitted, info is used. + sh.Plain.LogLevel = ptr("info") } - plain.FileFormat = fmt.Sprintf("%v", raw["file_format"]) - - *j = OpenTelemetryConfiguration(plain) + *j = OpenTelemetryConfiguration(sh.Plain) return nil } diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 8cd3158217b..03b624ab3d4 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -981,12 +981,23 @@ func TestUnmarshalOpenTelemetryConfiguration(t *testing.T) { wantType *OpenTelemetryConfiguration }{ { - name: "valid empty config", - input: `valid_empty`, - wantErr: nil, + name: "invalid config missing required file_format", + input: `missing_file_format`, + wantErr: newErrRequired(&OpenTelemetryConfiguration{}, "file_format"), + wantType: &OpenTelemetryConfiguration{}, + }, + { + name: "file_format invalid", + input: `invalid_file_format`, + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + wantType: &OpenTelemetryConfiguration{}, + }, + { + name: "valid defaults config", + input: `valid_defaults`, wantType: &OpenTelemetryConfiguration{ Disabled: ptr(false), - FileFormat: "0.1", + FileFormat: "1.0", LogLevel: ptr("info"), }, }, diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index 145b0b3a596..e2630735c71 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -43,112 +43,66 @@ func (j *PushMetricExporter) UnmarshalYAML(node *yaml.Node) error { // UnmarshalYAML implements yaml.Unmarshaler. func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { - var raw map[string]any - - if err := node.Decode(&raw); err != nil { - return errors.Join(newErrUnmarshal(j), err) + if !hasYAMLMapKey(node, "file_format") { + return newErrRequired(j, "file_format") } - type Plain OpenTelemetryConfiguration - var plain Plain - - if v, ok := raw["logger_provider"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - var lp LoggerProviderJson - if err := yaml.Unmarshal(marshaled, &lp); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.LoggerProvider = &lp + type shadow struct { + Plain + AttributeLimits *AttributeLimits `yaml:"attribute_limits,omitempty"` + Disabled *bool `yaml:"disabled,omitempty"` + FileFormat string `yaml:"file_format"` + LoggerProvider *LoggerProviderJson `yaml:"logger_provider,omitempty"` + MeterProvider *MeterProviderJson `yaml:"meter_provider,omitempty"` + TracerProvider *TracerProviderJson `yaml:"tracer_provider,omitempty"` + Propagator *PropagatorJson `yaml:"propagator,omitempty"` + Resource *ResourceJson `yaml:"resource,omitempty"` + InstrumentationDevelopment *InstrumentationJson `yaml:"instrumentation/development"` + } + var sh shadow + + if err := node.Decode(&sh); err != nil { + return errors.Join(newErrUnmarshal(j), err) } - if v, ok := raw["meter_provider"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - - var mp MeterProviderJson - if err := yaml.Unmarshal(marshaled, &mp); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.MeterProvider = &mp + if sh.AttributeLimits != nil { + sh.Plain.AttributeLimits = sh.AttributeLimits } - if v, ok := raw["tracer_provider"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - - var tp TracerProviderJson - if err := yaml.Unmarshal(marshaled, &tp); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.TracerProvider = &tp + sh.Plain.FileFormat = sh.FileFormat + if sh.Disabled != nil { + sh.Plain.Disabled = sh.Disabled + } else { + // Configure the log level of the internal logger used by the SDK. + // If omitted, info is used. + sh.Plain.Disabled = ptr(false) } - - if v, ok := raw["propagator"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - - var p PropagatorJson - if err := yaml.Unmarshal(marshaled, &p); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.Propagator = &p + if sh.LoggerProvider != nil { + sh.Plain.LoggerProvider = sh.LoggerProvider } - - if v, ok := raw["resource"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - - var r ResourceJson - if err := yaml.Unmarshal(marshaled, &r); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.Resource = &r + if sh.MeterProvider != nil { + sh.Plain.MeterProvider = sh.MeterProvider } - - if v, ok := raw["instrumentation/development"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - - var i InstrumentationJson - if err := yaml.Unmarshal(marshaled, &i); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.InstrumentationDevelopment = &i + if sh.TracerProvider != nil { + sh.Plain.TracerProvider = sh.TracerProvider } - - if v, ok := raw["attribute_limits"]; ok && v != nil { - marshaled, err := yaml.Marshal(v) - if err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - - var a AttributeLimits - if err := yaml.Unmarshal(marshaled, &a); err != nil { - return errors.Join(newErrUnmarshal(j), err) - } - plain.AttributeLimits = &a + if sh.Propagator != nil { + sh.Plain.Propagator = sh.Propagator + } + if sh.Resource != nil { + sh.Plain.Resource = sh.Resource + } + if sh.InstrumentationDevelopment != nil { + sh.Plain.InstrumentationDevelopment = sh.InstrumentationDevelopment } - plainConfig := (*OpenTelemetryConfiguration)(&plain) - if err := setConfigDefaults(raw, plainConfig, yamlCodec{}); err != nil { - return errors.Join(newErrUnmarshal(j), err) + if sh.Plain.LogLevel == nil { + // Configure the log level of the internal logger used by the SDK. + // If omitted, info is used. + sh.Plain.LogLevel = ptr("info") } - plain.FileFormat = fmt.Sprintf("%v", raw["file_format"]) - *j = *plainConfig + *j = OpenTelemetryConfiguration(sh.Plain) return nil } diff --git a/otelconf/testdata/invalid_file_format.json b/otelconf/testdata/invalid_file_format.json new file mode 100644 index 00000000000..78040798c6a --- /dev/null +++ b/otelconf/testdata/invalid_file_format.json @@ -0,0 +1 @@ +{"file_format":[], "disabled": false} \ No newline at end of file diff --git a/otelconf/testdata/invalid_file_format.yaml b/otelconf/testdata/invalid_file_format.yaml new file mode 100644 index 00000000000..481a0a1472d --- /dev/null +++ b/otelconf/testdata/invalid_file_format.yaml @@ -0,0 +1,2 @@ +file_format: [] +disabled: false \ No newline at end of file diff --git a/otelconf/testdata/missing_file_format.json b/otelconf/testdata/missing_file_format.json new file mode 100644 index 00000000000..4eeaa246c3b --- /dev/null +++ b/otelconf/testdata/missing_file_format.json @@ -0,0 +1 @@ +{"disabled": false} \ No newline at end of file diff --git a/otelconf/testdata/missing_file_format.yaml b/otelconf/testdata/missing_file_format.yaml new file mode 100644 index 00000000000..d3e9f4bc851 --- /dev/null +++ b/otelconf/testdata/missing_file_format.yaml @@ -0,0 +1 @@ +disabled: false \ No newline at end of file diff --git a/otelconf/testdata/valid_defaults.json b/otelconf/testdata/valid_defaults.json new file mode 100644 index 00000000000..ef05941830a --- /dev/null +++ b/otelconf/testdata/valid_defaults.json @@ -0,0 +1 @@ +{"file_format": "1.0"} \ No newline at end of file diff --git a/otelconf/testdata/valid_defaults.yaml b/otelconf/testdata/valid_defaults.yaml new file mode 100644 index 00000000000..00e9eb3d5d7 --- /dev/null +++ b/otelconf/testdata/valid_defaults.yaml @@ -0,0 +1 @@ +file_format: 1.0 \ No newline at end of file From e10a1b21652727169cf8c00d40b567dc7e88618c Mon Sep 17 00:00:00 2001 From: Sonal Gaud <82362774+sonalgaud12@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:07:47 +0530 Subject: [PATCH 36/39] Added Test for http.Handler returned from zpages.NewTracezHandler (#8108) Co-authored-by: Damien Mathieu <42@dmathieu.com> --- otelconf/config_json.go | 5 - otelconf/config_test.go | 157 ++++++++++++--- otelconf/config_yaml.go | 5 +- otelconf/example_test.go | 4 +- otelconf/testdata/invalid_file_format.json | 1 - otelconf/testdata/invalid_file_format.yaml | 2 - otelconf/testdata/missing_file_format.json | 1 - otelconf/testdata/missing_file_format.yaml | 1 - otelconf/testdata/valid_defaults.json | 1 - otelconf/testdata/valid_defaults.yaml | 1 - otelconf/trace.go | 2 +- zpages/tracez_test.go | 218 +++++++++++++++++++++ 12 files changed, 354 insertions(+), 44 deletions(-) delete mode 100644 otelconf/testdata/invalid_file_format.json delete mode 100644 otelconf/testdata/invalid_file_format.yaml delete mode 100644 otelconf/testdata/missing_file_format.json delete mode 100644 otelconf/testdata/missing_file_format.yaml delete mode 100644 otelconf/testdata/valid_defaults.json delete mode 100644 otelconf/testdata/valid_defaults.yaml create mode 100644 zpages/tracez_test.go diff --git a/otelconf/config_json.go b/otelconf/config_json.go index 495cd16e386..1d018bf0512 100644 --- a/otelconf/config_json.go +++ b/otelconf/config_json.go @@ -194,11 +194,6 @@ func (j *LogRecordExporter) UnmarshalJSON(b []byte) error { return nil } -// MarshalJSON implements json.Marshaler. -func (j *AttributeType) MarshalJSON() ([]byte, error) { - return json.Marshal(j.Value) -} - // UnmarshalJSON implements json.Unmarshaler. func (j *TextMapPropagator) UnmarshalJSON(b []byte) error { type Plain TextMapPropagator diff --git a/otelconf/config_test.go b/otelconf/config_test.go index 03b624ab3d4..d73b9376633 100644 --- a/otelconf/config_test.go +++ b/otelconf/config_test.go @@ -394,6 +394,51 @@ func TestNewSDK(t *testing.T) { wantMeterProvider: metricnoop.NewMeterProvider(), wantLoggerProvider: lognoop.NewLoggerProvider(), }, + { + name: "invalid resource", + cfg: []ConfigurationOption{ + WithContext(t.Context()), + WithOpenTelemetryConfiguration(OpenTelemetryConfiguration{ + TracerProvider: &TracerProviderJson{}, + MeterProvider: &MeterProviderJson{}, + LoggerProvider: &LoggerProviderJson{}, + Resource: &LoggerProviderJson{}, + }), + }, + wantErr: newErrInvalid("resource"), + wantTracerProvider: tracenoop.NewTracerProvider(), + wantMeterProvider: metricnoop.NewMeterProvider(), + wantLoggerProvider: lognoop.NewLoggerProvider(), + }, + { + name: "invalid logger provider", + cfg: []ConfigurationOption{ + WithContext(t.Context()), + WithOpenTelemetryConfiguration(OpenTelemetryConfiguration{ + TracerProvider: &TracerProviderJson{}, + MeterProvider: &MeterProviderJson{}, + LoggerProvider: &ResourceJson{}, + Resource: &ResourceJson{}, + }), + }, + wantErr: newErrInvalid("logger_provider"), + wantTracerProvider: tracenoop.NewTracerProvider(), + wantMeterProvider: metricnoop.NewMeterProvider(), + wantLoggerProvider: lognoop.NewLoggerProvider(), + }, + { + name: "invalid tracer provider", + cfg: []ConfigurationOption{ + WithContext(t.Context()), + WithOpenTelemetryConfiguration(OpenTelemetryConfiguration{ + TracerProvider: &ResourceJson{}, + }), + }, + wantErr: newErrInvalid("tracer_provider"), + wantTracerProvider: tracenoop.NewTracerProvider(), + wantMeterProvider: metricnoop.NewMeterProvider(), + wantLoggerProvider: lognoop.NewLoggerProvider(), + }, } for _, tt := range tests { sdk, err := NewSDK(tt.cfg...) @@ -973,40 +1018,13 @@ var v100OpenTelemetryConfigEnvParsing = OpenTelemetryConfiguration{ }, } -func TestUnmarshalOpenTelemetryConfiguration(t *testing.T) { +func TestParseFiles(t *testing.T) { tests := []struct { name string input string wantErr error wantType *OpenTelemetryConfiguration }{ - { - name: "invalid config missing required file_format", - input: `missing_file_format`, - wantErr: newErrRequired(&OpenTelemetryConfiguration{}, "file_format"), - wantType: &OpenTelemetryConfiguration{}, - }, - { - name: "file_format invalid", - input: `invalid_file_format`, - wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), - wantType: &OpenTelemetryConfiguration{}, - }, - { - name: "valid defaults config", - input: `valid_defaults`, - wantType: &OpenTelemetryConfiguration{ - Disabled: ptr(false), - FileFormat: "1.0", - LogLevel: ptr("info"), - }, - }, - { - name: "invalid config", - input: "invalid_bool", - wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), - wantType: &OpenTelemetryConfiguration{}, - }, { name: "invalid nil name", input: "v1.0.0_invalid_nil_name", @@ -1061,6 +1079,89 @@ func TestUnmarshalOpenTelemetryConfiguration(t *testing.T) { } } +func TestUnmarshalOpenTelemetryConfiguration(t *testing.T) { + tests := []struct { + name string + jsonConfig []byte + yamlConfig []byte + wantErr error + wantType OpenTelemetryConfiguration + }{ + { + name: "valid defaults config", + jsonConfig: []byte(`{"file_format": "1.0"}`), + yamlConfig: []byte("file_format: 1.0"), + wantType: OpenTelemetryConfiguration{ + Disabled: ptr(false), + FileFormat: "1.0", + LogLevel: ptr("info"), + }, + }, + { + name: "invalid config missing required file_format", + jsonConfig: []byte(`{"disabled": false}`), + yamlConfig: []byte("disabled: false"), + wantErr: newErrRequired(&OpenTelemetryConfiguration{}, "file_format"), + }, + { + name: "file_format invalid", + jsonConfig: []byte(`{"file_format":[], "disabled": false}`), + yamlConfig: []byte("file_format: []\ndisabled: false"), + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + }, + { + name: "invalid config", + jsonConfig: []byte(`{"file_format": "yaml", "disabled": "notabool"}`), + yamlConfig: []byte("file_format: []\ndisabled: notabool"), + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + }, + { + name: "invalid data", + jsonConfig: []byte(`{:2000}`), + yamlConfig: []byte("disabled: []\nconsole: {}\nfile_format: str"), + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + }, + { + name: "resource invalid", + jsonConfig: []byte(`{"resource":[], "file_format": "1.0"}`), + yamlConfig: []byte("resource: []\nfile_format: 1.0"), + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + }, + { + name: "attribute_limits invalid", + jsonConfig: []byte(`{"attribute_limits":[], "file_format": "1.0"}`), + yamlConfig: []byte("attribute_limits: []\nfile_format: 1.0"), + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + }, + { + name: "instrumentation invalid", + jsonConfig: []byte(`{"instrumentation/development":[], "file_format": "1.0"}`), + yamlConfig: []byte("instrumentation/development: []\nfile_format: 1.0"), + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + }, + { + name: "log_level invalid", + jsonConfig: []byte(`{"log_level":[], "file_format": "1.0"}`), + yamlConfig: []byte("log_level: []\nfile_format: 1.0"), + wantErr: newErrUnmarshal(&OpenTelemetryConfiguration{}), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := OpenTelemetryConfiguration{} + err := got.UnmarshalJSON(tt.jsonConfig) + assert.ErrorIs(t, err, tt.wantErr) + assert.Equal(t, tt.wantType, got) + + got = OpenTelemetryConfiguration{} + err = yaml.Unmarshal(tt.yamlConfig, &got) + assert.ErrorIs(t, err, tt.wantErr) + assert.Equal(t, tt.wantType, got) + }) + } +} + func TestUnmarshalBatchSpanProcessor(t *testing.T) { for _, tt := range []struct { name string diff --git a/otelconf/config_yaml.go b/otelconf/config_yaml.go index e2630735c71..e116dab207c 100644 --- a/otelconf/config_yaml.go +++ b/otelconf/config_yaml.go @@ -49,6 +49,7 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { type Plain OpenTelemetryConfiguration type shadow struct { Plain + LogLevel *string `yaml:"log_level,omitempty"` AttributeLimits *AttributeLimits `yaml:"attribute_limits,omitempty"` Disabled *bool `yaml:"disabled,omitempty"` FileFormat string `yaml:"file_format"` @@ -96,7 +97,9 @@ func (j *OpenTelemetryConfiguration) UnmarshalYAML(node *yaml.Node) error { sh.Plain.InstrumentationDevelopment = sh.InstrumentationDevelopment } - if sh.Plain.LogLevel == nil { + if sh.LogLevel != nil { + sh.Plain.LogLevel = sh.LogLevel + } else { // Configure the log level of the internal logger used by the SDK. // If omitted, info is used. sh.Plain.LogLevel = ptr("info") diff --git a/otelconf/example_test.go b/otelconf/example_test.go index 8cfdc0c39eb..0d9b67e67f6 100644 --- a/otelconf/example_test.go +++ b/otelconf/example_test.go @@ -12,11 +12,11 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/log/global" - otelconf "go.opentelemetry.io/contrib/otelconf/v0.3.0" + "go.opentelemetry.io/contrib/otelconf" ) func Example() { - b, err := os.ReadFile(filepath.Join("testdata", "v0.3.yaml")) + b, err := os.ReadFile(filepath.Join("testdata", "v1.0.0.yaml")) if err != nil { log.Fatal(err) } diff --git a/otelconf/testdata/invalid_file_format.json b/otelconf/testdata/invalid_file_format.json deleted file mode 100644 index 78040798c6a..00000000000 --- a/otelconf/testdata/invalid_file_format.json +++ /dev/null @@ -1 +0,0 @@ -{"file_format":[], "disabled": false} \ No newline at end of file diff --git a/otelconf/testdata/invalid_file_format.yaml b/otelconf/testdata/invalid_file_format.yaml deleted file mode 100644 index 481a0a1472d..00000000000 --- a/otelconf/testdata/invalid_file_format.yaml +++ /dev/null @@ -1,2 +0,0 @@ -file_format: [] -disabled: false \ No newline at end of file diff --git a/otelconf/testdata/missing_file_format.json b/otelconf/testdata/missing_file_format.json deleted file mode 100644 index 4eeaa246c3b..00000000000 --- a/otelconf/testdata/missing_file_format.json +++ /dev/null @@ -1 +0,0 @@ -{"disabled": false} \ No newline at end of file diff --git a/otelconf/testdata/missing_file_format.yaml b/otelconf/testdata/missing_file_format.yaml deleted file mode 100644 index d3e9f4bc851..00000000000 --- a/otelconf/testdata/missing_file_format.yaml +++ /dev/null @@ -1 +0,0 @@ -disabled: false \ No newline at end of file diff --git a/otelconf/testdata/valid_defaults.json b/otelconf/testdata/valid_defaults.json deleted file mode 100644 index ef05941830a..00000000000 --- a/otelconf/testdata/valid_defaults.json +++ /dev/null @@ -1 +0,0 @@ -{"file_format": "1.0"} \ No newline at end of file diff --git a/otelconf/testdata/valid_defaults.yaml b/otelconf/testdata/valid_defaults.yaml deleted file mode 100644 index 00e9eb3d5d7..00000000000 --- a/otelconf/testdata/valid_defaults.yaml +++ /dev/null @@ -1 +0,0 @@ -file_format: 1.0 \ No newline at end of file diff --git a/otelconf/trace.go b/otelconf/trace.go index 54638a742be..c7e57d2867c 100644 --- a/otelconf/trace.go +++ b/otelconf/trace.go @@ -30,7 +30,7 @@ func tracerProvider(cfg configOptions, res *resource.Resource) (trace.TracerProv } provider, ok := cfg.opentelemetryConfig.TracerProvider.(*TracerProviderJson) if !ok { - return noop.NewTracerProvider(), noopShutdown, newErrInvalid("invalid tracer provider") + return noop.NewTracerProvider(), noopShutdown, newErrInvalid("tracer_provider") } opts := append(cfg.tracerProviderOptions, sdktrace.WithResource(res)) diff --git a/zpages/tracez_test.go b/zpages/tracez_test.go new file mode 100644 index 00000000000..2069814e3b2 --- /dev/null +++ b/zpages/tracez_test.go @@ -0,0 +1,218 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package zpages + +import ( + "context" + "net/http" + "net/http/httptest" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +func TestNewTracezHandler(t *testing.T) { + sp := NewSpanProcessor() + handler := NewTracezHandler(sp) + require.NotNil(t, handler, "NewTracezHandler returned nil") +} + +func TestTracezHandler_ServeHTTP(t *testing.T) { + // Setup common test infrastructure + sp := NewSpanProcessor() + defer func() { + require.NoError(t, sp.Shutdown(t.Context())) + }() + + tp := sdktrace.NewTracerProvider( + sdktrace.WithSpanProcessor(sp), + ) + defer func() { + require.NoError(t, tp.Shutdown(t.Context())) + }() + + tracer := tp.Tracer("test-tracer") + ctx := t.Context() + + _, completedSpan := tracer.Start(ctx, "completed-span") + completedSpan.End() + + _, errorSpan := tracer.Start(ctx, "error-span") + errorSpan.RecordError(context.DeadlineExceeded) + errorSpan.End() + + _, querySpan := tracer.Start(ctx, "query-span") + querySpan.End() + + for range 5 { + _, span := tracer.Start(ctx, "multi-span") + span.End() + } + + handler := NewTracezHandler(sp) + + tests := []struct { + name string + url string + wantStatus int + wantContains []string + wantNotContain []string + }{ + { + name: "basic response with no query params", + url: "/tracez", + wantStatus: http.StatusOK, + wantContains: []string{"completed-span", "error-span", "query-span", "multi-span"}, + }, + { + name: "query for existing span", + url: "/tracez?zspanname=query-span", + wantStatus: http.StatusOK, + wantContains: []string{"query-span"}, + }, + { + name: "query for non-existing span", + url: "/tracez?zspanname=non-existing", + wantStatus: http.StatusOK, + // Note: The handler displays the queried span name in the response + // (e.g., "Span Name: non-existing") even when no matching spans exist. + // This verifies the query parameter was processed, but doesn't verify + // that the span was actually found (which it shouldn't be). + wantContains: []string{"non-existing"}, + }, + { + name: "latency spans (type=1)", + url: "/tracez?zspanname=completed-span&ztype=1", + wantStatus: http.StatusOK, + wantContains: []string{}, + }, + { + name: "error spans (type=2)", + url: "/tracez?zspanname=error-span&ztype=2", + wantStatus: http.StatusOK, + wantContains: []string{}, + }, + { + name: "with latency bucket", + url: "/tracez?zspanname=completed-span&ztype=1&zlatencybucket=0", + wantStatus: http.StatusOK, + }, + { + name: "all parameters", + url: "/tracez?zspanname=completed-span&ztype=1&zlatencybucket=2", + wantStatus: http.StatusOK, + wantContains: []string{}, + }, + { + name: "type only", + url: "/tracez?ztype=1", + wantStatus: http.StatusOK, + }, + { + name: "latency bucket only", + url: "/tracez?zlatencybucket=3", + wantStatus: http.StatusOK, + }, + { + name: "invalid type value", + url: "/tracez?ztype=invalid", + wantStatus: http.StatusOK, + }, + { + name: "negative latency bucket", + url: "/tracez?zlatencybucket=-1", + wantStatus: http.StatusOK, + }, + { + name: "multiple spans with same name", + url: "/tracez?zspanname=multi-span&ztype=1", + wantStatus: http.StatusOK, + wantContains: []string{"multi-span"}, + }, + { + name: "invalid form encoding", + url: "/tracez?%zzz", + wantStatus: http.StatusBadRequest, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, tt.url, http.NoBody) + w := httptest.NewRecorder() + + handler.ServeHTTP(w, req) + + resp := w.Result() + defer resp.Body.Close() + + assert.Equal(t, tt.wantStatus, resp.StatusCode) + + // Verify content type for successful responses + if resp.StatusCode == http.StatusOK && tt.url == "/tracez" { + assert.Equal(t, "text/html; charset=utf-8", resp.Header.Get("Content-Type")) + } + + body := w.Body.String() + + // Only check body content for successful responses + if resp.StatusCode == http.StatusOK { + assert.NotEmpty(t, body, "expected non-empty response body") + + for _, want := range tt.wantContains { + assert.Contains(t, body, want) + } + for _, notWant := range tt.wantNotContain { + assert.NotContains(t, body, notWant) + } + } + }) + } +} + +func TestTracezHandler_ConcurrentSafe(t *testing.T) { + sp := NewSpanProcessor() + defer func() { + require.NoError(t, sp.Shutdown(t.Context())) + }() + + tp := sdktrace.NewTracerProvider( + sdktrace.WithSpanProcessor(sp), + ) + defer func() { + require.NoError(t, tp.Shutdown(t.Context())) + }() + + tracer := tp.Tracer("test-tracer") + ctx := t.Context() + + for range 10 { + _, span := tracer.Start(ctx, "concurrent-span") + span.End() + } + + handler := NewTracezHandler(sp) + + var wg sync.WaitGroup + for range 5 { + wg.Add(1) + go func() { + defer wg.Done() + req := httptest.NewRequest(http.MethodGet, "/tracez", http.NoBody) + w := httptest.NewRecorder() + + handler.ServeHTTP(w, req) + + resp := w.Result() + _ = resp.Body.Close() + + assert.Equal(t, http.StatusOK, resp.StatusCode) + }() + } + + wg.Wait() +} From 6b54d7369417c0ceda55748221c04d7977eb359c Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:19:42 -0800 Subject: [PATCH 37/39] support translation strategy Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/metric.go | 21 +++++++++++------ otelconf/metric_test.go | 52 +++++++++++++++++++++++++++-------------- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/otelconf/metric.go b/otelconf/metric.go index b6e12114401..338cb04a71f 100644 --- a/otelconf/metric.go +++ b/otelconf/metric.go @@ -18,6 +18,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/otlptranslator" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" @@ -403,18 +404,24 @@ func prometheusReader(ctx context.Context, prometheusConfig *ExperimentalPrometh return readerWithServer{reader, &server}, nil } +func validTranslationStrategy(strategy ExperimentalPrometheusMetricExporterTranslationStrategy) bool { + return strategy == ExperimentalPrometheusMetricExporterTranslationStrategyNoTranslation || + strategy == ExperimentalPrometheusMetricExporterTranslationStrategyNoUTF8EscapingWithSuffixes || + strategy == ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithSuffixes || + strategy == ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithoutSuffixes +} + func prometheusReaderOpts(prometheusConfig *ExperimentalPrometheusMetricExporter) ([]otelprom.Option, error) { var opts []otelprom.Option if prometheusConfig.WithoutScopeInfo != nil && *prometheusConfig.WithoutScopeInfo { opts = append(opts, otelprom.WithoutScopeInfo()) } - // TODO: fix the following to use with translation strategy - // if prometheusConfig.WithoutTypeSuffix != nil && *prometheusConfig.WithoutTypeSuffix { - // opts = append(opts, otelprom.WithoutCounterSuffixes()) //nolint:staticcheck // WithouTypeSuffix is deprecated, but we still need it for backwards compatibility. - // } - // if prometheusConfig.WithoutUnits != nil && *prometheusConfig.WithoutUnits { - // opts = append(opts, otelprom.WithoutUnits()) //nolint:staticcheck // WithouTypeSuffix is deprecated, but we still need it for backwards compatibility. - // } + if prometheusConfig.TranslationStrategy != nil { + if !validTranslationStrategy(*prometheusConfig.TranslationStrategy) { + return nil, newErrInvalid("translation strategy invalid") + } + opts = append(opts, otelprom.WithTranslationStrategy(otlptranslator.TranslationStrategyOption(*prometheusConfig.TranslationStrategy))) + } if prometheusConfig.WithResourceConstantLabels != nil { f, err := newIncludeExcludeFilter(prometheusConfig.WithResourceConstantLabels) if err != nil { diff --git a/otelconf/metric_test.go b/otelconf/metric_test.go index 0dd8d0b2315..b07f6d14a69 100644 --- a/otelconf/metric_test.go +++ b/otelconf/metric_test.go @@ -223,11 +223,10 @@ func TestReader(t *testing.T) { Pull: &PullMetricReader{ Exporter: PullMetricExporter{ PrometheusDevelopment: &ExperimentalPrometheusMetricExporter{ - Host: ptr("localhost"), - Port: ptr(0), - WithoutScopeInfo: ptr(true), - // WithoutUnits: ptr(true), - // WithoutTypeSuffix: ptr(true), + Host: ptr("localhost"), + Port: ptr(0), + WithoutScopeInfo: ptr(true), + TranslationStrategy: ptr(ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithoutSuffixes), WithResourceConstantLabels: &IncludeExclude{ Included: []string{"include"}, Excluded: []string{"exclude"}, @@ -238,6 +237,26 @@ func TestReader(t *testing.T) { }, wantReader: readerWithServer{promExporter, nil}, }, + { + name: "pull/prometheus/invalid strategy", + reader: MetricReader{ + Pull: &PullMetricReader{ + Exporter: PullMetricExporter{ + PrometheusDevelopment: &ExperimentalPrometheusMetricExporter{ + Host: ptr("localhost"), + Port: ptr(0), + WithoutScopeInfo: ptr(true), + TranslationStrategy: ptr(ExperimentalPrometheusMetricExporterTranslationStrategy("invalid-strategy")), + WithResourceConstantLabels: &IncludeExclude{ + Included: []string{"include"}, + Excluded: []string{"exclude"}, + }, + }, + }, + }, + }, + wantErrT: newErrInvalid("translation strategy invalid"), + }, { name: "periodic/otlp-grpc-exporter", reader: MetricReader{ @@ -1351,22 +1370,20 @@ func TestPrometheusReaderOpts(t *testing.T) { { name: "all set", cfg: ExperimentalPrometheusMetricExporter{ - WithoutScopeInfo: ptr(true), - // WithoutTypeSuffix: ptr(true), - // WithoutUnits: ptr(true), + WithoutScopeInfo: ptr(true), + TranslationStrategy: ptr(ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithoutSuffixes), WithResourceConstantLabels: &IncludeExclude{}, }, - wantOptions: 2, + wantOptions: 3, }, { name: "all set false", cfg: ExperimentalPrometheusMetricExporter{ - WithoutScopeInfo: ptr(false), - // WithoutTypeSuffix: ptr(false), - // WithoutUnits: ptr(false), + WithoutScopeInfo: ptr(false), + TranslationStrategy: ptr(ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithSuffixes), WithResourceConstantLabels: &IncludeExclude{}, }, - wantOptions: 1, + wantOptions: 2, }, } for _, tt := range testCases { @@ -1396,11 +1413,10 @@ func TestPrometheusIPv6(t *testing.T) { t.Run(tt.name, func(t *testing.T) { port := 0 cfg := ExperimentalPrometheusMetricExporter{ - Host: &tt.host, - Port: &port, - WithoutScopeInfo: ptr(true), - // WithoutTypeSuffix: ptr(true), - // WithoutUnits: ptr(true), + Host: &tt.host, + Port: &port, + WithoutScopeInfo: ptr(true), + TranslationStrategy: ptr(ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithSuffixes), WithResourceConstantLabels: &IncludeExclude{}, } From 820d03a1a484aef08a6f3fba7f678de30422a9a5 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Tue, 18 Nov 2025 13:35:59 -0800 Subject: [PATCH 38/39] tidy Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- otelconf/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/otelconf/go.mod b/otelconf/go.mod index f67373cec4e..ce3ac4f4188 100644 --- a/otelconf/go.mod +++ b/otelconf/go.mod @@ -4,6 +4,7 @@ go 1.24.0 require ( github.com/prometheus/client_golang v1.23.2 + github.com/prometheus/otlptranslator v1.0.0 github.com/stretchr/testify v1.11.1 go.opentelemetry.io/otel v1.38.0 go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0 @@ -41,7 +42,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.3 // indirect - github.com/prometheus/otlptranslator v1.0.0 // indirect github.com/prometheus/procfs v0.19.2 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect From dfc76085c6fa33171e632c1cf5c8cfacc04375b6 Mon Sep 17 00:00:00 2001 From: alex boten <223565+codeboten@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:49:43 -0800 Subject: [PATCH 39/39] otelconf: experimental x package This is an attempt at producing a separate `otelconf/x` package to support experimental features in the configuration schema. This is doing the bare minimum of using a `sed` patch to hide all experimental structs from the generated model code before moving it to the `otelconf` package. This has the upside of being pretty straight forward to do, but ends up with a lot of duplicate code. Part of #8203 Signed-off-by: alex boten <223565+codeboten@users.noreply.github.com> --- Makefile | 9 +- otelconf/generated_config.go | 162 +++--- otelconf/x/generated_config.go | 986 +++++++++++++++++++++++++++++++++ otelconf/x/go.mod | 3 + 4 files changed, 1075 insertions(+), 85 deletions(-) create mode 100644 otelconf/x/generated_config.go create mode 100644 otelconf/x/go.mod diff --git a/Makefile b/Makefile index 12a7f5c9e5e..d3a94996fd4 100644 --- a/Makefile +++ b/Makefile @@ -329,6 +329,7 @@ OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_VERSION=v1.0.0-rc.2 genjsonschema-cleanup: rm -Rf ${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR} +GENERATED_CONFIG_EXPERIMENTAL=./otelconf/x/generated_config.go GENERATED_CONFIG=./otelconf/generated_config.go # Generate structs for configuration from opentelemetry-configuration schema @@ -339,13 +340,13 @@ genjsonschema: genjsonschema-cleanup $(GOJSONSCHEMA) --capitalization ID \ --capitalization OTLP \ --struct-name-from-title \ - --package otelconf \ + --package x \ --only-models \ - --output ${GENERATED_CONFIG} \ + --output ${GENERATED_CONFIG_EXPERIMENTAL} \ ${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR}/schema/opentelemetry_configuration.json @echo Modify jsonschema generated files. - sed -f ./otelconf/jsonschema_patch.sed ${GENERATED_CONFIG} > ${GENERATED_CONFIG}.tmp - mv ${GENERATED_CONFIG}.tmp ${GENERATED_CONFIG} + sed -f ./otelconf/jsonschema_patch.sed ${GENERATED_CONFIG_EXPERIMENTAL} > ${GENERATED_CONFIG_EXPERIMENTAL}.tmp + mv ${GENERATED_CONFIG_EXPERIMENTAL}.tmp ${GENERATED_CONFIG} $(MAKE) genjsonschema-cleanup .PHONY: codespell diff --git a/otelconf/generated_config.go b/otelconf/generated_config.go index 6c508e9b030..0b79250a1cd 100644 --- a/otelconf/generated_config.go +++ b/otelconf/generated_config.go @@ -147,27 +147,27 @@ const ExemplarFilterAlwaysOff ExemplarFilter = "always_off" const ExemplarFilterAlwaysOn ExemplarFilter = "always_on" const ExemplarFilterTraceBased ExemplarFilter = "trace_based" -type ExperimentalContainerResourceDetector map[string]interface{} +type experimentalContainerResourceDetector map[string]interface{} -type ExperimentalGeneralInstrumentation struct { +type experimentalGeneralInstrumentation struct { // Http corresponds to the JSON schema field "http". - Http *ExperimentalHttpInstrumentation `json:"http,omitempty" yaml:"http,omitempty" mapstructure:"http,omitempty"` + Http *experimentalHttpInstrumentation `json:"http,omitempty" yaml:"http,omitempty" mapstructure:"http,omitempty"` // Peer corresponds to the JSON schema field "peer". - Peer *ExperimentalPeerInstrumentation `json:"peer,omitempty" yaml:"peer,omitempty" mapstructure:"peer,omitempty"` + Peer *experimentalPeerInstrumentation `json:"peer,omitempty" yaml:"peer,omitempty" mapstructure:"peer,omitempty"` } -type ExperimentalHostResourceDetector map[string]interface{} +type experimentalHostResourceDetector map[string]interface{} -type ExperimentalHttpInstrumentation struct { +type experimentalHttpInstrumentation struct { // Client corresponds to the JSON schema field "client". - Client *ExperimentalHttpInstrumentationClient `json:"client,omitempty" yaml:"client,omitempty" mapstructure:"client,omitempty"` + Client *experimentalHttpInstrumentationClient `json:"client,omitempty" yaml:"client,omitempty" mapstructure:"client,omitempty"` // Server corresponds to the JSON schema field "server". - Server *ExperimentalHttpInstrumentationServer `json:"server,omitempty" yaml:"server,omitempty" mapstructure:"server,omitempty"` + Server *experimentalHttpInstrumentationServer `json:"server,omitempty" yaml:"server,omitempty" mapstructure:"server,omitempty"` } -type ExperimentalHttpInstrumentationClient struct { +type experimentalHttpInstrumentationClient struct { // RequestCapturedHeaders corresponds to the JSON schema field // "request_captured_headers". RequestCapturedHeaders []string `json:"request_captured_headers,omitempty" yaml:"request_captured_headers,omitempty" mapstructure:"request_captured_headers,omitempty"` @@ -177,7 +177,7 @@ type ExperimentalHttpInstrumentationClient struct { ResponseCapturedHeaders []string `json:"response_captured_headers,omitempty" yaml:"response_captured_headers,omitempty" mapstructure:"response_captured_headers,omitempty"` } -type ExperimentalHttpInstrumentationServer struct { +type experimentalHttpInstrumentationServer struct { // RequestCapturedHeaders corresponds to the JSON schema field // "request_captured_headers". RequestCapturedHeaders []string `json:"request_captured_headers,omitempty" yaml:"request_captured_headers,omitempty" mapstructure:"request_captured_headers,omitempty"` @@ -187,56 +187,56 @@ type ExperimentalHttpInstrumentationServer struct { ResponseCapturedHeaders []string `json:"response_captured_headers,omitempty" yaml:"response_captured_headers,omitempty" mapstructure:"response_captured_headers,omitempty"` } -type ExperimentalLanguageSpecificInstrumentation map[string]interface{} +type experimentalLanguageSpecificInstrumentation map[string]interface{} -type ExperimentalLoggerConfig struct { +type experimentalLoggerConfig struct { // Disabled corresponds to the JSON schema field "disabled". Disabled *bool `json:"disabled,omitempty" yaml:"disabled,omitempty" mapstructure:"disabled,omitempty"` } -type ExperimentalLoggerConfigurator struct { +type experimentalLoggerConfigurator struct { // DefaultConfig corresponds to the JSON schema field "default_config". - DefaultConfig *ExperimentalLoggerConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` + DefaultConfig *experimentalLoggerConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` // Loggers corresponds to the JSON schema field "loggers". - Loggers []ExperimentalLoggerMatcherAndConfig `json:"loggers,omitempty" yaml:"loggers,omitempty" mapstructure:"loggers,omitempty"` + Loggers []experimentalLoggerMatcherAndConfig `json:"loggers,omitempty" yaml:"loggers,omitempty" mapstructure:"loggers,omitempty"` } -type ExperimentalLoggerMatcherAndConfig struct { +type experimentalLoggerMatcherAndConfig struct { // Config corresponds to the JSON schema field "config". - Config *ExperimentalLoggerConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` + Config *experimentalLoggerConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` } -type ExperimentalMeterConfig struct { +type experimentalMeterConfig struct { // Disabled corresponds to the JSON schema field "disabled". Disabled *bool `json:"disabled,omitempty" yaml:"disabled,omitempty" mapstructure:"disabled,omitempty"` } -type ExperimentalMeterConfigurator struct { +type experimentalMeterConfigurator struct { // DefaultConfig corresponds to the JSON schema field "default_config". - DefaultConfig *ExperimentalMeterConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` + DefaultConfig *experimentalMeterConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` // Meters corresponds to the JSON schema field "meters". - Meters []ExperimentalMeterMatcherAndConfig `json:"meters,omitempty" yaml:"meters,omitempty" mapstructure:"meters,omitempty"` + Meters []experimentalMeterMatcherAndConfig `json:"meters,omitempty" yaml:"meters,omitempty" mapstructure:"meters,omitempty"` } -type ExperimentalMeterMatcherAndConfig struct { +type experimentalMeterMatcherAndConfig struct { // Config corresponds to the JSON schema field "config". - Config *ExperimentalMeterConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` + Config *experimentalMeterConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` } -type ExperimentalOTLPFileExporter struct { +type experimentalOTLPFileExporter struct { // OutputStream corresponds to the JSON schema field "output_stream". OutputStream *string `json:"output_stream,omitempty" yaml:"output_stream,omitempty" mapstructure:"output_stream,omitempty"` } -type ExperimentalOTLPFileMetricExporter struct { +type experimentalOTLPFileMetricExporter struct { // DefaultHistogramAggregation corresponds to the JSON schema field // "default_histogram_aggregation". DefaultHistogramAggregation *ExporterDefaultHistogramAggregation `json:"default_histogram_aggregation,omitempty" yaml:"default_histogram_aggregation,omitempty" mapstructure:"default_histogram_aggregation,omitempty"` @@ -249,12 +249,12 @@ type ExperimentalOTLPFileMetricExporter struct { TemporalityPreference *ExporterTemporalityPreference `json:"temporality_preference,omitempty" yaml:"temporality_preference,omitempty" mapstructure:"temporality_preference,omitempty"` } -type ExperimentalPeerInstrumentation struct { +type experimentalPeerInstrumentation struct { // ServiceMapping corresponds to the JSON schema field "service_mapping". - ServiceMapping []ExperimentalPeerInstrumentationServiceMappingElem `json:"service_mapping,omitempty" yaml:"service_mapping,omitempty" mapstructure:"service_mapping,omitempty"` + ServiceMapping []experimentalPeerInstrumentationServiceMappingElem `json:"service_mapping,omitempty" yaml:"service_mapping,omitempty" mapstructure:"service_mapping,omitempty"` } -type ExperimentalPeerInstrumentationServiceMappingElem struct { +type experimentalPeerInstrumentationServiceMappingElem struct { // Peer corresponds to the JSON schema field "peer". Peer string `json:"peer" yaml:"peer" mapstructure:"peer"` @@ -262,9 +262,9 @@ type ExperimentalPeerInstrumentationServiceMappingElem struct { Service string `json:"service" yaml:"service" mapstructure:"service"` } -type ExperimentalProcessResourceDetector map[string]interface{} +type experimentalProcessResourceDetector map[string]interface{} -type ExperimentalPrometheusMetricExporter struct { +type experimentalPrometheusMetricExporter struct { // Host corresponds to the JSON schema field "host". Host *string `json:"host,omitempty" yaml:"host,omitempty" mapstructure:"host,omitempty"` @@ -273,7 +273,7 @@ type ExperimentalPrometheusMetricExporter struct { // TranslationStrategy corresponds to the JSON schema field // "translation_strategy". - TranslationStrategy *ExperimentalPrometheusMetricExporterTranslationStrategy `json:"translation_strategy,omitempty" yaml:"translation_strategy,omitempty" mapstructure:"translation_strategy,omitempty"` + TranslationStrategy *experimentalPrometheusMetricExporterTranslationStrategy `json:"translation_strategy,omitempty" yaml:"translation_strategy,omitempty" mapstructure:"translation_strategy,omitempty"` // WithResourceConstantLabels corresponds to the JSON schema field // "with_resource_constant_labels". @@ -283,55 +283,55 @@ type ExperimentalPrometheusMetricExporter struct { WithoutScopeInfo *bool `json:"without_scope_info,omitempty" yaml:"without_scope_info,omitempty" mapstructure:"without_scope_info,omitempty"` } -type ExperimentalPrometheusMetricExporterTranslationStrategy string +type experimentalPrometheusMetricExporterTranslationStrategy string -const ExperimentalPrometheusMetricExporterTranslationStrategyNoTranslation ExperimentalPrometheusMetricExporterTranslationStrategy = "NoTranslation" -const ExperimentalPrometheusMetricExporterTranslationStrategyNoUTF8EscapingWithSuffixes ExperimentalPrometheusMetricExporterTranslationStrategy = "NoUTF8EscapingWithSuffixes" -const ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithSuffixes ExperimentalPrometheusMetricExporterTranslationStrategy = "UnderscoreEscapingWithSuffixes" -const ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithoutSuffixes ExperimentalPrometheusMetricExporterTranslationStrategy = "UnderscoreEscapingWithoutSuffixes" +const experimentalPrometheusMetricExporterTranslationStrategyNoTranslation experimentalPrometheusMetricExporterTranslationStrategy = "NoTranslation" +const experimentalPrometheusMetricExporterTranslationStrategyNoUTF8EscapingWithSuffixes experimentalPrometheusMetricExporterTranslationStrategy = "NoUTF8EscapingWithSuffixes" +const experimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithSuffixes experimentalPrometheusMetricExporterTranslationStrategy = "UnderscoreEscapingWithSuffixes" +const experimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithoutSuffixes experimentalPrometheusMetricExporterTranslationStrategy = "UnderscoreEscapingWithoutSuffixes" -type ExperimentalResourceDetection struct { +type experimentalResourceDetection struct { // Attributes corresponds to the JSON schema field "attributes". Attributes *IncludeExclude `json:"attributes,omitempty" yaml:"attributes,omitempty" mapstructure:"attributes,omitempty"` // Detectors corresponds to the JSON schema field "detectors". - Detectors []ExperimentalResourceDetector `json:"detectors,omitempty" yaml:"detectors,omitempty" mapstructure:"detectors,omitempty"` + Detectors []experimentalResourceDetector `json:"detectors,omitempty" yaml:"detectors,omitempty" mapstructure:"detectors,omitempty"` } -type ExperimentalResourceDetector struct { +type experimentalResourceDetector struct { // Container corresponds to the JSON schema field "container". - Container ExperimentalContainerResourceDetector `json:"container,omitempty" yaml:"container,omitempty" mapstructure:"container,omitempty"` + Container experimentalContainerResourceDetector `json:"container,omitempty" yaml:"container,omitempty" mapstructure:"container,omitempty"` // Host corresponds to the JSON schema field "host". - Host ExperimentalHostResourceDetector `json:"host,omitempty" yaml:"host,omitempty" mapstructure:"host,omitempty"` + Host experimentalHostResourceDetector `json:"host,omitempty" yaml:"host,omitempty" mapstructure:"host,omitempty"` // Process corresponds to the JSON schema field "process". - Process ExperimentalProcessResourceDetector `json:"process,omitempty" yaml:"process,omitempty" mapstructure:"process,omitempty"` + Process experimentalProcessResourceDetector `json:"process,omitempty" yaml:"process,omitempty" mapstructure:"process,omitempty"` // Service corresponds to the JSON schema field "service". - Service ExperimentalServiceResourceDetector `json:"service,omitempty" yaml:"service,omitempty" mapstructure:"service,omitempty"` + Service experimentalServiceResourceDetector `json:"service,omitempty" yaml:"service,omitempty" mapstructure:"service,omitempty"` AdditionalProperties interface{} `mapstructure:",remain"` } -type ExperimentalServiceResourceDetector map[string]interface{} +type experimentalServiceResourceDetector map[string]interface{} -type ExperimentalTracerConfig struct { +type experimentalTracerConfig struct { // Disabled corresponds to the JSON schema field "disabled". Disabled *bool `json:"disabled,omitempty" yaml:"disabled,omitempty" mapstructure:"disabled,omitempty"` } -type ExperimentalTracerConfigurator struct { +type experimentalTracerConfigurator struct { // DefaultConfig corresponds to the JSON schema field "default_config". - DefaultConfig *ExperimentalTracerConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` + DefaultConfig *experimentalTracerConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` // Tracers corresponds to the JSON schema field "tracers". - Tracers []ExperimentalTracerMatcherAndConfig `json:"tracers,omitempty" yaml:"tracers,omitempty" mapstructure:"tracers,omitempty"` + Tracers []experimentalTracerMatcherAndConfig `json:"tracers,omitempty" yaml:"tracers,omitempty" mapstructure:"tracers,omitempty"` } -type ExperimentalTracerMatcherAndConfig struct { +type experimentalTracerMatcherAndConfig struct { // Config corresponds to the JSON schema field "config". - Config *ExperimentalTracerConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` + Config *experimentalTracerConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` @@ -376,40 +376,40 @@ const InstrumentTypeUpDownCounter InstrumentType = "up_down_counter" type InstrumentationJson struct { // Cpp corresponds to the JSON schema field "cpp". - Cpp ExperimentalLanguageSpecificInstrumentation `json:"cpp,omitempty" yaml:"cpp,omitempty" mapstructure:"cpp,omitempty"` + Cpp experimentalLanguageSpecificInstrumentation `json:"cpp,omitempty" yaml:"cpp,omitempty" mapstructure:"cpp,omitempty"` // Dotnet corresponds to the JSON schema field "dotnet". - Dotnet ExperimentalLanguageSpecificInstrumentation `json:"dotnet,omitempty" yaml:"dotnet,omitempty" mapstructure:"dotnet,omitempty"` + Dotnet experimentalLanguageSpecificInstrumentation `json:"dotnet,omitempty" yaml:"dotnet,omitempty" mapstructure:"dotnet,omitempty"` // Erlang corresponds to the JSON schema field "erlang". - Erlang ExperimentalLanguageSpecificInstrumentation `json:"erlang,omitempty" yaml:"erlang,omitempty" mapstructure:"erlang,omitempty"` + Erlang experimentalLanguageSpecificInstrumentation `json:"erlang,omitempty" yaml:"erlang,omitempty" mapstructure:"erlang,omitempty"` // General corresponds to the JSON schema field "general". - General *ExperimentalGeneralInstrumentation `json:"general,omitempty" yaml:"general,omitempty" mapstructure:"general,omitempty"` + General *experimentalGeneralInstrumentation `json:"general,omitempty" yaml:"general,omitempty" mapstructure:"general,omitempty"` // Go corresponds to the JSON schema field "go". - Go ExperimentalLanguageSpecificInstrumentation `json:"go,omitempty" yaml:"go,omitempty" mapstructure:"go,omitempty"` + Go experimentalLanguageSpecificInstrumentation `json:"go,omitempty" yaml:"go,omitempty" mapstructure:"go,omitempty"` // Java corresponds to the JSON schema field "java". - Java ExperimentalLanguageSpecificInstrumentation `json:"java,omitempty" yaml:"java,omitempty" mapstructure:"java,omitempty"` + Java experimentalLanguageSpecificInstrumentation `json:"java,omitempty" yaml:"java,omitempty" mapstructure:"java,omitempty"` // Js corresponds to the JSON schema field "js". - Js ExperimentalLanguageSpecificInstrumentation `json:"js,omitempty" yaml:"js,omitempty" mapstructure:"js,omitempty"` + Js experimentalLanguageSpecificInstrumentation `json:"js,omitempty" yaml:"js,omitempty" mapstructure:"js,omitempty"` // Php corresponds to the JSON schema field "php". - Php ExperimentalLanguageSpecificInstrumentation `json:"php,omitempty" yaml:"php,omitempty" mapstructure:"php,omitempty"` + Php experimentalLanguageSpecificInstrumentation `json:"php,omitempty" yaml:"php,omitempty" mapstructure:"php,omitempty"` // Python corresponds to the JSON schema field "python". - Python ExperimentalLanguageSpecificInstrumentation `json:"python,omitempty" yaml:"python,omitempty" mapstructure:"python,omitempty"` + Python experimentalLanguageSpecificInstrumentation `json:"python,omitempty" yaml:"python,omitempty" mapstructure:"python,omitempty"` // Ruby corresponds to the JSON schema field "ruby". - Ruby ExperimentalLanguageSpecificInstrumentation `json:"ruby,omitempty" yaml:"ruby,omitempty" mapstructure:"ruby,omitempty"` + Ruby experimentalLanguageSpecificInstrumentation `json:"ruby,omitempty" yaml:"ruby,omitempty" mapstructure:"ruby,omitempty"` // Rust corresponds to the JSON schema field "rust". - Rust ExperimentalLanguageSpecificInstrumentation `json:"rust,omitempty" yaml:"rust,omitempty" mapstructure:"rust,omitempty"` + Rust experimentalLanguageSpecificInstrumentation `json:"rust,omitempty" yaml:"rust,omitempty" mapstructure:"rust,omitempty"` // Swift corresponds to the JSON schema field "swift". - Swift ExperimentalLanguageSpecificInstrumentation `json:"swift,omitempty" yaml:"swift,omitempty" mapstructure:"swift,omitempty"` + Swift experimentalLanguageSpecificInstrumentation `json:"swift,omitempty" yaml:"swift,omitempty" mapstructure:"swift,omitempty"` } type JaegerPropagator map[string]interface{} @@ -431,9 +431,9 @@ type LogRecordExporter struct { // Console corresponds to the JSON schema field "console". Console ConsoleExporter `json:"console,omitempty" yaml:"console,omitempty" mapstructure:"console,omitempty"` - // OTLPFileDevelopment corresponds to the JSON schema field + // unexportedOTLPFileDevelopment corresponds to the JSON schema field // "otlp_file/development". - OTLPFileDevelopment *ExperimentalOTLPFileExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` + unexportedOTLPFileDevelopment *experimentalOTLPFileExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` // OTLPGrpc corresponds to the JSON schema field "otlp_grpc". OTLPGrpc *OTLPGrpcExporter `json:"otlp_grpc,omitempty" yaml:"otlp_grpc,omitempty" mapstructure:"otlp_grpc,omitempty"` @@ -468,9 +468,9 @@ type LoggerProviderJson struct { // Limits corresponds to the JSON schema field "limits". Limits *LogRecordLimits `json:"limits,omitempty" yaml:"limits,omitempty" mapstructure:"limits,omitempty"` - // LoggerConfiguratorDevelopment corresponds to the JSON schema field + // unexportedLoggerConfiguratorDevelopment corresponds to the JSON schema field // "logger_configurator/development". - LoggerConfiguratorDevelopment *ExperimentalLoggerConfigurator `json:"logger_configurator/development,omitempty" yaml:"logger_configurator/development,omitempty" mapstructure:"logger_configurator/development,omitempty"` + unexportedLoggerConfiguratorDevelopment *experimentalLoggerConfigurator `json:"logger_configurator/development,omitempty" yaml:"logger_configurator/development,omitempty" mapstructure:"logger_configurator/development,omitempty"` // Processors corresponds to the JSON schema field "processors". Processors []LogRecordProcessor `json:"processors" yaml:"processors" mapstructure:"processors"` @@ -480,9 +480,9 @@ type MeterProviderJson struct { // ExemplarFilter corresponds to the JSON schema field "exemplar_filter". ExemplarFilter *ExemplarFilter `json:"exemplar_filter,omitempty" yaml:"exemplar_filter,omitempty" mapstructure:"exemplar_filter,omitempty"` - // MeterConfiguratorDevelopment corresponds to the JSON schema field + // unexportedMeterConfiguratorDevelopment corresponds to the JSON schema field // "meter_configurator/development". - MeterConfiguratorDevelopment *ExperimentalMeterConfigurator `json:"meter_configurator/development,omitempty" yaml:"meter_configurator/development,omitempty" mapstructure:"meter_configurator/development,omitempty"` + unexportedMeterConfiguratorDevelopment *experimentalMeterConfigurator `json:"meter_configurator/development,omitempty" yaml:"meter_configurator/development,omitempty" mapstructure:"meter_configurator/development,omitempty"` // Readers corresponds to the JSON schema field "readers". Readers []MetricReader `json:"readers" yaml:"readers" mapstructure:"readers"` @@ -667,9 +667,9 @@ type OpenTelemetryConfiguration struct { // FileFormat corresponds to the JSON schema field "file_format". FileFormat string `json:"file_format" yaml:"file_format" mapstructure:"file_format"` - // InstrumentationDevelopment corresponds to the JSON schema field + // unexportedInstrumentationDevelopment corresponds to the JSON schema field // "instrumentation/development". - InstrumentationDevelopment OpenTelemetryConfigurationInstrumentationDevelopment `json:"instrumentation/development,omitempty" yaml:"instrumentation/development,omitempty" mapstructure:"instrumentation/development,omitempty"` + unexportedInstrumentationDevelopment OpenTelemetryConfigurationInstrumentationDevelopment `json:"instrumentation/development,omitempty" yaml:"instrumentation/development,omitempty" mapstructure:"instrumentation/development,omitempty"` // LogLevel corresponds to the JSON schema field "log_level". LogLevel *string `json:"log_level,omitempty" yaml:"log_level,omitempty" mapstructure:"log_level,omitempty"` @@ -692,7 +692,7 @@ type OpenTelemetryConfiguration struct { AdditionalProperties interface{} `mapstructure:",remain"` } -type OpenTelemetryConfigurationInstrumentationDevelopment interface{} +type unexportedOpenTelemetryConfigurationInstrumentationDevelopment interface{} type OpenTelemetryConfigurationLoggerProvider interface{} @@ -752,9 +752,9 @@ type PropagatorJson struct { } type PullMetricExporter struct { - // PrometheusDevelopment corresponds to the JSON schema field + // unexportedPrometheusDevelopment corresponds to the JSON schema field // "prometheus/development". - PrometheusDevelopment *ExperimentalPrometheusMetricExporter `json:"prometheus/development,omitempty" yaml:"prometheus/development,omitempty" mapstructure:"prometheus/development,omitempty"` + unexportedPrometheusDevelopment *experimentalPrometheusMetricExporter `json:"prometheus/development,omitempty" yaml:"prometheus/development,omitempty" mapstructure:"prometheus/development,omitempty"` AdditionalProperties interface{} `mapstructure:",remain"` } @@ -774,9 +774,9 @@ type PushMetricExporter struct { // Console corresponds to the JSON schema field "console". Console ConsoleExporter `json:"console,omitempty" yaml:"console,omitempty" mapstructure:"console,omitempty"` - // OTLPFileDevelopment corresponds to the JSON schema field + // unexportedOTLPFileDevelopment corresponds to the JSON schema field // "otlp_file/development". - OTLPFileDevelopment *ExperimentalOTLPFileMetricExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` + unexportedOTLPFileDevelopment *experimentalOTLPFileMetricExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` // OTLPGrpc corresponds to the JSON schema field "otlp_grpc". OTLPGrpc *OTLPGrpcMetricExporter `json:"otlp_grpc,omitempty" yaml:"otlp_grpc,omitempty" mapstructure:"otlp_grpc,omitempty"` @@ -794,9 +794,9 @@ type ResourceJson struct { // AttributesList corresponds to the JSON schema field "attributes_list". AttributesList *string `json:"attributes_list,omitempty" yaml:"attributes_list,omitempty" mapstructure:"attributes_list,omitempty"` - // DetectionDevelopment corresponds to the JSON schema field + // unexportedDetectionDevelopment corresponds to the JSON schema field // "detection/development". - DetectionDevelopment *ExperimentalResourceDetection `json:"detection/development,omitempty" yaml:"detection/development,omitempty" mapstructure:"detection/development,omitempty"` + unexportedDetectionDevelopment *experimentalResourceDetection `json:"detection/development,omitempty" yaml:"detection/development,omitempty" mapstructure:"detection/development,omitempty"` // SchemaUrl corresponds to the JSON schema field "schema_url". SchemaUrl *string `json:"schema_url,omitempty" yaml:"schema_url,omitempty" mapstructure:"schema_url,omitempty"` @@ -835,9 +835,9 @@ type SpanExporter struct { // Console corresponds to the JSON schema field "console". Console ConsoleExporter `json:"console,omitempty" yaml:"console,omitempty" mapstructure:"console,omitempty"` - // OTLPFileDevelopment corresponds to the JSON schema field + // unexportedOTLPFileDevelopment corresponds to the JSON schema field // "otlp_file/development". - OTLPFileDevelopment *ExperimentalOTLPFileExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` + unexportedOTLPFileDevelopment *experimentalOTLPFileExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` // OTLPGrpc corresponds to the JSON schema field "otlp_grpc". OTLPGrpc *OTLPGrpcExporter `json:"otlp_grpc,omitempty" yaml:"otlp_grpc,omitempty" mapstructure:"otlp_grpc,omitempty"` @@ -926,9 +926,9 @@ type TracerProviderJson struct { // Sampler corresponds to the JSON schema field "sampler". Sampler *Sampler `json:"sampler,omitempty" yaml:"sampler,omitempty" mapstructure:"sampler,omitempty"` - // TracerConfiguratorDevelopment corresponds to the JSON schema field + // unexportedTracerConfiguratorDevelopment corresponds to the JSON schema field // "tracer_configurator/development". - TracerConfiguratorDevelopment *ExperimentalTracerConfigurator `json:"tracer_configurator/development,omitempty" yaml:"tracer_configurator/development,omitempty" mapstructure:"tracer_configurator/development,omitempty"` + unexportedTracerConfiguratorDevelopment *experimentalTracerConfigurator `json:"tracer_configurator/development,omitempty" yaml:"tracer_configurator/development,omitempty" mapstructure:"tracer_configurator/development,omitempty"` } type View struct { diff --git a/otelconf/x/generated_config.go b/otelconf/x/generated_config.go new file mode 100644 index 00000000000..f68c46411f7 --- /dev/null +++ b/otelconf/x/generated_config.go @@ -0,0 +1,986 @@ +// Code generated by github.com/atombender/go-jsonschema, DO NOT EDIT. + +package x + +type Aggregation struct { + // Base2ExponentialBucketHistogram corresponds to the JSON schema field + // "base2_exponential_bucket_histogram". + Base2ExponentialBucketHistogram *Base2ExponentialBucketHistogramAggregation `json:"base2_exponential_bucket_histogram,omitempty" yaml:"base2_exponential_bucket_histogram,omitempty" mapstructure:"base2_exponential_bucket_histogram,omitempty"` + + // Default corresponds to the JSON schema field "default". + Default DefaultAggregation `json:"default,omitempty" yaml:"default,omitempty" mapstructure:"default,omitempty"` + + // Drop corresponds to the JSON schema field "drop". + Drop DropAggregation `json:"drop,omitempty" yaml:"drop,omitempty" mapstructure:"drop,omitempty"` + + // ExplicitBucketHistogram corresponds to the JSON schema field + // "explicit_bucket_histogram". + ExplicitBucketHistogram *ExplicitBucketHistogramAggregation `json:"explicit_bucket_histogram,omitempty" yaml:"explicit_bucket_histogram,omitempty" mapstructure:"explicit_bucket_histogram,omitempty"` + + // LastValue corresponds to the JSON schema field "last_value". + LastValue LastValueAggregation `json:"last_value,omitempty" yaml:"last_value,omitempty" mapstructure:"last_value,omitempty"` + + // Sum corresponds to the JSON schema field "sum". + Sum SumAggregation `json:"sum,omitempty" yaml:"sum,omitempty" mapstructure:"sum,omitempty"` +} + +type AlwaysOffSampler map[string]interface{} + +type AlwaysOnSampler map[string]interface{} + +type AttributeLimits struct { + // AttributeCountLimit corresponds to the JSON schema field + // "attribute_count_limit". + AttributeCountLimit *int `json:"attribute_count_limit,omitempty" yaml:"attribute_count_limit,omitempty" mapstructure:"attribute_count_limit,omitempty"` + + // AttributeValueLengthLimit corresponds to the JSON schema field + // "attribute_value_length_limit". + AttributeValueLengthLimit *int `json:"attribute_value_length_limit,omitempty" yaml:"attribute_value_length_limit,omitempty" mapstructure:"attribute_value_length_limit,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type AttributeNameValue struct { + // Name corresponds to the JSON schema field "name". + Name string `json:"name" yaml:"name" mapstructure:"name"` + + // Type corresponds to the JSON schema field "type". + Type *AttributeType `json:"type,omitempty" yaml:"type,omitempty" mapstructure:"type,omitempty"` + + // Value corresponds to the JSON schema field "value". + Value interface{} `json:"value" yaml:"value" mapstructure:"value"` +} + +type AttributeType struct { + Value interface{} +} + +type B3MultiPropagator map[string]interface{} + +type B3Propagator map[string]interface{} + +type BaggagePropagator map[string]interface{} + +type Base2ExponentialBucketHistogramAggregation struct { + // MaxScale corresponds to the JSON schema field "max_scale". + MaxScale *int `json:"max_scale,omitempty" yaml:"max_scale,omitempty" mapstructure:"max_scale,omitempty"` + + // MaxSize corresponds to the JSON schema field "max_size". + MaxSize *int `json:"max_size,omitempty" yaml:"max_size,omitempty" mapstructure:"max_size,omitempty"` + + // RecordMinMax corresponds to the JSON schema field "record_min_max". + RecordMinMax *bool `json:"record_min_max,omitempty" yaml:"record_min_max,omitempty" mapstructure:"record_min_max,omitempty"` +} + +type BatchLogRecordProcessor struct { + // ExportTimeout corresponds to the JSON schema field "export_timeout". + ExportTimeout *int `json:"export_timeout,omitempty" yaml:"export_timeout,omitempty" mapstructure:"export_timeout,omitempty"` + + // Exporter corresponds to the JSON schema field "exporter". + Exporter LogRecordExporter `json:"exporter" yaml:"exporter" mapstructure:"exporter"` + + // MaxExportBatchSize corresponds to the JSON schema field + // "max_export_batch_size". + MaxExportBatchSize *int `json:"max_export_batch_size,omitempty" yaml:"max_export_batch_size,omitempty" mapstructure:"max_export_batch_size,omitempty"` + + // MaxQueueSize corresponds to the JSON schema field "max_queue_size". + MaxQueueSize *int `json:"max_queue_size,omitempty" yaml:"max_queue_size,omitempty" mapstructure:"max_queue_size,omitempty"` + + // ScheduleDelay corresponds to the JSON schema field "schedule_delay". + ScheduleDelay *int `json:"schedule_delay,omitempty" yaml:"schedule_delay,omitempty" mapstructure:"schedule_delay,omitempty"` +} + +type BatchSpanProcessor struct { + // ExportTimeout corresponds to the JSON schema field "export_timeout". + ExportTimeout *int `json:"export_timeout,omitempty" yaml:"export_timeout,omitempty" mapstructure:"export_timeout,omitempty"` + + // Exporter corresponds to the JSON schema field "exporter". + Exporter SpanExporter `json:"exporter" yaml:"exporter" mapstructure:"exporter"` + + // MaxExportBatchSize corresponds to the JSON schema field + // "max_export_batch_size". + MaxExportBatchSize *int `json:"max_export_batch_size,omitempty" yaml:"max_export_batch_size,omitempty" mapstructure:"max_export_batch_size,omitempty"` + + // MaxQueueSize corresponds to the JSON schema field "max_queue_size". + MaxQueueSize *int `json:"max_queue_size,omitempty" yaml:"max_queue_size,omitempty" mapstructure:"max_queue_size,omitempty"` + + // ScheduleDelay corresponds to the JSON schema field "schedule_delay". + ScheduleDelay *int `json:"schedule_delay,omitempty" yaml:"schedule_delay,omitempty" mapstructure:"schedule_delay,omitempty"` +} + +type CardinalityLimits struct { + // Counter corresponds to the JSON schema field "counter". + Counter *int `json:"counter,omitempty" yaml:"counter,omitempty" mapstructure:"counter,omitempty"` + + // Default corresponds to the JSON schema field "default". + Default *int `json:"default,omitempty" yaml:"default,omitempty" mapstructure:"default,omitempty"` + + // Gauge corresponds to the JSON schema field "gauge". + Gauge *int `json:"gauge,omitempty" yaml:"gauge,omitempty" mapstructure:"gauge,omitempty"` + + // Histogram corresponds to the JSON schema field "histogram". + Histogram *int `json:"histogram,omitempty" yaml:"histogram,omitempty" mapstructure:"histogram,omitempty"` + + // ObservableCounter corresponds to the JSON schema field "observable_counter". + ObservableCounter *int `json:"observable_counter,omitempty" yaml:"observable_counter,omitempty" mapstructure:"observable_counter,omitempty"` + + // ObservableGauge corresponds to the JSON schema field "observable_gauge". + ObservableGauge *int `json:"observable_gauge,omitempty" yaml:"observable_gauge,omitempty" mapstructure:"observable_gauge,omitempty"` + + // ObservableUpDownCounter corresponds to the JSON schema field + // "observable_up_down_counter". + ObservableUpDownCounter *int `json:"observable_up_down_counter,omitempty" yaml:"observable_up_down_counter,omitempty" mapstructure:"observable_up_down_counter,omitempty"` + + // UpDownCounter corresponds to the JSON schema field "up_down_counter". + UpDownCounter *int `json:"up_down_counter,omitempty" yaml:"up_down_counter,omitempty" mapstructure:"up_down_counter,omitempty"` +} + +type ConsoleExporter map[string]interface{} + +type DefaultAggregation map[string]interface{} + +type DropAggregation map[string]interface{} + +type ExemplarFilter string + +const ExemplarFilterAlwaysOff ExemplarFilter = "always_off" +const ExemplarFilterAlwaysOn ExemplarFilter = "always_on" +const ExemplarFilterTraceBased ExemplarFilter = "trace_based" + +type ExperimentalContainerResourceDetector map[string]interface{} + +type ExperimentalGeneralInstrumentation struct { + // Http corresponds to the JSON schema field "http". + Http *ExperimentalHttpInstrumentation `json:"http,omitempty" yaml:"http,omitempty" mapstructure:"http,omitempty"` + + // Peer corresponds to the JSON schema field "peer". + Peer *ExperimentalPeerInstrumentation `json:"peer,omitempty" yaml:"peer,omitempty" mapstructure:"peer,omitempty"` +} + +type ExperimentalHostResourceDetector map[string]interface{} + +type ExperimentalHttpInstrumentation struct { + // Client corresponds to the JSON schema field "client". + Client *ExperimentalHttpInstrumentationClient `json:"client,omitempty" yaml:"client,omitempty" mapstructure:"client,omitempty"` + + // Server corresponds to the JSON schema field "server". + Server *ExperimentalHttpInstrumentationServer `json:"server,omitempty" yaml:"server,omitempty" mapstructure:"server,omitempty"` +} + +type ExperimentalHttpInstrumentationClient struct { + // RequestCapturedHeaders corresponds to the JSON schema field + // "request_captured_headers". + RequestCapturedHeaders []string `json:"request_captured_headers,omitempty" yaml:"request_captured_headers,omitempty" mapstructure:"request_captured_headers,omitempty"` + + // ResponseCapturedHeaders corresponds to the JSON schema field + // "response_captured_headers". + ResponseCapturedHeaders []string `json:"response_captured_headers,omitempty" yaml:"response_captured_headers,omitempty" mapstructure:"response_captured_headers,omitempty"` +} + +type ExperimentalHttpInstrumentationServer struct { + // RequestCapturedHeaders corresponds to the JSON schema field + // "request_captured_headers". + RequestCapturedHeaders []string `json:"request_captured_headers,omitempty" yaml:"request_captured_headers,omitempty" mapstructure:"request_captured_headers,omitempty"` + + // ResponseCapturedHeaders corresponds to the JSON schema field + // "response_captured_headers". + ResponseCapturedHeaders []string `json:"response_captured_headers,omitempty" yaml:"response_captured_headers,omitempty" mapstructure:"response_captured_headers,omitempty"` +} + +type ExperimentalLanguageSpecificInstrumentation map[string]interface{} + +type ExperimentalLoggerConfig struct { + // Disabled corresponds to the JSON schema field "disabled". + Disabled *bool `json:"disabled,omitempty" yaml:"disabled,omitempty" mapstructure:"disabled,omitempty"` +} + +type ExperimentalLoggerConfigurator struct { + // DefaultConfig corresponds to the JSON schema field "default_config". + DefaultConfig *ExperimentalLoggerConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` + + // Loggers corresponds to the JSON schema field "loggers". + Loggers []ExperimentalLoggerMatcherAndConfig `json:"loggers,omitempty" yaml:"loggers,omitempty" mapstructure:"loggers,omitempty"` +} + +type ExperimentalLoggerMatcherAndConfig struct { + // Config corresponds to the JSON schema field "config". + Config *ExperimentalLoggerConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` + + // Name corresponds to the JSON schema field "name". + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` +} + +type ExperimentalMeterConfig struct { + // Disabled corresponds to the JSON schema field "disabled". + Disabled *bool `json:"disabled,omitempty" yaml:"disabled,omitempty" mapstructure:"disabled,omitempty"` +} + +type ExperimentalMeterConfigurator struct { + // DefaultConfig corresponds to the JSON schema field "default_config". + DefaultConfig *ExperimentalMeterConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` + + // Meters corresponds to the JSON schema field "meters". + Meters []ExperimentalMeterMatcherAndConfig `json:"meters,omitempty" yaml:"meters,omitempty" mapstructure:"meters,omitempty"` +} + +type ExperimentalMeterMatcherAndConfig struct { + // Config corresponds to the JSON schema field "config". + Config *ExperimentalMeterConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` + + // Name corresponds to the JSON schema field "name". + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` +} + +type ExperimentalOTLPFileExporter struct { + // OutputStream corresponds to the JSON schema field "output_stream". + OutputStream *string `json:"output_stream,omitempty" yaml:"output_stream,omitempty" mapstructure:"output_stream,omitempty"` +} + +type ExperimentalOTLPFileMetricExporter struct { + // DefaultHistogramAggregation corresponds to the JSON schema field + // "default_histogram_aggregation". + DefaultHistogramAggregation *ExporterDefaultHistogramAggregation `json:"default_histogram_aggregation,omitempty" yaml:"default_histogram_aggregation,omitempty" mapstructure:"default_histogram_aggregation,omitempty"` + + // OutputStream corresponds to the JSON schema field "output_stream". + OutputStream *string `json:"output_stream,omitempty" yaml:"output_stream,omitempty" mapstructure:"output_stream,omitempty"` + + // TemporalityPreference corresponds to the JSON schema field + // "temporality_preference". + TemporalityPreference *ExporterTemporalityPreference `json:"temporality_preference,omitempty" yaml:"temporality_preference,omitempty" mapstructure:"temporality_preference,omitempty"` +} + +type ExperimentalPeerInstrumentation struct { + // ServiceMapping corresponds to the JSON schema field "service_mapping". + ServiceMapping []ExperimentalPeerInstrumentationServiceMappingElem `json:"service_mapping,omitempty" yaml:"service_mapping,omitempty" mapstructure:"service_mapping,omitempty"` +} + +type ExperimentalPeerInstrumentationServiceMappingElem struct { + // Peer corresponds to the JSON schema field "peer". + Peer string `json:"peer" yaml:"peer" mapstructure:"peer"` + + // Service corresponds to the JSON schema field "service". + Service string `json:"service" yaml:"service" mapstructure:"service"` +} + +type ExperimentalProcessResourceDetector map[string]interface{} + +type ExperimentalPrometheusMetricExporter struct { + // Host corresponds to the JSON schema field "host". + Host *string `json:"host,omitempty" yaml:"host,omitempty" mapstructure:"host,omitempty"` + + // Port corresponds to the JSON schema field "port". + Port *int `json:"port,omitempty" yaml:"port,omitempty" mapstructure:"port,omitempty"` + + // TranslationStrategy corresponds to the JSON schema field + // "translation_strategy". + TranslationStrategy *ExperimentalPrometheusMetricExporterTranslationStrategy `json:"translation_strategy,omitempty" yaml:"translation_strategy,omitempty" mapstructure:"translation_strategy,omitempty"` + + // WithResourceConstantLabels corresponds to the JSON schema field + // "with_resource_constant_labels". + WithResourceConstantLabels *IncludeExclude `json:"with_resource_constant_labels,omitempty" yaml:"with_resource_constant_labels,omitempty" mapstructure:"with_resource_constant_labels,omitempty"` + + // WithoutScopeInfo corresponds to the JSON schema field "without_scope_info". + WithoutScopeInfo *bool `json:"without_scope_info,omitempty" yaml:"without_scope_info,omitempty" mapstructure:"without_scope_info,omitempty"` +} + +type ExperimentalPrometheusMetricExporterTranslationStrategy string + +const ExperimentalPrometheusMetricExporterTranslationStrategyNoTranslation ExperimentalPrometheusMetricExporterTranslationStrategy = "NoTranslation" +const ExperimentalPrometheusMetricExporterTranslationStrategyNoUTF8EscapingWithSuffixes ExperimentalPrometheusMetricExporterTranslationStrategy = "NoUTF8EscapingWithSuffixes" +const ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithSuffixes ExperimentalPrometheusMetricExporterTranslationStrategy = "UnderscoreEscapingWithSuffixes" +const ExperimentalPrometheusMetricExporterTranslationStrategyUnderscoreEscapingWithoutSuffixes ExperimentalPrometheusMetricExporterTranslationStrategy = "UnderscoreEscapingWithoutSuffixes" + +type ExperimentalResourceDetection struct { + // Attributes corresponds to the JSON schema field "attributes". + Attributes *IncludeExclude `json:"attributes,omitempty" yaml:"attributes,omitempty" mapstructure:"attributes,omitempty"` + + // Detectors corresponds to the JSON schema field "detectors". + Detectors []ExperimentalResourceDetector `json:"detectors,omitempty" yaml:"detectors,omitempty" mapstructure:"detectors,omitempty"` +} + +type ExperimentalResourceDetector struct { + // Container corresponds to the JSON schema field "container". + Container ExperimentalContainerResourceDetector `json:"container,omitempty" yaml:"container,omitempty" mapstructure:"container,omitempty"` + + // Host corresponds to the JSON schema field "host". + Host ExperimentalHostResourceDetector `json:"host,omitempty" yaml:"host,omitempty" mapstructure:"host,omitempty"` + + // Process corresponds to the JSON schema field "process". + Process ExperimentalProcessResourceDetector `json:"process,omitempty" yaml:"process,omitempty" mapstructure:"process,omitempty"` + + // Service corresponds to the JSON schema field "service". + Service ExperimentalServiceResourceDetector `json:"service,omitempty" yaml:"service,omitempty" mapstructure:"service,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type ExperimentalServiceResourceDetector map[string]interface{} + +type ExperimentalTracerConfig struct { + // Disabled corresponds to the JSON schema field "disabled". + Disabled *bool `json:"disabled,omitempty" yaml:"disabled,omitempty" mapstructure:"disabled,omitempty"` +} + +type ExperimentalTracerConfigurator struct { + // DefaultConfig corresponds to the JSON schema field "default_config". + DefaultConfig *ExperimentalTracerConfig `json:"default_config,omitempty" yaml:"default_config,omitempty" mapstructure:"default_config,omitempty"` + + // Tracers corresponds to the JSON schema field "tracers". + Tracers []ExperimentalTracerMatcherAndConfig `json:"tracers,omitempty" yaml:"tracers,omitempty" mapstructure:"tracers,omitempty"` +} + +type ExperimentalTracerMatcherAndConfig struct { + // Config corresponds to the JSON schema field "config". + Config *ExperimentalTracerConfig `json:"config,omitempty" yaml:"config,omitempty" mapstructure:"config,omitempty"` + + // Name corresponds to the JSON schema field "name". + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` +} + +type ExplicitBucketHistogramAggregation struct { + // Boundaries corresponds to the JSON schema field "boundaries". + Boundaries []float64 `json:"boundaries,omitempty" yaml:"boundaries,omitempty" mapstructure:"boundaries,omitempty"` + + // RecordMinMax corresponds to the JSON schema field "record_min_max". + RecordMinMax *bool `json:"record_min_max,omitempty" yaml:"record_min_max,omitempty" mapstructure:"record_min_max,omitempty"` +} + +type ExporterDefaultHistogramAggregation string + +const ExporterDefaultHistogramAggregationBase2ExponentialBucketHistogram ExporterDefaultHistogramAggregation = "base2_exponential_bucket_histogram" +const ExporterDefaultHistogramAggregationExplicitBucketHistogram ExporterDefaultHistogramAggregation = "explicit_bucket_histogram" + +type ExporterTemporalityPreference string + +const ExporterTemporalityPreferenceCumulative ExporterTemporalityPreference = "cumulative" +const ExporterTemporalityPreferenceDelta ExporterTemporalityPreference = "delta" +const ExporterTemporalityPreferenceLowMemory ExporterTemporalityPreference = "low_memory" + +type IncludeExclude struct { + // Excluded corresponds to the JSON schema field "excluded". + Excluded []string `json:"excluded,omitempty" yaml:"excluded,omitempty" mapstructure:"excluded,omitempty"` + + // Included corresponds to the JSON schema field "included". + Included []string `json:"included,omitempty" yaml:"included,omitempty" mapstructure:"included,omitempty"` +} + +type InstrumentType string + +const InstrumentTypeCounter InstrumentType = "counter" +const InstrumentTypeGauge InstrumentType = "gauge" +const InstrumentTypeHistogram InstrumentType = "histogram" +const InstrumentTypeObservableCounter InstrumentType = "observable_counter" +const InstrumentTypeObservableGauge InstrumentType = "observable_gauge" +const InstrumentTypeObservableUpDownCounter InstrumentType = "observable_up_down_counter" +const InstrumentTypeUpDownCounter InstrumentType = "up_down_counter" + +type InstrumentationJson struct { + // Cpp corresponds to the JSON schema field "cpp". + Cpp ExperimentalLanguageSpecificInstrumentation `json:"cpp,omitempty" yaml:"cpp,omitempty" mapstructure:"cpp,omitempty"` + + // Dotnet corresponds to the JSON schema field "dotnet". + Dotnet ExperimentalLanguageSpecificInstrumentation `json:"dotnet,omitempty" yaml:"dotnet,omitempty" mapstructure:"dotnet,omitempty"` + + // Erlang corresponds to the JSON schema field "erlang". + Erlang ExperimentalLanguageSpecificInstrumentation `json:"erlang,omitempty" yaml:"erlang,omitempty" mapstructure:"erlang,omitempty"` + + // General corresponds to the JSON schema field "general". + General *ExperimentalGeneralInstrumentation `json:"general,omitempty" yaml:"general,omitempty" mapstructure:"general,omitempty"` + + // Go corresponds to the JSON schema field "go". + Go ExperimentalLanguageSpecificInstrumentation `json:"go,omitempty" yaml:"go,omitempty" mapstructure:"go,omitempty"` + + // Java corresponds to the JSON schema field "java". + Java ExperimentalLanguageSpecificInstrumentation `json:"java,omitempty" yaml:"java,omitempty" mapstructure:"java,omitempty"` + + // Js corresponds to the JSON schema field "js". + Js ExperimentalLanguageSpecificInstrumentation `json:"js,omitempty" yaml:"js,omitempty" mapstructure:"js,omitempty"` + + // Php corresponds to the JSON schema field "php". + Php ExperimentalLanguageSpecificInstrumentation `json:"php,omitempty" yaml:"php,omitempty" mapstructure:"php,omitempty"` + + // Python corresponds to the JSON schema field "python". + Python ExperimentalLanguageSpecificInstrumentation `json:"python,omitempty" yaml:"python,omitempty" mapstructure:"python,omitempty"` + + // Ruby corresponds to the JSON schema field "ruby". + Ruby ExperimentalLanguageSpecificInstrumentation `json:"ruby,omitempty" yaml:"ruby,omitempty" mapstructure:"ruby,omitempty"` + + // Rust corresponds to the JSON schema field "rust". + Rust ExperimentalLanguageSpecificInstrumentation `json:"rust,omitempty" yaml:"rust,omitempty" mapstructure:"rust,omitempty"` + + // Swift corresponds to the JSON schema field "swift". + Swift ExperimentalLanguageSpecificInstrumentation `json:"swift,omitempty" yaml:"swift,omitempty" mapstructure:"swift,omitempty"` +} + +type JaegerPropagator map[string]interface{} + +type JaegerRemoteSampler struct { + // Endpoint corresponds to the JSON schema field "endpoint". + Endpoint *string `json:"endpoint,omitempty" yaml:"endpoint,omitempty" mapstructure:"endpoint,omitempty"` + + // InitialSampler corresponds to the JSON schema field "initial_sampler". + InitialSampler *Sampler `json:"initial_sampler,omitempty" yaml:"initial_sampler,omitempty" mapstructure:"initial_sampler,omitempty"` + + // Interval corresponds to the JSON schema field "interval". + Interval *int `json:"interval,omitempty" yaml:"interval,omitempty" mapstructure:"interval,omitempty"` +} + +type LastValueAggregation map[string]interface{} + +type LogRecordExporter struct { + // Console corresponds to the JSON schema field "console". + Console ConsoleExporter `json:"console,omitempty" yaml:"console,omitempty" mapstructure:"console,omitempty"` + + // OTLPFileDevelopment corresponds to the JSON schema field + // "otlp_file/development". + OTLPFileDevelopment *ExperimentalOTLPFileExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` + + // OTLPGrpc corresponds to the JSON schema field "otlp_grpc". + OTLPGrpc *OTLPGrpcExporter `json:"otlp_grpc,omitempty" yaml:"otlp_grpc,omitempty" mapstructure:"otlp_grpc,omitempty"` + + // OTLPHttp corresponds to the JSON schema field "otlp_http". + OTLPHttp *OTLPHttpExporter `json:"otlp_http,omitempty" yaml:"otlp_http,omitempty" mapstructure:"otlp_http,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type LogRecordLimits struct { + // AttributeCountLimit corresponds to the JSON schema field + // "attribute_count_limit". + AttributeCountLimit *int `json:"attribute_count_limit,omitempty" yaml:"attribute_count_limit,omitempty" mapstructure:"attribute_count_limit,omitempty"` + + // AttributeValueLengthLimit corresponds to the JSON schema field + // "attribute_value_length_limit". + AttributeValueLengthLimit *int `json:"attribute_value_length_limit,omitempty" yaml:"attribute_value_length_limit,omitempty" mapstructure:"attribute_value_length_limit,omitempty"` +} + +type LogRecordProcessor struct { + // Batch corresponds to the JSON schema field "batch". + Batch *BatchLogRecordProcessor `json:"batch,omitempty" yaml:"batch,omitempty" mapstructure:"batch,omitempty"` + + // Simple corresponds to the JSON schema field "simple". + Simple *SimpleLogRecordProcessor `json:"simple,omitempty" yaml:"simple,omitempty" mapstructure:"simple,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type LoggerProviderJson struct { + // Limits corresponds to the JSON schema field "limits". + Limits *LogRecordLimits `json:"limits,omitempty" yaml:"limits,omitempty" mapstructure:"limits,omitempty"` + + // LoggerConfiguratorDevelopment corresponds to the JSON schema field + // "logger_configurator/development". + LoggerConfiguratorDevelopment *ExperimentalLoggerConfigurator `json:"logger_configurator/development,omitempty" yaml:"logger_configurator/development,omitempty" mapstructure:"logger_configurator/development,omitempty"` + + // Processors corresponds to the JSON schema field "processors". + Processors []LogRecordProcessor `json:"processors" yaml:"processors" mapstructure:"processors"` +} + +type MeterProviderJson struct { + // ExemplarFilter corresponds to the JSON schema field "exemplar_filter". + ExemplarFilter *ExemplarFilter `json:"exemplar_filter,omitempty" yaml:"exemplar_filter,omitempty" mapstructure:"exemplar_filter,omitempty"` + + // MeterConfiguratorDevelopment corresponds to the JSON schema field + // "meter_configurator/development". + MeterConfiguratorDevelopment *ExperimentalMeterConfigurator `json:"meter_configurator/development,omitempty" yaml:"meter_configurator/development,omitempty" mapstructure:"meter_configurator/development,omitempty"` + + // Readers corresponds to the JSON schema field "readers". + Readers []MetricReader `json:"readers" yaml:"readers" mapstructure:"readers"` + + // Views corresponds to the JSON schema field "views". + Views []View `json:"views,omitempty" yaml:"views,omitempty" mapstructure:"views,omitempty"` +} + +type MetricProducer struct { + // Opencensus corresponds to the JSON schema field "opencensus". + Opencensus OpenCensusMetricProducer `json:"opencensus,omitempty" yaml:"opencensus,omitempty" mapstructure:"opencensus,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type MetricReader struct { + // Periodic corresponds to the JSON schema field "periodic". + Periodic *PeriodicMetricReader `json:"periodic,omitempty" yaml:"periodic,omitempty" mapstructure:"periodic,omitempty"` + + // Pull corresponds to the JSON schema field "pull". + Pull *PullMetricReader `json:"pull,omitempty" yaml:"pull,omitempty" mapstructure:"pull,omitempty"` +} + +type NameStringValuePair struct { + // Name corresponds to the JSON schema field "name". + Name string `json:"name" yaml:"name" mapstructure:"name"` + + // Value corresponds to the JSON schema field "value". + Value *string `json:"value" yaml:"value" mapstructure:"value"` +} + +type OTLPGrpcExporter struct { + // CertificateFile corresponds to the JSON schema field "certificate_file". + CertificateFile *string `json:"certificate_file,omitempty" yaml:"certificate_file,omitempty" mapstructure:"certificate_file,omitempty"` + + // ClientCertificateFile corresponds to the JSON schema field + // "client_certificate_file". + ClientCertificateFile *string `json:"client_certificate_file,omitempty" yaml:"client_certificate_file,omitempty" mapstructure:"client_certificate_file,omitempty"` + + // ClientKeyFile corresponds to the JSON schema field "client_key_file". + ClientKeyFile *string `json:"client_key_file,omitempty" yaml:"client_key_file,omitempty" mapstructure:"client_key_file,omitempty"` + + // Compression corresponds to the JSON schema field "compression". + Compression *string `json:"compression,omitempty" yaml:"compression,omitempty" mapstructure:"compression,omitempty"` + + // Endpoint corresponds to the JSON schema field "endpoint". + Endpoint *string `json:"endpoint,omitempty" yaml:"endpoint,omitempty" mapstructure:"endpoint,omitempty"` + + // Headers corresponds to the JSON schema field "headers". + Headers []NameStringValuePair `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // HeadersList corresponds to the JSON schema field "headers_list". + HeadersList *string `json:"headers_list,omitempty" yaml:"headers_list,omitempty" mapstructure:"headers_list,omitempty"` + + // Insecure corresponds to the JSON schema field "insecure". + Insecure *bool `json:"insecure,omitempty" yaml:"insecure,omitempty" mapstructure:"insecure,omitempty"` + + // Timeout corresponds to the JSON schema field "timeout". + Timeout *int `json:"timeout,omitempty" yaml:"timeout,omitempty" mapstructure:"timeout,omitempty"` +} + +type OTLPGrpcMetricExporter struct { + // CertificateFile corresponds to the JSON schema field "certificate_file". + CertificateFile *string `json:"certificate_file,omitempty" yaml:"certificate_file,omitempty" mapstructure:"certificate_file,omitempty"` + + // ClientCertificateFile corresponds to the JSON schema field + // "client_certificate_file". + ClientCertificateFile *string `json:"client_certificate_file,omitempty" yaml:"client_certificate_file,omitempty" mapstructure:"client_certificate_file,omitempty"` + + // ClientKeyFile corresponds to the JSON schema field "client_key_file". + ClientKeyFile *string `json:"client_key_file,omitempty" yaml:"client_key_file,omitempty" mapstructure:"client_key_file,omitempty"` + + // Compression corresponds to the JSON schema field "compression". + Compression *string `json:"compression,omitempty" yaml:"compression,omitempty" mapstructure:"compression,omitempty"` + + // DefaultHistogramAggregation corresponds to the JSON schema field + // "default_histogram_aggregation". + DefaultHistogramAggregation *ExporterDefaultHistogramAggregation `json:"default_histogram_aggregation,omitempty" yaml:"default_histogram_aggregation,omitempty" mapstructure:"default_histogram_aggregation,omitempty"` + + // Endpoint corresponds to the JSON schema field "endpoint". + Endpoint *string `json:"endpoint,omitempty" yaml:"endpoint,omitempty" mapstructure:"endpoint,omitempty"` + + // Headers corresponds to the JSON schema field "headers". + Headers []NameStringValuePair `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // HeadersList corresponds to the JSON schema field "headers_list". + HeadersList *string `json:"headers_list,omitempty" yaml:"headers_list,omitempty" mapstructure:"headers_list,omitempty"` + + // Insecure corresponds to the JSON schema field "insecure". + Insecure *bool `json:"insecure,omitempty" yaml:"insecure,omitempty" mapstructure:"insecure,omitempty"` + + // TemporalityPreference corresponds to the JSON schema field + // "temporality_preference". + TemporalityPreference *ExporterTemporalityPreference `json:"temporality_preference,omitempty" yaml:"temporality_preference,omitempty" mapstructure:"temporality_preference,omitempty"` + + // Timeout corresponds to the JSON schema field "timeout". + Timeout *int `json:"timeout,omitempty" yaml:"timeout,omitempty" mapstructure:"timeout,omitempty"` +} + +type OTLPHttpEncoding string + +const OTLPHttpEncodingJson OTLPHttpEncoding = "json" +const OTLPHttpEncodingProtobuf OTLPHttpEncoding = "protobuf" + +type OTLPHttpExporter struct { + // CertificateFile corresponds to the JSON schema field "certificate_file". + CertificateFile *string `json:"certificate_file,omitempty" yaml:"certificate_file,omitempty" mapstructure:"certificate_file,omitempty"` + + // ClientCertificateFile corresponds to the JSON schema field + // "client_certificate_file". + ClientCertificateFile *string `json:"client_certificate_file,omitempty" yaml:"client_certificate_file,omitempty" mapstructure:"client_certificate_file,omitempty"` + + // ClientKeyFile corresponds to the JSON schema field "client_key_file". + ClientKeyFile *string `json:"client_key_file,omitempty" yaml:"client_key_file,omitempty" mapstructure:"client_key_file,omitempty"` + + // Compression corresponds to the JSON schema field "compression". + Compression *string `json:"compression,omitempty" yaml:"compression,omitempty" mapstructure:"compression,omitempty"` + + // Encoding corresponds to the JSON schema field "encoding". + Encoding *OTLPHttpEncoding `json:"encoding,omitempty" yaml:"encoding,omitempty" mapstructure:"encoding,omitempty"` + + // Endpoint corresponds to the JSON schema field "endpoint". + Endpoint *string `json:"endpoint,omitempty" yaml:"endpoint,omitempty" mapstructure:"endpoint,omitempty"` + + // Headers corresponds to the JSON schema field "headers". + Headers []NameStringValuePair `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // HeadersList corresponds to the JSON schema field "headers_list". + HeadersList *string `json:"headers_list,omitempty" yaml:"headers_list,omitempty" mapstructure:"headers_list,omitempty"` + + // Timeout corresponds to the JSON schema field "timeout". + Timeout *int `json:"timeout,omitempty" yaml:"timeout,omitempty" mapstructure:"timeout,omitempty"` +} + +type OTLPHttpMetricExporter struct { + // CertificateFile corresponds to the JSON schema field "certificate_file". + CertificateFile *string `json:"certificate_file,omitempty" yaml:"certificate_file,omitempty" mapstructure:"certificate_file,omitempty"` + + // ClientCertificateFile corresponds to the JSON schema field + // "client_certificate_file". + ClientCertificateFile *string `json:"client_certificate_file,omitempty" yaml:"client_certificate_file,omitempty" mapstructure:"client_certificate_file,omitempty"` + + // ClientKeyFile corresponds to the JSON schema field "client_key_file". + ClientKeyFile *string `json:"client_key_file,omitempty" yaml:"client_key_file,omitempty" mapstructure:"client_key_file,omitempty"` + + // Compression corresponds to the JSON schema field "compression". + Compression *string `json:"compression,omitempty" yaml:"compression,omitempty" mapstructure:"compression,omitempty"` + + // DefaultHistogramAggregation corresponds to the JSON schema field + // "default_histogram_aggregation". + DefaultHistogramAggregation *ExporterDefaultHistogramAggregation `json:"default_histogram_aggregation,omitempty" yaml:"default_histogram_aggregation,omitempty" mapstructure:"default_histogram_aggregation,omitempty"` + + // Encoding corresponds to the JSON schema field "encoding". + Encoding *OTLPHttpEncoding `json:"encoding,omitempty" yaml:"encoding,omitempty" mapstructure:"encoding,omitempty"` + + // Endpoint corresponds to the JSON schema field "endpoint". + Endpoint *string `json:"endpoint,omitempty" yaml:"endpoint,omitempty" mapstructure:"endpoint,omitempty"` + + // Headers corresponds to the JSON schema field "headers". + Headers []NameStringValuePair `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // HeadersList corresponds to the JSON schema field "headers_list". + HeadersList *string `json:"headers_list,omitempty" yaml:"headers_list,omitempty" mapstructure:"headers_list,omitempty"` + + // TemporalityPreference corresponds to the JSON schema field + // "temporality_preference". + TemporalityPreference *ExporterTemporalityPreference `json:"temporality_preference,omitempty" yaml:"temporality_preference,omitempty" mapstructure:"temporality_preference,omitempty"` + + // Timeout corresponds to the JSON schema field "timeout". + Timeout *int `json:"timeout,omitempty" yaml:"timeout,omitempty" mapstructure:"timeout,omitempty"` +} + +type OpenCensusMetricProducer map[string]interface{} + +type OpenTelemetryConfiguration struct { + // AttributeLimits corresponds to the JSON schema field "attribute_limits". + AttributeLimits *AttributeLimits `json:"attribute_limits,omitempty" yaml:"attribute_limits,omitempty" mapstructure:"attribute_limits,omitempty"` + + // Disabled corresponds to the JSON schema field "disabled". + Disabled *bool `json:"disabled,omitempty" yaml:"disabled,omitempty" mapstructure:"disabled,omitempty"` + + // FileFormat corresponds to the JSON schema field "file_format". + FileFormat string `json:"file_format" yaml:"file_format" mapstructure:"file_format"` + + // InstrumentationDevelopment corresponds to the JSON schema field + // "instrumentation/development". + InstrumentationDevelopment OpenTelemetryConfigurationInstrumentationDevelopment `json:"instrumentation/development,omitempty" yaml:"instrumentation/development,omitempty" mapstructure:"instrumentation/development,omitempty"` + + // LogLevel corresponds to the JSON schema field "log_level". + LogLevel *string `json:"log_level,omitempty" yaml:"log_level,omitempty" mapstructure:"log_level,omitempty"` + + // LoggerProvider corresponds to the JSON schema field "logger_provider". + LoggerProvider OpenTelemetryConfigurationLoggerProvider `json:"logger_provider,omitempty" yaml:"logger_provider,omitempty" mapstructure:"logger_provider,omitempty"` + + // MeterProvider corresponds to the JSON schema field "meter_provider". + MeterProvider OpenTelemetryConfigurationMeterProvider `json:"meter_provider,omitempty" yaml:"meter_provider,omitempty" mapstructure:"meter_provider,omitempty"` + + // Propagator corresponds to the JSON schema field "propagator". + Propagator OpenTelemetryConfigurationPropagator `json:"propagator,omitempty" yaml:"propagator,omitempty" mapstructure:"propagator,omitempty"` + + // Resource corresponds to the JSON schema field "resource". + Resource OpenTelemetryConfigurationResource `json:"resource,omitempty" yaml:"resource,omitempty" mapstructure:"resource,omitempty"` + + // TracerProvider corresponds to the JSON schema field "tracer_provider". + TracerProvider OpenTelemetryConfigurationTracerProvider `json:"tracer_provider,omitempty" yaml:"tracer_provider,omitempty" mapstructure:"tracer_provider,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type OpenTelemetryConfigurationInstrumentationDevelopment interface{} + +type OpenTelemetryConfigurationLoggerProvider interface{} + +type OpenTelemetryConfigurationMeterProvider interface{} + +type OpenTelemetryConfigurationPropagator interface{} + +type OpenTelemetryConfigurationResource interface{} + +type OpenTelemetryConfigurationTracerProvider interface{} + +type OpenTracingPropagator map[string]interface{} + +type ParentBasedSampler struct { + // LocalParentNotSampled corresponds to the JSON schema field + // "local_parent_not_sampled". + LocalParentNotSampled *Sampler `json:"local_parent_not_sampled,omitempty" yaml:"local_parent_not_sampled,omitempty" mapstructure:"local_parent_not_sampled,omitempty"` + + // LocalParentSampled corresponds to the JSON schema field "local_parent_sampled". + LocalParentSampled *Sampler `json:"local_parent_sampled,omitempty" yaml:"local_parent_sampled,omitempty" mapstructure:"local_parent_sampled,omitempty"` + + // RemoteParentNotSampled corresponds to the JSON schema field + // "remote_parent_not_sampled". + RemoteParentNotSampled *Sampler `json:"remote_parent_not_sampled,omitempty" yaml:"remote_parent_not_sampled,omitempty" mapstructure:"remote_parent_not_sampled,omitempty"` + + // RemoteParentSampled corresponds to the JSON schema field + // "remote_parent_sampled". + RemoteParentSampled *Sampler `json:"remote_parent_sampled,omitempty" yaml:"remote_parent_sampled,omitempty" mapstructure:"remote_parent_sampled,omitempty"` + + // Root corresponds to the JSON schema field "root". + Root *Sampler `json:"root,omitempty" yaml:"root,omitempty" mapstructure:"root,omitempty"` +} + +type PeriodicMetricReader struct { + // CardinalityLimits corresponds to the JSON schema field "cardinality_limits". + CardinalityLimits *CardinalityLimits `json:"cardinality_limits,omitempty" yaml:"cardinality_limits,omitempty" mapstructure:"cardinality_limits,omitempty"` + + // Exporter corresponds to the JSON schema field "exporter". + Exporter PushMetricExporter `json:"exporter" yaml:"exporter" mapstructure:"exporter"` + + // Interval corresponds to the JSON schema field "interval". + Interval *int `json:"interval,omitempty" yaml:"interval,omitempty" mapstructure:"interval,omitempty"` + + // Producers corresponds to the JSON schema field "producers". + Producers []MetricProducer `json:"producers,omitempty" yaml:"producers,omitempty" mapstructure:"producers,omitempty"` + + // Timeout corresponds to the JSON schema field "timeout". + Timeout *int `json:"timeout,omitempty" yaml:"timeout,omitempty" mapstructure:"timeout,omitempty"` +} + +type PropagatorJson struct { + // Composite corresponds to the JSON schema field "composite". + Composite []TextMapPropagator `json:"composite,omitempty" yaml:"composite,omitempty" mapstructure:"composite,omitempty"` + + // CompositeList corresponds to the JSON schema field "composite_list". + CompositeList *string `json:"composite_list,omitempty" yaml:"composite_list,omitempty" mapstructure:"composite_list,omitempty"` +} + +type PullMetricExporter struct { + // PrometheusDevelopment corresponds to the JSON schema field + // "prometheus/development". + PrometheusDevelopment *ExperimentalPrometheusMetricExporter `json:"prometheus/development,omitempty" yaml:"prometheus/development,omitempty" mapstructure:"prometheus/development,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type PullMetricReader struct { + // CardinalityLimits corresponds to the JSON schema field "cardinality_limits". + CardinalityLimits *CardinalityLimits `json:"cardinality_limits,omitempty" yaml:"cardinality_limits,omitempty" mapstructure:"cardinality_limits,omitempty"` + + // Exporter corresponds to the JSON schema field "exporter". + Exporter PullMetricExporter `json:"exporter" yaml:"exporter" mapstructure:"exporter"` + + // Producers corresponds to the JSON schema field "producers". + Producers []MetricProducer `json:"producers,omitempty" yaml:"producers,omitempty" mapstructure:"producers,omitempty"` +} + +type PushMetricExporter struct { + // Console corresponds to the JSON schema field "console". + Console ConsoleExporter `json:"console,omitempty" yaml:"console,omitempty" mapstructure:"console,omitempty"` + + // OTLPFileDevelopment corresponds to the JSON schema field + // "otlp_file/development". + OTLPFileDevelopment *ExperimentalOTLPFileMetricExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` + + // OTLPGrpc corresponds to the JSON schema field "otlp_grpc". + OTLPGrpc *OTLPGrpcMetricExporter `json:"otlp_grpc,omitempty" yaml:"otlp_grpc,omitempty" mapstructure:"otlp_grpc,omitempty"` + + // OTLPHttp corresponds to the JSON schema field "otlp_http". + OTLPHttp *OTLPHttpMetricExporter `json:"otlp_http,omitempty" yaml:"otlp_http,omitempty" mapstructure:"otlp_http,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type ResourceJson struct { + // Attributes corresponds to the JSON schema field "attributes". + Attributes []AttributeNameValue `json:"attributes,omitempty" yaml:"attributes,omitempty" mapstructure:"attributes,omitempty"` + + // AttributesList corresponds to the JSON schema field "attributes_list". + AttributesList *string `json:"attributes_list,omitempty" yaml:"attributes_list,omitempty" mapstructure:"attributes_list,omitempty"` + + // DetectionDevelopment corresponds to the JSON schema field + // "detection/development". + DetectionDevelopment *ExperimentalResourceDetection `json:"detection/development,omitempty" yaml:"detection/development,omitempty" mapstructure:"detection/development,omitempty"` + + // SchemaUrl corresponds to the JSON schema field "schema_url". + SchemaUrl *string `json:"schema_url,omitempty" yaml:"schema_url,omitempty" mapstructure:"schema_url,omitempty"` +} + +type Sampler struct { + // AlwaysOff corresponds to the JSON schema field "always_off". + AlwaysOff AlwaysOffSampler `json:"always_off,omitempty" yaml:"always_off,omitempty" mapstructure:"always_off,omitempty"` + + // AlwaysOn corresponds to the JSON schema field "always_on". + AlwaysOn AlwaysOnSampler `json:"always_on,omitempty" yaml:"always_on,omitempty" mapstructure:"always_on,omitempty"` + + // JaegerRemote corresponds to the JSON schema field "jaeger_remote". + JaegerRemote *JaegerRemoteSampler `json:"jaeger_remote,omitempty" yaml:"jaeger_remote,omitempty" mapstructure:"jaeger_remote,omitempty"` + + // ParentBased corresponds to the JSON schema field "parent_based". + ParentBased *ParentBasedSampler `json:"parent_based,omitempty" yaml:"parent_based,omitempty" mapstructure:"parent_based,omitempty"` + + // TraceIDRatioBased corresponds to the JSON schema field "trace_id_ratio_based". + TraceIDRatioBased *TraceIDRatioBasedSampler `json:"trace_id_ratio_based,omitempty" yaml:"trace_id_ratio_based,omitempty" mapstructure:"trace_id_ratio_based,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type SimpleLogRecordProcessor struct { + // Exporter corresponds to the JSON schema field "exporter". + Exporter LogRecordExporter `json:"exporter" yaml:"exporter" mapstructure:"exporter"` +} + +type SimpleSpanProcessor struct { + // Exporter corresponds to the JSON schema field "exporter". + Exporter SpanExporter `json:"exporter" yaml:"exporter" mapstructure:"exporter"` +} + +type SpanExporter struct { + // Console corresponds to the JSON schema field "console". + Console ConsoleExporter `json:"console,omitempty" yaml:"console,omitempty" mapstructure:"console,omitempty"` + + // OTLPFileDevelopment corresponds to the JSON schema field + // "otlp_file/development". + OTLPFileDevelopment *ExperimentalOTLPFileExporter `json:"otlp_file/development,omitempty" yaml:"otlp_file/development,omitempty" mapstructure:"otlp_file/development,omitempty"` + + // OTLPGrpc corresponds to the JSON schema field "otlp_grpc". + OTLPGrpc *OTLPGrpcExporter `json:"otlp_grpc,omitempty" yaml:"otlp_grpc,omitempty" mapstructure:"otlp_grpc,omitempty"` + + // OTLPHttp corresponds to the JSON schema field "otlp_http". + OTLPHttp *OTLPHttpExporter `json:"otlp_http,omitempty" yaml:"otlp_http,omitempty" mapstructure:"otlp_http,omitempty"` + + // Zipkin corresponds to the JSON schema field "zipkin". + Zipkin *ZipkinSpanExporter `json:"zipkin,omitempty" yaml:"zipkin,omitempty" mapstructure:"zipkin,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type SpanLimits struct { + // AttributeCountLimit corresponds to the JSON schema field + // "attribute_count_limit". + AttributeCountLimit *int `json:"attribute_count_limit,omitempty" yaml:"attribute_count_limit,omitempty" mapstructure:"attribute_count_limit,omitempty"` + + // AttributeValueLengthLimit corresponds to the JSON schema field + // "attribute_value_length_limit". + AttributeValueLengthLimit *int `json:"attribute_value_length_limit,omitempty" yaml:"attribute_value_length_limit,omitempty" mapstructure:"attribute_value_length_limit,omitempty"` + + // EventAttributeCountLimit corresponds to the JSON schema field + // "event_attribute_count_limit". + EventAttributeCountLimit *int `json:"event_attribute_count_limit,omitempty" yaml:"event_attribute_count_limit,omitempty" mapstructure:"event_attribute_count_limit,omitempty"` + + // EventCountLimit corresponds to the JSON schema field "event_count_limit". + EventCountLimit *int `json:"event_count_limit,omitempty" yaml:"event_count_limit,omitempty" mapstructure:"event_count_limit,omitempty"` + + // LinkAttributeCountLimit corresponds to the JSON schema field + // "link_attribute_count_limit". + LinkAttributeCountLimit *int `json:"link_attribute_count_limit,omitempty" yaml:"link_attribute_count_limit,omitempty" mapstructure:"link_attribute_count_limit,omitempty"` + + // LinkCountLimit corresponds to the JSON schema field "link_count_limit". + LinkCountLimit *int `json:"link_count_limit,omitempty" yaml:"link_count_limit,omitempty" mapstructure:"link_count_limit,omitempty"` +} + +type SpanProcessor struct { + // Batch corresponds to the JSON schema field "batch". + Batch *BatchSpanProcessor `json:"batch,omitempty" yaml:"batch,omitempty" mapstructure:"batch,omitempty"` + + // Simple corresponds to the JSON schema field "simple". + Simple *SimpleSpanProcessor `json:"simple,omitempty" yaml:"simple,omitempty" mapstructure:"simple,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type SumAggregation map[string]interface{} + +type TextMapPropagator struct { + // B3 corresponds to the JSON schema field "b3". + B3 B3Propagator `json:"b3,omitempty" yaml:"b3,omitempty" mapstructure:"b3,omitempty"` + + // B3Multi corresponds to the JSON schema field "b3multi". + B3Multi B3MultiPropagator `json:"b3multi,omitempty" yaml:"b3multi,omitempty" mapstructure:"b3multi,omitempty"` + + // Baggage corresponds to the JSON schema field "baggage". + Baggage BaggagePropagator `json:"baggage,omitempty" yaml:"baggage,omitempty" mapstructure:"baggage,omitempty"` + + // Jaeger corresponds to the JSON schema field "jaeger". + Jaeger JaegerPropagator `json:"jaeger,omitempty" yaml:"jaeger,omitempty" mapstructure:"jaeger,omitempty"` + + // Ottrace corresponds to the JSON schema field "ottrace". + Ottrace OpenTracingPropagator `json:"ottrace,omitempty" yaml:"ottrace,omitempty" mapstructure:"ottrace,omitempty"` + + // Tracecontext corresponds to the JSON schema field "tracecontext". + Tracecontext TraceContextPropagator `json:"tracecontext,omitempty" yaml:"tracecontext,omitempty" mapstructure:"tracecontext,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +type TraceContextPropagator map[string]interface{} + +type TraceIDRatioBasedSampler struct { + // Ratio corresponds to the JSON schema field "ratio". + Ratio *float64 `json:"ratio,omitempty" yaml:"ratio,omitempty" mapstructure:"ratio,omitempty"` +} + +type TracerProviderJson struct { + // Limits corresponds to the JSON schema field "limits". + Limits *SpanLimits `json:"limits,omitempty" yaml:"limits,omitempty" mapstructure:"limits,omitempty"` + + // Processors corresponds to the JSON schema field "processors". + Processors []SpanProcessor `json:"processors" yaml:"processors" mapstructure:"processors"` + + // Sampler corresponds to the JSON schema field "sampler". + Sampler *Sampler `json:"sampler,omitempty" yaml:"sampler,omitempty" mapstructure:"sampler,omitempty"` + + // TracerConfiguratorDevelopment corresponds to the JSON schema field + // "tracer_configurator/development". + TracerConfiguratorDevelopment *ExperimentalTracerConfigurator `json:"tracer_configurator/development,omitempty" yaml:"tracer_configurator/development,omitempty" mapstructure:"tracer_configurator/development,omitempty"` +} + +type View struct { + // Selector corresponds to the JSON schema field "selector". + Selector *ViewSelector `json:"selector,omitempty" yaml:"selector,omitempty" mapstructure:"selector,omitempty"` + + // Stream corresponds to the JSON schema field "stream". + Stream *ViewStream `json:"stream,omitempty" yaml:"stream,omitempty" mapstructure:"stream,omitempty"` +} + +type ViewSelector struct { + // InstrumentName corresponds to the JSON schema field "instrument_name". + InstrumentName *string `json:"instrument_name,omitempty" yaml:"instrument_name,omitempty" mapstructure:"instrument_name,omitempty"` + + // InstrumentType corresponds to the JSON schema field "instrument_type". + InstrumentType *InstrumentType `json:"instrument_type,omitempty" yaml:"instrument_type,omitempty" mapstructure:"instrument_type,omitempty"` + + // MeterName corresponds to the JSON schema field "meter_name". + MeterName *string `json:"meter_name,omitempty" yaml:"meter_name,omitempty" mapstructure:"meter_name,omitempty"` + + // MeterSchemaUrl corresponds to the JSON schema field "meter_schema_url". + MeterSchemaUrl *string `json:"meter_schema_url,omitempty" yaml:"meter_schema_url,omitempty" mapstructure:"meter_schema_url,omitempty"` + + // MeterVersion corresponds to the JSON schema field "meter_version". + MeterVersion *string `json:"meter_version,omitempty" yaml:"meter_version,omitempty" mapstructure:"meter_version,omitempty"` + + // Unit corresponds to the JSON schema field "unit". + Unit *string `json:"unit,omitempty" yaml:"unit,omitempty" mapstructure:"unit,omitempty"` +} + +type ViewStream struct { + // Aggregation corresponds to the JSON schema field "aggregation". + Aggregation *Aggregation `json:"aggregation,omitempty" yaml:"aggregation,omitempty" mapstructure:"aggregation,omitempty"` + + // AggregationCardinalityLimit corresponds to the JSON schema field + // "aggregation_cardinality_limit". + AggregationCardinalityLimit *int `json:"aggregation_cardinality_limit,omitempty" yaml:"aggregation_cardinality_limit,omitempty" mapstructure:"aggregation_cardinality_limit,omitempty"` + + // AttributeKeys corresponds to the JSON schema field "attribute_keys". + AttributeKeys *IncludeExclude `json:"attribute_keys,omitempty" yaml:"attribute_keys,omitempty" mapstructure:"attribute_keys,omitempty"` + + // Description corresponds to the JSON schema field "description". + Description *string `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // Name corresponds to the JSON schema field "name". + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` +} + +type ZipkinSpanExporter struct { + // Endpoint corresponds to the JSON schema field "endpoint". + Endpoint *string `json:"endpoint,omitempty" yaml:"endpoint,omitempty" mapstructure:"endpoint,omitempty"` + + // Timeout corresponds to the JSON schema field "timeout". + Timeout *int `json:"timeout,omitempty" yaml:"timeout,omitempty" mapstructure:"timeout,omitempty"` +} diff --git a/otelconf/x/go.mod b/otelconf/x/go.mod new file mode 100644 index 00000000000..3c7227c619b --- /dev/null +++ b/otelconf/x/go.mod @@ -0,0 +1,3 @@ +module go.opentelemetry.io/contrib/otelconf/x + +go 1.24.0