Skip to content

Commit

Permalink
Implement new nop factor constructor for specific data type
Browse files Browse the repository at this point in the history
  • Loading branch information
ycombinator committed Mar 19, 2024
1 parent 4b9d206 commit da1f5d8
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 98 deletions.
2 changes: 1 addition & 1 deletion otelcol/collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ func TestCollectorDryRun(t *testing.T) {
Factories: nopFactories,
ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid-receiver-type.yaml")}),
},
expectedErr: `failed to build pipelines: failed to create "nop_notraces" receiver for data type "traces": telemetry type is not supported`,
expectedErr: `failed to build pipelines: failed to create "nop_logs" receiver for data type "traces": telemetry type is not supported`,
},
}

Expand Down
85 changes: 56 additions & 29 deletions otelcol/command_components.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ package otelcol // import "go.opentelemetry.io/collector/otelcol"

import (
"fmt"
"go.opentelemetry.io/collector/connector"
"go.opentelemetry.io/collector/exporter"
"go.opentelemetry.io/collector/extension"
"go.opentelemetry.io/collector/processor"
"go.opentelemetry.io/collector/receiver"
"sort"

"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -41,59 +47,59 @@ func newComponentsCommand(set CollectorSettings) *cobra.Command {
}

components := componentsOutput{}
for con := range factories.Connectors {
for _, con := range sortFactoriesByType[connector.Factory](factories.Connectors) {
components.Connectors = append(components.Connectors, componentWithStability{
Name: con,
Name: con.Type(),
Stability: map[string]string{
"logs-to-logs": factories.Connectors[con].LogsToLogsStability().String(),
"logs-to-metrics": factories.Connectors[con].LogsToMetricsStability().String(),
"logs-to-traces": factories.Connectors[con].LogsToTracesStability().String(),
"logs-to-logs": con.LogsToLogsStability().String(),
"logs-to-metrics": con.LogsToMetricsStability().String(),
"logs-to-traces": con.LogsToTracesStability().String(),

"metrics-to-logs": factories.Connectors[con].MetricsToLogsStability().String(),
"metrics-to-metrics": factories.Connectors[con].MetricsToMetricsStability().String(),
"metrics-to-traces": factories.Connectors[con].MetricsToTracesStability().String(),
"metrics-to-logs": con.MetricsToLogsStability().String(),
"metrics-to-metrics": con.MetricsToMetricsStability().String(),
"metrics-to-traces": con.MetricsToTracesStability().String(),

"traces-to-logs": factories.Connectors[con].TracesToLogsStability().String(),
"traces-to-metrics": factories.Connectors[con].TracesToMetricsStability().String(),
"traces-to-traces": factories.Connectors[con].TracesToTracesStability().String(),
"traces-to-logs": con.TracesToLogsStability().String(),
"traces-to-metrics": con.TracesToMetricsStability().String(),
"traces-to-traces": con.TracesToTracesStability().String(),
},
})
}
for ext := range factories.Extensions {
for _, ext := range sortFactoriesByType[extension.Factory](factories.Extensions) {
components.Extensions = append(components.Extensions, componentWithStability{
Name: ext,
Name: ext.Type(),
Stability: map[string]string{
"extension": factories.Extensions[ext].ExtensionStability().String(),
"extension": ext.ExtensionStability().String(),
},
})
}
for prs := range factories.Processors {
for _, prs := range sortFactoriesByType[processor.Factory](factories.Processors) {
components.Processors = append(components.Processors, componentWithStability{
Name: prs,
Name: prs.Type(),
Stability: map[string]string{
"logs": factories.Processors[prs].LogsProcessorStability().String(),
"metrics": factories.Processors[prs].MetricsProcessorStability().String(),
"traces": factories.Processors[prs].TracesProcessorStability().String(),
"logs": prs.LogsProcessorStability().String(),
"metrics": prs.MetricsProcessorStability().String(),
"traces": prs.TracesProcessorStability().String(),
},
})
}
for rcv := range factories.Receivers {
for _, rcv := range sortFactoriesByType[receiver.Factory](factories.Receivers) {
components.Receivers = append(components.Receivers, componentWithStability{
Name: rcv,
Name: rcv.Type(),
Stability: map[string]string{
"logs": factories.Receivers[rcv].LogsReceiverStability().String(),
"metrics": factories.Receivers[rcv].MetricsReceiverStability().String(),
"traces": factories.Receivers[rcv].TracesReceiverStability().String(),
"logs": rcv.LogsReceiverStability().String(),
"metrics": rcv.MetricsReceiverStability().String(),
"traces": rcv.TracesReceiverStability().String(),
},
})
}
for exp := range factories.Exporters {
for _, exp := range sortFactoriesByType[exporter.Factory](factories.Exporters) {
components.Exporters = append(components.Exporters, componentWithStability{
Name: exp,
Name: exp.Type(),
Stability: map[string]string{
"logs": factories.Exporters[exp].LogsExporterStability().String(),
"metrics": factories.Exporters[exp].MetricsExporterStability().String(),
"traces": factories.Exporters[exp].TracesExporterStability().String(),
"logs": exp.LogsExporterStability().String(),
"metrics": exp.MetricsExporterStability().String(),
"traces": exp.TracesExporterStability().String(),
},
})
}
Expand All @@ -107,3 +113,24 @@ func newComponentsCommand(set CollectorSettings) *cobra.Command {
},
}
}

func sortFactoriesByType[T component.Factory](factories map[component.Type]T) []T {
// Gather component types (factories map keys)
componentTypes := make([]component.Type, 0, len(factories))
for componentType := range factories {
componentTypes = append(componentTypes, componentType)
}

// Sort component types as strings
sort.Slice(componentTypes, func(i, j int) bool {
return componentTypes[i].String() < componentTypes[j].String()
})

// Build and return list of factories, sorted by component types
sortedFactories := make([]T, 0, len(factories))
for _, componentType := range componentTypes {
sortedFactories = append(sortedFactories, factories[componentType])
}

return sortedFactories
}
24 changes: 17 additions & 7 deletions otelcol/command_components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,24 @@ func TestNewBuildSubCommand(t *testing.T) {

ExpectedYamlStruct := componentsOutput{
BuildInfo: component.NewDefaultBuildInfo(),
Receivers: []componentWithStability{{
Name: nopType,
Stability: map[string]string{
"logs": "Stable",
"metrics": "Stable",
"traces": "Stable",
Receivers: []componentWithStability{
{
Name: nopType,
Stability: map[string]string{
"logs": "Stable",
"metrics": "Stable",
"traces": "Stable",
},
},
}},
{
Name: nopType,
Stability: map[string]string{
"logs": "Stable",
"metrics": "Undefined",
"traces": "Undefined",
},
},
},
Processors: []componentWithStability{{
Name: nopType,
Stability: map[string]string{
Expand Down
3 changes: 2 additions & 1 deletion otelcol/factories_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package otelcol

import (
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/connector"
"go.opentelemetry.io/collector/connector/connectortest"
"go.opentelemetry.io/collector/exporter"
Expand All @@ -28,7 +29,7 @@ func nopFactories() (Factories, error) {
return Factories{}, err
}

if factories.Receivers, err = receiver.MakeFactoryMap(receivertest.NewNopFactory(), receivertest.NewNopFactory(receivertest.WithoutTraces())); err != nil {
if factories.Receivers, err = receiver.MakeFactoryMap(receivertest.NewNopFactory(), receivertest.NewNopFactoryForType(component.DataTypeLogs)); err != nil {
return Factories{}, err
}

Expand Down
4 changes: 2 additions & 2 deletions otelcol/testdata/otelcol-invalid-receiver-type.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
receivers:
nop_notraces:
nop_logs:

processors:
nop:
Expand All @@ -13,6 +13,6 @@ service:
address: localhost:8888
pipelines:
traces:
receivers: [nop_notraces]
receivers: [nop_logs]
processors: [nop]
exporters: [nop]
82 changes: 24 additions & 58 deletions receiver/receivertest/nop_receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,70 +25,36 @@ func NewNopCreateSettings() receiver.CreateSettings {
}
}

// NewNopFactory returns a receiver.Factory that constructs nop receivers.
func NewNopFactory(opts ...NopOption) receiver.Factory {
cfg := defaultNopConfig()
for _, opt := range opts {
opt(cfg)
}

factoryOpts := make([]receiver.FactoryOption, 0)
componentType := defaultComponentType.String()
if cfg.withTraces {
factoryOpts = append(factoryOpts, receiver.WithTraces(createTraces, component.StabilityLevelStable))
} else {
componentType += "_notraces"
}
if cfg.withMetrics {
factoryOpts = append(factoryOpts, receiver.WithMetrics(createMetrics, component.StabilityLevelStable))
} else {
componentType += "_nometrics"
}
if cfg.withLogs {
factoryOpts = append(factoryOpts, receiver.WithLogs(createLogs, component.StabilityLevelStable))
} else {
componentType += "_nologs"
}

return receiver.NewFactory(component.MustNewType(componentType), func() component.Config { return cfg }, factoryOpts...)
}

type nopConfig struct {
withTraces bool
withMetrics bool
withLogs bool
// NewNopFactory returns a receiver.Factory that constructs nop receivers supporting all data types.
func NewNopFactory() receiver.Factory {
return receiver.NewFactory(
defaultComponentType,
func() component.Config { return &nopConfig{} },
receiver.WithTraces(createTraces, component.StabilityLevelStable),
receiver.WithMetrics(createMetrics, component.StabilityLevelStable),
receiver.WithLogs(createLogs, component.StabilityLevelStable))
}

func defaultNopConfig() *nopConfig {
return &nopConfig{
withTraces: true,
withMetrics: true,
withLogs: true,
// NewNopFactoryForType returns a receiver.Factory that constructs nop receivers supporting only the
// given data type.
func NewNopFactoryForType(dataType component.DataType) receiver.Factory {
var factoryOpt receiver.FactoryOption
switch dataType {
case component.DataTypeTraces:
factoryOpt = receiver.WithTraces(createTraces, component.StabilityLevelStable)
case component.DataTypeMetrics:
factoryOpt = receiver.WithMetrics(createMetrics, component.StabilityLevelStable)
case component.DataTypeLogs:
factoryOpt = receiver.WithLogs(createLogs, component.StabilityLevelStable)
default:
panic("unsupported data type for creating nop receiver factory: " + dataType.String())

Check warning on line 50 in receiver/receivertest/nop_receiver.go

View check run for this annotation

Codecov / codecov/patch

receiver/receivertest/nop_receiver.go#L40-L50

Added lines #L40 - L50 were not covered by tests
}
}

type NopOption func(*nopConfig)

// WithoutTraces creates a NopReceiver that cannot produce traces.
func WithoutTraces() NopOption {
return func(c *nopConfig) {
c.withTraces = false
}
}

// WithoutMetrics creates a NopReceiver that cannot produce metrics.
func WithoutMetrics() NopOption {
return func(c *nopConfig) {
c.withMetrics = false
}
componentType := component.MustNewType(defaultComponentType.String() + "_" + dataType.String())
return receiver.NewFactory(componentType, func() component.Config { return &nopConfig{} }, factoryOpt)

Check warning on line 54 in receiver/receivertest/nop_receiver.go

View check run for this annotation

Codecov / codecov/patch

receiver/receivertest/nop_receiver.go#L53-L54

Added lines #L53 - L54 were not covered by tests
}

// WithoutLogs creates a NopReceiver that cannot produce logs.
func WithoutLogs() NopOption {
return func(c *nopConfig) {
c.withLogs = false
}
}
type nopConfig struct{}

func createTraces(context.Context, receiver.CreateSettings, component.Config, consumer.Traces) (receiver.Traces, error) {
return nopInstance, nil
Expand Down

0 comments on commit da1f5d8

Please sign in to comment.