diff --git a/cmd/builder/internal/builder/templates/main.go.tmpl b/cmd/builder/internal/builder/templates/main.go.tmpl index bc73cc5582b..64a81295bcb 100644 --- a/cmd/builder/internal/builder/templates/main.go.tmpl +++ b/cmd/builder/internal/builder/templates/main.go.tmpl @@ -11,22 +11,13 @@ import ( ) func main() { - if err := otelcol.NewCommandFeatureGate().Execute(); err != nil { - log.Fatalf("failed to validate featuregates: %v", err) - } - - factories, err := components() - if err != nil { - log.Fatalf("failed to build components: %v", err) - } - info := component.BuildInfo{ Command: "{{ .Distribution.Name }}", Description: "{{ .Distribution.Description }}", Version: "{{ .Distribution.Version }}", } - if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: factories}); err != nil { + if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: components}); err != nil { log.Fatal(err) } } diff --git a/cmd/otelcorecol/main.go b/cmd/otelcorecol/main.go index f58f5779fa6..154adfddeeb 100644 --- a/cmd/otelcorecol/main.go +++ b/cmd/otelcorecol/main.go @@ -11,22 +11,13 @@ import ( ) func main() { - if err := otelcol.NewCommandFeatureGate().Execute(); err != nil { - log.Fatalf("failed to validate featuregates: %v", err) - } - - factories, err := components() - if err != nil { - log.Fatalf("failed to build components: %v", err) - } - info := component.BuildInfo{ Command: "otelcorecol", Description: "Local OpenTelemetry Collector binary, testing only.", Version: "0.86.0-dev", } - if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: factories}); err != nil { + if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: components}); err != nil { log.Fatal(err) } } diff --git a/otelcol/collector.go b/otelcol/collector.go index 557ff6f18aa..1e369bdaad3 100644 --- a/otelcol/collector.go +++ b/otelcol/collector.go @@ -55,7 +55,7 @@ func (s State) String() string { // CollectorSettings holds configuration for creating a new Collector. type CollectorSettings struct { // Factories service factories. - Factories Factories + Factories func() (Factories, error) // BuildInfo provides collector start information. BuildInfo component.BuildInfo @@ -155,7 +155,11 @@ func (col *Collector) setupConfigurationComponents(ctx context.Context) error { } } - cfg, err := col.set.ConfigProvider.Get(ctx, col.set.Factories) + factories, err := col.set.Factories() + if err != nil { + return fmt.Errorf("failed to initialize factories: %w", err) + } + cfg, err := col.set.ConfigProvider.Get(ctx, factories) if err != nil { return fmt.Errorf("failed to get config: %w", err) } @@ -167,11 +171,11 @@ func (col *Collector) setupConfigurationComponents(ctx context.Context) error { col.service, err = service.New(ctx, service.Settings{ BuildInfo: col.set.BuildInfo, CollectorConf: conf, - Receivers: receiver.NewBuilder(cfg.Receivers, col.set.Factories.Receivers), - Processors: processor.NewBuilder(cfg.Processors, col.set.Factories.Processors), - Exporters: exporter.NewBuilder(cfg.Exporters, col.set.Factories.Exporters), - Connectors: connector.NewBuilder(cfg.Connectors, col.set.Factories.Connectors), - Extensions: extension.NewBuilder(cfg.Extensions, col.set.Factories.Extensions), + Receivers: receiver.NewBuilder(cfg.Receivers, factories.Receivers), + Processors: processor.NewBuilder(cfg.Processors, factories.Processors), + Exporters: exporter.NewBuilder(cfg.Exporters, factories.Exporters), + Connectors: connector.NewBuilder(cfg.Connectors, factories.Connectors), + Extensions: extension.NewBuilder(cfg.Extensions, factories.Extensions), AsyncErrorChannel: col.asyncErrorChannel, LoggingOptions: col.set.LoggingOptions, }, cfg.Service) @@ -207,7 +211,11 @@ func (col *Collector) reloadConfiguration(ctx context.Context) error { } func (col *Collector) DryRun(ctx context.Context) error { - cfg, err := col.set.ConfigProvider.Get(ctx, col.set.Factories) + factories, err := col.set.Factories() + if err != nil { + return fmt.Errorf("failed to initialize factories: %w", err) + } + cfg, err := col.set.ConfigProvider.Get(ctx, factories) if err != nil { return fmt.Errorf("failed to get config: %w", err) } diff --git a/otelcol/collector_test.go b/otelcol/collector_test.go index 1a0ad8d0607..d2fca3cce8f 100644 --- a/otelcol/collector_test.go +++ b/otelcol/collector_test.go @@ -30,15 +30,12 @@ func TestStateString(t *testing.T) { } func TestCollectorStartAsGoRoutine(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } col, err := NewCollector(set) @@ -57,15 +54,12 @@ func TestCollectorStartAsGoRoutine(t *testing.T) { } func TestCollectorCancelContext(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } col, err := NewCollector(set) @@ -93,16 +87,13 @@ func (p mockCfgProvider) Watch() <-chan error { } func TestCollectorStateAfterConfigChange(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - provider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) watcher := make(chan error, 1) col, err := NewCollector(CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: &mockCfgProvider{ConfigProvider: provider, watcher: watcher}, }) require.NoError(t, err) @@ -126,15 +117,12 @@ func TestCollectorStateAfterConfigChange(t *testing.T) { } func TestCollectorReportError(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) col, err := NewCollector(CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, }) require.NoError(t, err) @@ -152,15 +140,12 @@ func TestCollectorReportError(t *testing.T) { } func TestCollectorSendSignal(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) col, err := NewCollector(CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, }) require.NoError(t, err) @@ -185,15 +170,13 @@ func TestCollectorSendSignal(t *testing.T) { func TestCollectorFailedShutdown(t *testing.T) { t.Skip("This test was using telemetry shutdown failure, switch to use a component that errors on shutdown.") - factories, err := nopFactories() - require.NoError(t, err) cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) col, err := NewCollector(CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, }) require.NoError(t, err) @@ -216,15 +199,12 @@ func TestCollectorFailedShutdown(t *testing.T) { } func TestCollectorStartInvalidConfig(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")})) require.NoError(t, err) col, err := NewCollector(CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, }) require.NoError(t, err) @@ -243,15 +223,12 @@ func TestCollectorStartWithTraceContextPropagation(t *testing.T) { for _, tt := range tests { t.Run(tt.file, func(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", tt.file)})) require.NoError(t, err) set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } @@ -281,15 +258,12 @@ func TestCollectorRun(t *testing.T) { for _, tt := range tests { t.Run(tt.file, func(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", tt.file)})) require.NoError(t, err) set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } col, err := NewCollector(set) @@ -305,15 +279,12 @@ func TestCollectorRun(t *testing.T) { } func TestCollectorShutdownBeforeRun(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } col, err := NewCollector(set) @@ -330,16 +301,13 @@ func TestCollectorShutdownBeforeRun(t *testing.T) { } func TestCollectorClosedStateOnStartUpError(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")})) require.NoError(t, err) // Load a bad config causing startup to fail set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } col, err := NewCollector(set) @@ -353,16 +321,13 @@ func TestCollectorClosedStateOnStartUpError(t *testing.T) { } func TestCollectorDryRun(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")})) require.NoError(t, err) // Load a bad config causing startup to fail set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } col, err := NewCollector(set) @@ -372,9 +337,6 @@ func TestCollectorDryRun(t *testing.T) { } func TestPassConfmapToServiceFailure(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, @@ -386,7 +348,7 @@ func TestPassConfmapToServiceFailure(t *testing.T) { set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } col, err := NewCollector(set) diff --git a/otelcol/collector_windows_test.go b/otelcol/collector_windows_test.go index fb12df6d11b..a9aaf6bf922 100644 --- a/otelcol/collector_windows_test.go +++ b/otelcol/collector_windows_test.go @@ -12,7 +12,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "golang.org/x/sys/windows/svc" "go.opentelemetry.io/collector/component" @@ -23,10 +22,7 @@ func TestNewSvcHandler(t *testing.T) { defer func() { os.Args = oldArgs }() os.Args = []string{"otelcol", "--config", filepath.Join("testdata", "otelcol-nop.yaml")} - factories, err := nopFactories() - require.NoError(t, err) - - s := NewSvcHandler(CollectorSettings{BuildInfo: component.NewDefaultBuildInfo(), Factories: factories}) + s := NewSvcHandler(CollectorSettings{BuildInfo: component.NewDefaultBuildInfo(), Factories: nopFactories}) colDone := make(chan struct{}) requests := make(chan svc.ChangeRequest) diff --git a/otelcol/command.go b/otelcol/command.go index fed69df2d18..a9baff305f3 100644 --- a/otelcol/command.go +++ b/otelcol/command.go @@ -12,20 +12,6 @@ import ( "go.opentelemetry.io/collector/featuregate" ) -// NewCommandFeatureGate constructs a new cobra.Command used to parse given FeatureGates. -func NewCommandFeatureGate() *cobra.Command { - flagSet := new(flag.FlagSet) - flagFeatureGate(flagSet, featuregate.GlobalRegistry()) - rootCmd := &cobra.Command{ - SilenceUsage: true, - FParseErrWhitelist: cobra.FParseErrWhitelist{ - UnknownFlags: true, - }, - } - rootCmd.Flags().AddGoFlagSet(flagSet) - return rootCmd -} - // NewCommand constructs a new cobra.Command using the given CollectorSettings. func NewCommand(set CollectorSettings) *cobra.Command { flagSet := flags(featuregate.GlobalRegistry()) diff --git a/otelcol/command_components.go b/otelcol/command_components.go index f63fce8e55f..4bf18103d05 100644 --- a/otelcol/command_components.go +++ b/otelcol/command_components.go @@ -35,60 +35,65 @@ func newComponentsCommand(set CollectorSettings) *cobra.Command { Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { + factories, err := set.Factories() + if err != nil { + return fmt.Errorf("failed to initialize factories: %w", err) + } + components := componentsOutput{} - for con := range set.Factories.Connectors { + for con := range factories.Connectors { components.Connectors = append(components.Connectors, componentWithStability{ Name: con, Stability: map[string]string{ - "logs-to-logs": set.Factories.Connectors[con].LogsToLogsStability().String(), - "logs-to-metrics": set.Factories.Connectors[con].LogsToMetricsStability().String(), - "logs-to-traces": set.Factories.Connectors[con].LogsToTracesStability().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(), - "metrics-to-logs": set.Factories.Connectors[con].MetricsToLogsStability().String(), - "metrics-to-metrics": set.Factories.Connectors[con].MetricsToMetricsStability().String(), - "metrics-to-traces": set.Factories.Connectors[con].MetricsToTracesStability().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(), - "traces-to-logs": set.Factories.Connectors[con].TracesToLogsStability().String(), - "traces-to-metrics": set.Factories.Connectors[con].TracesToMetricsStability().String(), - "traces-to-traces": set.Factories.Connectors[con].TracesToTracesStability().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(), }, }) } - for ext := range set.Factories.Extensions { + for ext := range factories.Extensions { components.Extensions = append(components.Extensions, componentWithStability{ Name: ext, Stability: map[string]string{ - "extension": set.Factories.Extensions[ext].ExtensionStability().String(), + "extension": factories.Extensions[ext].ExtensionStability().String(), }, }) } - for prs := range set.Factories.Processors { + for prs := range factories.Processors { components.Processors = append(components.Processors, componentWithStability{ Name: prs, Stability: map[string]string{ - "logs": set.Factories.Processors[prs].LogsProcessorStability().String(), - "metrics": set.Factories.Processors[prs].MetricsProcessorStability().String(), - "traces": set.Factories.Processors[prs].TracesProcessorStability().String(), + "logs": factories.Processors[prs].LogsProcessorStability().String(), + "metrics": factories.Processors[prs].MetricsProcessorStability().String(), + "traces": factories.Processors[prs].TracesProcessorStability().String(), }, }) } - for rcv := range set.Factories.Receivers { + for rcv := range factories.Receivers { components.Receivers = append(components.Receivers, componentWithStability{ Name: rcv, Stability: map[string]string{ - "logs": set.Factories.Receivers[rcv].LogsReceiverStability().String(), - "metrics": set.Factories.Receivers[rcv].MetricsReceiverStability().String(), - "traces": set.Factories.Receivers[rcv].TracesReceiverStability().String(), + "logs": factories.Receivers[rcv].LogsReceiverStability().String(), + "metrics": factories.Receivers[rcv].MetricsReceiverStability().String(), + "traces": factories.Receivers[rcv].TracesReceiverStability().String(), }, }) } - for exp := range set.Factories.Exporters { + for exp := range factories.Exporters { components.Exporters = append(components.Exporters, componentWithStability{ Name: exp, Stability: map[string]string{ - "logs": set.Factories.Exporters[exp].LogsExporterStability().String(), - "metrics": set.Factories.Exporters[exp].MetricsExporterStability().String(), - "traces": set.Factories.Exporters[exp].TracesExporterStability().String(), + "logs": factories.Exporters[exp].LogsExporterStability().String(), + "metrics": factories.Exporters[exp].MetricsExporterStability().String(), + "traces": factories.Exporters[exp].TracesExporterStability().String(), }, }) } diff --git a/otelcol/command_components_test.go b/otelcol/command_components_test.go index b143023eb5c..3fe9a2cdd51 100644 --- a/otelcol/command_components_test.go +++ b/otelcol/command_components_test.go @@ -17,15 +17,12 @@ import ( ) func TestNewBuildSubCommand(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } cmd := NewCommand(set) diff --git a/otelcol/command_test.go b/otelcol/command_test.go index fdf2885dc1e..ef922049470 100644 --- a/otelcol/command_test.go +++ b/otelcol/command_test.go @@ -22,17 +22,11 @@ func TestNewCommandVersion(t *testing.T) { } func TestNewCommandNoConfigURI(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cmd := NewCommand(CollectorSettings{Factories: factories}) + cmd := NewCommand(CollectorSettings{Factories: nopFactories}) require.Error(t, cmd.Execute()) } func TestNewCommandInvalidComponent(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider( ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ @@ -43,6 +37,6 @@ func TestNewCommandInvalidComponent(t *testing.T) { }) require.NoError(t, err) - cmd := NewCommand(CollectorSettings{Factories: factories, ConfigProvider: cfgProvider}) + cmd := NewCommand(CollectorSettings{Factories: nopFactories, ConfigProvider: cfgProvider}) require.Error(t, cmd.Execute()) } diff --git a/otelcol/command_validate_test.go b/otelcol/command_validate_test.go index 4511eb73097..ffc47b5d71f 100644 --- a/otelcol/command_validate_test.go +++ b/otelcol/command_validate_test.go @@ -16,19 +16,13 @@ import ( ) func TestValidateSubCommandNoConfig(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cmd := newValidateSubCommand(CollectorSettings{Factories: factories}, flags(featuregate.GlobalRegistry())) - err = cmd.Execute() + cmd := newValidateSubCommand(CollectorSettings{Factories: nopFactories}, flags(featuregate.GlobalRegistry())) + err := cmd.Execute() require.Error(t, err) require.Contains(t, err.Error(), "at least one config flag must be provided") } func TestValidateSubCommandInvalidComponents(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider( ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ @@ -39,7 +33,7 @@ func TestValidateSubCommandInvalidComponents(t *testing.T) { }) require.NoError(t, err) - cmd := newValidateSubCommand(CollectorSettings{Factories: factories, ConfigProvider: cfgProvider}, flags(featuregate.GlobalRegistry())) + cmd := newValidateSubCommand(CollectorSettings{Factories: nopFactories, ConfigProvider: cfgProvider}, flags(featuregate.GlobalRegistry())) err = cmd.Execute() require.Error(t, err) require.Contains(t, err.Error(), "unknown type: \"nosuchprocessor\"") diff --git a/otelcol/flags.go b/otelcol/flags.go index c41467ebf48..a2d0885f53e 100644 --- a/otelcol/flags.go +++ b/otelcol/flags.go @@ -50,14 +50,10 @@ func flags(reg *featuregate.Registry) *flag.FlagSet { return nil }) - flagFeatureGate(flagSet, reg) - - return flagSet -} - -func flagFeatureGate(flagSet *flag.FlagSet, reg *featuregate.Registry) { flagSet.Var(featuregate.NewFlag(reg), featureGatesFlag, "Comma-delimited list of feature gate identifiers. Prefix with '-' to disable the feature. '+' or no prefix will enable the feature.") + + return flagSet } func getConfigFlag(flagSet *flag.FlagSet) []string {