forked from open-telemetry/opentelemetry-collector-contrib
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add DataDog exporter back from old fork
commit 99129fb96e29e9c1a92da00b7e3f8efcae8a31e8 Author: Pablo Baeyens <[email protected]> Date: Thu Sep 3 18:10:28 2020 +0200 Handle namespace at initialization time commit babca25927926a60c0c416294af3aadf784d41b9 Author: Pablo Baeyens <[email protected]> Date: Thu Sep 3 17:23:53 2020 +0200 Initialize on a separate function This way the variables can be checked without worrying about the env commit 24d0cb4cc566fa5313a8650c904a27bea68bf555 Author: Pablo Baeyens <[email protected]> Date: Thu Sep 3 14:30:35 2020 +0200 Check environment variables for unified service tagging commit 6695f8297ab8b1fcae71b05acb027c4a0992e3a0 Author: Pablo Baeyens <[email protected]> Date: Wed Sep 2 14:57:37 2020 +0200 Add support for sending metrics through the API - Use datadog.Metric type for simplicity - Get host if unset commit c366603 Author: Pablo Baeyens <[email protected]> Date: Wed Sep 2 09:56:24 2020 +0200 Disable Queue and Retry settings (#72) These are handled by the statsd package. OpenTelemetry docs are confusing and the default configuration (disabled) is different from the one returned by "GetDefault..." functions commit a660b56 Author: Pablo Baeyens <[email protected]> Date: Tue Sep 1 15:26:14 2020 +0200 Add support for summary and distribution metric types (#65) * Add support for summary metric type * Add support for distribution metrics * Refactor metrics construction - Drop name in Metrics (now they act as Metric values) - Refactor constructor so that errors happen at compile-time * Report Summary total sum and count values Snapshot values are not filled in by OpenTelemetry * Report p00 and p100 as `.min` and `.max` This is more similar to what we do for our own non-additive type * Keep hostname if it has not been overridden commit c95adc4 Author: Pablo Baeyens <[email protected]> Date: Thu Aug 27 13:00:02 2020 +0200 Update dependencies and `make gofmt` The collector was updated to 0.9.0 upstream commit 20afb0e Author: Pablo Baeyens <[email protected]> Date: Wed Aug 26 18:25:49 2020 +0200 Refactor configuration (#45) * Refactor configuration * Implement telemetry and tags configuration handling * Update example configuration and README file Co-authored-by: Kylian Serrania <[email protected]> commit fdc98b5 Author: Pablo Baeyens <[email protected]> Date: Fri Aug 21 11:09:08 2020 +0200 Initial DogStatsD implementation (#15) Initial metrics exporter through DogStatsD with support for all metric types but summary and distribution commit e848a60 Author: Pablo Baeyens <[email protected]> Date: Fri Aug 21 10:42:45 2020 +0200 Bump collector version commit 58be9a4 Author: Pablo Baeyens <[email protected]> Date: Thu Aug 6 10:04:32 2020 +0200 Address linter commit 695430c Author: Pablo Baeyens <[email protected]> Date: Tue Aug 4 13:28:01 2020 +0200 Fix field name error MetricsEndpoint was renamed to MetricsURL commit 168b319 Author: Pablo Baeyens <[email protected]> Date: Mon Aug 3 11:05:01 2020 +0200 Create initial outline for Datadog exporter (#1) * Add support for basic configuration options * Documents configuration options
- Loading branch information
Showing
18 changed files
with
3,108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include ../../Makefile.Common |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Datadog Exporter | ||
|
||
This exporter sends metric data to [Datadog](https://datadoghq.com). | ||
|
||
## Configuration | ||
|
||
The metrics exporter has two modes: | ||
- If sending metrics through DogStatsD (the default mode), there are no required settings. | ||
- If sending metrics without an Agent the mode must be set explicitly and | ||
you must provide a [Datadog API key](https://app.datadoghq.com/account/settings#api). | ||
```yaml | ||
datadog: | ||
api: | ||
key: "<API key>" | ||
# site: datadoghq.eu for sending data to the Datadog EU site | ||
metrics: | ||
mode: agentless | ||
``` | ||
The hostname, environment, service and version can be set in the configuration for unified service tagging. | ||
See the sample configuration file under the `example` folder for other available options. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
// 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 datadogexporter | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"go.opentelemetry.io/collector/config/configmodels" | ||
) | ||
|
||
var ( | ||
errUnsetAPIKey = errors.New("the Datadog API key is unset") | ||
) | ||
|
||
const ( | ||
NoneMode = "none" | ||
AgentlessMode = "agentless" | ||
DogStatsDMode = "dogstatsd" | ||
) | ||
|
||
// APIConfig defines the API configuration options | ||
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 | ||
Key string `mapstructure:"key"` | ||
|
||
// Site is the site of the Datadog intake to send data to. | ||
// The default value is "datadoghq.com". | ||
Site string `mapstructure:"site"` | ||
} | ||
|
||
// GetCensoredKey returns the API key censored for logging purposes | ||
func (api *APIConfig) GetCensoredKey() string { | ||
if len(api.Key) <= 5 { | ||
return api.Key | ||
} | ||
return strings.Repeat("*", len(api.Key)-5) + api.Key[:len(api.Key)-5] | ||
} | ||
|
||
// DogStatsDConfig defines the DogStatsd related configuration | ||
type DogStatsDConfig struct { | ||
// Endpoint is the DogStatsD address. | ||
// The default value is 127.0.0.1:8125 | ||
// A Unix address is supported | ||
Endpoint string `mapstructure:"endpoint"` | ||
|
||
// Telemetry states whether to send metrics | ||
Telemetry bool `mapstructure:"telemetry"` | ||
} | ||
|
||
// AgentlessConfig defines the Agentless related configuration | ||
type AgentlessConfig struct { | ||
// Endpoint is the host of the Datadog intake server to send metrics to. | ||
// If unset, the value is obtained from the Site. | ||
Endpoint string `mapstructure:"endpoint"` | ||
} | ||
|
||
// MetricsConfig defines the metrics exporter specific configuration options | ||
type MetricsConfig struct { | ||
// Namespace is the namespace under which the metrics are sent | ||
// By default metrics are not namespaced | ||
Namespace string `mapstructure:"namespace"` | ||
|
||
// Mode is the metrics sending mode: either 'dogstatsd' or 'agentless' | ||
Mode string `mapstructure:"mode"` | ||
|
||
// Percentiles states whether to report percentiles for summary metrics, | ||
// including the minimum and maximum | ||
Percentiles bool `mapstructure:"report_percentiles"` | ||
|
||
// Buckets states whether to report buckets from distribution metrics | ||
Buckets bool `mapstructure:"report_buckets"` | ||
|
||
// DogStatsD defines the DogStatsD configuration options. | ||
DogStatsD DogStatsDConfig `mapstructure:"dogstatsd"` | ||
|
||
// Agentless defines the Agentless configuration options. | ||
Agentless AgentlessConfig `mapstructure:"agentless"` | ||
} | ||
|
||
// TagsConfig defines the tag-related configuration | ||
// It is embedded in the configuration | ||
type TagsConfig struct { | ||
// Hostname is the host name for unified service tagging. | ||
// 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. | ||
Env string `mapstructure:"env"` | ||
|
||
// Service is the service for unified service tagging. | ||
// It can also be set through the `DD_SERVICE` environment variable. | ||
Service string `mapstructure:"service"` | ||
|
||
// Version is the version for unified service tagging. | ||
// It can also be set through the `DD_VERSION` version variable. | ||
Version string `mapstructure:"version"` | ||
|
||
// Tags is the list of default tags to add to every metric or trace. | ||
Tags []string `mapstructure:"tags"` | ||
} | ||
|
||
// UpdateWithEnv gets the unified service tagging information | ||
// from the environment variables. | ||
func (t *TagsConfig) UpdateWithEnv() { | ||
if t.Hostname == "" { | ||
t.Hostname = os.Getenv("DD_HOST") | ||
} | ||
|
||
if t.Env == "" { | ||
t.Env = os.Getenv("DD_ENV") | ||
} | ||
|
||
if t.Service == "" { | ||
t.Service = os.Getenv("DD_SERVICE") | ||
} | ||
|
||
if t.Version == "" { | ||
t.Version = os.Getenv("DD_VERSION") | ||
} | ||
} | ||
|
||
// GetTags gets the default tags extracted from the configuration | ||
func (t *TagsConfig) GetTags(addHost bool) []string { | ||
tags := make([]string, 0, 4) | ||
|
||
vars := map[string]string{ | ||
"env": t.Env, | ||
"service": t.Service, | ||
"version": t.Version, | ||
} | ||
|
||
if addHost { | ||
vars["host"] = t.Hostname | ||
} | ||
|
||
for name, val := range vars { | ||
if val != "" { | ||
tags = append(tags, fmt.Sprintf("%s:%s", name, val)) | ||
} | ||
} | ||
|
||
tags = append(tags, t.Tags...) | ||
|
||
return tags | ||
} | ||
|
||
// Config defines configuration for the Datadog exporter. | ||
type Config struct { | ||
configmodels.ExporterSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. | ||
|
||
TagsConfig `mapstructure:",squash"` | ||
|
||
// API defines the Datadog API configuration. | ||
API APIConfig `mapstructure:"api"` | ||
|
||
// Metrics defines the Metrics exporter specific configuration | ||
Metrics MetricsConfig `mapstructure:"metrics"` | ||
} | ||
|
||
// Sanitize tries to sanitize a given configuration | ||
func (c *Config) Sanitize() error { | ||
|
||
if c.Metrics.Mode != AgentlessMode && c.Metrics.Mode != DogStatsDMode { | ||
return fmt.Errorf("Metrics mode '%s' is not recognized", c.Metrics.Mode) | ||
} | ||
|
||
// Get info from environment variables | ||
// if unset | ||
c.TagsConfig.UpdateWithEnv() | ||
|
||
// Add '.' at the end of namespace | ||
// to have the same behavior on DogStatsD and the API | ||
if c.Metrics.Namespace != "" && !strings.HasSuffix(c.Metrics.Namespace, ".") { | ||
c.Metrics.Namespace = c.Metrics.Namespace + "." | ||
} | ||
|
||
// Exactly one configuration for metrics must be set | ||
if c.Metrics.Mode == AgentlessMode { | ||
if c.API.Key == "" { | ||
return errUnsetAPIKey | ||
} | ||
|
||
c.API.Key = strings.TrimSpace(c.API.Key) | ||
|
||
// Set the endpoint based on the Site | ||
if c.Metrics.Agentless.Endpoint == "" { | ||
c.Metrics.Agentless.Endpoint = fmt.Sprintf("https://api.%s", c.API.Site) | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// 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 datadogexporter | ||
|
||
import ( | ||
"path" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"go.opentelemetry.io/collector/component/componenttest" | ||
"go.opentelemetry.io/collector/config/configmodels" | ||
"go.opentelemetry.io/collector/config/configtest" | ||
) | ||
|
||
// TestLoadConfig tests that the configuration is loaded correctly | ||
func TestLoadConfig(t *testing.T) { | ||
factories, err := componenttest.ExampleComponents() | ||
assert.NoError(t, err) | ||
|
||
factory := NewFactory() | ||
factories.Exporters[typeStr] = factory | ||
cfg, err := configtest.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories) | ||
|
||
require.NoError(t, err) | ||
require.NotNil(t, cfg) | ||
|
||
apiConfig := cfg.Exporters["datadog/api"].(*Config) | ||
err = apiConfig.Sanitize() | ||
|
||
require.NoError(t, err) | ||
assert.Equal(t, apiConfig, &Config{ | ||
ExporterSettings: configmodels.ExporterSettings{ | ||
NameVal: "datadog/api", | ||
TypeVal: "datadog", | ||
}, | ||
|
||
TagsConfig: TagsConfig{ | ||
Hostname: "customhostname", | ||
Env: "prod", | ||
Service: "myservice", | ||
Version: "myversion", | ||
Tags: []string{"example:tag"}, | ||
}, | ||
|
||
API: APIConfig{ | ||
Key: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
Site: "datadoghq.eu", | ||
}, | ||
|
||
Metrics: MetricsConfig{ | ||
Mode: AgentlessMode, | ||
Namespace: "opentelemetry.", | ||
Percentiles: false, | ||
|
||
DogStatsD: DogStatsDConfig{ | ||
Endpoint: "127.0.0.1:8125", | ||
Telemetry: true, | ||
}, | ||
|
||
Agentless: AgentlessConfig{ | ||
Endpoint: "https://api.datadoghq.eu", | ||
}, | ||
}, | ||
}) | ||
|
||
dogstatsdConfig := cfg.Exporters["datadog/dogstatsd"].(*Config) | ||
err = dogstatsdConfig.Sanitize() | ||
|
||
require.NoError(t, err) | ||
assert.Equal(t, dogstatsdConfig, &Config{ | ||
ExporterSettings: configmodels.ExporterSettings{ | ||
NameVal: "datadog/dogstatsd", | ||
TypeVal: "datadog", | ||
}, | ||
|
||
TagsConfig: TagsConfig{}, | ||
API: APIConfig{Site: "datadoghq.com"}, | ||
|
||
Metrics: MetricsConfig{ | ||
Mode: DogStatsDMode, | ||
Percentiles: true, | ||
DogStatsD: DogStatsDConfig{ | ||
Endpoint: "127.0.0.1:8125", | ||
Telemetry: true, | ||
}, | ||
|
||
Agentless: AgentlessConfig{}, | ||
}, | ||
}) | ||
|
||
invalidConfig := cfg.Exporters["datadog/invalid"].(*Config) | ||
err = invalidConfig.Sanitize() | ||
require.Error(t, err) | ||
|
||
invalidConfig2 := cfg.Exporters["datadog/agentless/invalid"].(*Config) | ||
err = invalidConfig2.Sanitize() | ||
require.Error(t, err) | ||
|
||
} | ||
|
||
// TestOverrideMetricsURL tests that the metrics URL is overridden | ||
// correctly when set manually. | ||
func TestOverrideMetricsURL(t *testing.T) { | ||
|
||
const DebugEndpoint string = "http://localhost:8080" | ||
|
||
cfg := Config{ | ||
API: APIConfig{Key: "notnull", Site: DefaultSite}, | ||
Metrics: MetricsConfig{ | ||
Mode: AgentlessMode, | ||
Agentless: AgentlessConfig{Endpoint: DebugEndpoint}, | ||
}, | ||
} | ||
|
||
err := cfg.Sanitize() | ||
require.NoError(t, err) | ||
assert.Equal(t, cfg.Metrics.Agentless.Endpoint, DebugEndpoint) | ||
} |
Oops, something went wrong.