-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
Copy pathconfig.go
151 lines (125 loc) · 5.14 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package receivercreator // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/receivercreator"
import (
"fmt"
"github.com/spf13/cast"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/confmap"
"github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer"
)
const (
// receiversConfigKey is the config key name used to specify the subreceivers.
receiversConfigKey = "receivers"
// endpointConfigKey is the key name mapping to ReceiverSettings.Endpoint.
endpointConfigKey = "endpoint"
// configKey is the key name in a subreceiver.
configKey = "config"
)
// receiverConfig describes a receiver instance with a default config.
type receiverConfig struct {
// id is the id of the subreceiver (ie <receiver type>/<id>).
id component.ID
// config is the map configured by the user in the config file. It is the contents of the map from
// the "config" section. The keys and values are arbitrarily configured by the user.
config userConfigMap
endpointID observer.EndpointID
}
// userConfigMap is an arbitrary map of string keys to arbitrary values as specified by the user
type userConfigMap map[string]any
type receiverSignals struct {
metrics bool
logs bool
traces bool
}
// receiverTemplate is the configuration of a single subreceiver.
type receiverTemplate struct {
receiverConfig
// Rule is the discovery rule that when matched will create a receiver instance
// based on receiverTemplate.
Rule string `mapstructure:"rule"`
// ResourceAttributes is a map of resource attributes to add to just this receiver's resource metrics.
// It can contain expr expressions for endpoint env value expansion
ResourceAttributes map[string]any `mapstructure:"resource_attributes"`
rule rule
signals receiverSignals
}
// resourceAttributes holds a map of default resource attributes for each Endpoint type.
type resourceAttributes map[observer.EndpointType]map[string]string
// newReceiverTemplate creates a receiverTemplate instance from the full name of a subreceiver
// and its arbitrary config map values.
func newReceiverTemplate(name string, cfg userConfigMap) (receiverTemplate, error) {
id := component.ID{}
if err := id.UnmarshalText([]byte(name)); err != nil {
return receiverTemplate{}, err
}
return receiverTemplate{
signals: receiverSignals{metrics: true, logs: true, traces: true},
receiverConfig: receiverConfig{
id: id,
config: cfg,
endpointID: observer.EndpointID("endpoint.id"),
},
}, nil
}
var _ confmap.Unmarshaler = (*Config)(nil)
// Config defines configuration for receiver_creator.
type Config struct {
receiverTemplates map[string]receiverTemplate
// WatchObservers are the extensions to listen to endpoints from.
WatchObservers []component.ID `mapstructure:"watch_observers"`
// ResourceAttributes is a map of default resource attributes to add to each resource
// object received by this receiver from dynamically created receivers.
ResourceAttributes resourceAttributes `mapstructure:"resource_attributes"`
Discovery DiscoveryConfig `mapstructure:"discovery"`
}
type DiscoveryConfig struct {
Enabled bool `mapstructure:"enabled"`
IgnoreReceivers []string `mapstructure:"ignore_receivers"`
}
func (cfg *Config) Unmarshal(componentParser *confmap.Conf) error {
if componentParser == nil {
// Nothing to do if there is no config given.
return nil
}
if err := componentParser.Unmarshal(cfg, confmap.WithIgnoreUnused()); err != nil {
return err
}
for endpointType := range cfg.ResourceAttributes {
switch endpointType {
case observer.ContainerType, observer.K8sServiceType, observer.K8sIngressType, observer.HostPortType, observer.K8sNodeType, observer.PodType, observer.PortType, observer.PodContainerType:
default:
return fmt.Errorf("resource attributes for unsupported endpoint type %q", endpointType)
}
}
receiversCfg, err := componentParser.Sub(receiversConfigKey)
if err != nil {
return fmt.Errorf("unable to extract key %v: %w", receiversConfigKey, err)
}
for subreceiverKey := range receiversCfg.ToStringMap() {
subreceiverSection, err := receiversCfg.Sub(subreceiverKey)
if err != nil {
return fmt.Errorf("unable to extract subreceiver key %v: %w", subreceiverKey, err)
}
cfgSection := cast.ToStringMap(subreceiverSection.Get(configKey))
subreceiver, err := newReceiverTemplate(subreceiverKey, cfgSection)
if err != nil {
return err
}
// Unmarshals receiver_creator configuration like rule.
if err = subreceiverSection.Unmarshal(&subreceiver, confmap.WithIgnoreUnused()); err != nil {
return fmt.Errorf("failed to deserialize sub-receiver %q: %w", subreceiverKey, err)
}
subreceiver.rule, err = newRule(subreceiver.Rule)
if err != nil {
return fmt.Errorf("subreceiver %q rule is invalid: %w", subreceiverKey, err)
}
for k, v := range subreceiver.ResourceAttributes {
if _, ok := v.(string); !ok {
return fmt.Errorf("unsupported `resource_attributes` %q value %v in %s", k, v, subreceiverKey)
}
}
cfg.receiverTemplates[subreceiverKey] = subreceiver
}
return nil
}