diff --git a/exporter/debugexporter/go.mod b/exporter/debugexporter/go.mod index 07f15eb0454..a99178a33f2 100644 --- a/exporter/debugexporter/go.mod +++ b/exporter/debugexporter/go.mod @@ -31,6 +31,7 @@ require ( go.opentelemetry.io/collector/extension v0.88.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0017 // indirect + go.opentelemetry.io/collector/receiver v0.88.0 // indirect go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect diff --git a/exporter/exportertest/contract_checker.go b/exporter/exportertest/contract_checker.go index 5f8c821875e..55694bf632e 100644 --- a/exporter/exportertest/contract_checker.go +++ b/exporter/exportertest/contract_checker.go @@ -19,24 +19,27 @@ import ( "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" ) -// UniqueIDAttrName is the attribute name that is used in log records/spans/datapoints as the unique identifier. -const UniqueIDAttrName = "test_id" +// uniqueIDAttrName is the attribute name that is used in log records/spans/datapoints as the unique identifier. +const uniqueIDAttrName = "test_id" -// UniqueIDAttrVal is the value type of the UniqueIDAttrName. -type UniqueIDAttrVal string +// uniqueIDAttrVal is the value type of the uniqueIDAttrName. +type uniqueIDAttrVal string type CheckConsumeContractParams struct { - T *testing.T - // Factory that allows to create an exporter. - Factory exporter.Factory + T *testing.T + NumberOfTestElements int // DataType to test for. DataType component.DataType - // Config of the exporter to use. - Config component.Config - NumberOfTestElements int - MockReceiverFactory MockReceiverFactory + // ExporterFactory to create an exporter to be tested. + ExporterFactory exporter.Factory + ExporterConfig component.Config + // ReceiverFactory to create a mock receiver. + ReceiverFactory receiver.Factory + ReceiverConfig component.Config } func CheckConsumeContract(params CheckConsumeContractParams) { @@ -73,50 +76,57 @@ func CheckConsumeContract(params CheckConsumeContractParams) { for _, scenario := range scenarios { params.T.Run( scenario.name, func(t *testing.T) { - checkConsumeContractScenario(params, scenario.decisionFunc, scenario.checkIfTestPassed) + checkConsumeContractScenario(t, params, scenario.decisionFunc, scenario.checkIfTestPassed) }, ) } } -func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFunc func() error, checkIfTestPassed func(*testing.T, int, requestCounter)) { +func checkConsumeContractScenario(t *testing.T, params CheckConsumeContractParams, decisionFunc func() error, checkIfTestPassed func(*testing.T, int, requestCounter)) { mockConsumerInstance := newMockConsumer(decisionFunc) - rcv := params.MockReceiverFactory(&mockConsumerInstance) switch params.DataType { case component.DataTypeLogs: - checkLogs(params, rcv, &mockConsumerInstance, checkIfTestPassed) + r, err := params.ReceiverFactory.CreateLogsReceiver(context.Background(), receivertest.NewNopCreateSettings(), params.ReceiverConfig, &mockConsumerInstance) + require.NoError(t, err) + require.NoError(t, r.Start(context.Background(), componenttest.NewNopHost())) + checkLogs(t, params, r, &mockConsumerInstance, checkIfTestPassed) case component.DataTypeTraces: - checkTraces(params, rcv, &mockConsumerInstance, checkIfTestPassed) + r, err := params.ReceiverFactory.CreateTracesReceiver(context.Background(), receivertest.NewNopCreateSettings(), params.ReceiverConfig, &mockConsumerInstance) + require.NoError(t, err) + require.NoError(t, r.Start(context.Background(), componenttest.NewNopHost())) + checkTraces(t, params, r, &mockConsumerInstance, checkIfTestPassed) case component.DataTypeMetrics: - checkMetrics(params, rcv, &mockConsumerInstance, checkIfTestPassed) + r, err := params.ReceiverFactory.CreateMetricsReceiver(context.Background(), receivertest.NewNopCreateSettings(), params.ReceiverConfig, &mockConsumerInstance) + require.NoError(t, err) + require.NoError(t, r.Start(context.Background(), componenttest.NewNopHost())) + checkMetrics(t, params, r, &mockConsumerInstance, checkIfTestPassed) default: - require.FailNow(params.T, "must specify a valid DataType to test for") + require.FailNow(t, "must specify a valid DataType to test for") } - } -func checkMetrics(params CheckConsumeContractParams, mockReceiver component.Component, mockConsumer *MockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { +func checkMetrics(t *testing.T, params CheckConsumeContractParams, mockReceiver component.Component, + mockConsumer *mockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { ctx := context.Background() var exp exporter.Metrics var err error - exp, err = params.Factory.CreateMetricsExporter(ctx, NewNopCreateSettings(), params.Config) - require.NoError(params.T, err) - require.NotNil(params.T, exp) + exp, err = params.ExporterFactory.CreateMetricsExporter(ctx, NewNopCreateSettings(), params.ExporterConfig) + require.NoError(t, err) + require.NotNil(t, exp) err = exp.Start(ctx, componenttest.NewNopHost()) - require.NoError(params.T, err) + require.NoError(t, err) defer func(exp exporter.Metrics, ctx context.Context) { err = exp.Shutdown(ctx) - require.NoError(params.T, err) + require.NoError(t, err) err = mockReceiver.Shutdown(ctx) - require.NoError(params.T, err) + require.NoError(t, err) mockConsumer.clear() }(exp, ctx) for i := 0; i < params.NumberOfTestElements; i++ { - id := UniqueIDAttrVal(strconv.Itoa(i)) - fmt.Println("Preparing metric number: ", id) + id := uniqueIDAttrVal(strconv.Itoa(i)) data := createOneMetricWithID(id) err = exp.ConsumeMetrics(ctx, data) @@ -131,33 +141,32 @@ func checkMetrics(params CheckConsumeContractParams, mockReceiver component.Comp fmt.Printf("Number of permanent errors: %d\n", reqCounter.error.permanent) fmt.Printf("Number of non-permanent errors: %d\n", reqCounter.error.nonpermanent) - assert.EventuallyWithT(params.T, func(c *assert.CollectT) { - checkIfTestPassed(params.T, params.NumberOfTestElements, *reqCounter) + assert.EventuallyWithT(t, func(c *assert.CollectT) { + checkIfTestPassed(t, params.NumberOfTestElements, *reqCounter) }, 2*time.Second, 100*time.Millisecond) } -func checkTraces(params CheckConsumeContractParams, mockReceiver component.Component, mockConsumer *MockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { +func checkTraces(t *testing.T, params CheckConsumeContractParams, mockReceiver component.Component, mockConsumer *mockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { ctx := context.Background() var exp exporter.Traces var err error - exp, err = params.Factory.CreateTracesExporter(ctx, NewNopCreateSettings(), params.Config) - require.NoError(params.T, err) - require.NotNil(params.T, exp) + exp, err = params.ExporterFactory.CreateTracesExporter(ctx, NewNopCreateSettings(), params.ExporterConfig) + require.NoError(t, err) + require.NotNil(t, exp) err = exp.Start(ctx, componenttest.NewNopHost()) - require.NoError(params.T, err) + require.NoError(t, err) defer func(exp exporter.Traces, ctx context.Context) { err = exp.Shutdown(ctx) - require.NoError(params.T, err) + require.NoError(t, err) err = mockReceiver.Shutdown(ctx) - require.NoError(params.T, err) + require.NoError(t, err) mockConsumer.clear() }(exp, ctx) for i := 0; i < params.NumberOfTestElements; i++ { - id := UniqueIDAttrVal(strconv.Itoa(i)) - fmt.Println("Preparing trace number: ", id) + id := uniqueIDAttrVal(strconv.Itoa(i)) data := createOneTraceWithID(id) err = exp.ConsumeTraces(ctx, data) @@ -172,33 +181,32 @@ func checkTraces(params CheckConsumeContractParams, mockReceiver component.Compo fmt.Printf("Number of permanent errors: %d\n", reqCounter.error.permanent) fmt.Printf("Number of non-permanent errors: %d\n", reqCounter.error.nonpermanent) - assert.EventuallyWithT(params.T, func(c *assert.CollectT) { - checkIfTestPassed(params.T, params.NumberOfTestElements, *reqCounter) + assert.EventuallyWithT(t, func(c *assert.CollectT) { + checkIfTestPassed(t, params.NumberOfTestElements, *reqCounter) }, 2*time.Second, 100*time.Millisecond) } -func checkLogs(params CheckConsumeContractParams, mockReceiver component.Component, mockConsumer *MockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { +func checkLogs(t *testing.T, params CheckConsumeContractParams, mockReceiver component.Component, mockConsumer *mockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { ctx := context.Background() var exp exporter.Logs var err error - exp, err = params.Factory.CreateLogsExporter(ctx, NewNopCreateSettings(), params.Config) - require.NoError(params.T, err) - require.NotNil(params.T, exp) + exp, err = params.ExporterFactory.CreateLogsExporter(ctx, NewNopCreateSettings(), params.ExporterConfig) + require.NoError(t, err) + require.NotNil(t, exp) err = exp.Start(ctx, componenttest.NewNopHost()) - require.NoError(params.T, err) + require.NoError(t, err) defer func(exp exporter.Logs, ctx context.Context) { err = exp.Shutdown(ctx) - require.NoError(params.T, err) + require.NoError(t, err) err = mockReceiver.Shutdown(ctx) - require.NoError(params.T, err) + require.NoError(t, err) mockConsumer.clear() }(exp, ctx) for i := 0; i < params.NumberOfTestElements; i++ { - id := UniqueIDAttrVal(strconv.Itoa(i)) - fmt.Println("Preparing log number: ", id) + id := uniqueIDAttrVal(strconv.Itoa(i)) data := createOneLogWithID(id) err = exp.ConsumeLogs(ctx, data) @@ -212,8 +220,8 @@ func checkLogs(params CheckConsumeContractParams, mockReceiver component.Compone fmt.Printf("Number of permanent errors: %d\n", reqCounter.error.permanent) fmt.Printf("Number of non-permanent errors: %d\n", reqCounter.error.nonpermanent) - assert.EventuallyWithT(params.T, func(c *assert.CollectT) { - checkIfTestPassed(params.T, params.NumberOfTestElements, *reqCounter) + assert.EventuallyWithT(t, func(c *assert.CollectT) { + checkIfTestPassed(t, params.NumberOfTestElements, *reqCounter) }, 2*time.Second, 100*time.Millisecond) } @@ -246,26 +254,27 @@ func randomErrorConsumeDecisionPassed(t *testing.T, allRecordsNumber int, reqCou require.Equal(t, reqCounter.total, allRecordsNumber+reqCounter.error.nonpermanent) } -func createOneLogWithID(id UniqueIDAttrVal) plog.Logs { +func createOneLogWithID(id uniqueIDAttrVal) plog.Logs { data := plog.NewLogs() data.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes().PutStr( - UniqueIDAttrName, + uniqueIDAttrName, string(id), ) return data } -func createOneTraceWithID(id UniqueIDAttrVal) ptrace.Traces { +func createOneTraceWithID(id uniqueIDAttrVal) ptrace.Traces { data := ptrace.NewTraces() data.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes().PutStr( - UniqueIDAttrName, + uniqueIDAttrName, string(id), ) return data } -func createOneMetricWithID(id UniqueIDAttrVal) pmetric.Metrics { +func createOneMetricWithID(id uniqueIDAttrVal) pmetric.Metrics { data := pmetric.NewMetrics() - data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutStr(UniqueIDAttrName, string(id)) + data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram(). + DataPoints().AppendEmpty().Attributes().PutStr(uniqueIDAttrName, string(id)) return data } diff --git a/exporter/exportertest/contract_checker_test.go b/exporter/exportertest/contract_checker_test.go index de978332c85..2ea2ac9be35 100644 --- a/exporter/exportertest/contract_checker_test.go +++ b/exporter/exportertest/contract_checker_test.go @@ -8,239 +8,135 @@ import ( "testing" "time" - "github.com/cenkalti/backoff/v4" - "go.opentelemetry.io/otel/metric/noop" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/consumer/consumererror" + "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper" - "go.opentelemetry.io/collector/pdata/pcommon" - "go.opentelemetry.io/collector/pdata/plog" - "go.opentelemetry.io/collector/pdata/pmetric" - "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/receiver" ) -func (bor *testMockReceiver) Start(_ context.Context, _ component.Host) error { - return nil -} - -func (bor *testMockReceiver) Shutdown(_ context.Context) error { - return nil -} - -func newExampleFactory() exporter.Factory { - return exporter.NewFactory( - typeStr, - createDefaultConfig, - exporter.WithLogs(CreateLogsExporter, component.StabilityLevelBeta), - exporter.WithTraces(CreateTracesExporter, component.StabilityLevelBeta), - exporter.WithMetrics(CreateMetricsExporter, component.StabilityLevelBeta), +// retryConfig is a configuration to quickly retry failed exports. +var retryConfig = func() exporterhelper.RetrySettings { + c := exporterhelper.NewDefaultRetrySettings() + c.InitialInterval = time.Millisecond + return c +}() + +// mockReceiver is a receiver with pass-through consumers. +type mockReceiver struct { + component.StartFunc + component.ShutdownFunc + consumer.Traces + consumer.Metrics + consumer.Logs +} + +// mockExporterFactory is a factory to create exporters sending data to the mockReceiver. +type mockExporterFactory struct { + mr *mockReceiver + component.StartFunc + component.ShutdownFunc +} + +func (mef *mockExporterFactory) createMockTracesExporter( + ctx context.Context, + set exporter.CreateSettings, + cfg component.Config, +) (exporter.Traces, error) { + return exporterhelper.NewTracesExporter(ctx, set, cfg, + mef.mr.Traces.ConsumeTraces, + exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), + exporterhelper.WithRetry(retryConfig), ) } -func CreateLogsExporter(_ context.Context, _ exporter.CreateSettings, cfg component.Config) (exporter.Logs, error) { - set := exporter.CreateSettings{ - ID: component.NewIDWithName(component.DataTypeLogs, "test-exporter"), - TelemetrySettings: component.TelemetrySettings{ - Logger: zap.NewNop(), - TracerProvider: trace.NewNoopTracerProvider(), - MeterProvider: noop.NewMeterProvider(), - MetricsLevel: 0, - Resource: pcommon.Resource{}, - ReportComponentStatus: nil, - }, - BuildInfo: component.BuildInfo{Version: "0.0.0"}, - } - expConfig := cfg.(*ConnectionConfig) - le, err := exporterhelper.NewLogsExporter( - context.Background(), - set, - cfg, - pushLogs, - exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), - exporterhelper.WithRetry(expConfig.RetrySettings), - exporterhelper.WithQueue(expConfig.QueueSettings)) - return le, err -} - -func CreateTracesExporter(_ context.Context, _ exporter.CreateSettings, cfg component.Config) (exporter.Traces, error) { - set := exporter.CreateSettings{ - ID: component.NewIDWithName(component.DataTypeTraces, "test-exporter"), - TelemetrySettings: component.TelemetrySettings{ - Logger: zap.NewNop(), - TracerProvider: trace.NewNoopTracerProvider(), - MeterProvider: noop.NewMeterProvider(), - MetricsLevel: 0, - Resource: pcommon.Resource{}, - ReportComponentStatus: nil, - }, - BuildInfo: component.BuildInfo{Version: "0.0.0"}, - } - expConfig := cfg.(*ConnectionConfig) - le, err := exporterhelper.NewTracesExporter( - context.Background(), - set, - cfg, - pushTraces, - exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), - exporterhelper.WithRetry(expConfig.RetrySettings), - exporterhelper.WithQueue(expConfig.QueueSettings)) - return le, err -} - -func pushTraces(_ context.Context, _ ptrace.Traces) error { - return pushAny() -} - -func CreateMetricsExporter(_ context.Context, _ exporter.CreateSettings, cfg component.Config) (exporter.Metrics, error) { - set := exporter.CreateSettings{ - ID: component.NewIDWithName(component.DataTypeMetrics, "test-exporter"), - TelemetrySettings: component.TelemetrySettings{ - Logger: zap.NewNop(), - TracerProvider: trace.NewNoopTracerProvider(), - MeterProvider: noop.NewMeterProvider(), - MetricsLevel: 0, - Resource: pcommon.Resource{}, - ReportComponentStatus: nil, - }, - BuildInfo: component.BuildInfo{Version: "0.0.0"}, - } - expConfig := cfg.(*ConnectionConfig) - le, err := exporterhelper.NewMetricsExporter( - context.Background(), - set, - cfg, - pushMetrics, - exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), - exporterhelper.WithRetry(expConfig.RetrySettings), - exporterhelper.WithQueue(expConfig.QueueSettings)) - return le, err -} - -func pushAny() error { - joinedRequestCounter.total++ - generatedError := fakeMockConsumer.exportErrorFunction() - if generatedError != nil { - if consumererror.IsPermanent(generatedError) { - joinedRequestCounter.error.permanent++ - } else { - joinedRequestCounter.error.nonpermanent++ - } - return generatedError - } - joinedRequestCounter.success++ - return nil -} - -func pushMetrics(_ context.Context, _ pmetric.Metrics) error { - return pushAny() -} - -func pushLogs(_ context.Context, _ plog.Logs) error { - return pushAny() -} - -func createDefaultConfig() component.Config { - return &ConnectionConfig{ - TimeoutSettings: exporterhelper.NewDefaultTimeoutSettings(), - RetrySettings: exporterhelper.NewDefaultRetrySettings(), - QueueSettings: exporterhelper.NewDefaultQueueSettings(), - } -} - -func newTestRetrySettings() exporterhelper.RetrySettings { - return exporterhelper.RetrySettings{ - Enabled: true, - // interval is short for the test purposes - InitialInterval: 10 * time.Millisecond, - RandomizationFactor: backoff.DefaultRandomizationFactor, - Multiplier: 1.1, - MaxInterval: 10 * time.Second, - MaxElapsedTime: 1 * time.Minute, - } -} - -type ConnectionConfig struct { - exporterhelper.TimeoutSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. - exporterhelper.QueueSettings `mapstructure:"sending_queue"` - exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` -} - -func testConfig() *ConnectionConfig { - return &ConnectionConfig{ - TimeoutSettings: exporterhelper.TimeoutSettings{}, - QueueSettings: exporterhelper.QueueSettings{Enabled: false}, - RetrySettings: newTestRetrySettings(), - } +func (mef *mockExporterFactory) createMockMetricsExporter( + ctx context.Context, + set exporter.CreateSettings, + cfg component.Config, +) (exporter.Metrics, error) { + return exporterhelper.NewMetricsExporter(ctx, set, cfg, + mef.mr.Metrics.ConsumeMetrics, + exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), + exporterhelper.WithRetry(retryConfig), + ) } -type testMockReceiver struct { - mockConsumer *MockConsumer +func (mef *mockExporterFactory) createMockLogsExporter( + ctx context.Context, + set exporter.CreateSettings, + cfg component.Config, +) (exporter.Logs, error) { + return exporterhelper.NewLogsExporter(ctx, set, cfg, + mef.mr.Logs.ConsumeLogs, + exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), + exporterhelper.WithRetry(retryConfig), + ) } -func newOTLPDataReceiver(mockConsumer *MockConsumer) *testMockReceiver { - return &testMockReceiver{mockConsumer: mockConsumer} +func newMockExporterFactory(mr *mockReceiver) exporter.Factory { + mef := &mockExporterFactory{mr: mr} + return exporter.NewFactory( + "pass_through_exporter", + func() component.Config { return &nopConfig{} }, + exporter.WithTraces(mef.createMockTracesExporter, component.StabilityLevelBeta), + exporter.WithMetrics(mef.createMockMetricsExporter, component.StabilityLevelBeta), + exporter.WithLogs(mef.createMockLogsExporter, component.StabilityLevelBeta), + ) } -var joinedRequestCounter = newRequestCounter() - -var fakeMockConsumer = &MockConsumer{reqCounter: joinedRequestCounter} - -// Define a function that matches the MockReceiverFactory signature -func createMockOtlpReceiver(mockConsumer *MockConsumer) component.Component { - rcv := newOTLPDataReceiver(mockConsumer) - joinedRequestCounter = newRequestCounter() - fakeMockConsumer.exportErrorFunction = mockConsumer.exportErrorFunction - mockConsumer.reqCounter = joinedRequestCounter - err := rcv.Start(context.Background(), nil) - if err != nil { - return nil - } - return rcv +func newMockReceiverFactory(mr *mockReceiver) receiver.Factory { + return receiver.NewFactory("pass_through_receiver", + func() component.Config { return &nopConfig{} }, + receiver.WithTraces(func(_ context.Context, _ receiver.CreateSettings, _ component.Config, c consumer.Traces) (receiver.Traces, error) { + mr.Traces = c + return mr, nil + }, component.StabilityLevelStable), + receiver.WithMetrics(func(_ context.Context, _ receiver.CreateSettings, _ component.Config, c consumer.Metrics) (receiver.Metrics, error) { + mr.Metrics = c + return mr, nil + }, component.StabilityLevelStable), + receiver.WithLogs(func(_ context.Context, _ receiver.CreateSettings, _ component.Config, c consumer.Logs) (receiver.Logs, error) { + mr.Logs = c + return mr, nil + }, component.StabilityLevelStable), + ) } func TestCheckConsumeContractLogs(t *testing.T) { - + mr := &mockReceiver{} params := CheckConsumeContractParams{ T: t, - Factory: newExampleFactory(), // Replace with your exporter factory - DataType: component.DataTypeLogs, // Change to the appropriate data type - Config: testConfig(), - NumberOfTestElements: 10, // Number of test elements you want to send - MockReceiverFactory: createMockOtlpReceiver, + ExporterFactory: newMockExporterFactory(mr), + DataType: component.DataTypeLogs, + ExporterConfig: nopConfig{}, + NumberOfTestElements: 10, + ReceiverFactory: newMockReceiverFactory(mr), } CheckConsumeContract(params) } func TestCheckConsumeContractMetrics(t *testing.T) { - - // Create a CheckConsumeContractParams - params := CheckConsumeContractParams{ + mr := &mockReceiver{} + CheckConsumeContract(CheckConsumeContractParams{ T: t, - Factory: newExampleFactory(), // Replace with your exporter factory + ExporterFactory: newMockExporterFactory(mr), DataType: component.DataTypeMetrics, // Change to the appropriate data type - Config: testConfig(), - NumberOfTestElements: 10, // Number of test elements you want to send - MockReceiverFactory: createMockOtlpReceiver, - } - - CheckConsumeContract(params) + ExporterConfig: nopConfig{}, + NumberOfTestElements: 10, + ReceiverFactory: newMockReceiverFactory(mr), + }) } func TestCheckConsumeContractTraces(t *testing.T) { - - params := CheckConsumeContractParams{ + mr := &mockReceiver{} + CheckConsumeContract(CheckConsumeContractParams{ T: t, - Factory: newExampleFactory(), // Replace with your exporter factory - DataType: component.DataTypeTraces, // Change to the appropriate data type - Config: testConfig(), - NumberOfTestElements: 10, // Number of test elements you want to send - MockReceiverFactory: createMockOtlpReceiver, - } - - CheckConsumeContract(params) + ExporterFactory: newMockExporterFactory(mr), + DataType: component.DataTypeTraces, + ExporterConfig: nopConfig{}, + NumberOfTestElements: 10, + ReceiverFactory: newMockReceiverFactory(mr), + }) } diff --git a/exporter/exportertest/mock_receiver.go b/exporter/exportertest/mock_consumer.go similarity index 78% rename from exporter/exportertest/mock_receiver.go rename to exporter/exportertest/mock_consumer.go index b26047f6dd4..89e075407c6 100644 --- a/exporter/exportertest/mock_receiver.go +++ b/exporter/exportertest/mock_consumer.go @@ -11,7 +11,6 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/pdata/pcommon" @@ -23,8 +22,6 @@ import ( var errNonPermanent = status.Error(codes.DeadlineExceeded, "non Permanent error") var errPermanent = status.Error(codes.Internal, "Permanent error") -type MockReceiverFactory func(consumer *MockConsumer) component.Component - // // randomNonPermanentErrorConsumeDecision is a decision function that succeeds approximately // // half of the time and fails with a non-permanent error the rest of the time. func randomNonPermanentErrorConsumeDecision() error { @@ -58,7 +55,10 @@ func randomErrorsConsumeDecision() error { return nil } -type MockConsumer struct { +type mockConsumer struct { + consumer.Traces + consumer.Logs + consumer.Metrics reqCounter *requestCounter mux sync.Mutex exportErrorFunction func() error @@ -67,8 +67,8 @@ type MockConsumer struct { receivedLogs []plog.Logs } -func newMockConsumer(decisionFunc func() error) MockConsumer { - return MockConsumer{ +func newMockConsumer(decisionFunc func() error) mockConsumer { + return mockConsumer{ reqCounter: newRequestCounter(), mux: sync.Mutex{}, exportErrorFunction: decisionFunc, @@ -78,7 +78,7 @@ func newMockConsumer(decisionFunc func() error) MockConsumer { } } -func (r *MockConsumer) ConsumeLogs(_ context.Context, ld plog.Logs) error { +func (r *mockConsumer) ConsumeLogs(_ context.Context, ld plog.Logs) error { r.mux.Lock() defer r.mux.Unlock() r.reqCounter.total++ @@ -88,13 +88,12 @@ func (r *MockConsumer) ConsumeLogs(_ context.Context, ld plog.Logs) error { r.processError(generatedError, "log", logID) return generatedError } - fmt.Println("Successfully sent log number:", logID) r.reqCounter.success++ r.receivedLogs = append(r.receivedLogs, ld) return nil } -func (r *MockConsumer) ConsumeTraces(_ context.Context, td ptrace.Traces) error { +func (r *mockConsumer) ConsumeTraces(_ context.Context, td ptrace.Traces) error { r.mux.Lock() defer r.mux.Unlock() r.reqCounter.total++ @@ -104,13 +103,12 @@ func (r *MockConsumer) ConsumeTraces(_ context.Context, td ptrace.Traces) error r.processError(generatedError, "log", traceID) return generatedError } - fmt.Println("Successfully sent log number:", traceID) r.reqCounter.success++ r.receivedTraces = append(r.receivedTraces, td) return nil } -func (r *MockConsumer) ConsumeMetrics(_ context.Context, md pmetric.Metrics) error { +func (r *mockConsumer) ConsumeMetrics(_ context.Context, md pmetric.Metrics) error { r.mux.Lock() defer r.mux.Unlock() r.reqCounter.total++ @@ -120,35 +118,30 @@ func (r *MockConsumer) ConsumeMetrics(_ context.Context, md pmetric.Metrics) err r.processError(generatedError, "log", traceID) return generatedError } - fmt.Println("Successfully sent log number:", traceID) r.reqCounter.success++ r.receivedMetrics = append(r.receivedMetrics, md) return nil } -func (r *MockConsumer) Capabilities() consumer.Capabilities { +func (r *mockConsumer) Capabilities() consumer.Capabilities { return consumer.Capabilities{} } -func (r *MockConsumer) processError(err error, dataType string, idOfElement string) { +func (r *mockConsumer) processError(err error, dataType string, idOfElement string) { if consumererror.IsPermanent(err) { - fmt.Println("permanent error happened") - fmt.Printf("Dropping %s number: %s\n", dataType, idOfElement) r.reqCounter.error.permanent++ } else { - fmt.Println("non-permanent error happened") - fmt.Printf("Retrying %s number: %s\n", dataType, idOfElement) r.reqCounter.error.nonpermanent++ } } -func (r *MockConsumer) clear() { +func (r *mockConsumer) clear() { r.mux.Lock() defer r.mux.Unlock() r.reqCounter = newRequestCounter() } -func (r *MockConsumer) getRequestCounter() *requestCounter { +func (r *mockConsumer) getRequestCounter() *requestCounter { return r.reqCounter } @@ -181,12 +174,12 @@ func newRequestCounter() *requestCounter { func idFromLogs(data plog.Logs) (string, error) { var logID string rss := data.ResourceLogs() - key, exists := rss.At(0).ScopeLogs().At(0).LogRecords().At(0).Attributes().Get(UniqueIDAttrName) + key, exists := rss.At(0).ScopeLogs().At(0).LogRecords().At(0).Attributes().Get(uniqueIDAttrName) if !exists { - return "", fmt.Errorf("invalid data element, attribute %q is missing", UniqueIDAttrName) + return "", fmt.Errorf("invalid data element, attribute %q is missing", uniqueIDAttrName) } if key.Type() != pcommon.ValueTypeStr { - return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", UniqueIDAttrName, key.Type()) + return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", uniqueIDAttrName, key.Type()) } logID = key.Str() return logID, nil @@ -195,12 +188,12 @@ func idFromLogs(data plog.Logs) (string, error) { func idFromTraces(data ptrace.Traces) (string, error) { var traceID string rss := data.ResourceSpans() - key, exists := rss.At(0).ScopeSpans().At(0).Spans().At(0).Attributes().Get(UniqueIDAttrName) + key, exists := rss.At(0).ScopeSpans().At(0).Spans().At(0).Attributes().Get(uniqueIDAttrName) if !exists { - return "", fmt.Errorf("invalid data element, attribute %q is missing", UniqueIDAttrName) + return "", fmt.Errorf("invalid data element, attribute %q is missing", uniqueIDAttrName) } if key.Type() != pcommon.ValueTypeStr { - return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", UniqueIDAttrName, key.Type()) + return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", uniqueIDAttrName, key.Type()) } traceID = key.Str() return traceID, nil @@ -209,12 +202,13 @@ func idFromTraces(data ptrace.Traces) (string, error) { func idFromMetrics(data pmetric.Metrics) (string, error) { var metricID string rss := data.ResourceMetrics() - key, exists := rss.At(0).ScopeMetrics().At(0).Metrics().At(0).Histogram().DataPoints().At(0).Attributes().Get(UniqueIDAttrName) + key, exists := rss.At(0).ScopeMetrics().At(0).Metrics().At(0).Histogram().DataPoints().At(0).Attributes().Get( + uniqueIDAttrName) if !exists { - return "", fmt.Errorf("invalid data element, attribute %q is missing", UniqueIDAttrName) + return "", fmt.Errorf("invalid data element, attribute %q is missing", uniqueIDAttrName) } if key.Type() != pcommon.ValueTypeStr { - return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", UniqueIDAttrName, key.Type()) + return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", uniqueIDAttrName, key.Type()) } metricID = key.Str() return metricID, nil diff --git a/exporter/exportertest/mock_receiver_test.go b/exporter/exportertest/mock_consumer_test.go similarity index 53% rename from exporter/exportertest/mock_receiver_test.go rename to exporter/exportertest/mock_consumer_test.go index 6a10a36451a..63eec26d7fd 100644 --- a/exporter/exportertest/mock_receiver_test.go +++ b/exporter/exportertest/mock_consumer_test.go @@ -19,7 +19,7 @@ import ( func createLog(id string) plog.Logs { validData := plog.NewLogs() validData.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes().PutStr( - UniqueIDAttrName, + uniqueIDAttrName, id, ) return validData @@ -28,7 +28,7 @@ func createLog(id string) plog.Logs { func createTrace(id string) ptrace.Traces { validData := ptrace.NewTraces() validData.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes().PutStr( - UniqueIDAttrName, + uniqueIDAttrName, id, ) return validData @@ -36,7 +36,7 @@ func createTrace(id string) ptrace.Traces { func createMetric(id string) pmetric.Metrics { validData := pmetric.NewMetrics() - validData.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutStr(UniqueIDAttrName, id) + validData.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutStr(uniqueIDAttrName, id) return validData } @@ -48,20 +48,21 @@ func TestIDFromMetrics(t *testing.T) { assert.Equal(t, metricID, id) assert.NoError(t, err) - // Test case 2: Missing UniqueIDAttrName attribute + // Test case 2: Missing uniqueIDAttrName attribute invalidData := pmetric.NewMetrics() // Create an invalid pmetric.Metrics object with missing attribute invalidData.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes() _, err = idFromMetrics(invalidData) assert.Error(t, err) - assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", UniqueIDAttrName)) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", uniqueIDAttrName)) // Test case 3: Wrong attribute type var intID int64 = 12 wrongAttribute := pmetric.NewMetrics() // Create a valid pmetric.Metrics object - wrongAttribute.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutInt(UniqueIDAttrName, intID) + wrongAttribute.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty(). + SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutInt(uniqueIDAttrName, intID) _, err = idFromMetrics(wrongAttribute) assert.Error(t, err) - assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", UniqueIDAttrName)) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", uniqueIDAttrName)) } func TestIDFromTraces(t *testing.T) { @@ -72,20 +73,21 @@ func TestIDFromTraces(t *testing.T) { assert.Equal(t, traceID, id) assert.NoError(t, err) - // Test case 2: Missing UniqueIDAttrName attribute + // Test case 2: Missing uniqueIDAttrName attribute invalidData := ptrace.NewTraces() invalidData.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes() _, err = idFromTraces(invalidData) assert.Error(t, err) - assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", UniqueIDAttrName)) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", uniqueIDAttrName)) // Test case 3: Wrong attribute type var intID int64 = 12 wrongAttribute := ptrace.NewTraces() - wrongAttribute.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes().PutInt(UniqueIDAttrName, intID) + wrongAttribute.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes(). + PutInt(uniqueIDAttrName, intID) _, err = idFromTraces(wrongAttribute) assert.Error(t, err) - assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", UniqueIDAttrName)) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", uniqueIDAttrName)) } func TestIDFromLogs(t *testing.T) { @@ -96,20 +98,21 @@ func TestIDFromLogs(t *testing.T) { assert.Equal(t, logID, id) assert.NoError(t, err) - // Test case 2: Missing UniqueIDAttrName attribute + // Test case 2: Missing uniqueIDAttrName attribute invalidData := plog.NewLogs() invalidData.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes() _, err = idFromLogs(invalidData) assert.Error(t, err) - assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", UniqueIDAttrName)) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", uniqueIDAttrName)) // Test case 3: Wrong attribute type var intID int64 = 12 wrongAttribute := plog.NewLogs() // Create a valid plog.Metrics object - wrongAttribute.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes().PutInt(UniqueIDAttrName, intID) + wrongAttribute.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes(). + PutInt(uniqueIDAttrName, intID) _, err = idFromLogs(wrongAttribute) assert.Error(t, err) - assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", UniqueIDAttrName)) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", uniqueIDAttrName)) } func returnNonPermanentError() error { @@ -121,140 +124,133 @@ func returnPermanentError() error { } func TestConsumeLogsNonPermanent(t *testing.T) { - - mockConsumer := newMockConsumer(returnNonPermanentError) + mc := newMockConsumer(returnNonPermanentError) validData := createLog("logId") - err := mockConsumer.ConsumeLogs(context.Background(), validData) + err := mc.ConsumeLogs(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 1) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 0) - assert.Equal(t, mockConsumer.reqCounter.success, 0) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 1) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) } func TestConsumeLogsPermanent(t *testing.T) { - mockConsumer := newMockConsumer(returnPermanentError) + mc := newMockConsumer(returnPermanentError) validData := createLog("logId") - err := mockConsumer.ConsumeLogs(context.Background(), validData) + err := mc.ConsumeLogs(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 0) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 1) - assert.Equal(t, mockConsumer.reqCounter.success, 0) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 1) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) } func TestConsumeLogsSuccess(t *testing.T) { - - mockConsumer := newMockConsumer(func() error { return nil }) + mc := newMockConsumer(func() error { return nil }) validData := createLog("logId") - err := mockConsumer.ConsumeLogs(context.Background(), validData) + err := mc.ConsumeLogs(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 0) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 0) - assert.Equal(t, mockConsumer.reqCounter.success, 1) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 1) + assert.Equal(t, mc.reqCounter.total, 1) } func TestConsumeTracesNonPermanent(t *testing.T) { - - mockConsumer := newMockConsumer(returnNonPermanentError) + mc := newMockConsumer(returnNonPermanentError) validData := createTrace("traceId") - err := mockConsumer.ConsumeTraces(context.Background(), validData) + err := mc.ConsumeTraces(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 1) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 0) - assert.Equal(t, mockConsumer.reqCounter.success, 0) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 1) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) } func TestConsumeTracesPermanent(t *testing.T) { - mockConsumer := newMockConsumer(returnPermanentError) + mc := newMockConsumer(returnPermanentError) validData := createTrace("traceId") - err := mockConsumer.ConsumeTraces(context.Background(), validData) + err := mc.ConsumeTraces(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 0) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 1) - assert.Equal(t, mockConsumer.reqCounter.success, 0) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 1) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) } func TestConsumeTracesSuccess(t *testing.T) { - - mockConsumer := newMockConsumer(func() error { return nil }) + mc := newMockConsumer(func() error { return nil }) validData := createTrace("traceId") - err := mockConsumer.ConsumeTraces(context.Background(), validData) + err := mc.ConsumeTraces(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 0) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 0) - assert.Equal(t, mockConsumer.reqCounter.success, 1) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 1) + assert.Equal(t, mc.reqCounter.total, 1) } func TestConsumeMetricsNonPermanent(t *testing.T) { - - mockConsumer := newMockConsumer(returnNonPermanentError) + mc := newMockConsumer(returnNonPermanentError) validData := createMetric("metricId") - err := mockConsumer.ConsumeMetrics(context.Background(), validData) + err := mc.ConsumeMetrics(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 1) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 0) - assert.Equal(t, mockConsumer.reqCounter.success, 0) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 1) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) } func TestConsumeMetricsPermanent(t *testing.T) { - - mockConsumer := newMockConsumer(returnPermanentError) + mc := newMockConsumer(returnPermanentError) validData := createMetric("metricId") - err := mockConsumer.ConsumeMetrics(context.Background(), validData) + err := mc.ConsumeMetrics(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 0) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 1) - assert.Equal(t, mockConsumer.reqCounter.success, 0) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 1) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) } func TestConsumeMetricsSuccess(t *testing.T) { - - mockConsumer := newMockConsumer(func() error { return nil }) + mc := newMockConsumer(func() error { return nil }) validData := createMetric("metricId") - err := mockConsumer.ConsumeMetrics(context.Background(), validData) + err := mc.ConsumeMetrics(context.Background(), validData) if err != nil { return } - assert.Equal(t, mockConsumer.reqCounter.error.nonpermanent, 0) - assert.Equal(t, mockConsumer.reqCounter.error.permanent, 0) - assert.Equal(t, mockConsumer.reqCounter.success, 1) - assert.Equal(t, mockConsumer.reqCounter.total, 1) + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 1) + assert.Equal(t, mc.reqCounter.total, 1) } func TestCapabilites(t *testing.T) { - mockConsumer := newMockConsumer(func() error { return nil }) - assert.Equal(t, mockConsumer.Capabilities(), consumer.Capabilities{}) + mc := newMockConsumer(func() error { return nil }) + assert.Equal(t, mc.Capabilities(), consumer.Capabilities{}) } diff --git a/exporter/go.mod b/exporter/go.mod index 8b9ae891655..e1eac145770 100644 --- a/exporter/go.mod +++ b/exporter/go.mod @@ -12,6 +12,7 @@ require ( go.opentelemetry.io/collector/consumer v0.88.0 go.opentelemetry.io/collector/extension v0.88.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0017 + go.opentelemetry.io/collector/receiver v0.88.0 go.opentelemetry.io/otel v1.19.0 go.opentelemetry.io/otel/metric v1.19.0 go.opentelemetry.io/otel/sdk v1.19.0 diff --git a/exporter/loggingexporter/go.mod b/exporter/loggingexporter/go.mod index 48bb1319877..9de1566503b 100644 --- a/exporter/loggingexporter/go.mod +++ b/exporter/loggingexporter/go.mod @@ -33,6 +33,7 @@ require ( go.opentelemetry.io/collector/extension v0.88.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0017 // indirect + go.opentelemetry.io/collector/receiver v0.88.0 // indirect go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect diff --git a/exporter/otlpexporter/consume_contract_test.go b/exporter/otlpexporter/consume_contract_test.go index cdd746ada2e..6dd0dcb6547 100644 --- a/exporter/otlpexporter/consume_contract_test.go +++ b/exporter/otlpexporter/consume_contract_test.go @@ -4,95 +4,77 @@ package otlpexporter import ( - "context" "testing" "time" - "github.com/cenkalti/backoff/v4" - "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configgrpc" "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/exporter/exporterhelper" "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/internal/testutil" + "go.opentelemetry.io/collector/receiver/otlpreceiver" ) -// newTestRetrySettings returns the default settings for otlp exporter test. -func newTestRetrySettings() exporterhelper.RetrySettings { - return exporterhelper.RetrySettings{ - Enabled: true, - // interval is short for the test purposes - InitialInterval: 10 * time.Millisecond, - RandomizationFactor: backoff.DefaultRandomizationFactor, - Multiplier: 1.1, - MaxInterval: 10 * time.Second, - MaxElapsedTime: 1 * time.Minute, - } -} - -func testConfig() component.Config { +func testExporterConfig(endpoint string) component.Config { + retryConfig := exporterhelper.NewDefaultRetrySettings() + retryConfig.InitialInterval = time.Millisecond // interval is short for the test purposes return &Config{ - TimeoutSettings: exporterhelper.TimeoutSettings{}, - QueueSettings: exporterhelper.QueueSettings{Enabled: false}, - RetrySettings: newTestRetrySettings(), + QueueSettings: exporterhelper.QueueSettings{Enabled: false}, + RetrySettings: retryConfig, GRPCClientSettings: configgrpc.GRPCClientSettings{ - Endpoint: "0.0.0.0:4317", + Endpoint: endpoint, TLSSetting: configtls.TLSClientSetting{ Insecure: true, - }}, + }, + }, } } -// Define a function that matches the MockReceiverFactory signature -func createMockOtlpReceiver(mockConsumer *exportertest.MockConsumer) component.Component { - rcv := newOTLPDataReceiver(mockConsumer) - err := rcv.Start(context.Background(), nil) - if err != nil { - return nil - } - return rcv +func testRecieverConfig(endpoint string) component.Config { + cfg := otlpreceiver.NewFactory().CreateDefaultConfig() + cfg.(*otlpreceiver.Config).HTTP = nil + cfg.(*otlpreceiver.Config).GRPC.NetAddr.Endpoint = endpoint + return cfg } // TestConsumeContract is an example of testing of the exporter for the contract between the // exporter and the receiver. func TestConsumeContractOtlpLogs(t *testing.T) { - - params := exportertest.CheckConsumeContractParams{ + addr := testutil.GetAvailableLocalAddress(t) + exportertest.CheckConsumeContract(exportertest.CheckConsumeContractParams{ T: t, - Factory: NewFactory(), - DataType: component.DataTypeLogs, - Config: testConfig(), NumberOfTestElements: 10, - MockReceiverFactory: createMockOtlpReceiver, - } - - exportertest.CheckConsumeContract(params) + ExporterFactory: NewFactory(), + DataType: component.DataTypeLogs, + ExporterConfig: testExporterConfig(addr), + ReceiverFactory: otlpreceiver.NewFactory(), + ReceiverConfig: testRecieverConfig(addr), + }) } func TestConsumeContractOtlpTraces(t *testing.T) { - - params := exportertest.CheckConsumeContractParams{ + addr := testutil.GetAvailableLocalAddress(t) + exportertest.CheckConsumeContract(exportertest.CheckConsumeContractParams{ T: t, - Factory: NewFactory(), - DataType: component.DataTypeTraces, - Config: testConfig(), NumberOfTestElements: 10, - MockReceiverFactory: createMockOtlpReceiver, - } - - exportertest.CheckConsumeContract(params) + DataType: component.DataTypeTraces, + ExporterFactory: NewFactory(), + ExporterConfig: testExporterConfig(addr), + ReceiverFactory: otlpreceiver.NewFactory(), + ReceiverConfig: testRecieverConfig(addr), + }) } func TestConsumeContractOtlpMetrics(t *testing.T) { - - params := exportertest.CheckConsumeContractParams{ + addr := testutil.GetAvailableLocalAddress(t) + exportertest.CheckConsumeContract(exportertest.CheckConsumeContractParams{ T: t, - Factory: NewFactory(), - DataType: component.DataTypeMetrics, - Config: testConfig(), NumberOfTestElements: 10, - MockReceiverFactory: createMockOtlpReceiver, - } - - exportertest.CheckConsumeContract(params) + ExporterFactory: NewFactory(), + DataType: component.DataTypeMetrics, + ExporterConfig: testExporterConfig(addr), + ReceiverFactory: otlpreceiver.NewFactory(), + ReceiverConfig: testRecieverConfig(addr), + }) } diff --git a/exporter/otlpexporter/go.mod b/exporter/otlpexporter/go.mod index 058c6face3f..d739c054298 100644 --- a/exporter/otlpexporter/go.mod +++ b/exporter/otlpexporter/go.mod @@ -3,7 +3,6 @@ module go.opentelemetry.io/collector/exporter/otlpexporter go 1.20 require ( - github.com/cenkalti/backoff/v4 v4.2.1 github.com/stretchr/testify v1.8.4 go.opentelemetry.io/collector v0.88.0 go.opentelemetry.io/collector/component v0.88.0 @@ -16,12 +15,14 @@ require ( go.opentelemetry.io/collector/consumer v0.88.0 go.opentelemetry.io/collector/exporter v0.88.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0017 + go.opentelemetry.io/collector/receiver/otlpreceiver v0.88.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 ) require ( + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect @@ -44,12 +45,14 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/cors v1.10.1 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/collector/config/confighttp v0.88.0 // indirect go.opentelemetry.io/collector/config/confignet v0.88.0 // indirect go.opentelemetry.io/collector/config/configtelemetry v0.88.0 // indirect go.opentelemetry.io/collector/config/internal v0.88.0 // indirect go.opentelemetry.io/collector/extension v0.88.0 // indirect go.opentelemetry.io/collector/extension/auth v0.88.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017 // indirect + go.opentelemetry.io/collector/receiver v0.88.0 // indirect go.opentelemetry.io/collector/service v0.88.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect diff --git a/exporter/otlpexporter/mock_receiver.go b/exporter/otlpexporter/mock_receiver.go deleted file mode 100644 index 0246c3a5ded..00000000000 --- a/exporter/otlpexporter/mock_receiver.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package otlpexporter // import "go.opentelemetry.io/collector/exporter/otlpexporter" - -import ( - "context" - "errors" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/component/componenttest" - "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/receiver" - "go.opentelemetry.io/collector/receiver/otlpreceiver" - "go.opentelemetry.io/collector/receiver/receivertest" -) - -type mockOtlpReceiver struct { - mockConsumer *exportertest.MockConsumer - traceReceiver receiver.Traces - metricsReceiver receiver.Metrics - logReceiver receiver.Logs -} - -func newOTLPDataReceiver(mockConsumer *exportertest.MockConsumer) *mockOtlpReceiver { - return &mockOtlpReceiver{ - mockConsumer: mockConsumer, - } -} - -func (bor *mockOtlpReceiver) Start(ctx context.Context, _ component.Host) error { - factory := otlpreceiver.NewFactory() - cfg := factory.CreateDefaultConfig().(*otlpreceiver.Config) - cfg.HTTP = nil - var err error - set := receivertest.NewNopCreateSettings() - if bor.traceReceiver, err = factory.CreateTracesReceiver(ctx, set, cfg, bor.mockConsumer); err != nil { - return err - } - if bor.metricsReceiver, err = factory.CreateMetricsReceiver(ctx, set, cfg, bor.mockConsumer); err != nil { - return err - } - if bor.logReceiver, err = factory.CreateLogsReceiver(ctx, set, cfg, bor.mockConsumer); err != nil { - return err - } - - if err = bor.traceReceiver.Start(ctx, componenttest.NewNopHost()); err != nil { - return err - } - if err = bor.metricsReceiver.Start(ctx, componenttest.NewNopHost()); err != nil { - return err - } - return bor.logReceiver.Start(ctx, componenttest.NewNopHost()) -} - -func (bor *mockOtlpReceiver) Shutdown(ctx context.Context) error { - err := bor.traceReceiver.Shutdown(ctx) - err = errors.Join(err, bor.metricsReceiver.Shutdown(ctx)) - return errors.Join(err, bor.logReceiver.Shutdown(ctx)) -} diff --git a/internal/tools/go.sum b/internal/tools/go.sum index dd4b0d0272e..676efa78d7d 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -72,9 +72,11 @@ github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGt github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0= +github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/participle/v2 v2.1.0 h1:z7dElHRrOEEq45F2TG5cbQihMtNTv8vwldytDj7Wrz4= github.com/alecthomas/participle/v2 v2.1.0/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= +github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -87,7 +89,9 @@ github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cv github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= @@ -152,6 +156,7 @@ github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYB github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/elliotchance/orderedmap v1.5.0 h1:1IsExUsjv5XNBD3ZdC7jkAAqLWOOKdbPTmkHx63OsBg= github.com/elliotchance/orderedmap v1.5.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -173,11 +178,13 @@ github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4 github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-critic/go-critic v0.9.0 h1:Pmys9qvU3pSML/3GEQ2Xd9RZ/ip+aXHKILuxczKGV/U= github.com/go-critic/go-critic v0.9.0/go.mod h1:5P8tdXL7m/6qnyG6oRAlYLORvoXH0WDypYgAEmagT40= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -185,6 +192,7 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmS github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY= github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -197,11 +205,16 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= @@ -214,6 +227,7 @@ github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlN github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= @@ -286,6 +300,7 @@ github.com/google/addlicense v1.1.1/go.mod h1:Sm/DHu7Jk+T5miFHHehdIjbi4M5+dJDRS3 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= +github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -315,6 +330,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -334,6 +350,7 @@ github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3 github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -388,9 +405,11 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= github.com/kunwardeep/paralleltest v1.0.8 h1:Ul2KsqtzFxTlSU7IP0JusWlLiNqQaloB9vguyjbE558= @@ -402,6 +421,7 @@ github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdB github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= @@ -459,9 +479,12 @@ github.com/nunnatsa/ginkgolinter v0.13.5/go.mod h1:OBHy4536xtuX3102NM63XRtOyxqZO github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= +github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= @@ -473,6 +496,7 @@ github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdU github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -519,6 +543,7 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4l github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= @@ -637,6 +662,7 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t gitlab.com/bosi/decorder v0.4.0 h1:HWuxAhSxIvsITcXeP+iIRg9d1cVfvVkmlF7M68GaoDY= gitlab.com/bosi/decorder v0.4.0/go.mod h1:xarnteyUoJiOTEldDysquWKTVDCKo2TOIOIibSuWqOg= go-simpler.org/assert v0.6.0 h1:QxSrXa4oRuo/1eHMXSBFHKvJIpWABayzKldqZyugG7E= +go-simpler.org/assert v0.6.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -658,6 +684,7 @@ go.opentelemetry.io/build-tools/semconvgen v0.12.0/go.mod h1:SRmou8pp+7gBmf1Avdx go.tmz.dev/musttag v0.7.2 h1:1J6S9ipDbalBSODNT5jCep8dhZyMr4ttnjQagmGYR5s= go.tmz.dev/musttag v0.7.2/go.mod h1:m6q5NiiSKMnQYokefa2xGoyoXnrswCbJ0AWYzf4Zs28= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -866,6 +893,7 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1058,6 +1086,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=