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

Merge internal changes to our external repository. #116

Merged
merged 3 commits into from
Apr 12, 2021
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
72 changes: 52 additions & 20 deletions exporter/newrelicexporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,76 @@ package newrelicexporter
import (
"time"

"github.com/newrelic/newrelic-telemetry-sdk-go/telemetry"
"go.opentelemetry.io/collector/config"
)

// Config defines configuration options for the New Relic exporter.
type Config struct {
*config.ExporterSettings `mapstructure:"-"`

// EndpointConfig defines configuration for a single endpoint in the New Relic exporter.
type EndpointConfig struct {
// APIKey is the required authentication credentials for New Relic APIs. This field specifies the default key.
APIKey string `mapstructure:"apikey"`

// APIKeyHeader may be specified to instruct the exporter to extract the API key from the request context.
APIKeyHeader string `mapstructure:"api_key_header"`

// HostOverride overrides the endpoint.
HostOverride string `mapstructure:"host_override"`

// Timeout is the total amount of time spent attempting a request,
// including retries, before abandoning and dropping data. Default is 15
// seconds.
Timeout time.Duration `mapstructure:"timeout"`

// CommonAttributes are the attributes to be applied to all telemetry
// sent to New Relic.
CommonAttributes map[string]interface{} `mapstructure:"common_attributes"`
// Insecure disables TLS on the endpoint.
insecure bool
}

// Config defines configuration options for the New Relic exporter.
type Config struct {
*config.ExporterSettings `mapstructure:"-"`

// MetricsHostOverride overrides the metrics endpoint.
MetricsHostOverride string `mapstructure:"metrics_host_override"`
// CommonConfig stores the base configuration for each endpoint.
CommonConfig EndpointConfig `mapstructure:",squash"`

// SpansHostOverride overrides the spans endpoint.
SpansHostOverride string `mapstructure:"spans_host_override"`
// TracesConfig stores the configuration for the traces endpoint.
TracesConfig EndpointConfig `mapstructure:"traces"`

// MetricsConfig stores the configuration for the metrics endpoint.
MetricsConfig EndpointConfig `mapstructure:"metrics"`

// LogsConfig stores the configuration for the logs endpoint.
LogsConfig EndpointConfig `mapstructure:"logs"`
}

// GetTracesConfig merges the common configuration section with the traces specific section.
func (c Config) GetTracesConfig() EndpointConfig {
return mergeConfig(c.CommonConfig, c.TracesConfig)
}

// GetMetricsConfig merges the common configuration section with the metrics specific section.
func (c Config) GetMetricsConfig() EndpointConfig {
return mergeConfig(c.CommonConfig, c.MetricsConfig)
}

// GetLogsConfig merges the common configuration section with the logs specific section.
func (c Config) GetLogsConfig() EndpointConfig {
return mergeConfig(c.CommonConfig, c.LogsConfig)
}

// LogsHostOverride overrides the logs endpoint.
LogsHostOverride string `mapstructure:"logs_host_override"`
func mergeConfig(baseConfig EndpointConfig, config EndpointConfig) EndpointConfig {
if config.APIKey == "" {
config.APIKey = baseConfig.APIKey
}

// metricsInsecure disables TLS on the metrics endpoint.
metricsInsecure bool
if config.APIKeyHeader == "" {
config.APIKeyHeader = baseConfig.APIKeyHeader
}

// spansInsecure disables TLS on the spans endpoint.
spansInsecure bool
if config.HostOverride == "" {
config.HostOverride = baseConfig.HostOverride
}

// logsInsecure disables TLS on the logs endpoint.
logsInsecure bool
if config.Timeout == 0 {
config.Timeout = baseConfig.Timeout
}
return config
}
146 changes: 132 additions & 14 deletions exporter/newrelicexporter/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,139 @@ func TestLoadConfig(t *testing.T) {
r1 := cfg.Exporters["newrelic/alt"].(*Config)
assert.Equal(t, r1, &Config{
ExporterSettings: &config.ExporterSettings{
TypeVal: config.Type(typeStr),
TypeVal: "newrelic",
NameVal: "newrelic/alt",
},
APIKey: "a1b2c3d4",
Timeout: time.Second * 30,
CommonAttributes: map[string]interface{}{
"server": "test-server",
"prod": true,
"weight": 3,
},
MetricsHostOverride: "alt.metrics.newrelic.com",
SpansHostOverride: "alt.spans.newrelic.com",
LogsHostOverride: "alt.logs.newrelic.com",
metricsInsecure: false,
spansInsecure: false,
logsInsecure: false,
CommonConfig: EndpointConfig{
APIKey: "a1b2c3d4",
Timeout: time.Second * 30,
},
MetricsConfig: EndpointConfig{
HostOverride: "alt.metrics.newrelic.com",
insecure: false,
},
TracesConfig: EndpointConfig{
HostOverride: "alt.spans.newrelic.com",
insecure: false,
},
LogsConfig: EndpointConfig{
HostOverride: "alt.logs.newrelic.com",
insecure: false,
},
})
}

func TestEndpointSpecificConfigTakesPrecedence(t *testing.T) {
config := Config{
CommonConfig: EndpointConfig{
APIKey: "commonapikey",
APIKeyHeader: "commonapikeyheader",
HostOverride: "commonhost",
Timeout: time.Second * 10,
},
TracesConfig: EndpointConfig{
APIKey: "tracesapikey",
APIKeyHeader: "tracesapikeyheader",
HostOverride: "traceshost",
Timeout: time.Second * 20,
},
MetricsConfig: EndpointConfig{
APIKey: "metricsapikey",
APIKeyHeader: "metricsapikeyheader",
HostOverride: "metricshost",
Timeout: time.Second * 30,
},
LogsConfig: EndpointConfig{
APIKey: "logsapikey",
APIKeyHeader: "logsapikeyheader",
HostOverride: "logshost",
Timeout: time.Second * 40,
},
}

assert.Equal(t, config.TracesConfig, config.GetTracesConfig())
assert.Equal(t, config.MetricsConfig, config.GetMetricsConfig())
assert.Equal(t, config.LogsConfig, config.GetLogsConfig())
}

func TestEndpointSpecificConfigUsedWhenDefined(t *testing.T) {
config := Config{
CommonConfig: EndpointConfig{
APIKey: "commonapikey",
APIKeyHeader: "commonapikeyheader",
HostOverride: "commonhost",
Timeout: time.Second * 10,
},
TracesConfig: EndpointConfig{
APIKey: "tracesapikey",
HostOverride: "traceshost",
Timeout: time.Second * 20,
},
MetricsConfig: EndpointConfig{
APIKeyHeader: "metricsapikeyheader",
HostOverride: "metricshost",
Timeout: time.Second * 30,
},
LogsConfig: EndpointConfig{
APIKey: "logsapikey",
APIKeyHeader: "logsapikeyheader",
HostOverride: "logshost",
},
}

expectedTraceConfig := EndpointConfig{
APIKey: "tracesapikey",
APIKeyHeader: "commonapikeyheader",
HostOverride: "traceshost",
Timeout: time.Second * 20,
}
expectedMetricConfig := EndpointConfig{
APIKey: "commonapikey",
APIKeyHeader: "metricsapikeyheader",
HostOverride: "metricshost",
Timeout: time.Second * 30,
}
expectedLogConfig := EndpointConfig{
APIKey: "logsapikey",
APIKeyHeader: "logsapikeyheader",
HostOverride: "logshost",
Timeout: time.Second * 10,
}

assert.Equal(t, expectedTraceConfig, config.GetTracesConfig())
assert.Equal(t, expectedMetricConfig, config.GetMetricsConfig())
assert.Equal(t, expectedLogConfig, config.GetLogsConfig())
}

func TestCommonConfigValuesUsed(t *testing.T) {
config := Config{
CommonConfig: EndpointConfig{
APIKey: "commonapikey",
APIKeyHeader: "commonapikeyheader",
HostOverride: "commonhost",
Timeout: time.Second * 10,
},
TracesConfig: EndpointConfig{
APIKey: "",
APIKeyHeader: "",
HostOverride: "",
Timeout: 0,
},
MetricsConfig: EndpointConfig{
APIKey: "",
APIKeyHeader: "",
HostOverride: "",
Timeout: 0,
},
LogsConfig: EndpointConfig{
APIKey: "",
APIKeyHeader: "",
HostOverride: "",
Timeout: 0,
},
}

assert.Equal(t, config.CommonConfig, config.GetTracesConfig())
assert.Equal(t, config.CommonConfig, config.GetMetricsConfig())
assert.Equal(t, config.CommonConfig, config.GetLogsConfig())
}
73 changes: 24 additions & 49 deletions exporter/newrelicexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,11 @@ func NewFactory() component.ExporterFactory {
func createDefaultConfig() config.Exporter {
return &Config{
ExporterSettings: config.NewExporterSettings(typeStr),
Timeout: time.Second * 15,
}
}

type endpointConfig struct {
// APIKey is the required authentication credentials for New Relic APIs. This field specifies the default key.
APIKey string `mapstructure:"apikey"`

// APIKeyHeader may be specified to instruct the exporter to extract the API key from the request context.
APIKeyHeader string `mapstructure:"api_key_header"`

// CommonAttributes are the attributes to be applied to all telemetry
// sent to New Relic.
CommonAttributes map[string]interface{} `mapstructure:"common_attributes"`

// HostOverride overrides the endpoint.
HostOverride string `mapstructure:"host_override"`

// Insecure disables TLS on the endpoint.
insecure bool
CommonConfig: EndpointConfig{
Timeout: time.Second * 15,
},
}
}

// CreateTracesExporter creates a New Relic trace exporter for this configuration.
Expand All @@ -78,24 +63,19 @@ func createTraceExporter(
if !ok {
return nil, fmt.Errorf("invalid config: %#v", cfg)
}
internalConfig := endpointConfig{
APIKey: nrConfig.APIKey,
APIKeyHeader: nrConfig.APIKeyHeader,
CommonAttributes: nil, // FIXME: missing common attributes
HostOverride: nrConfig.SpansHostOverride,
insecure: nrConfig.spansInsecure,
}
exp, err := newExporter(params.Logger, internalConfig, telemetry.NewSpanRequestFactory)
traceConfig := nrConfig.GetTracesConfig()
exp, err := newExporter(params.Logger, &params.ApplicationStartInfo, traceConfig, telemetry.NewSpanRequestFactory)
if err != nil {
return nil, err
}

// The logger is only used in a disabled queuedRetrySender, which noisily logs at
// the error level when it is disabled and errors occur.
return exporterhelper.NewTraceExporter(cfg, zap.NewNop(), exp.pushTraceData,
exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: nrConfig.Timeout}),
exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: traceConfig.Timeout}),
exporterhelper.WithRetry(exporterhelper.RetrySettings{Enabled: false}),
exporterhelper.WithQueue(exporterhelper.QueueSettings{Enabled: false}))
exporterhelper.WithQueue(exporterhelper.QueueSettings{Enabled: false}),
)
}

