Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[exporter/datadog] Deprecate automatic environment variable detection #8397

Merged
merged 4 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
- Use "--feature-gates=receiver.k8sclusterreceiver.reportCpuMetricsAsDouble" to enable reporting node and container
cpu metrics as a double values.

### 🚩 Deprecations 🚩

- `datadogexporter`: Deprecate automatic environment variable detection (#8397)

### 🚀 New components 🚀

## v0.46.0
Expand Down
24 changes: 15 additions & 9 deletions exporter/datadogexporter/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ const (
type APIConfig struct {
// Key is the Datadog API key to associate your Agent's data with your organization.
// Create a new API key here: https://app.datadoghq.com/account/settings
// It can also be set through the `DD_API_KEY` environment variable.
//
// It can also be set through the `DD_API_KEY` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
Key string `mapstructure:"key"`

// Site is the site of the Datadog intake to send data to.
// It can also be set through the `DD_SITE` environment variable.
// It can also be set through the `DD_SITE` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
// The default value is "datadoghq.com".
Site string `mapstructure:"site"`
}
Expand Down Expand Up @@ -82,7 +83,7 @@ type MetricsConfig struct {
DeltaTTL int64 `mapstructure:"delta_ttl"`

// TCPAddr.Endpoint is the host of the Datadog intake server to send metrics to.
// It can also be set through the `DD_URL` environment variable.
// It can also be set through the `DD_URL` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead)..
// If unset, the value is obtained from the Site.
confignet.TCPAddr `mapstructure:",squash"`

Expand Down Expand Up @@ -130,7 +131,7 @@ type MetricsExporterConfig struct {
// TracesConfig defines the traces exporter specific configuration options
type TracesConfig struct {
// TCPAddr.Endpoint is the host of the Datadog intake server to send traces to.
// It can also be set through the `DD_APM_URL` environment variable.
// It can also be set through the `DD_APM_URL` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
// If unset, the value is obtained from the Site.
confignet.TCPAddr `mapstructure:",squash"`

Expand Down Expand Up @@ -163,27 +164,29 @@ type TracesConfig struct {
// It is embedded in the configuration
type TagsConfig struct {
// Hostname is the host name for unified service tagging.
// It can also be set through the `DD_HOST` environment variable.
// It can also be set through the `DD_HOST` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
// If unset, it is determined automatically.
// See https://docs.datadoghq.com/agent/faq/how-datadog-agent-determines-the-hostname
// for more details.
Hostname string `mapstructure:"hostname"`

// Env is the environment for unified service tagging.
// It can also be set through the `DD_ENV` environment variable.
// It can also be set through the `DD_ENV` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
Env string `mapstructure:"env"`

// Service is the service for unified service tagging.
// It can also be set through the `DD_SERVICE` environment variable.
// It can also be set through the `DD_SERVICE` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
Service string `mapstructure:"service"`

// Version is the version for unified service tagging.
// It can also be set through the `DD_VERSION` environment variable.
// It can also be set through the `DD_VERSION` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
Version string `mapstructure:"version"`

// EnvVarTags is the list of space-separated tags passed by the `DD_TAGS` environment variable
// Superseded by Tags if the latter is set.
// Should not be set in the user-provided config.
//
// Deprecated: [v0.47.0] Use Tags instead.
EnvVarTags string `mapstructure:"envvartags"`

// Tags is the list of default tags to add to every metric or trace.
Expand Down Expand Up @@ -304,7 +307,7 @@ func (c *Config) Sanitize(logger *zap.Logger) error {
}

for _, err := range c.warnings {
logger.Warn("deprecation warning", zap.Error(err))
logger.Warn(fmt.Sprintf("Deprecated: %v", err))
}

return nil
Expand Down Expand Up @@ -352,5 +355,8 @@ func (c *Config) Unmarshal(configMap *config.Map) error {
return fmt.Errorf("invalid `mode` %s", c.Metrics.HistConfig.Mode)
}

// Add warnings about autodetected environment variables.
c.warnings = append(c.warnings, warnUseOfEnvVars(configMap, c)...)

return nil
}
145 changes: 145 additions & 0 deletions exporter/datadogexporter/config/warn_envvars.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package config // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter/config"

import (
"fmt"
"time"

"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/exporter/exporterhelper"
)

// futureDefaultConfig returns the future default config we will use from v0.50 onwards.
func futureDefaultConfig() *Config {
return &Config{
ExporterSettings: config.NewExporterSettings(config.NewComponentID("datadog")),
TimeoutSettings: exporterhelper.TimeoutSettings{
Timeout: 15 * time.Second,
},
RetrySettings: exporterhelper.NewDefaultRetrySettings(),
QueueSettings: exporterhelper.NewDefaultQueueSettings(),
Metrics: MetricsConfig{
SendMonotonic: true,
DeltaTTL: 3600,
Quantiles: true,
ExporterConfig: MetricsExporterConfig{
ResourceAttributesAsTags: false,
InstrumentationLibraryMetadataAsTags: false,
},
HistConfig: HistogramConfig{
Mode: "distributions",
SendCountSum: false,
},
},
Traces: TracesConfig{
SampleRate: 1,
IgnoreResources: []string{},
},
SendMetadata: true,
UseResourceMetadata: true,
}
}

// errUsedEnvVar constructs an error instructing users not to rely on
// the automatic environment variable detection and set the environment variable
// explicitly on configuration instead.
func errUsedEnvVar(settingName, envVarName string) error {
return fmt.Errorf(
"%q will not default to %q's value starting on v0.50.0. Set %s: ${%s} to remove this warning",
settingName,
envVarName,
settingName,
envVarName,
)
}

// tagsDiffer checks if the host tags from each configuration are different.
func tagsDiffer(cfgTags []string, futureTags []string) bool {
if len(cfgTags) != len(futureTags) {
return true
}

oldCfgSet := map[string]struct{}{}
for _, tag := range cfgTags {
oldCfgSet[tag] = struct{}{}
}

for _, tag := range futureTags {
if _, ok := oldCfgSet[tag]; !ok {
// tag is in old but not new
return true
}
}

return false
}

// warnUseOfEnvVars returns warnings related to automatic environment variable detection.
// Right now, we automatically get the value for e.g. the API key from DD_API_KEY, even if
// the user is not doing `api.key: ${DD_API_KEY}`. We are going to remove this functionality.
func warnUseOfEnvVars(configMap *config.Map, cfg *Config) (warnings []error) {
// We don't see the raw YAML contents from our exporter so, to compare with the new default,
// we unmarshal the config map on the future default config and compare the two structs.
// Any differences will be due to the change in default configuration.
futureCfg := futureDefaultConfig()
err := configMap.UnmarshalExact(futureCfg)

errIssue := fmt.Errorf("see github.com/open-telemetry/opentelemetry-collector-contrib/issues/8396 for more details")

if err != nil {
// This should never happen, since unmarshaling passed with the original config.
// If it happens, report the error and instruct users to check the issue.
return []error{
fmt.Errorf("failed to determine usage of env variable defaults: %w", err),
errIssue,
}
}

// We could probably do this with reflection but I don't want to risk
// an accidental panic so we check each field manually.
if cfg.API.Key != futureCfg.API.Key {
mx-psi marked this conversation as resolved.
Show resolved Hide resolved
warnings = append(warnings, errUsedEnvVar("api.key", "DD_API_KEY"))
}
if cfg.API.Site != futureCfg.API.Site {
warnings = append(warnings, errUsedEnvVar("api.site", "DD_SITE"))
}
if cfg.Hostname != futureCfg.Hostname {
warnings = append(warnings, errUsedEnvVar("hostname", "DD_HOST"))
}
if cfg.Env != futureCfg.Env {
warnings = append(warnings, errUsedEnvVar("env", "DD_ENV"))
}
if cfg.Service != futureCfg.Service {
warnings = append(warnings, errUsedEnvVar("service", "DD_SERVICE"))
}
if cfg.Version != futureCfg.Version {
warnings = append(warnings, errUsedEnvVar("version", "DD_VERSION"))
}
if cfg.Metrics.Endpoint != futureCfg.Metrics.Endpoint {
warnings = append(warnings, errUsedEnvVar("metrics.endpoint", "DD_URL"))
}
if cfg.Traces.Endpoint != futureCfg.Traces.Endpoint {
warnings = append(warnings, errUsedEnvVar("traces.endpoint", "DD_APM_URL"))
}
if tagsDiffer(cfg.GetHostTags(), futureCfg.GetHostTags()) {
warnings = append(warnings, fmt.Errorf("\"tags\" will not default to \"DD_TAGS\"'s value starting on v0.50.0. Use 'env' configuration source instead to remove this warning"))
}

if len(warnings) > 0 {
warnings = append(warnings, errIssue)
}
return
}
18 changes: 9 additions & 9 deletions exporter/datadogexporter/example/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,33 @@ exporters:
datadog:
## @param hostname - string - optional
## A custom hostname.
## If unset it will be determined from the `DD_HOST` environment variable.
## If unset it will be determined from the `DD_HOST` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
## If both this and `DD_HOST` are unset, this will be determined automatically if possible.
#
# hostname: customhostname

## @param env - string - optional
## The environment for unified service tagging.
## If unset it will be determined from the `DD_ENV` environment variable.
## If unset it will be determined from the `DD_ENV` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
#
# env: prod

## @param service - string - optional
## The service for unified service tagging.
## If unset it will be determined from the `DD_SERVICE` environment variable.
## If unset it will be determined from the `DD_SERVICE` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
#
# service: myservice

## @param version - string - optional
## The version for unified service tagging.
## If unset it will be determined from the `DD_VERSION` environment variable.
## If unset it will be determined from the `DD_VERSION` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
#
# version: myversion

## @param tags - list of strings - optional - default: []
## The list of default tags to add to every metric or trace.
## If unset it will be determined from the `DD_TAGS` environment variable, specified
## as a list of space-separated strings.
## as a list of space-separated strings (Deprecated: [v0.47.0] use 'env' config source instead).
#
# tags: []

Expand All @@ -50,14 +50,14 @@ exporters:
## @ param key - string - required
## The Datadog API key to associate your Agent's data with your organization.
## Create a new API key here: https://app.datadoghq.com/account/settings
## If unset it will be determined from the `DD_API_KEY` environment variable.
## If unset it will be determined from the `DD_API_KEY` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
#
key: "<YOUR API KEY>"

## @param site - string - optional - default: datadoghq.com
## The site of the Datadog intake to send Agent data to.
## Set to 'datadoghq.eu' to send data to the EU site.
## If unset it will be determined from the `DD_SITE` environment variable.
## If unset it will be determined from the `DD_SITE` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
#
# site: datadoghq.com

Expand Down Expand Up @@ -86,7 +86,7 @@ exporters:

## @param endpoint - string - optional
## The host of the Datadog intake server to send metrics to.
## If unset it will be determined from the `DD_URL` environment variable.
## If unset it will be determined from the `DD_URL` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
## If both this and `DD_URL` are unset, the value is obtained through the `site` parameter in the `api` section.
#
# endpoint: https://api.datadoghq.com
Expand Down Expand Up @@ -132,7 +132,7 @@ exporters:

## @param endpoint - string - optional
## The host of the Datadog intake server to send traces to.
## If unset it will be determined from the `DD_APM_URL` environment variable.
## If unset it will be determined from the `DD_APM_URL` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead).
## If both this and `DD_APM_URL` are unset, the value is obtained through the `site` parameter in the `api` section.
#
# endpoint: https://api.datadoghq.com
Expand Down
1 change: 1 addition & 0 deletions exporter/datadogexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func defaulttimeoutSettings() exporterhelper.TimeoutSettings {
}

// createDefaultConfig creates the default exporter configuration
// TODO (#8396): Remove `os.Getenv` everywhere.
func createDefaultConfig() config.Exporter {
return &ddconfig.Config{
ExporterSettings: config.NewExporterSettings(config.NewComponentID(typeStr)),
Expand Down
Loading