From fcc9b774501516797814f87ecbff64d991b80190 Mon Sep 17 00:00:00 2001 From: Pablo Baeyens Date: Wed, 23 Sep 2020 12:37:04 +0200 Subject: [PATCH] Remove DogStatsD mode (#2) * Remove DogStatsD mode * go mod tidy * Remove mentions to DogStatSD --- exporter/datadogexporter/README.md | 7 +- exporter/datadogexporter/config.go | 61 +++--------- exporter/datadogexporter/config_test.go | 49 ++-------- exporter/datadogexporter/dogstatd_test.go | 69 ------------- exporter/datadogexporter/dogstatsd.go | 98 ------------------- exporter/datadogexporter/example/config.yaml | 36 +------ exporter/datadogexporter/factory.go | 38 +------ exporter/datadogexporter/factory_test.go | 78 +++++---------- exporter/datadogexporter/go.mod | 1 - exporter/datadogexporter/go.sum | 2 - exporter/datadogexporter/metrics.go | 31 +----- exporter/datadogexporter/metrics_api.go | 37 ++----- exporter/datadogexporter/metrics_test.go | 49 +++------- exporter/datadogexporter/testdata/config.yaml | 25 +---- 14 files changed, 80 insertions(+), 501 deletions(-) delete mode 100644 exporter/datadogexporter/dogstatd_test.go delete mode 100644 exporter/datadogexporter/dogstatsd.go diff --git a/exporter/datadogexporter/README.md b/exporter/datadogexporter/README.md index 23df0cda6f37..82ba10f88d00 100644 --- a/exporter/datadogexporter/README.md +++ b/exporter/datadogexporter/README.md @@ -4,17 +4,12 @@ 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). +The only required setting is a [Datadog API key](https://app.datadoghq.com/account/settings#api). ```yaml datadog: 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. diff --git a/exporter/datadogexporter/config.go b/exporter/datadogexporter/config.go index c6d7342ed833..be53de09702b 100644 --- a/exporter/datadogexporter/config.go +++ b/exporter/datadogexporter/config.go @@ -28,12 +28,6 @@ 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. @@ -50,26 +44,7 @@ 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 { - // FIXME Use confignet.NetAddr - // 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 internal telemetry metrics from the statsd client - 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. - confignet.TCPAddr `mapstructure:",squash"` + return strings.Repeat("*", len(api.Key)-5) + api.Key[len(api.Key)-5:] } // MetricsConfig defines the metrics exporter specific configuration options @@ -78,9 +53,6 @@ type MetricsConfig struct { // 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"` @@ -88,11 +60,9 @@ type MetricsConfig struct { // 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"` + // TCPAddr.Endpoint is the host of the Datadog intake server to send metrics to. + // If unset, the value is obtained from the Site. + confignet.TCPAddr `mapstructure:",squash"` } // TagsConfig defines the tag-related configuration @@ -180,33 +150,24 @@ type Config struct { // 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 - } + if c.API.Key == "" { + return errUnsetAPIKey + } - c.API.Key = strings.TrimSpace(c.API.Key) + 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) - } + // Set the endpoint based on the Site + if c.Metrics.TCPAddr.Endpoint == "" { + c.Metrics.TCPAddr.Endpoint = fmt.Sprintf("https://api.%s", c.API.Site) } return nil diff --git a/exporter/datadogexporter/config_test.go b/exporter/datadogexporter/config_test.go index 1dda2268c948..63765c412956 100644 --- a/exporter/datadogexporter/config_test.go +++ b/exporter/datadogexporter/config_test.go @@ -62,51 +62,15 @@ func TestLoadConfig(t *testing.T) { }, Metrics: MetricsConfig{ - Mode: AgentlessMode, Namespace: "opentelemetry.", Percentiles: false, - - DogStatsD: DogStatsDConfig{ - Endpoint: "127.0.0.1:8125", - Telemetry: true, - }, - - Agentless: AgentlessConfig{ - confignet.TCPAddr{ - Endpoint: "https://api.datadoghq.eu", - }, + TCPAddr: confignet.TCPAddr{ + Endpoint: "https://api.datadoghq.eu", }, }, }, apiConfig) - dogstatsdConfig := cfg.Exporters["datadog/dogstatsd"].(*Config) - err = dogstatsdConfig.Sanitize() - - require.NoError(t, err) - assert.Equal(t, &Config{ - ExporterSettings: configmodels.ExporterSettings{ - NameVal: "datadog/dogstatsd", - TypeVal: typeStr, - }, - - TagsConfig: TagsConfig{}, - API: APIConfig{Site: "datadoghq.com"}, - - Metrics: MetricsConfig{ - Mode: DogStatsDMode, - Percentiles: true, - DogStatsD: DogStatsDConfig{ - Endpoint: "127.0.0.1:8125", - Telemetry: true, - }, - }, - }, dogstatsdConfig) - - invalidConfig := cfg.Exporters["datadog/invalid"].(*Config) - err = invalidConfig.Sanitize() - require.Error(t, err) - - invalidConfig2 := cfg.Exporters["datadog/agentless/invalid"].(*Config) + invalidConfig2 := cfg.Exporters["datadog/invalid"].(*Config) err = invalidConfig2.Sanitize() require.Error(t, err) @@ -143,12 +107,13 @@ func TestOverrideMetricsURL(t *testing.T) { cfg := Config{ API: APIConfig{Key: "notnull", Site: DefaultSite}, Metrics: MetricsConfig{ - Mode: AgentlessMode, - Agentless: AgentlessConfig{confignet.TCPAddr{Endpoint: DebugEndpoint}}, + TCPAddr: confignet.TCPAddr{ + Endpoint: DebugEndpoint, + }, }, } err := cfg.Sanitize() require.NoError(t, err) - assert.Equal(t, cfg.Metrics.Agentless.Endpoint, DebugEndpoint) + assert.Equal(t, cfg.Metrics.Endpoint, DebugEndpoint) } diff --git a/exporter/datadogexporter/dogstatd_test.go b/exporter/datadogexporter/dogstatd_test.go deleted file mode 100644 index f9ac523f97ad..000000000000 --- a/exporter/datadogexporter/dogstatd_test.go +++ /dev/null @@ -1,69 +0,0 @@ -// 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 ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap" -) - -func TestDogStatsDExporter(t *testing.T) { - var ( - testNamespace = "test." - testTags = []string{"key1:val1", "key2:val2"} - ) - - logger := zap.NewNop() - cfg := &Config{ - TagsConfig: TagsConfig{ - Tags: testTags, - }, - - Metrics: MetricsConfig{ - Namespace: testNamespace, - DogStatsD: DogStatsDConfig{ - Endpoint: "localhost:5000", - }, - }, - } - - exp, err := newDogStatsDExporter(logger, cfg) - require.NoError(t, err) - - assert.Equal(t, cfg, exp.GetConfig()) - assert.Equal(t, logger, exp.GetLogger()) - assert.Equal(t, testNamespace, exp.client.Namespace) - assert.Equal(t, testTags, exp.client.Tags) -} - -func TestInvalidDogStatsDExporter(t *testing.T) { - logger := zap.NewNop() - - // The configuration is invalid if no - // endpoint is set - cfg := &Config{ - Metrics: MetricsConfig{ - DogStatsD: DogStatsDConfig{ - Endpoint: "", - }, - }, - } - - _, err := newDogStatsDExporter(logger, cfg) - require.Error(t, err) -} diff --git a/exporter/datadogexporter/dogstatsd.go b/exporter/datadogexporter/dogstatsd.go deleted file mode 100644 index 2472add7b0a7..000000000000 --- a/exporter/datadogexporter/dogstatsd.go +++ /dev/null @@ -1,98 +0,0 @@ -// 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 ( - "context" - "fmt" - - "github.com/DataDog/datadog-go/statsd" - "go.opentelemetry.io/collector/consumer/pdata" - "go.opentelemetry.io/collector/exporter/exporterhelper" - "go.opentelemetry.io/collector/translator/internaldata" - "go.uber.org/zap" -) - -type dogStatsDExporter struct { - logger *zap.Logger - cfg *Config - client *statsd.Client -} - -func newDogStatsDExporter(logger *zap.Logger, cfg *Config) (*dogStatsDExporter, error) { - - options := []statsd.Option{ - statsd.WithNamespace(cfg.Metrics.Namespace), - statsd.WithTags(cfg.TagsConfig.GetTags(true)), // true: add host tag - } - - if !cfg.Metrics.DogStatsD.Telemetry { - options = append(options, statsd.WithoutTelemetry()) - } - - client, err := statsd.New( - cfg.Metrics.DogStatsD.Endpoint, - options..., - ) - - if err != nil { - return nil, fmt.Errorf("failed to initialize DogStatsD client: %s", err) - } - - return &dogStatsDExporter{logger, cfg, client}, nil -} - -func (exp *dogStatsDExporter) PushMetricsData(_ context.Context, md pdata.Metrics) (int, error) { - data := internaldata.MetricsToOC(md) - series, droppedTimeSeries := MapMetrics(exp, data) - - for _, metric := range series.metrics { - - tags := metric.Tags - - // Send the hostname if it has not been overridden - if exp.GetConfig().Hostname == "" && metric.GetHost() != "" { - tags = append(tags, fmt.Sprintf("host:%s", metric.GetHost())) - } - - var err error - switch metric.GetType() { - case Gauge: - err = exp.client.Gauge(metric.GetMetric(), *metric.Points[0][1], tags, 1) - } - - if err != nil { - exp.GetLogger().Warn("could not send metric to statsd", zap.String("metric", *metric.Metric), zap.Error(err)) - } - } - - return droppedTimeSeries, nil -} - -func (exp *dogStatsDExporter) GetLogger() *zap.Logger { - return exp.logger -} - -func (exp *dogStatsDExporter) GetConfig() *Config { - return exp.cfg -} - -func (exp *dogStatsDExporter) GetQueueSettings() exporterhelper.QueueSettings { - return exporterhelper.QueueSettings{Enabled: false} -} - -func (exp *dogStatsDExporter) GetRetrySettings() exporterhelper.RetrySettings { - return exporterhelper.RetrySettings{Enabled: false} -} diff --git a/exporter/datadogexporter/example/config.yaml b/exporter/datadogexporter/example/config.yaml index 11d575b844ad..3aba527264a1 100644 --- a/exporter/datadogexporter/example/config.yaml +++ b/exporter/datadogexporter/example/config.yaml @@ -57,17 +57,6 @@ exporters: ## Metric exporter specific configuration. # # metrics: - ## @param mode - string - optional - default: dogstatsd - ## The mode with which to send metrics. - ## It can be one of - ## - 'none' (to explicitly disable it) - ## - 'dogstatsd' (to send metrics to a DogStatsD endpoint) - ## - 'agentless' (to send metrics directly through the API) - ## - ## If the mode is 'agentless' the API key must be set. - # - # mode: dogstatsd - ## @param namespace - string - optional ## The namespace with which to prefix all metrics. ## By default metrics are not namespaced. @@ -87,29 +76,12 @@ exporters: # # report_buckets: false - ## @param dogstatsd - custom object - optional - ## DogStatSD mode specific configuration. + ## @param endpoint - string - optional + ## The host of the Datadog intake server to send metrics to. + ## If unset the value is obtained through the `site` parameter in the `api` section. # - # dogstatsd: - ## @param endpoint - string - default: 127.0.0.1:8125 - ## The DogStatsD endpoint. It can be an UDP or UDS endpoint - # - # endpoint: 127.0.0.1:8125 + # endpoint: https://api.datadoghq.com - ## @param telemetry - boolean - default: true - ## Whether to send telemetry metrics about the number of custom metrics sent. - # - # telemetry: true - - ## @param agentless - custom object - optional - ## Agentless metrics exporter specific configuration - # - # agentless: - ## @param endpoint - string - optional - ## The host of the Datadog intake server to send metrics to. - ## If unset the value is obtained through the `site` parameter in the `api` section. - # - # endpoint: https://api.datadoghq.com service: pipelines: traces: diff --git a/exporter/datadogexporter/factory.go b/exporter/datadogexporter/factory.go index be8c562b2aa2..9d153698e319 100644 --- a/exporter/datadogexporter/factory.go +++ b/exporter/datadogexporter/factory.go @@ -17,7 +17,6 @@ import ( "context" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/config/configerror" "go.opentelemetry.io/collector/config/configmodels" "go.opentelemetry.io/collector/config/confignet" "go.opentelemetry.io/collector/exporter/exporterhelper" @@ -37,7 +36,6 @@ func NewFactory() component.ExporterFactory { typeStr, createDefaultConfig, exporterhelper.WithMetrics(createMetricsExporter), - exporterhelper.WithTraces(createTracesExporter), ) } @@ -55,24 +53,15 @@ func createDefaultConfig() configmodels.Exporter { }, Metrics: MetricsConfig{ - Mode: DogStatsDMode, Percentiles: true, - - DogStatsD: DogStatsDConfig{ - Endpoint: "127.0.0.1:8125", - Telemetry: true, - }, - - Agentless: AgentlessConfig{ - confignet.TCPAddr{ - Endpoint: "", // set during config sanitization - }, + TCPAddr: confignet.TCPAddr{ + Endpoint: "", // set during config sanitization }, }, } } -// CreateMetricsExporter creates a metrics exporter based on this config. +// createMetricsExporter creates a metrics exporter based on this config. func createMetricsExporter( _ context.Context, params component.ExporterCreateParams, @@ -94,24 +83,7 @@ func createMetricsExporter( return exporterhelper.NewMetricsExporter( cfg, exp.PushMetricsData, - exporterhelper.WithQueue(exp.GetQueueSettings()), - exporterhelper.WithRetry(exp.GetRetrySettings()), + exporterhelper.WithQueue(exporterhelper.CreateDefaultQueueSettings()), + exporterhelper.WithRetry(exporterhelper.CreateDefaultRetrySettings()), ) } - -// CreateTracesExporter creates a traces exporter based on this config. -func createTracesExporter( - _ context.Context, - params component.ExporterCreateParams, - c configmodels.Exporter) (component.TraceExporter, error) { - - cfg := c.(*Config) - - params.Logger.Info("sanitizing Datadog metrics exporter configuration") - if err := cfg.Sanitize(); err != nil { - return nil, err - } - - // Traces are not yet supported - return nil, configerror.ErrDataTypeIsNotSupported -} diff --git a/exporter/datadogexporter/factory_test.go b/exporter/datadogexporter/factory_test.go index 0f33007c36aa..217ec080d871 100644 --- a/exporter/datadogexporter/factory_test.go +++ b/exporter/datadogexporter/factory_test.go @@ -15,6 +15,9 @@ package datadogexporter import ( "context" + "errors" + "net/http" + "net/http/httptest" "path" "testing" @@ -40,19 +43,14 @@ func TestCreateDefaultConfig(t *testing.T) { }, API: APIConfig{Site: "datadoghq.com"}, Metrics: MetricsConfig{ - Mode: DogStatsDMode, Percentiles: true, - DogStatsD: DogStatsDConfig{ - Endpoint: "127.0.0.1:8125", - Telemetry: true, - }, }, }, cfg, "failed to create default config") assert.NoError(t, configcheck.ValidateConfig(cfg)) } -func TestCreateAgentMetricsExporter(t *testing.T) { +func TestCreateAPIMetricsExporter(t *testing.T) { logger := zap.NewNop() factories, err := componenttest.ExampleComponents() @@ -65,39 +63,40 @@ func TestCreateAgentMetricsExporter(t *testing.T) { require.NoError(t, err) require.NotNil(t, cfg) + // Test with invalid API key + + // Mock http server + tsInvalid := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("{\"valid\": false}")) + })) + defer tsInvalid.Close() + cfg.Exporters["datadog/api"].(*Config).Metrics.Endpoint = tsInvalid.URL ctx := context.Background() exp, err := factory.CreateMetricsExporter( ctx, component.ExporterCreateParams{Logger: logger}, - cfg.Exporters["datadog/dogstatsd"], + cfg.Exporters["datadog/api"], ) - assert.Nil(t, err) - assert.NotNil(t, exp) -} - -func TestCreateAPIMetricsExporter(t *testing.T) { - logger := zap.NewNop() - - factories, err := componenttest.ExampleComponents() - assert.NoError(t, err) - factory := NewFactory() - factories.Exporters[configmodels.Type(typeStr)] = factory - cfg, err := configtest.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories) + assert.Equal(t, errors.New("provided Datadog API key is invalid: ***************************aaaaa"), err) + assert.Nil(t, exp) - require.NoError(t, err) - require.NotNil(t, cfg) + // Override endpoint to return that the API key is valid + tsValid := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("{\"valid\": true}")) + })) + defer tsValid.Close() + cfg.Exporters["datadog/api"].(*Config).Metrics.Endpoint = tsValid.URL - ctx := context.Background() - exp, err := factory.CreateMetricsExporter( + ctx = context.Background() + exp, err = factory.CreateMetricsExporter( ctx, component.ExporterCreateParams{Logger: logger}, cfg.Exporters["datadog/api"], ) - // Not implemented - assert.NotNil(t, err) - assert.Nil(t, exp) + assert.Nil(t, err) + assert.NotNil(t, exp) } func TestCreateInvalidMetricsExporter(t *testing.T) { @@ -117,35 +116,10 @@ func TestCreateInvalidMetricsExporter(t *testing.T) { exp, err := factory.CreateMetricsExporter( ctx, component.ExporterCreateParams{Logger: logger}, - cfg.Exporters["datadog/dogstatsd/invalid"], + cfg.Exporters["datadog/invalid"], ) // The address is invalid assert.NotNil(t, err) assert.Nil(t, exp) } - -func TestCreateAPITraceExporter(t *testing.T) { - logger := zap.NewNop() - - factories, err := componenttest.ExampleComponents() - assert.NoError(t, err) - - factory := NewFactory() - factories.Exporters[configmodels.Type(typeStr)] = factory - cfg, err := configtest.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories) - - require.NoError(t, err) - require.NotNil(t, cfg) - - ctx := context.Background() - exp, err := factory.CreateTraceExporter( - ctx, - component.ExporterCreateParams{Logger: logger}, - cfg.Exporters["datadog/api"], - ) - - // Not implemented - assert.NotNil(t, err) - assert.Nil(t, exp) -} diff --git a/exporter/datadogexporter/go.mod b/exporter/datadogexporter/go.mod index 29c33b57352b..b66737586914 100644 --- a/exporter/datadogexporter/go.mod +++ b/exporter/datadogexporter/go.mod @@ -3,7 +3,6 @@ module github.com/DataDog/opentelemetry-collector-contrib/exporter/datadogexport go 1.15 require ( - github.com/DataDog/datadog-go v4.0.0+incompatible github.com/census-instrumentation/opencensus-proto v0.3.0 github.com/stretchr/testify v1.6.1 github.com/zorkian/go-datadog-api v2.29.0+incompatible // indirect diff --git a/exporter/datadogexporter/go.sum b/exporter/datadogexporter/go.sum index 3d897f3ec9d4..071becb6d219 100644 --- a/exporter/datadogexporter/go.sum +++ b/exporter/datadogexporter/go.sum @@ -67,8 +67,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v4.0.0+incompatible h1:Dq8Dr+4sV1gBO1sHDWdW+4G+PdsA+YSJOK925MxrrCY= -github.com/DataDog/datadog-go v4.0.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.4/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5 h1:XTrzB+F8+SpRmbhAH8HLxhiiG6nYNwaBZjrFps1oWEk= diff --git a/exporter/datadogexporter/metrics.go b/exporter/datadogexporter/metrics.go index 59b3b1a6671c..b7a1c54714cc 100644 --- a/exporter/datadogexporter/metrics.go +++ b/exporter/datadogexporter/metrics.go @@ -15,39 +15,15 @@ package datadogexporter import ( - "context" "fmt" "math" v1 "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1" "go.opentelemetry.io/collector/consumer/consumerdata" - "go.opentelemetry.io/collector/consumer/pdata" - "go.opentelemetry.io/collector/exporter/exporterhelper" "go.uber.org/zap" "gopkg.in/zorkian/go-datadog-api.v2" ) -type MetricsExporter interface { - PushMetricsData(ctx context.Context, md pdata.Metrics) (int, error) - GetLogger() *zap.Logger - GetConfig() *Config - GetQueueSettings() exporterhelper.QueueSettings - GetRetrySettings() exporterhelper.RetrySettings -} - -func newMetricsExporter(logger *zap.Logger, cfg *Config) (MetricsExporter, error) { - switch cfg.Metrics.Mode { - case DogStatsDMode: - return newDogStatsDExporter(logger, cfg) - case AgentlessMode: - return newMetricsAPIExporter(logger, cfg) - case NoneMode: - return nil, fmt.Errorf("metrics exporter disabled for Datadog exporter") - } - - return nil, fmt.Errorf("unsupported mode: '%s'", cfg.Metrics.Mode) -} - const ( Gauge string = "gauge" ) @@ -83,8 +59,7 @@ func (m *Series) Add(metric datadog.Metric) { m.metrics = append(m.metrics, metric) } -func MapMetrics(exp MetricsExporter, data []consumerdata.MetricsData) (series Series, droppedTimeSeries int) { - logger := exp.GetLogger() +func MapMetrics(logger *zap.Logger, metricsCfg MetricsConfig, data []consumerdata.MetricsData) (series Series, droppedTimeSeries int) { for _, metricsData := range data { // The hostname provided by OpenTelemetry @@ -176,7 +151,7 @@ func MapMetrics(exp MetricsExporter, data []consumerdata.MetricsData) (series Se series.Add(NewGauge(host, fullName, ts, value, tags)) } - if exp.GetConfig().Metrics.Buckets { + if metricsCfg.Buckets { // We have a single metric, 'count_per_bucket', which is tagged with the bucket id. See: // https://github.com/DataDog/opencensus-go-exporter-datadog/blob/c3b47f1c6dcf1c47b59c32e8dbb7df5f78162daa/stats.go#L99-L104 fullName := fmt.Sprintf("%s.count_per_bucket", name) @@ -210,7 +185,7 @@ func MapMetrics(exp MetricsExporter, data []consumerdata.MetricsData) (series Se series.Add(NewGauge(host, fullName, ts, sum.GetValue(), tags)) } - if exp.GetConfig().Metrics.Percentiles { + if metricsCfg.Percentiles { snapshot := point.GetSummaryValue().GetSnapshot() for _, pair := range snapshot.GetPercentileValues() { var fullName string diff --git a/exporter/datadogexporter/metrics_api.go b/exporter/datadogexporter/metrics_api.go index d846249c6769..b28ff7ca5cec 100644 --- a/exporter/datadogexporter/metrics_api.go +++ b/exporter/datadogexporter/metrics_api.go @@ -19,22 +19,21 @@ import ( "fmt" "go.opentelemetry.io/collector/consumer/pdata" - "go.opentelemetry.io/collector/exporter/exporterhelper" "go.opentelemetry.io/collector/translator/internaldata" "go.uber.org/zap" "gopkg.in/zorkian/go-datadog-api.v2" ) -type metricsAPIExporter struct { +type metricsExporter struct { logger *zap.Logger cfg *Config client *datadog.Client tags []string } -func newMetricsAPIExporter(logger *zap.Logger, cfg *Config) (*metricsAPIExporter, error) { +func newMetricsExporter(logger *zap.Logger, cfg *Config) (*metricsExporter, error) { client := datadog.NewClient(cfg.API.Key, "") - client.SetBaseUrl(cfg.Metrics.Agentless.TCPAddr.Endpoint) + client.SetBaseUrl(cfg.Metrics.TCPAddr.Endpoint) if ok, err := client.Validate(); err != nil { logger.Warn("Error when validating API key", zap.Error(err)) @@ -47,26 +46,26 @@ func newMetricsAPIExporter(logger *zap.Logger, cfg *Config) (*metricsAPIExporter // Calculate tags at startup tags := cfg.TagsConfig.GetTags(false) - return &metricsAPIExporter{logger, cfg, client, tags}, nil + return &metricsExporter{logger, cfg, client, tags}, nil } -func (exp *metricsAPIExporter) PushMetricsData(ctx context.Context, md pdata.Metrics) (int, error) { +func (exp *metricsExporter) PushMetricsData(ctx context.Context, md pdata.Metrics) (int, error) { data := internaldata.MetricsToOC(md) - series, droppedTimeSeries := MapMetrics(exp, data) + series, droppedTimeSeries := MapMetrics(exp.logger, exp.cfg.Metrics, data) - addNamespace := exp.GetConfig().Metrics.Namespace != "" - overrideHostname := exp.GetConfig().Hostname != "" + addNamespace := exp.cfg.Metrics.Namespace != "" + overrideHostname := exp.cfg.Hostname != "" addTags := len(exp.tags) > 0 for i := range series.metrics { if addNamespace { - newName := exp.GetConfig().Metrics.Namespace + *series.metrics[i].Metric + newName := exp.cfg.Metrics.Namespace + *series.metrics[i].Metric series.metrics[i].Metric = &newName } if overrideHostname || series.metrics[i].GetHost() == "" { - series.metrics[i].Host = GetHost(exp.GetConfig()) + series.metrics[i].Host = GetHost(exp.cfg) } if addTags { @@ -78,19 +77,3 @@ func (exp *metricsAPIExporter) PushMetricsData(ctx context.Context, md pdata.Met err := exp.client.PostMetrics(series.metrics) return droppedTimeSeries, err } - -func (exp *metricsAPIExporter) GetLogger() *zap.Logger { - return exp.logger -} - -func (exp *metricsAPIExporter) GetConfig() *Config { - return exp.cfg -} - -func (exp *metricsAPIExporter) GetQueueSettings() exporterhelper.QueueSettings { - return exporterhelper.CreateDefaultQueueSettings() -} - -func (exp *metricsAPIExporter) GetRetrySettings() exporterhelper.RetrySettings { - return exporterhelper.CreateDefaultRetrySettings() -} diff --git a/exporter/datadogexporter/metrics_test.go b/exporter/datadogexporter/metrics_test.go index 14d8e6cc407e..c5ee826b4e78 100644 --- a/exporter/datadogexporter/metrics_test.go +++ b/exporter/datadogexporter/metrics_test.go @@ -15,8 +15,6 @@ package datadogexporter import ( - "context" - "fmt" "math" "testing" "time" @@ -25,38 +23,11 @@ import ( v1 "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1" "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/consumer/consumerdata" - "go.opentelemetry.io/collector/consumer/pdata" - "go.opentelemetry.io/collector/exporter/exporterhelper" metricstest "go.opentelemetry.io/collector/testutil/metricstestutil" "go.uber.org/zap" "gopkg.in/zorkian/go-datadog-api.v2" ) -type MockMetricsExporter struct { - cfg *Config -} - -func (m *MockMetricsExporter) PushMetricsData(ctx context.Context, md pdata.Metrics) (int, error) { - return 0, fmt.Errorf("Mock metrics exporter") -} - -func (m *MockMetricsExporter) GetLogger() *zap.Logger { - return zap.NewNop() -} - -func (m *MockMetricsExporter) GetConfig() *Config { - return m.cfg -} - -func (m *MockMetricsExporter) GetQueueSettings() exporterhelper.QueueSettings { - return exporterhelper.CreateDefaultQueueSettings() -} - -func (m *MockMetricsExporter) GetRetrySettings() exporterhelper.RetrySettings { - return exporterhelper.CreateDefaultRetrySettings() - -} - func TestMetricValue(t *testing.T) { var ( hostname string = "unknown" @@ -74,11 +45,11 @@ func TestMetricValue(t *testing.T) { } var ( - testHost = "unknown" - mockExporter = &MockMetricsExporter{cfg: &Config{}} - testKeys = [...]string{"key1", "key2", "key3"} - testValues = [...]string{"val1", "val2", ""} - testTags = [...]string{"key1:val1", "key2:val2", "key3:n/a"} + testHost = "unknown" + testKeys = [...]string{"key1", "key2", "key3"} + testValues = [...]string{"val1", "val2", ""} + testTags = [...]string{"key1:val1", "key2:val2", "key3:n/a"} + logger = zap.NewNop() ) func NewMetricsData(metrics []*v1.Metric) []consumerdata.MetricsData { @@ -113,7 +84,7 @@ func TestMapNumericMetric(t *testing.T) { metricstest.Timeseries(ts, testValues[:], intValue)), }) - series, droppedTimeSeries := MapMetrics(mockExporter, md) + series, droppedTimeSeries := MapMetrics(logger, MetricsConfig{}, md) assert.Equal(t, 0, droppedTimeSeries) assert.ElementsMatch(t, @@ -160,7 +131,8 @@ func TestMapDistributionMetric(t *testing.T) { }) series, _ := MapMetrics( - &MockMetricsExporter{cfg: &Config{Metrics: MetricsConfig{Buckets: true}}}, + logger, + MetricsConfig{Buckets: true}, md, ) @@ -226,8 +198,9 @@ func TestMapSummaryMetric(t *testing.T) { }) series, _ := MapMetrics( + logger, // Enable percentiles for test - &MockMetricsExporter{cfg: &Config{Metrics: MetricsConfig{Percentiles: true}}}, + MetricsConfig{Percentiles: true}, md, ) @@ -289,7 +262,7 @@ func TestMapInvalid(t *testing.T) { ts, []string{}, metricstest.Double(ts, 0.0))}, }}) - metrics, droppedTimeSeries := MapMetrics(mockExporter, md) + metrics, droppedTimeSeries := MapMetrics(logger, MetricsConfig{}, md) assert.Equal(t, droppedTimeSeries, 1) assert.Equal(t, metrics, Series{}) diff --git a/exporter/datadogexporter/testdata/config.yaml b/exporter/datadogexporter/testdata/config.yaml index 8a035af597ea..a2d145d7f019 100644 --- a/exporter/datadogexporter/testdata/config.yaml +++ b/exporter/datadogexporter/testdata/config.yaml @@ -19,37 +19,16 @@ exporters: site: datadoghq.eu metrics: - mode: agentless namespace: opentelemetry report_percentiles: false - datadog/dogstatsd: - metrics: - mode: dogstatsd - - datadog/dogstatsd/config: - metrics: - mode: dogstatsd - dogstatsd: - endpoint: "localhost:5000" - telemetry: false - - datadog/dogstatsd/invalid: - metrics: - dogstatsd: - endpoint: "invalid:" - datadog/invalid: metrics: - mode: invalid - - datadog/agentless/invalid: - metrics: - mode: agentless + endpoint: "invalid:" service: pipelines: metrics: receivers: [examplereceiver] processors: [exampleprocessor] - exporters: [datadog/api, datadog/dogstatsd] + exporters: [datadog/api, datadog/invalid]