// CreateMetricsExporter creates a New Relic metrics exporter for this configuration.
Expand All @@ -109,43 +89,38 @@ func createMetricsExporter(
return nil, fmt.Errorf("invalid config: %#v", cfg)
}

internalConfig := endpointConfig{
APIKey: nrConfig.APIKey,
APIKeyHeader: nrConfig.APIKeyHeader,
CommonAttributes: nil, // FIXME: missing common attributes
HostOverride: nrConfig.MetricsHostOverride,
insecure: nrConfig.metricsInsecure,
}

exp, err := newExporter(params.Logger, internalConfig, telemetry.NewMetricRequestFactory)
metricsConfig := nrConfig.GetMetricsConfig()
exp, err := newExporter(params.Logger, &params.ApplicationStartInfo, metricsConfig, telemetry.NewMetricRequestFactory)
if err != nil {
return nil, err
}

return exporterhelper.NewMetricsExporter(cfg, zap.NewNop(), exp.pushMetricData)
return exporterhelper.NewMetricsExporter(cfg, zap.NewNop(), exp.pushMetricData,
exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: metricsConfig.Timeout}),
exporterhelper.WithRetry(exporterhelper.RetrySettings{Enabled: false}),
exporterhelper.WithQueue(exporterhelper.QueueSettings{Enabled: false}),
)
}

