Skip to content

Commit 452bd6c

Browse files
committed
Validate exporter config based on go tags
Signed-off-by: Arthur Silva Sens <[email protected]>
1 parent 7033f27 commit 452bd6c

File tree

3 files changed

+24
-12
lines changed

3 files changed

+24
-12
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/alecthomas/kingpin/v2 v2.4.0
77
github.com/coreos/go-systemd/v22 v22.6.0
88
github.com/mdlayher/vsock v1.2.1
9+
github.com/mitchellh/mapstructure v1.5.0
910
github.com/prometheus/common v0.66.1
1011
go.opentelemetry.io/collector/component v1.44.0
1112
go.opentelemetry.io/collector/consumer v1.44.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U
4343
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
4444
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
4545
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
46+
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
47+
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
4648
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
4749
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
4850
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

otlpreceiver/factory.go

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"context"
1818
"fmt"
1919

20+
"github.com/mitchellh/mapstructure"
2021
"github.com/prometheus/client_golang/prometheus"
2122
"go.opentelemetry.io/collector/component"
2223
"go.opentelemetry.io/collector/consumer"
@@ -30,21 +31,21 @@ type ExporterInitializer interface {
3031
// containing all the metrics collectors.
3132
Initialize(ctx context.Context, exporterConfig Config) (*prometheus.Registry, error)
3233

33-
// Shutdown cleanly stops the exporter and releases resources.
34+
// Shutdown is used to release resources when the receiver is shutting down.
3435
Shutdown(ctx context.Context) error
3536
}
3637

37-
// ConfigUnmarshaler is the interface for unmarshaling exporter-specific configuration.
38+
// ConfigUnmarshaler is the interface used to unmarshal the exporter-specific
39+
// configuration using mapstructure and struct tags.
3840
type ConfigUnmarshaler interface {
39-
// UnmarshalExporterConfig parses the exporter-specific configuration
40-
// from the raw map into a Config instance.
41-
UnmarshalExporterConfig(data map[string]interface{}) (Config, error)
41+
// GetConfigStruct returns a pointer to the config struct that mapstructure
42+
// will populate. The struct should have appropriate mapstructure tags.
43+
GetConfigStruct() Config
4244
}
4345

4446
// FactoryOption is a function that configures a Factory.
4547
type FactoryOption func(*factoryConfig)
4648

47-
// factoryConfig holds the configuration for creating a receiver factory.
4849
type factoryConfig struct {
4950
typeStr component.Type
5051
initializer ExporterInitializer
@@ -73,6 +74,7 @@ func WithConfigUnmarshaler(unmarshaler ConfigUnmarshaler) FactoryOption {
7374
}
7475
}
7576

77+
// WithComponentDefaults sets the default configuration for the component.
7678
func WithComponentDefaults(defaults map[string]interface{}) FactoryOption {
7779
return func(cfg *factoryConfig) {
7880
cfg.defaultConfig = defaults
@@ -114,7 +116,6 @@ func NewFactory(opts ...FactoryOption) receiver.Factory {
114116
)
115117
}
116118

117-
// createMetricsReceiver returns a function that creates a metrics receiver instance.
118119
func createMetricsReceiver(
119120
initializer ExporterInitializer,
120121
unmarshaler ConfigUnmarshaler,
@@ -130,21 +131,29 @@ func createMetricsReceiver(
130131
return nil, fmt.Errorf("invalid config type: %T", cfg)
131132
}
132133

133-
// Unmarshal the exporter-specific config
134134
if len(receiverCfg.ExporterConfig) > 0 {
135-
exporterCfg, err := unmarshaler.UnmarshalExporterConfig(receiverCfg.ExporterConfig)
135+
exporterCfg := unmarshaler.GetConfigStruct()
136+
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
137+
Result: exporterCfg,
138+
ErrorUnused: true, // Reject unknown fields
139+
WeaklyTypedInput: false, // Strict type checking
140+
TagName: "mapstructure",
141+
})
136142
if err != nil {
137-
return nil, fmt.Errorf("failed to unmarshal exporter config: %w", err)
143+
return nil, fmt.Errorf("failed to create decoder: %w", err)
138144
}
145+
146+
if err = decoder.Decode(receiverCfg.ExporterConfig); err != nil {
147+
return nil, fmt.Errorf("configuration validation failed: %w", err)
148+
}
149+
139150
receiverCfg.SetExporterConfig(exporterCfg)
140151
}
141152

142-
// Validate the complete configuration
143153
if err := receiverCfg.Validate(); err != nil {
144154
return nil, fmt.Errorf("invalid configuration: %w", err)
145155
}
146156

147-
// Create the receiver instance
148157
return newPrometheusReceiver(
149158
receiverCfg,
150159
consumer,

0 commit comments

Comments
 (0)