diff --git a/exporter/sentryexporter/sentry_exporter.go b/exporter/sentryexporter/sentry_exporter.go index 43cde37bec01..2b41b1a0cdf4 100644 --- a/exporter/sentryexporter/sentry_exporter.go +++ b/exporter/sentryexporter/sentry_exporter.go @@ -21,7 +21,6 @@ import ( "encoding/hex" "errors" "fmt" - "log" "net/http" "strconv" "strings" @@ -444,7 +443,7 @@ func CreateSentryExporter(config *Config, set component.ExporterCreateSettings) allEventsFlushed := transport.Flush(ctx) if !allEventsFlushed { - log.Print("Could not flush all events, reached timeout") + set.Logger.Warn("Could not flush all events, reached timeout") } return nil diff --git a/internal/components/exporters_test.go b/internal/components/exporters_test.go index 79be6c01a651..fc3e1c6a9a71 100644 --- a/internal/components/exporters_test.go +++ b/internal/components/exporters_test.go @@ -17,8 +17,6 @@ package components import ( "context" "errors" - "io/ioutil" - "os" "runtime" "testing" @@ -32,16 +30,39 @@ import ( "go.opentelemetry.io/collector/exporter/otlpexporter" "go.opentelemetry.io/collector/exporter/otlphttpexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/alibabacloudlogserviceexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsemfexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awskinesisexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsprometheusremotewriteexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitorexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/carbonexporter" + ddconf "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter/config" + dtconf "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/dynatraceexporter/config" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/elasticexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/f5cloudexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/honeycombexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/humioexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/influxdbexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/jaegerexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/jaegerthrifthttpexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/logzioexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/lokiexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/newrelicexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/opencensusexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/parquetexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/sapmexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/sentryexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/signalfxexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/skywalkingexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/splunkhecexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/sumologicexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/tanzuobservabilityexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/tencentcloudlogserviceexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/zipkinexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/testutil" ) @@ -52,9 +73,6 @@ func TestDefaultExporters(t *testing.T) { expFactories := factories.Exporters endpoint := testutil.GetAvailableLocalAddress(t) - parquetTempDir, err := ioutil.TempDir("", "*") - assert.NoError(t, err) - defer os.RemoveAll(parquetTempDir) tests := []struct { exporter config.Type @@ -65,8 +83,7 @@ func TestDefaultExporters(t *testing.T) { exporter: "file", getConfigFn: func() config.Exporter { cfg := expFactories["file"].CreateDefaultConfig().(*fileexporter.Config) - f, err := ioutil.TempFile("", "otelcol_defaults_file_exporter_test*.tmp") - require.NoError(t, err) + f := testutil.NewTemporaryFile(t) assert.NoError(t, f.Close()) cfg.Path = f.Name() return cfg @@ -134,7 +151,7 @@ func TestDefaultExporters(t *testing.T) { exporter: "parquet", getConfigFn: func() config.Exporter { cfg := expFactories["parquet"].CreateDefaultConfig().(*parquetexporter.Config) - cfg.Path = parquetTempDir + cfg.Path = testutil.NewTemporaryDirectory(t) return cfg }, }, @@ -184,11 +201,215 @@ func TestDefaultExporters(t *testing.T) { return cfg }, }, + { + exporter: "awskinesis", + getConfigFn: func() config.Exporter { + cfg := expFactories["awskinesis"].CreateDefaultConfig().(*awskinesisexporter.Config) + cfg.AWS.KinesisEndpoint = endpoint + return cfg + }, + }, + { + exporter: "awsprometheusremotewrite", + getConfigFn: func() config.Exporter { + cfg := expFactories["awsprometheusremotewrite"].CreateDefaultConfig().(*awsprometheusremotewriteexporter.Config) + cfg.HTTPClientSettings.Endpoint = "http://" + endpoint + return cfg + }, + }, + { + exporter: "alibabacloud_logservice", + getConfigFn: func() config.Exporter { + cfg := expFactories["alibabacloud_logservice"].CreateDefaultConfig().(*alibabacloudlogserviceexporter.Config) + cfg.Endpoint = "http://" + endpoint + cfg.Project = "otel-testing" + cfg.Logstore = "otel-data" + return cfg + }, + }, + { + exporter: "awsemf", + getConfigFn: func() config.Exporter { + cfg := expFactories["awsemf"].CreateDefaultConfig().(*awsemfexporter.Config) + cfg.Endpoint = "http://" + endpoint + cfg.Region = "local" + return cfg + }, + }, + { + exporter: "awsxray", + getConfigFn: func() config.Exporter { + cfg := expFactories["awsxray"].CreateDefaultConfig().(*awsxrayexporter.Config) + cfg.Endpoint = "http://" + endpoint + cfg.Region = "local" + return cfg + }, + }, + { + exporter: "azuremonitor", + getConfigFn: func() config.Exporter { + cfg := expFactories["azuremonitor"].CreateDefaultConfig().(*azuremonitorexporter.Config) + cfg.Endpoint = "http://" + endpoint + + return cfg + }, + }, + { + exporter: "carbon", + getConfigFn: func() config.Exporter { + cfg := expFactories["carbon"].CreateDefaultConfig().(*carbonexporter.Config) + cfg.Endpoint = "http://" + endpoint + return cfg + }, + }, + { + exporter: "datadog", + getConfigFn: func() config.Exporter { + cfg := expFactories["datadog"].CreateDefaultConfig().(*ddconf.Config) + cfg.API.Key = "cutedogsgotoheaven" + return cfg + }, + }, + { + exporter: "dynatrace", + getConfigFn: func() config.Exporter { + cfg := expFactories["dynatrace"].CreateDefaultConfig().(*dtconf.Config) + cfg.Endpoint = "http://" + endpoint + cfg.APIToken = "dynamictracing" + return cfg + }, + }, + { + exporter: "elastic", + getConfigFn: func() config.Exporter { + cfg := expFactories["elastic"].CreateDefaultConfig().(*elasticexporter.Config) + cfg.APMServerURL = "http://" + endpoint + return cfg + }, + }, + { + exporter: "f5cloud", + getConfigFn: func() config.Exporter { + f := testutil.NewTemporaryFile(t) + + cfg := expFactories["f5cloud"].CreateDefaultConfig().(*f5cloudexporter.Config) + cfg.Endpoint = "http://" + endpoint + cfg.Source = "magic-source" + cfg.AuthConfig.CredentialFile = f.Name() + + return cfg + }, + }, + { + exporter: "googlecloud", + skipLifecycle: true, // Requires credentials to be able to successfully load the exporter + }, + { + exporter: "honeycomb", + getConfigFn: func() config.Exporter { + cfg := expFactories["honeycomb"].CreateDefaultConfig().(*honeycombexporter.Config) + cfg.APIURL = "http://" + endpoint + cfg.APIKey = "busybeesworking" + return cfg + }, + }, + { + exporter: "humio", + getConfigFn: func() config.Exporter { + cfg := expFactories["humio"].CreateDefaultConfig().(*humioexporter.Config) + cfg.Endpoint = "http://" + endpoint + return cfg + }, + }, + { + exporter: "influxdb", + getConfigFn: func() config.Exporter { + cfg := expFactories["influxdb"].CreateDefaultConfig().(*influxdbexporter.Config) + cfg.Endpoint = "http://" + endpoint + return cfg + }, + }, + { + exporter: "loadbalancing", + getConfigFn: func() config.Exporter { + cfg := expFactories["loadbalancing"].CreateDefaultConfig().(*loadbalancingexporter.Config) + return cfg + }, + }, + { + exporter: "logzio", + getConfigFn: func() config.Exporter { + cfg := expFactories["logzio"].CreateDefaultConfig().(*logzioexporter.Config) + cfg.CustomEndpoint = "http://" + endpoint + return cfg + }, + }, + { + exporter: "loki", + getConfigFn: func() config.Exporter { + cfg := expFactories["loki"].CreateDefaultConfig().(*lokiexporter.Config) + cfg.Endpoint = "http://" + endpoint + return cfg + }, + }, + { + exporter: "newrelic", + getConfigFn: func() config.Exporter { + cfg := expFactories["newrelic"].CreateDefaultConfig().(*newrelicexporter.Config) + cfg.CommonConfig.HostOverride = "http://" + endpoint + return cfg + }, + }, + { + exporter: "sentry", + getConfigFn: func() config.Exporter { + cfg := expFactories["sentry"].CreateDefaultConfig().(*sentryexporter.Config) + return cfg + }, + }, + { + exporter: "skywalking", + getConfigFn: func() config.Exporter { + cfg := expFactories["skywalking"].CreateDefaultConfig().(*skywalkingexporter.Config) + return cfg + }, + }, + { + exporter: "stackdriver", + skipLifecycle: true, // Is a deprecated exporter that has moved to google cloud exporter + }, + { + exporter: "sumologic", + getConfigFn: func() config.Exporter { + cfg := expFactories["sumologic"].CreateDefaultConfig().(*sumologicexporter.Config) + cfg.Endpoint = "http://" + endpoint + + return cfg + }, + }, + { + exporter: "tanzuobservability", + getConfigFn: func() config.Exporter { + cfg := expFactories["tanzuobservability"].CreateDefaultConfig().(*tanzuobservabilityexporter.Config) + cfg.Traces.Endpoint = "http://" + endpoint + return cfg + }, + }, + { + exporter: "tencentcloud_logservice", + getConfigFn: func() config.Exporter { + cfg := expFactories["tencentcloud_logservice"].CreateDefaultConfig().(*tencentcloudlogserviceexporter.Config) + + return cfg + }, + }, } - assert.Equal(t, len(tests)+25 /* not tested */, len(expFactories)) + assert.Equal(t, len(tests), len(expFactories), "All user configurable components must be added to the lifecycle test") for _, tt := range tests { t.Run(string(tt.exporter), func(t *testing.T) { + t.Parallel() + factory, ok := expFactories[tt.exporter] require.True(t, ok) assert.Equal(t, tt.exporter, factory.Type()) diff --git a/internal/coreinternal/testutil/testutil.go b/internal/coreinternal/testutil/testutil.go index bfe3e2eba299..8f3d0c532e5a 100644 --- a/internal/coreinternal/testutil/testutil.go +++ b/internal/coreinternal/testutil/testutil.go @@ -16,12 +16,14 @@ package testutil // import "github.com/open-telemetry/opentelemetry-collector-co import ( "net" + "os" "os/exec" "runtime" "strconv" "strings" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -109,3 +111,26 @@ func createExclusionsList(exclusionsText string, t *testing.T) []portpair { } return exclusions } + +// NewTemporaryFile creates a file that can be used within the scope of the test +// and will be closed then removed from the file system during the test cleanup +func NewTemporaryFile(tb testing.TB) *os.File { + file, err := os.CreateTemp("", "otelcol_defaults_file_exporter_test*.tmp") + require.NoError(tb, err, "Must not error when creating a temporary file") + tb.Cleanup(func() { + assert.NoError(tb, file.Close(), "Must not error when closing the file") + assert.NoError(tb, os.Remove(file.Name()), "Must not fail removing temporary file used for testing") + }) + return file +} + +// NewTemporaryDirectory creates a new temporary directory that can be used within the scope of +// test or benchmark and the directory will be cleaned up with all files contained within directory. +func NewTemporaryDirectory(tb testing.TB) (absolutePath string) { + name, err := os.MkdirTemp("", "open-telemetry-test-dir-*") + require.NoError(tb, err, "Must not error when creating a test dir") + tb.Cleanup(func() { + assert.NoError(tb, os.RemoveAll(name), "Must not error when removing temporary directory") + }) + return name +} diff --git a/internal/coreinternal/testutil/testutil_test.go b/internal/coreinternal/testutil/testutil_test.go index 4d1c6f87468b..62b5edd6bfc2 100644 --- a/internal/coreinternal/testutil/testutil_test.go +++ b/internal/coreinternal/testutil/testutil_test.go @@ -16,9 +16,11 @@ package testutil import ( "net" + "os" "strconv" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -73,3 +75,33 @@ Start Port End Port emptyExclusions := createExclusionsList(emptyExclusionsText, t) require.Equal(t, len(emptyExclusions), 0) } + +func TestTemporaryFile(t *testing.T) { + var filename string + + t.Run("scoped lifetime", func(t *testing.T) { + f := NewTemporaryFile(t) + filename = f.Name() + + _, err := os.Stat(filename) + assert.ErrorIs(t, err, nil) + }) + + _, err := os.Stat(filename) + assert.ErrorIs(t, err, os.ErrNotExist) +} + +func TestTemporaryDirectory(t *testing.T) { + var tmp string + + t.Run("scoped lifetime", func(t *testing.T) { + tmp = NewTemporaryDirectory(t) + + stat, err := os.Stat(tmp) + assert.NoError(t, err) + assert.True(t, stat.IsDir(), "Must have the directory permissions set") + }) + + _, err := os.Stat(tmp) + assert.ErrorIs(t, err, os.ErrNotExist) +}