// CreateLogsExporter creates a New Relic logs exporter for this configuration.
func createLogsExporter(
_ context.Context,
params component.ExporterCreateParams,
cfg configmodels.Exporter,
cfg config.Exporter,
) (component.LogsExporter, error) {
nrConfig, ok := cfg.(*Config)
if !ok {
return nil, fmt.Errorf("invalid config: %#v", cfg)
}

internalConfig := endpointConfig{
APIKey: nrConfig.APIKey,
APIKeyHeader: nrConfig.APIKeyHeader,
CommonAttributes: nil, // FIXME: missing common attributes
HostOverride: nrConfig.LogsHostOverride,
insecure: nrConfig.logsInsecure,
}
exp, err := newExporter(params.Logger, internalConfig, telemetry.NewLogRequestFactory)
logsConfig := nrConfig.GetLogsConfig()
exp, err := newExporter(params.Logger, &params.ApplicationStartInfo, logsConfig, telemetry.NewLogRequestFactory)
if err != nil {
return nil, err
}
return exporterhelper.NewLogsExporter(cfg, zap.NewNop(), exp.pushLogData)
return exporterhelper.NewLogsExporter(cfg, zap.NewNop(), exp.pushLogData,
exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: logsConfig.Timeout}),
exporterhelper.WithRetry(exporterhelper.RetrySettings{Enabled: false}),
exporterhelper.WithQueue(exporterhelper.QueueSettings{Enabled: false}),
)
}
Loading