config.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package datadogexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter"
  4. import (
  5. "encoding"
  6. "errors"
  7. "fmt"
  8. "regexp"
  9. "strings"
  10. "go.opentelemetry.io/collector/component"
  11. "go.opentelemetry.io/collector/config/confignet"
  12. "go.opentelemetry.io/collector/config/configopaque"
  13. "go.opentelemetry.io/collector/confmap"
  14. "go.opentelemetry.io/collector/exporter/exporterhelper"
  15. "go.uber.org/zap"
  16. "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter/internal/hostmetadata/valid"
  17. )
  18. var (
  19. errUnsetAPIKey = errors.New("api.key is not set")
  20. errNoMetadata = errors.New("only_metadata can't be enabled when host_metadata::enabled = false or host_metadata::hostname_source != first_resource")
  21. errEmptyEndpoint = errors.New("endpoint cannot be empty")
  22. )
  23. const (
  24. // DefaultSite is the default site of the Datadog intake to send data to
  25. DefaultSite = "datadoghq.com"
  26. )
  27. // APIConfig defines the API configuration options
  28. type APIConfig struct {
  29. // Key is the Datadog API key to associate your Agent's data with your organization.
  30. // Create a new API key here: https://app.datadoghq.com/account/settings
  31. Key configopaque.String `mapstructure:"key"`
  32. // Site is the site of the Datadog intake to send data to.
  33. // The default value is "datadoghq.com".
  34. Site string `mapstructure:"site"`
  35. // FailOnInvalidKey states whether to exit at startup on invalid API key.
  36. // The default value is false.
  37. FailOnInvalidKey bool `mapstructure:"fail_on_invalid_key"`
  38. }
  39. // MetricsConfig defines the metrics exporter specific configuration options
  40. type MetricsConfig struct {
  41. // DeltaTTL defines the time that previous points of a cumulative monotonic
  42. // metric are kept in memory to calculate deltas
  43. DeltaTTL int64 `mapstructure:"delta_ttl"`
  44. // TCPAddr.Endpoint is the host of the Datadog intake server to send metrics to.
  45. // If unset, the value is obtained from the Site.
  46. confignet.TCPAddr `mapstructure:",squash"`
  47. ExporterConfig MetricsExporterConfig `mapstructure:",squash"`
  48. // HistConfig defines the export of OTLP Histograms.
  49. HistConfig HistogramConfig `mapstructure:"histograms"`
  50. // SumConfig defines the export of OTLP Sums.
  51. SumConfig SumConfig `mapstructure:"sums"`
  52. // SummaryConfig defines the export for OTLP Summaries.
  53. SummaryConfig SummaryConfig `mapstructure:"summaries"`
  54. }
  55. type HistogramMode string
  56. const (
  57. // HistogramModeNoBuckets reports no bucket histogram metrics. .sum and .count metrics will still be sent
  58. // if `send_count_sum_metrics` is enabled.
  59. HistogramModeNoBuckets HistogramMode = "nobuckets"
  60. // HistogramModeCounters reports histograms as Datadog counts, one metric per bucket.
  61. HistogramModeCounters HistogramMode = "counters"
  62. // HistogramModeDistributions reports histograms as Datadog distributions (recommended).
  63. HistogramModeDistributions HistogramMode = "distributions"
  64. )
  65. var _ encoding.TextUnmarshaler = (*HistogramMode)(nil)
  66. func (hm *HistogramMode) UnmarshalText(in []byte) error {
  67. switch mode := HistogramMode(in); mode {
  68. case HistogramModeCounters, HistogramModeDistributions, HistogramModeNoBuckets:
  69. *hm = mode
  70. return nil
  71. default:
  72. return fmt.Errorf("invalid histogram mode %q", mode)
  73. }
  74. }
  75. // HistogramConfig customizes export of OTLP Histograms.
  76. type HistogramConfig struct {
  77. // Mode for exporting histograms. Valid values are 'distributions', 'counters' or 'nobuckets'.
  78. // - 'distributions' sends histograms as Datadog distributions (recommended).
  79. // - 'counters' sends histograms as Datadog counts, one metric per bucket.
  80. // - 'nobuckets' sends no bucket histogram metrics. Aggregation metrics will still be sent
  81. // if `send_aggregation_metrics` is enabled.
  82. //
  83. // The current default is 'distributions'.
  84. Mode HistogramMode `mapstructure:"mode"`
  85. // SendCountSum states if the export should send .sum and .count metrics for histograms.
  86. // The default is false.
  87. // Deprecated: [v0.75.0] Use `send_aggregation_metrics` (HistogramConfig.SendAggregations) instead.
  88. SendCountSum bool `mapstructure:"send_count_sum_metrics"`
  89. // SendAggregations states if the exporter should send .sum, .count, .min and .max metrics for histograms.
  90. // The default is false.
  91. SendAggregations bool `mapstructure:"send_aggregation_metrics"`
  92. }
  93. func (c *HistogramConfig) validate() error {
  94. if c.Mode == HistogramModeNoBuckets && !c.SendAggregations {
  95. return fmt.Errorf("'nobuckets' mode and `send_aggregation_metrics` set to false will send no histogram metrics")
  96. }
  97. return nil
  98. }
  99. // CumulativeMonotonicSumMode is the export mode for OTLP Sum metrics.
  100. type CumulativeMonotonicSumMode string
  101. const (
  102. // CumulativeMonotonicSumModeToDelta calculates delta for
  103. // cumulative monotonic sum metrics in the client side and reports
  104. // them as Datadog counts.
  105. CumulativeMonotonicSumModeToDelta CumulativeMonotonicSumMode = "to_delta"
  106. // CumulativeMonotonicSumModeRawValue reports the raw value for
  107. // cumulative monotonic sum metrics as a Datadog gauge.
  108. CumulativeMonotonicSumModeRawValue CumulativeMonotonicSumMode = "raw_value"
  109. )
  110. var _ encoding.TextUnmarshaler = (*CumulativeMonotonicSumMode)(nil)
  111. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  112. func (sm *CumulativeMonotonicSumMode) UnmarshalText(in []byte) error {
  113. switch mode := CumulativeMonotonicSumMode(in); mode {
  114. case CumulativeMonotonicSumModeToDelta,
  115. CumulativeMonotonicSumModeRawValue:
  116. *sm = mode
  117. return nil
  118. default:
  119. return fmt.Errorf("invalid cumulative monotonic sum mode %q", mode)
  120. }
  121. }
  122. // InitialValueMode defines what the exporter should do with the initial value
  123. // of a time series when transforming from cumulative to delta.
  124. type InitialValueMode string
  125. const (
  126. // InitialValueModeAuto reports the initial value if its start timestamp
  127. // is set and it happens after the process was started.
  128. InitialValueModeAuto InitialValueMode = "auto"
  129. // InitialValueModeDrop always drops the initial value.
  130. InitialValueModeDrop InitialValueMode = "drop"
  131. // InitialValueModeKeep always reports the initial value.
  132. InitialValueModeKeep InitialValueMode = "keep"
  133. )
  134. var _ encoding.TextUnmarshaler = (*InitialValueMode)(nil)
  135. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  136. func (iv *InitialValueMode) UnmarshalText(in []byte) error {
  137. switch mode := InitialValueMode(in); mode {
  138. case InitialValueModeAuto,
  139. InitialValueModeDrop,
  140. InitialValueModeKeep:
  141. *iv = mode
  142. return nil
  143. default:
  144. return fmt.Errorf("invalid initial value mode %q", mode)
  145. }
  146. }
  147. // SumConfig customizes export of OTLP Sums.
  148. type SumConfig struct {
  149. // CumulativeMonotonicMode is the mode for exporting OTLP Cumulative Monotonic Sums.
  150. // Valid values are 'to_delta' or 'raw_value'.
  151. // - 'to_delta' calculates delta for cumulative monotonic sums and sends it as a Datadog count.
  152. // - 'raw_value' sends the raw value of cumulative monotonic sums as Datadog gauges.
  153. //
  154. // The default is 'to_delta'.
  155. // See https://docs.datadoghq.com/metrics/otlp/?tab=sum#mapping for details and examples.
  156. CumulativeMonotonicMode CumulativeMonotonicSumMode `mapstructure:"cumulative_monotonic_mode"`
  157. // InitialCumulativeMonotonicMode defines the behavior of the exporter when receiving the first value
  158. // of a cumulative monotonic sum.
  159. InitialCumulativeMonotonicMode InitialValueMode `mapstructure:"initial_cumulative_monotonic_value"`
  160. }
  161. // SummaryMode is the export mode for OTLP Summary metrics.
  162. type SummaryMode string
  163. const (
  164. // SummaryModeNoQuantiles sends no `.quantile` metrics. `.sum` and `.count` metrics will still be sent.
  165. SummaryModeNoQuantiles SummaryMode = "noquantiles"
  166. // SummaryModeGauges sends `.quantile` metrics as gauges tagged by the quantile.
  167. SummaryModeGauges SummaryMode = "gauges"
  168. )
  169. var _ encoding.TextUnmarshaler = (*SummaryMode)(nil)
  170. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  171. func (sm *SummaryMode) UnmarshalText(in []byte) error {
  172. switch mode := SummaryMode(in); mode {
  173. case SummaryModeNoQuantiles,
  174. SummaryModeGauges:
  175. *sm = mode
  176. return nil
  177. default:
  178. return fmt.Errorf("invalid summary mode %q", mode)
  179. }
  180. }
  181. // SummaryConfig customizes export of OTLP Summaries.
  182. type SummaryConfig struct {
  183. // Mode is the the mode for exporting OTLP Summaries.
  184. // Valid values are 'noquantiles' or 'gauges'.
  185. // - 'noquantiles' sends no `.quantile` metrics. `.sum` and `.count` metrics will still be sent.
  186. // - 'gauges' sends `.quantile` metrics as gauges tagged by the quantile.
  187. //
  188. // The default is 'gauges'.
  189. // See https://docs.datadoghq.com/metrics/otlp/?tab=summary#mapping for details and examples.
  190. Mode SummaryMode `mapstructure:"mode"`
  191. }
  192. // MetricsExporterConfig provides options for a user to customize the behavior of the
  193. // metrics exporter
  194. type MetricsExporterConfig struct {
  195. // ResourceAttributesAsTags, if set to true, will use the exporterhelper feature to transform all
  196. // resource attributes into metric labels, which are then converted into tags
  197. ResourceAttributesAsTags bool `mapstructure:"resource_attributes_as_tags"`
  198. // InstrumentationScopeMetadataAsTags, if set to true, adds the name and version of the
  199. // instrumentation scope that created a metric to the metric tags
  200. InstrumentationScopeMetadataAsTags bool `mapstructure:"instrumentation_scope_metadata_as_tags"`
  201. }
  202. // TracesConfig defines the traces exporter specific configuration options
  203. type TracesConfig struct {
  204. // TCPAddr.Endpoint is the host of the Datadog intake server to send traces to.
  205. // If unset, the value is obtained from the Site.
  206. confignet.TCPAddr `mapstructure:",squash"`
  207. // ignored resources
  208. // A blacklist of regular expressions can be provided to disable certain traces based on their resource name
  209. // all entries must be surrounded by double quotes and separated by commas.
  210. // ignore_resources: ["(GET|POST) /healthcheck"]
  211. IgnoreResources []string `mapstructure:"ignore_resources"`
  212. // SpanNameRemappings is the map of datadog span names and preferred name to map to. This can be used to
  213. // automatically map Datadog Span Operation Names to an updated value. All entries should be key/value pairs.
  214. // span_name_remappings:
  215. // io.opentelemetry.javaagent.spring.client: spring.client
  216. // instrumentation:express.server: express
  217. // go.opentelemetry.io_contrib_instrumentation_net_http_otelhttp.client: http.client
  218. SpanNameRemappings map[string]string `mapstructure:"span_name_remappings"`
  219. // If set to true the OpenTelemetry span name will used in the Datadog resource name.
  220. // If set to false the resource name will be filled with the instrumentation library name + span kind.
  221. // The default value is `false`.
  222. SpanNameAsResourceName bool `mapstructure:"span_name_as_resource_name"`
  223. // If set to true, enables an additional stats computation check on spans to see they have an eligible `span.kind` (server, consumer, client, producer).
  224. // If enabled, a span with an eligible `span.kind` will have stats computed. If disabled, only top-level and measured spans will have stats computed.
  225. // NOTE: For stats computed from OTel traces, only top-level spans are considered when this option is off.
  226. ComputeStatsBySpanKind bool `mapstructure:"compute_stats_by_span_kind"`
  227. // If set to true, enables `peer.service` aggregation in the exporter. If disabled, aggregated trace stats will not include `peer.service` as a dimension.
  228. // For the best experience with `peer.service`, it is recommended to also enable `compute_stats_by_span_kind`.
  229. // If enabling both causes the datadog exporter to consume too many resources, try disabling `compute_stats_by_span_kind` first.
  230. // If the overhead remains high, it will be due to a high cardinality of `peer.service` values from the traces. You may need to check your instrumentation.
  231. // Deprecated: Please use PeerTagsAggregation instead
  232. PeerServiceAggregation bool `mapstructure:"peer_service_aggregation"`
  233. // If set to true, enables aggregation of peer related tags (e.g., `peer.service`, `db.instance`, etc.) in the datadog exporter.
  234. // If disabled, aggregated trace stats will not include these tags as dimensions on trace metrics.
  235. // For the best experience with peer tags, Datadog also recommends enabling `compute_stats_by_span_kind`.
  236. // If you are using an OTel tracer, it's best to have both enabled because client/producer spans with relevant peer tags
  237. // may not be marked by the datadog exporter as top-level spans.
  238. // If enabling both causes the datadog exporter to consume too many resources, try disabling `compute_stats_by_span_kind` first.
  239. // A high cardinality of peer tags or APM resources can also contribute to higher CPU and memory consumption.
  240. // You can check for the cardinality of these fields by making trace search queries in the Datadog UI.
  241. // The default list of peer tags can be found in https://github.com/DataDog/datadog-agent/blob/main/pkg/trace/stats/concentrator.go.
  242. PeerTagsAggregation bool `mapstructure:"peer_tags_aggregation"`
  243. // TraceBuffer specifies the number of Datadog Agent TracerPayloads to buffer before dropping.
  244. // The default value is 0, meaning the Datadog Agent TracerPayloads are unbuffered.
  245. TraceBuffer int `mapstructure:"trace_buffer"`
  246. // flushInterval defines the interval in seconds at which the writer flushes traces
  247. // to the intake; used in tests.
  248. flushInterval float64
  249. }
  250. // LogsConfig defines logs exporter specific configuration
  251. type LogsConfig struct {
  252. // TCPAddr.Endpoint is the host of the Datadog intake server to send logs to.
  253. // If unset, the value is obtained from the Site.
  254. confignet.TCPAddr `mapstructure:",squash"`
  255. // DumpPayloads report whether payloads should be dumped when logging level is debug.
  256. DumpPayloads bool `mapstructure:"dump_payloads"`
  257. }
  258. // TagsConfig defines the tag-related configuration
  259. // It is embedded in the configuration
  260. type TagsConfig struct {
  261. // Hostname is the host name for unified service tagging.
  262. // If unset, it is determined automatically.
  263. Hostname string `mapstructure:"hostname"`
  264. }
  265. // HostnameSource is the source for the hostname of host metadata.
  266. type HostnameSource string
  267. const (
  268. // HostnameSourceFirstResource picks the host metadata hostname from the resource
  269. // attributes on the first OTLP payload that gets to the exporter. If it is lacking any
  270. // hostname-like attributes, it will fallback to 'config_or_system' behavior (see below).
  271. //
  272. // Do not use this hostname source if receiving data from multiple hosts.
  273. HostnameSourceFirstResource HostnameSource = "first_resource"
  274. // HostnameSourceConfigOrSystem picks the host metadata hostname from the 'hostname' setting,
  275. // and if this is empty, from available system APIs and cloud provider endpoints.
  276. HostnameSourceConfigOrSystem HostnameSource = "config_or_system"
  277. )
  278. var _ encoding.TextUnmarshaler = (*HostnameSource)(nil)
  279. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  280. func (sm *HostnameSource) UnmarshalText(in []byte) error {
  281. switch mode := HostnameSource(in); mode {
  282. case HostnameSourceFirstResource,
  283. HostnameSourceConfigOrSystem:
  284. *sm = mode
  285. return nil
  286. default:
  287. return fmt.Errorf("invalid host metadata hostname source %q", mode)
  288. }
  289. }
  290. // HostMetadataConfig defines the host metadata related configuration.
  291. // Host metadata is the information used for populating the infrastructure list,
  292. // the host map and providing host tags functionality.
  293. //
  294. // The exporter will send host metadata for a single host, whose name is chosen
  295. // according to `host_metadata::hostname_source`.
  296. type HostMetadataConfig struct {
  297. // Enabled enables the host metadata functionality.
  298. Enabled bool `mapstructure:"enabled"`
  299. // HostnameSource is the source for the hostname of host metadata.
  300. // Valid values are 'first_resource' and 'config_or_system':
  301. // - 'first_resource' picks the host metadata hostname from the resource
  302. // attributes on the first OTLP payload that gets to the exporter.
  303. // If the first payload lacks hostname-like attributes, it will fallback to 'config_or_system'.
  304. // Do not use this hostname source if receiving data from multiple hosts.
  305. // - 'config_or_system' picks the host metadata hostname from the 'hostname' setting,
  306. // If this is empty it will use available system APIs and cloud provider endpoints.
  307. //
  308. // The default is 'config_or_system'.
  309. HostnameSource HostnameSource `mapstructure:"hostname_source"`
  310. // Tags is a list of host tags.
  311. // These tags will be attached to telemetry signals that have the host metadata hostname.
  312. // To attach tags to telemetry signals regardless of the host, use a processor instead.
  313. Tags []string `mapstructure:"tags"`
  314. }
  315. // LimitedTLSClientSetting is a subset of TLSClientSetting, see LimitedHTTPClientSettings for more details
  316. type LimitedTLSClientSettings struct {
  317. // InsecureSkipVerify controls whether a client verifies the server's
  318. // certificate chain and host name.
  319. InsecureSkipVerify bool `mapstructure:"insecure_skip_verify"`
  320. }
  321. type LimitedHTTPClientSettings struct {
  322. TLSSetting LimitedTLSClientSettings `mapstructure:"tls,omitempty"`
  323. }
  324. // Config defines configuration for the Datadog exporter.
  325. type Config struct {
  326. exporterhelper.TimeoutSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct.
  327. exporterhelper.QueueSettings `mapstructure:"sending_queue"`
  328. exporterhelper.RetrySettings `mapstructure:"retry_on_failure"`
  329. LimitedHTTPClientSettings `mapstructure:",squash"`
  330. TagsConfig `mapstructure:",squash"`
  331. // API defines the Datadog API configuration.
  332. API APIConfig `mapstructure:"api"`
  333. // Metrics defines the Metrics exporter specific configuration
  334. Metrics MetricsConfig `mapstructure:"metrics"`
  335. // Traces defines the Traces exporter specific configuration
  336. Traces TracesConfig `mapstructure:"traces"`
  337. // Logs defines the Logs exporter specific configuration
  338. Logs LogsConfig `mapstructure:"logs"`
  339. // HostMetadata defines the host metadata specific configuration
  340. HostMetadata HostMetadataConfig `mapstructure:"host_metadata"`
  341. // OnlyMetadata defines whether to only send metadata
  342. // This is useful for agent-collector setups, so that
  343. // metadata about a host is sent to the backend even
  344. // when telemetry data is reported via a different host.
  345. //
  346. // This flag is incompatible with disabling host metadata,
  347. // `use_resource_metadata`, or `host_metadata::hostname_source != first_resource`
  348. OnlyMetadata bool `mapstructure:"only_metadata"`
  349. // Non-fatal warnings found during configuration loading.
  350. warnings []error
  351. }
  352. // logWarnings logs warning messages that were generated on unmarshaling.
  353. func (c *Config) logWarnings(logger *zap.Logger) {
  354. for _, err := range c.warnings {
  355. logger.Warn(fmt.Sprintf("%v", err))
  356. }
  357. }
  358. var _ component.Config = (*Config)(nil)
  359. // Validate the configuration for errors. This is required by component.Config.
  360. func (c *Config) Validate() error {
  361. if c.OnlyMetadata && (!c.HostMetadata.Enabled || c.HostMetadata.HostnameSource != HostnameSourceFirstResource) {
  362. return errNoMetadata
  363. }
  364. if err := valid.Hostname(c.Hostname); c.Hostname != "" && err != nil {
  365. return fmt.Errorf("hostname field is invalid: %w", err)
  366. }
  367. if c.API.Key == "" {
  368. return errUnsetAPIKey
  369. }
  370. if c.Traces.IgnoreResources != nil {
  371. for _, entry := range c.Traces.IgnoreResources {
  372. _, err := regexp.Compile(entry)
  373. if err != nil {
  374. return fmt.Errorf("'%s' is not valid resource filter regular expression", entry)
  375. }
  376. }
  377. }
  378. if c.Traces.SpanNameRemappings != nil {
  379. for key, value := range c.Traces.SpanNameRemappings {
  380. if value == "" {
  381. return fmt.Errorf("'%s' is not valid value for span name remapping", value)
  382. }
  383. if key == "" {
  384. return fmt.Errorf("'%s' is not valid key for span name remapping", key)
  385. }
  386. }
  387. }
  388. err := c.Metrics.HistConfig.validate()
  389. if err != nil {
  390. return err
  391. }
  392. return nil
  393. }
  394. var _ error = (*renameError)(nil)
  395. // renameError is an error related to a renamed setting.
  396. type renameError struct {
  397. // oldName of the configuration option.
  398. oldName string
  399. // newName of the configuration option.
  400. newName string
  401. // issueNumber on opentelemetry-collector-contrib for tracking
  402. issueNumber uint
  403. }
  404. // List of settings that have been removed, but for which we keep a custom error.
  405. var removedSettings = []renameError{
  406. {
  407. oldName: "metrics::send_monotonic_counter",
  408. newName: "metrics::sums::cumulative_monotonic_mode",
  409. issueNumber: 8489,
  410. },
  411. {
  412. oldName: "tags",
  413. newName: "host_metadata::tags",
  414. issueNumber: 9099,
  415. },
  416. {
  417. oldName: "send_metadata",
  418. newName: "host_metadata::enabled",
  419. issueNumber: 9099,
  420. },
  421. {
  422. oldName: "use_resource_metadata",
  423. newName: "host_metadata::hostname_source",
  424. issueNumber: 9099,
  425. },
  426. {
  427. oldName: "metrics::report_quantiles",
  428. newName: "metrics::summaries::mode",
  429. issueNumber: 8845,
  430. },
  431. {
  432. oldName: "metrics::instrumentation_library_metadata_as_tags",
  433. newName: "metrics::instrumentation_scope_as_tags",
  434. issueNumber: 11135,
  435. },
  436. }
  437. // Error implements the error interface.
  438. func (e renameError) Error() string {
  439. return fmt.Sprintf(
  440. "%q was removed in favor of %q. See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/%d",
  441. e.oldName,
  442. e.newName,
  443. e.issueNumber,
  444. )
  445. }
  446. func handleRemovedSettings(configMap *confmap.Conf) error {
  447. var errs []error
  448. for _, removedErr := range removedSettings {
  449. if configMap.IsSet(removedErr.oldName) {
  450. errs = append(errs, removedErr)
  451. }
  452. }
  453. return errors.Join(errs...)
  454. }
  455. var _ confmap.Unmarshaler = (*Config)(nil)
  456. // Unmarshal a configuration map into the configuration struct.
  457. func (c *Config) Unmarshal(configMap *confmap.Conf) error {
  458. if err := handleRemovedSettings(configMap); err != nil {
  459. return err
  460. }
  461. err := configMap.Unmarshal(c, confmap.WithErrorUnused())
  462. if err != nil {
  463. return err
  464. }
  465. // Add deprecation warnings for deprecated settings.
  466. renamingWarnings, err := handleRenamedSettings(configMap, c)
  467. if err != nil {
  468. return err
  469. }
  470. c.warnings = append(c.warnings, renamingWarnings...)
  471. c.API.Key = configopaque.String(strings.TrimSpace(string(c.API.Key)))
  472. // If an endpoint is not explicitly set, override it based on the site.
  473. if !configMap.IsSet("metrics::endpoint") {
  474. c.Metrics.TCPAddr.Endpoint = fmt.Sprintf("https://api.%s", c.API.Site)
  475. }
  476. if !configMap.IsSet("traces::endpoint") {
  477. c.Traces.TCPAddr.Endpoint = fmt.Sprintf("https://trace.agent.%s", c.API.Site)
  478. }
  479. if !configMap.IsSet("logs::endpoint") {
  480. c.Logs.TCPAddr.Endpoint = fmt.Sprintf("https://http-intake.logs.%s", c.API.Site)
  481. }
  482. // Return an error if an endpoint is explicitly set to ""
  483. if c.Metrics.TCPAddr.Endpoint == "" || c.Traces.TCPAddr.Endpoint == "" || c.Logs.TCPAddr.Endpoint == "" {
  484. return errEmptyEndpoint
  485. }
  486. const (
  487. initialValueSetting = "metrics::sums::initial_cumulative_monotonic_value"
  488. cumulMonoMode = "metrics::sums::cumulative_monotonic_mode"
  489. )
  490. if configMap.IsSet(initialValueSetting) && c.Metrics.SumConfig.CumulativeMonotonicMode != CumulativeMonotonicSumModeToDelta {
  491. return fmt.Errorf("%q can only be configured when %q is set to %q",
  492. initialValueSetting, cumulMonoMode, CumulativeMonotonicSumModeToDelta)
  493. }
  494. return nil
  495. }