From effd258b249b837ccf5d4141a9bd183724dca668 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 3 May 2024 17:52:35 -0700 Subject: [PATCH] Add a roundrobin connector, that can help single thread components to scale (#32853) --- .chloggen/roundrobinconnector.yaml | 22 +++ .github/CODEOWNERS | 1 + .github/ISSUE_TEMPLATE/bug_report.yaml | 1 + .github/ISSUE_TEMPLATE/feature_request.yaml | 1 + .github/ISSUE_TEMPLATE/other.yaml | 1 + .github/ISSUE_TEMPLATE/unmaintained.yaml | 1 + cmd/otelcontribcol/builder-config.yaml | 2 + cmd/otelcontribcol/components.go | 2 + cmd/otelcontribcol/go.mod | 3 + connector/roundrobinconnector/Makefile | 1 + connector/roundrobinconnector/README.md | 71 +++++++++ connector/roundrobinconnector/config.go | 7 + connector/roundrobinconnector/connector.go | 86 +++++++++++ .../roundrobinconnector/connector_test.go | 140 ++++++++++++++++++ connector/roundrobinconnector/doc.go | 4 + connector/roundrobinconnector/factory.go | 62 ++++++++ .../generated_component_test.go | 87 +++++++++++ .../generated_package_test.go | 13 ++ connector/roundrobinconnector/go.mod | 54 +++++++ connector/roundrobinconnector/go.sum | 138 +++++++++++++++++ .../internal/metadata/generated_status.go | 17 +++ .../internal/metadata/generated_telemetry.go | 17 +++ .../metadata/generated_telemetry_test.go | 63 ++++++++ connector/roundrobinconnector/metadata.yaml | 13 ++ reports/distributions/contrib.yaml | 1 + versions.yaml | 1 + 26 files changed, 809 insertions(+) create mode 100644 .chloggen/roundrobinconnector.yaml create mode 100644 connector/roundrobinconnector/Makefile create mode 100644 connector/roundrobinconnector/README.md create mode 100644 connector/roundrobinconnector/config.go create mode 100644 connector/roundrobinconnector/connector.go create mode 100644 connector/roundrobinconnector/connector_test.go create mode 100644 connector/roundrobinconnector/doc.go create mode 100644 connector/roundrobinconnector/factory.go create mode 100644 connector/roundrobinconnector/generated_component_test.go create mode 100644 connector/roundrobinconnector/generated_package_test.go create mode 100644 connector/roundrobinconnector/go.mod create mode 100644 connector/roundrobinconnector/go.sum create mode 100644 connector/roundrobinconnector/internal/metadata/generated_status.go create mode 100644 connector/roundrobinconnector/internal/metadata/generated_telemetry.go create mode 100644 connector/roundrobinconnector/internal/metadata/generated_telemetry_test.go create mode 100644 connector/roundrobinconnector/metadata.yaml diff --git a/.chloggen/roundrobinconnector.yaml b/.chloggen/roundrobinconnector.yaml new file mode 100644 index 0000000000000..641cdccb15e47 --- /dev/null +++ b/.chloggen/roundrobinconnector.yaml @@ -0,0 +1,22 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: new_component + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: roundrobinconnector + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add a roundrobin connector, that can help single thread components to scale + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [32853] + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [user, api] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index de39c9f0e224e..186034127aa9e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -30,6 +30,7 @@ connector/datadogconnector/ @open-telemetry/collect connector/exceptionsconnector/ @open-telemetry/collector-contrib-approvers @jpkrohling @marctc connector/failoverconnector/ @open-telemetry/collector-contrib-approvers @akats7 @djaglowski @fatsheep9146 connector/grafanacloudconnector/ @open-telemetry/collector-contrib-approvers @jpkrohling @rlankfo @jcreixell +connector/roundrobinconnector/ @open-telemetry/collector-contrib-approvers @bogdandrutu connector/routingconnector/ @open-telemetry/collector-contrib-approvers @jpkrohling @mwear connector/servicegraphconnector/ @open-telemetry/collector-contrib-approvers @jpkrohling @mapno connector/spanmetricsconnector/ @open-telemetry/collector-contrib-approvers @portertech @Frapschen diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 50841dd025ac4..ece9b9b14bba6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -31,6 +31,7 @@ body: - connector/exceptions - connector/failover - connector/grafanacloud + - connector/roundrobin - connector/routing - connector/servicegraph - connector/spanmetrics diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index e608a0f0a06de..e01c8066b3978 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -25,6 +25,7 @@ body: - connector/exceptions - connector/failover - connector/grafanacloud + - connector/roundrobin - connector/routing - connector/servicegraph - connector/spanmetrics diff --git a/.github/ISSUE_TEMPLATE/other.yaml b/.github/ISSUE_TEMPLATE/other.yaml index 312a5cfbf0493..503aaa5a2cf44 100644 --- a/.github/ISSUE_TEMPLATE/other.yaml +++ b/.github/ISSUE_TEMPLATE/other.yaml @@ -25,6 +25,7 @@ body: - connector/exceptions - connector/failover - connector/grafanacloud + - connector/roundrobin - connector/routing - connector/servicegraph - connector/spanmetrics diff --git a/.github/ISSUE_TEMPLATE/unmaintained.yaml b/.github/ISSUE_TEMPLATE/unmaintained.yaml index cc7dcedb5b832..0a3306ead60dd 100644 --- a/.github/ISSUE_TEMPLATE/unmaintained.yaml +++ b/.github/ISSUE_TEMPLATE/unmaintained.yaml @@ -30,6 +30,7 @@ body: - connector/exceptions - connector/failover - connector/grafanacloud + - connector/roundrobin - connector/routing - connector/servicegraph - connector/spanmetrics diff --git a/cmd/otelcontribcol/builder-config.yaml b/cmd/otelcontribcol/builder-config.yaml index 4e9ca88f29df1..5a106eea68c18 100644 --- a/cmd/otelcontribcol/builder-config.yaml +++ b/cmd/otelcontribcol/builder-config.yaml @@ -214,6 +214,7 @@ connectors: - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/connector/exceptionsconnector v0.99.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/connector/failoverconnector v0.99.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/connector/grafanacloudconnector v0.99.0 + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector v0.99.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector v0.99.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector v0.99.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector v0.99.0 @@ -434,6 +435,7 @@ replaces: - github.com/open-telemetry/opentelemetry-collector-contrib/connector/exceptionsconnector => ../../connector/exceptionsconnector - github.com/open-telemetry/opentelemetry-collector-contrib/connector/failoverconnector => ../../connector/failoverconnector - github.com/open-telemetry/opentelemetry-collector-contrib/connector/grafanacloudconnector => ../../connector/grafanacloudconnector + - github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector => ../../connector/roundrobinconnector - github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector => ../../connector/routingconnector - github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector => ../../connector/servicegraphconnector - github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector => ../../connector/spanmetricsconnector diff --git a/cmd/otelcontribcol/components.go b/cmd/otelcontribcol/components.go index 760cc2346b5b6..f96684a550516 100644 --- a/cmd/otelcontribcol/components.go +++ b/cmd/otelcontribcol/components.go @@ -26,6 +26,7 @@ import ( exceptionsconnector "github.com/open-telemetry/opentelemetry-collector-contrib/connector/exceptionsconnector" failoverconnector "github.com/open-telemetry/opentelemetry-collector-contrib/connector/failoverconnector" grafanacloudconnector "github.com/open-telemetry/opentelemetry-collector-contrib/connector/grafanacloudconnector" + roundrobinconnector "github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector" routingconnector "github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector" servicegraphconnector "github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector" spanmetricsconnector "github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector" @@ -436,6 +437,7 @@ func components() (otelcol.Factories, error) { exceptionsconnector.NewFactory(), failoverconnector.NewFactory(), grafanacloudconnector.NewFactory(), + roundrobinconnector.NewFactory(), routingconnector.NewFactory(), servicegraphconnector.NewFactory(), spanmetricsconnector.NewFactory(), diff --git a/cmd/otelcontribcol/go.mod b/cmd/otelcontribcol/go.mod index 71f567d50da1c..fc643e6f3cc08 100644 --- a/cmd/otelcontribcol/go.mod +++ b/cmd/otelcontribcol/go.mod @@ -12,6 +12,7 @@ require ( github.com/open-telemetry/opentelemetry-collector-contrib/connector/exceptionsconnector v0.99.0 github.com/open-telemetry/opentelemetry-collector-contrib/connector/failoverconnector v0.99.0 github.com/open-telemetry/opentelemetry-collector-contrib/connector/grafanacloudconnector v0.99.0 + github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector v0.99.0 github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector v0.99.0 github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector v0.99.0 github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector v0.99.0 @@ -1170,6 +1171,8 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/connector/fail replace github.com/open-telemetry/opentelemetry-collector-contrib/connector/grafanacloudconnector => ../../connector/grafanacloudconnector +replace github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector => ../../connector/roundrobinconnector + replace github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector => ../../connector/routingconnector replace github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector => ../../connector/servicegraphconnector diff --git a/connector/roundrobinconnector/Makefile b/connector/roundrobinconnector/Makefile new file mode 100644 index 0000000000000..ded7a36092dc3 --- /dev/null +++ b/connector/roundrobinconnector/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/connector/roundrobinconnector/README.md b/connector/roundrobinconnector/README.md new file mode 100644 index 0000000000000..f2b315f188b5e --- /dev/null +++ b/connector/roundrobinconnector/README.md @@ -0,0 +1,71 @@ +# Round-Robin Connector + +| Status | | +| ------------- |-----------| +| Distributions | [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aconnector%2Froundrobin%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aconnector%2Froundrobin) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aconnector%2Froundrobin%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aconnector%2Froundrobin) | +| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@bogdandrutu](https://www.github.com/bogdandrutu) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + +## Supported Pipeline Types + +| [Exporter Pipeline Type] | [Receiver Pipeline Type] | [Stability Level] | +| ------------------------ | ------------------------ | ----------------- | +| traces | traces | [beta] | +| metrics | metrics | [beta] | +| logs | logs | [beta] | + +[Exporter Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#exporter-pipeline-type +[Receiver Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#receiver-pipeline-type +[Stability Level]: https://github.com/open-telemetry/opentelemetry-collector#stability-levels + + +The `roundrobin` connector can fork pipelines of the same type and equally split the load between them. + +## Configuration + +If you are not already familiar with connectors, you may find it helpful to first visit the [Connectors README]. + +The `roundrobin` connector does not have any configuration settings. + +```yaml +receivers: + otlp: +exporters: + prometheusremotewrite/1: + prometheusremotewrite/2: +connectors: + roundrobin: +``` + +Preprocess data, then export using multiple exporter instances to scale the throughput if the exporter +does not support scale well (e.g. prometheusremotewrite). + +```yaml +receivers: + otlp: +processors: + resourcedetection: + batch: +exporters: + prometheusremotewrite/1: + prometheusremotewrite/2: +connectors: + roundrobin: +service: + pipelines: + metrics: + receivers: [otlp] + processors: [resourcedetection, batch] + exporters: [roundrobin] + metrics/1: + receivers: [roundrobin] + exporters: [prometheusremotewrite/1] + metrics/2: + receivers: [roundrobin] + exporters: [prometheusremotewrite/2] +``` + +[Connectors README]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md diff --git a/connector/roundrobinconnector/config.go b/connector/roundrobinconnector/config.go new file mode 100644 index 0000000000000..e9b04ad4561e7 --- /dev/null +++ b/connector/roundrobinconnector/config.go @@ -0,0 +1,7 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package roundrobinconnector // import "github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector" + +// Config for the connector +type Config struct{} diff --git a/connector/roundrobinconnector/connector.go b/connector/roundrobinconnector/connector.go new file mode 100644 index 0000000000000..845dae033d158 --- /dev/null +++ b/connector/roundrobinconnector/connector.go @@ -0,0 +1,86 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package roundrobinconnector // import "github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector" + +import ( + "context" + "sync/atomic" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func allConsumers[T any](r router[T]) ([]T, error) { + pipeIDs := r.PipelineIDs() + consumers := make([]T, len(pipeIDs)) + for i, pipeID := range pipeIDs { + cons, err := r.Consumer(pipeID) + if err != nil { + return nil, err + } + consumers[i] = cons + } + return consumers, nil +} + +type router[T any] interface { + PipelineIDs() []component.ID + Consumer(pipelineIDs ...component.ID) (T, error) +} + +func newLogs(nextConsumer consumer.Logs) (connector.Logs, error) { + nextConsumers, err := allConsumers[consumer.Logs](nextConsumer.(connector.LogsRouterAndConsumer)) + if err != nil { + return nil, err + } + return &roundRobin{nextLogs: nextConsumers}, nil +} + +func newMetrics(nextConsumer consumer.Metrics) (connector.Metrics, error) { + nextConsumers, err := allConsumers[consumer.Metrics](nextConsumer.(connector.MetricsRouterAndConsumer)) + if err != nil { + return nil, err + } + return &roundRobin{nextMetrics: nextConsumers}, nil +} + +func newTraces(nextConsumer consumer.Traces) (connector.Traces, error) { + nextConsumers, err := allConsumers[consumer.Traces](nextConsumer.(connector.TracesRouterAndConsumer)) + if err != nil { + return nil, err + } + return &roundRobin{nextTraces: nextConsumers}, nil +} + +// roundRobin is used to pass signals directly from one pipeline to one of the configured once in a round-robin mode. +// This is useful when there is a need to scale (shard) data processing and downstream components do not +// handle concurrent requests very well. +type roundRobin struct { + component.StartFunc + component.ShutdownFunc + nextConsumer atomic.Uint64 + nextMetrics []consumer.Metrics + nextLogs []consumer.Logs + nextTraces []consumer.Traces +} + +func (rr *roundRobin) Capabilities() consumer.Capabilities { + return consumer.Capabilities{MutatesData: false} +} + +func (rr *roundRobin) ConsumeLogs(ctx context.Context, ld plog.Logs) error { + return rr.nextLogs[rr.nextConsumer.Add(1)%uint64(len(rr.nextLogs))].ConsumeLogs(ctx, ld) +} + +func (rr *roundRobin) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) error { + return rr.nextMetrics[rr.nextConsumer.Add(1)%uint64(len(rr.nextMetrics))].ConsumeMetrics(ctx, md) +} + +func (rr *roundRobin) ConsumeTraces(ctx context.Context, td ptrace.Traces) error { + return rr.nextTraces[rr.nextConsumer.Add(1)%uint64(len(rr.nextTraces))].ConsumeTraces(ctx, td) +} diff --git a/connector/roundrobinconnector/connector_test.go b/connector/roundrobinconnector/connector_test.go new file mode 100644 index 0000000000000..3342093e9a970 --- /dev/null +++ b/connector/roundrobinconnector/connector_test.go @@ -0,0 +1,140 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package roundrobinconnector + +import ( + "context" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/connector/connectortest" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func newPipelineMap[T any](tp component.Type, consumers ...T) map[component.ID]T { + ret := make(map[component.ID]T, len(consumers)) + for i, cons := range consumers { + ret[component.NewIDWithName(tp, strconv.Itoa(i))] = cons + } + return ret +} + +func TestLogsRoundRobin(t *testing.T) { + f := NewFactory() + cfg := f.CreateDefaultConfig() + assert.Equal(t, &Config{}, cfg) + + ctx := context.Background() + set := connectortest.NewNopCreateSettings() + host := componenttest.NewNopHost() + + sink1 := new(consumertest.LogsSink) + sink2 := new(consumertest.LogsSink) + sink3 := new(consumertest.LogsSink) + logs, err := f.CreateLogsToLogs(ctx, set, cfg, connector.NewLogsRouter(newPipelineMap[consumer.Logs](component.DataTypeLogs, sink1, sink2, sink3))) + assert.NoError(t, err) + assert.NotNil(t, logs) + + assert.NoError(t, logs.Start(ctx, host)) + + assert.NoError(t, logs.ConsumeLogs(ctx, plog.NewLogs())) + assert.NoError(t, logs.ConsumeLogs(ctx, plog.NewLogs())) + assert.NoError(t, logs.ConsumeLogs(ctx, plog.NewLogs())) + + assert.Equal(t, 1, len(sink1.AllLogs())) + assert.Equal(t, 1, len(sink2.AllLogs())) + assert.Equal(t, 1, len(sink3.AllLogs())) + + assert.NoError(t, logs.ConsumeLogs(ctx, plog.NewLogs())) + assert.NoError(t, logs.ConsumeLogs(ctx, plog.NewLogs())) + assert.NoError(t, logs.ConsumeLogs(ctx, plog.NewLogs())) + + assert.Equal(t, 2, len(sink1.AllLogs())) + assert.Equal(t, 2, len(sink2.AllLogs())) + assert.Equal(t, 2, len(sink3.AllLogs())) + + assert.NoError(t, logs.Shutdown(ctx)) +} + +func TestMetricsRoundRobin(t *testing.T) { + f := NewFactory() + cfg := f.CreateDefaultConfig() + assert.Equal(t, &Config{}, cfg) + + ctx := context.Background() + set := connectortest.NewNopCreateSettings() + host := componenttest.NewNopHost() + + sink1 := new(consumertest.MetricsSink) + sink2 := new(consumertest.MetricsSink) + sink3 := new(consumertest.MetricsSink) + metrics, err := f.CreateMetricsToMetrics(ctx, set, cfg, connector.NewMetricsRouter(newPipelineMap[consumer.Metrics](component.DataTypeMetrics, sink1, sink2, sink3))) + assert.NoError(t, err) + assert.NotNil(t, metrics) + + assert.NoError(t, metrics.Start(ctx, host)) + + assert.NoError(t, metrics.ConsumeMetrics(ctx, pmetric.NewMetrics())) + assert.NoError(t, metrics.ConsumeMetrics(ctx, pmetric.NewMetrics())) + assert.NoError(t, metrics.ConsumeMetrics(ctx, pmetric.NewMetrics())) + + assert.Equal(t, 1, len(sink1.AllMetrics())) + assert.Equal(t, 1, len(sink2.AllMetrics())) + assert.Equal(t, 1, len(sink3.AllMetrics())) + + assert.NoError(t, metrics.ConsumeMetrics(ctx, pmetric.NewMetrics())) + assert.NoError(t, metrics.ConsumeMetrics(ctx, pmetric.NewMetrics())) + assert.NoError(t, metrics.ConsumeMetrics(ctx, pmetric.NewMetrics())) + + assert.Equal(t, 2, len(sink1.AllMetrics())) + assert.Equal(t, 2, len(sink2.AllMetrics())) + assert.Equal(t, 2, len(sink3.AllMetrics())) + + assert.NoError(t, metrics.Shutdown(ctx)) +} + +func TestTracesRoundRobin(t *testing.T) { + f := NewFactory() + cfg := f.CreateDefaultConfig() + assert.Equal(t, &Config{}, cfg) + + ctx := context.Background() + set := connectortest.NewNopCreateSettings() + host := componenttest.NewNopHost() + + sink1 := new(consumertest.TracesSink) + sink2 := new(consumertest.TracesSink) + sink3 := new(consumertest.TracesSink) + traces, err := f.CreateTracesToTraces(ctx, set, cfg, connector.NewTracesRouter(newPipelineMap[consumer.Traces](component.DataTypeTraces, sink1, sink2, sink3))) + assert.NoError(t, err) + assert.NotNil(t, traces) + + assert.NoError(t, traces.Start(ctx, host)) + + assert.NoError(t, traces.ConsumeTraces(ctx, ptrace.NewTraces())) + assert.NoError(t, traces.ConsumeTraces(ctx, ptrace.NewTraces())) + assert.NoError(t, traces.ConsumeTraces(ctx, ptrace.NewTraces())) + + assert.Equal(t, 1, len(sink1.AllTraces())) + assert.Equal(t, 1, len(sink2.AllTraces())) + assert.Equal(t, 1, len(sink3.AllTraces())) + + assert.NoError(t, traces.ConsumeTraces(ctx, ptrace.NewTraces())) + assert.NoError(t, traces.ConsumeTraces(ctx, ptrace.NewTraces())) + assert.NoError(t, traces.ConsumeTraces(ctx, ptrace.NewTraces())) + + assert.Equal(t, 2, len(sink1.AllTraces())) + assert.Equal(t, 2, len(sink2.AllTraces())) + assert.Equal(t, 2, len(sink3.AllTraces())) + + assert.NoError(t, traces.Shutdown(ctx)) +} diff --git a/connector/roundrobinconnector/doc.go b/connector/roundrobinconnector/doc.go new file mode 100644 index 0000000000000..8ae6f45cbedc5 --- /dev/null +++ b/connector/roundrobinconnector/doc.go @@ -0,0 +1,4 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package roundrobinconnector // import "github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector" diff --git a/connector/roundrobinconnector/factory.go b/connector/roundrobinconnector/factory.go new file mode 100644 index 0000000000000..da917a37a3787 --- /dev/null +++ b/connector/roundrobinconnector/factory.go @@ -0,0 +1,62 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:generate mdatagen metadata.yaml + +package roundrobinconnector // import "github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector" + +import ( + "context" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/consumer" + + "github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector/internal/metadata" +) + +// NewFactory returns a ConnectorFactory. +func NewFactory() connector.Factory { + return connector.NewFactory( + metadata.Type, + createDefaultConfig, + connector.WithTracesToTraces(createTracesToTraces, metadata.TracesToTracesStability), + connector.WithMetricsToMetrics(createMetricsToMetrics, metadata.MetricsToMetricsStability), + connector.WithLogsToLogs(createLogsToLogs, metadata.LogsToLogsStability), + ) +} + +// createDefaultConfig creates the default configuration. +func createDefaultConfig() component.Config { + return &Config{} +} + +// createLogsToLogs creates a log receiver based on provided config. +func createLogsToLogs( + _ context.Context, + _ connector.CreateSettings, + _ component.Config, + nextConsumer consumer.Logs, +) (connector.Logs, error) { + return newLogs(nextConsumer) +} + +// createMetricsToMetrics creates a metrics receiver based on provided config. +func createMetricsToMetrics( + _ context.Context, + _ connector.CreateSettings, + _ component.Config, + nextConsumer consumer.Metrics, +) (connector.Metrics, error) { + return newMetrics(nextConsumer) +} + +// createTracesToTraces creates a trace receiver based on provided config. +func createTracesToTraces( + _ context.Context, + _ connector.CreateSettings, + _ component.Config, + nextConsumer consumer.Traces, +) (connector.Traces, error) { + return newTraces(nextConsumer) +} diff --git a/connector/roundrobinconnector/generated_component_test.go b/connector/roundrobinconnector/generated_component_test.go new file mode 100644 index 0000000000000..796843e7e9520 --- /dev/null +++ b/connector/roundrobinconnector/generated_component_test.go @@ -0,0 +1,87 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package roundrobinconnector + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/connector/connectortest" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "roundrobin", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +func TestComponentLifecycle(t *testing.T) { + factory := NewFactory() + + tests := []struct { + name string + createFn func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) + }{ + + { + name: "logs_to_logs", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + router := connector.NewLogsRouter(map[component.ID]consumer.Logs{component.NewID(component.DataTypeLogs): consumertest.NewNop()}) + return factory.CreateLogsToLogs(ctx, set, cfg, router) + }, + }, + + { + name: "metrics_to_metrics", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + router := connector.NewMetricsRouter(map[component.ID]consumer.Metrics{component.NewID(component.DataTypeMetrics): consumertest.NewNop()}) + return factory.CreateMetricsToMetrics(ctx, set, cfg, router) + }, + }, + + { + name: "traces_to_traces", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + router := connector.NewTracesRouter(map[component.ID]consumer.Traces{component.NewID(component.DataTypeTraces): consumertest.NewNop()}) + return factory.CreateTracesToTraces(ctx, set, cfg, router) + }, + }, + } + + cm, err := confmaptest.LoadConf("metadata.yaml") + require.NoError(t, err) + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub("tests::config") + require.NoError(t, err) + require.NoError(t, component.UnmarshalConfig(sub, cfg)) + + for _, test := range tests { + t.Run(test.name+"-shutdown", func(t *testing.T) { + c, err := test.createFn(context.Background(), connectortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + err = c.Shutdown(context.Background()) + require.NoError(t, err) + }) + t.Run(test.name+"-lifecycle", func(t *testing.T) { + firstConnector, err := test.createFn(context.Background(), connectortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + host := componenttest.NewNopHost() + require.NoError(t, err) + require.NoError(t, firstConnector.Start(context.Background(), host)) + require.NoError(t, firstConnector.Shutdown(context.Background())) + secondConnector, err := test.createFn(context.Background(), connectortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + require.NoError(t, secondConnector.Start(context.Background(), host)) + require.NoError(t, secondConnector.Shutdown(context.Background())) + }) + } +} diff --git a/connector/roundrobinconnector/generated_package_test.go b/connector/roundrobinconnector/generated_package_test.go new file mode 100644 index 0000000000000..51c1313bda0d9 --- /dev/null +++ b/connector/roundrobinconnector/generated_package_test.go @@ -0,0 +1,13 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package roundrobinconnector + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/connector/roundrobinconnector/go.mod b/connector/roundrobinconnector/go.mod new file mode 100644 index 0000000000000..3c3aef1251790 --- /dev/null +++ b/connector/roundrobinconnector/go.mod @@ -0,0 +1,54 @@ +module github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector + +go 1.21.0 + +require ( + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.99.1-0.20240503221155-67d37183e6ac + go.opentelemetry.io/collector/confmap v0.99.1-0.20240503221155-67d37183e6ac + go.opentelemetry.io/collector/connector v0.99.1-0.20240503221155-67d37183e6ac + go.opentelemetry.io/collector/consumer v0.99.1-0.20240503221155-67d37183e6ac + go.opentelemetry.io/collector/pdata v1.6.1-0.20240503221155-67d37183e6ac + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector v0.99.1-0.20240503221155-67d37183e6ac // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.99.1-0.20240503221155-67d37183e6ac // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/connector/roundrobinconnector/go.sum b/connector/roundrobinconnector/go.sum new file mode 100644 index 0000000000000..49cd0557dbead --- /dev/null +++ b/connector/roundrobinconnector/go.sum @@ -0,0 +1,138 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/collector v0.99.1-0.20240503221155-67d37183e6ac h1:ocNeUgdnQqEKR91u+WQNbuZlavaQXNk6osl+xq5wXu4= +go.opentelemetry.io/collector v0.99.1-0.20240503221155-67d37183e6ac/go.mod h1:Zk+qxQvmKjl/w5pymY8tNohve+5/IeFZJ6rpCkMOZg4= +go.opentelemetry.io/collector/component v0.99.1-0.20240503221155-67d37183e6ac h1:bfiV2I1+4qqrGdbKVNgQQmDm4rXXIee90xpUd2RzQdk= +go.opentelemetry.io/collector/component v0.99.1-0.20240503221155-67d37183e6ac/go.mod h1:+b56nMIvo3CO5TShFn38RwX4FsXv0lVt2HoGmsaXObo= +go.opentelemetry.io/collector/config/configtelemetry v0.99.1-0.20240503221155-67d37183e6ac h1:ChdEN9VrDjHqn7qGPfQ/8l9yYpSV234mJGzjJnT30ro= +go.opentelemetry.io/collector/config/configtelemetry v0.99.1-0.20240503221155-67d37183e6ac/go.mod h1:YV5PaOdtnU1xRomPcYqoHmyCr48tnaAREeGO96EZw8o= +go.opentelemetry.io/collector/confmap v0.99.1-0.20240503221155-67d37183e6ac h1:Fk18kuApclP09NwUjDQb3yc//O/R3UBy88ZJ/02oHsU= +go.opentelemetry.io/collector/confmap v0.99.1-0.20240503221155-67d37183e6ac/go.mod h1:BWKPIpYeUzSG6ZgCJMjF7xsLvyrvJCfYURl57E5vhiQ= +go.opentelemetry.io/collector/connector v0.99.1-0.20240503221155-67d37183e6ac h1:k6F62/hrNsM89XRLX8IrCIdfruiY1C4xEAZ4c66IuGU= +go.opentelemetry.io/collector/connector v0.99.1-0.20240503221155-67d37183e6ac/go.mod h1:R65OjDuU/HyYFp6C4GwZrHZhQpn3Y1bhA0/F6uoUm80= +go.opentelemetry.io/collector/consumer v0.99.1-0.20240503221155-67d37183e6ac h1:SiEhFzNqO6twKvkUp28rJGql67fUgaOc4f+Ay7+yyBQ= +go.opentelemetry.io/collector/consumer v0.99.1-0.20240503221155-67d37183e6ac/go.mod h1:RzH6GFXabPHDXEC/ajPl/FJhCNVStCCGjZ8gDJVYQIM= +go.opentelemetry.io/collector/pdata v1.6.1-0.20240503221155-67d37183e6ac h1:+FnNEftMuQPg86UOZnLUXzdIjxmHKNsnmSiRTYTCVok= +go.opentelemetry.io/collector/pdata v1.6.1-0.20240503221155-67d37183e6ac/go.mod h1:ehCBBA5GoFrMZkwyZAKGY/lAVSgZf6rzUt3p9mddmPU= +go.opentelemetry.io/collector/pdata/testdata v0.99.0 h1:/cEg4jdR3ntR3kZ0XjSelaBnm7GNSsFF1K3VK+ZHvL8= +go.opentelemetry.io/collector/pdata/testdata v0.99.0/go.mod h1:YzEkHFLPsxeNI2gv6UQvvn73nsgRNxMRnBpY63qvdsg= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +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.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/connector/roundrobinconnector/internal/metadata/generated_status.go b/connector/roundrobinconnector/internal/metadata/generated_status.go new file mode 100644 index 0000000000000..b43d2b3fe5182 --- /dev/null +++ b/connector/roundrobinconnector/internal/metadata/generated_status.go @@ -0,0 +1,17 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("roundrobin") +) + +const ( + TracesToTracesStability = component.StabilityLevelBeta + MetricsToMetricsStability = component.StabilityLevelBeta + LogsToLogsStability = component.StabilityLevelBeta +) diff --git a/connector/roundrobinconnector/internal/metadata/generated_telemetry.go b/connector/roundrobinconnector/internal/metadata/generated_telemetry.go new file mode 100644 index 0000000000000..3552054dff683 --- /dev/null +++ b/connector/roundrobinconnector/internal/metadata/generated_telemetry.go @@ -0,0 +1,17 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("otelcol/roundrobinconnector") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("otelcol/roundrobinconnector") +} diff --git a/connector/roundrobinconnector/internal/metadata/generated_telemetry_test.go b/connector/roundrobinconnector/internal/metadata/generated_telemetry_test.go new file mode 100644 index 0000000000000..236dea42f0480 --- /dev/null +++ b/connector/roundrobinconnector/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "otelcol/roundrobinconnector", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "otelcol/roundrobinconnector", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/connector/roundrobinconnector/metadata.yaml b/connector/roundrobinconnector/metadata.yaml new file mode 100644 index 0000000000000..6c09dfad1dc3c --- /dev/null +++ b/connector/roundrobinconnector/metadata.yaml @@ -0,0 +1,13 @@ +type: roundrobin +scope_name: otelcol/roundrobinconnector + +status: + class: connector + stability: + beta: [traces_to_traces, metrics_to_metrics, logs_to_logs] + distributions: [contrib] + codeowners: + active: [bogdandrutu] + +tests: + config: diff --git a/reports/distributions/contrib.yaml b/reports/distributions/contrib.yaml index 1a4b4b57a2256..b947298b32460 100644 --- a/reports/distributions/contrib.yaml +++ b/reports/distributions/contrib.yaml @@ -8,6 +8,7 @@ components: - exceptions - failover - grafanacloud + - roundrobin - routing - servicegraph - spanmetrics diff --git a/versions.yaml b/versions.yaml index cbe7b9de2098f..553569f6852bf 100644 --- a/versions.yaml +++ b/versions.yaml @@ -20,6 +20,7 @@ module-sets: - github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector - github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector - github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector + - github.com/open-telemetry/opentelemetry-collector-contrib/connector/roundrobinconnector - github.com/open-telemetry/opentelemetry-collector-contrib/examples/demo/client - github.com/open-telemetry/opentelemetry-collector-contrib/examples/demo/server - github.com/open-telemetry/opentelemetry-collector-contrib/exporter/alertmanagerexporter