Skip to content

Commit

Permalink
feat(build): use the builder to set config providers
Browse files Browse the repository at this point in the history
  • Loading branch information
swiatekm committed May 20, 2024
1 parent 023b0e5 commit 84421a2
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 148 deletions.
11 changes: 11 additions & 0 deletions otelcolbuilder/.otelcol-builder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,17 @@ connectors:
- 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

providers:
- gomod: github.com/SumoLogic/sumologic-otel-collector/pkg/configprovider/globprovider v0.0.0-00010101000000-000000000000
- gomod: github.com/SumoLogic/sumologic-otel-collector/pkg/configprovider/opampprovider v0.0.0-00010101000000-000000000000
# Upstream providers
- gomod: go.opentelemetry.io/collector/confmap/provider/envprovider v0.99.0
- gomod: go.opentelemetry.io/collector/confmap/provider/fileprovider v0.99.0
- gomod: go.opentelemetry.io/collector/confmap/provider/httpprovider v0.99.0
- gomod: go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.99.0
- gomod: go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.99.0


excludes:
- github.com/knadh/koanf v1.5.0

Expand Down
3 changes: 0 additions & 3 deletions otelcolbuilder/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,6 @@ build-fips:
generate-sources:
@$(MAKE) _builder SKIP_COMPILATION=true
# the changes below allow us to use a custom config provider
# this requires some additions to the main.go file generated by the builder
cd cmd && go get github.com/SumoLogic/sumologic-otel-collector/pkg/configprovider/globprovider@v0.0.0-00010101000000-000000000000
cd cmd && go get github.com/SumoLogic/sumologic-otel-collector/pkg/configprovider/opampprovider@v0.0.0-00010101000000-000000000000
patch cmd/main.go cmd/00_main.go.patch
patch cmd/main.go cmd/01_main.go.patch
patch cmd/main_windows.go cmd/main_windows.go.patch
Expand Down
2 changes: 1 addition & 1 deletion otelcolbuilder/cmd/01_main.go.patch
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

cmd := otelcol.NewCommand(params)
+ // this is only here so that the flag can be recognized by the upstream parser and displayed in help
+ cmd.Flags().StringVarP(&opAmpConfig, "remote-config", "", "", "path to opamp config file")
+ addOpampConfigFlag(cmd.Flags())
if err := cmd.Execute(); err != nil {
log.Fatalf("collector server run finished with error: %v", err)
}
10 changes: 5 additions & 5 deletions otelcolbuilder/cmd/collector_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@ func TestBuiltCollectorWithConfigurationFiles(t *testing.T) {
t.Parallel()

locations := []string{tc.configFile}
cp, err := NewConfigProvider(locations)
require.NoError(t, err)
settings := NewConfigProviderSettings()
settings.ResolverSettings.URIs = locations

t.Log("Creating new app...")
app, err := otelcol.NewCollector(otelcol.CollectorSettings{
BuildInfo: component.NewDefaultBuildInfo(),
Factories: components,
ConfigProvider: cp,
BuildInfo: component.NewDefaultBuildInfo(),
Factories: components,
ConfigProviderSettings: settings,
})
require.NoError(t, err)

Expand Down
73 changes: 2 additions & 71 deletions otelcolbuilder/cmd/collector_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,26 @@
package main // import "go.opentelemetry.io/collector/otelcol"

import (
"bytes"
"context"
"errors"
"flag"
"fmt"
"os"
"time"

"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/converter/expandconverter"
"go.opentelemetry.io/collector/confmap/provider/envprovider"
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
"go.opentelemetry.io/collector/confmap/provider/httpprovider"
"go.opentelemetry.io/collector/confmap/provider/httpsprovider"
"go.opentelemetry.io/collector/confmap/provider/yamlprovider"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/eventlog"

"go.opentelemetry.io/collector/featuregate"
"go.opentelemetry.io/collector/otelcol"

"github.com/SumoLogic/sumologic-otel-collector/pkg/configprovider/globprovider"
)

type windowsService struct {
settings otelcol.CollectorSettings
col *otelcol.Collector
flags *flag.FlagSet
}

// NewSvcHandler constructs a new svc.Handler using the given CollectorSettings.
func NewSvcHandler(set otelcol.CollectorSettings) svc.Handler {
return &windowsService{settings: set, flags: flags(featuregate.GlobalRegistry())}
return &windowsService{settings: set}
}

// Execute implements https://godoc.org/golang.org/x/sys/windows/svc#Handler
Expand Down Expand Up @@ -99,22 +83,7 @@ func (s *windowsService) start(elog *eventlog.Log, colErrorChannel chan error) e
[]zap.Option{zap.WrapCore(withWindowsCore(elog))},
s.settings.LoggingOptions...,
)
// Parse all the flags manually.
buf := bytes.NewBufferString("")
s.flags.SetOutput(buf)
s.flags.PrintDefaults()
_ = elog.Info(6667, fmt.Sprintf("usage: %s", buf.String()))

// Parse all the flags manually.
_ = elog.Info(6668, "parsing arguments")
if err := s.flags.Parse(os.Args[1:]); err != nil {
_ = elog.Info(6669, fmt.Sprintf("error parsing argument: %v", err))
return err
}

_ = elog.Info(6670, "new collector with flags")
var err error
err = updateSettingsUsingFlags(&s.settings, s.flags)
err := UseCustomConfigProvider(&s.settings)
if err != nil {
return err
}
Expand Down Expand Up @@ -226,41 +195,3 @@ func withWindowsCore(elog *eventlog.Log) func(zapcore.Core) zapcore.Core {
return windowsEventLogCore{core, elog, zapcore.NewConsoleEncoder(encoderConfig)}
}
}

func updateSettingsUsingFlags(set *otelcol.CollectorSettings, flags *flag.FlagSet) error {
if set.ConfigProvider == nil {
resolverSet := &set.ConfigProviderSettings.ResolverSettings
configFlags := getConfigFlag(flags)

if len(configFlags) > 0 {
resolverSet.URIs = configFlags
}
if len(resolverSet.URIs) == 0 {
return errors.New("at least one config flag must be provided")
}
// Provide a default set of providers and converters if none have been specified.
// TODO: Remove this after CollectorSettings.ConfigProvider is removed and instead
// do it in the builder.
if len(resolverSet.ProviderFactories) == 0 && len(resolverSet.ConverterFactories) == 0 {
set.ConfigProviderSettings = newDefaultConfigProviderSettings(resolverSet.URIs)
}
}
return nil
}

func newDefaultConfigProviderSettings(uris []string) otelcol.ConfigProviderSettings {
return otelcol.ConfigProviderSettings{
ResolverSettings: confmap.ResolverSettings{
URIs: uris,
ProviderFactories: []confmap.ProviderFactory{
fileprovider.NewFactory(),
envprovider.NewFactory(),
yamlprovider.NewFactory(),
httpprovider.NewFactory(),
httpsprovider.NewFactory(),
globprovider.NewFactory(),
},
ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
},
}
}
53 changes: 8 additions & 45 deletions otelcolbuilder/cmd/configprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,9 @@ import (

"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/converter/expandconverter"
"go.opentelemetry.io/collector/confmap/provider/envprovider"
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
"go.opentelemetry.io/collector/confmap/provider/httpprovider"
"go.opentelemetry.io/collector/confmap/provider/httpsprovider"
"go.opentelemetry.io/collector/confmap/provider/yamlprovider"
"go.opentelemetry.io/collector/featuregate"
"go.opentelemetry.io/collector/otelcol"

"github.com/SumoLogic/sumologic-otel-collector/pkg/configprovider/globprovider"
"github.com/SumoLogic/sumologic-otel-collector/pkg/configprovider/opampprovider"
)

Expand All @@ -45,9 +39,8 @@ func UseCustomConfigProvider(params *otelcol.CollectorSettings) error {
if err != nil {
return fmt.Errorf("setting feature gate flags failed: %s", err)
}
// to create the provider, we need config locations passed in via the command line
// to get these, we take the command the service uses to start, parse the flags, and read the values
flagset := flags(featuregate.GlobalRegistry())
// we need to check if any config locations have been set alongside the opamp config
flagset := flags()

// drop the output from the flagset, we only want to parse
// by default it prints error messages to stdout :(
Expand All @@ -63,53 +56,23 @@ func UseCustomConfigProvider(params *otelcol.CollectorSettings) error {
}

locations := getConfigFlag(flagset)
opAmpPath := flagset.Lookup(opAmpConfigFlag)
opAmpPath := getOpampConfigFlag(flagset)

if len(locations) > 0 && opAmpPath.Value.String() != "" {
if len(locations) > 0 && opAmpPath != "" {
return fmt.Errorf("cannot use --%s and --%s flags together", configFlag, opAmpConfigFlag)
}

if len(locations) == 0 && opAmpPath.Value.String() == "" {
// if no locations, use defaults
// either this is a command, or the default provider will throw an error
if opAmpPath == "" {
// let the default config provider handle things, we don't need to do anything
return nil
}

// create the config provider using the locations
if len(locations) > 0 {
params.ConfigProviderSettings = NewConfigProviderSettings(locations)
} else {
params.ConfigProviderSettings = NewOpAmpConfigProviderSettings(opAmpPath.Value.String())
}
// opamp path is set, use a custom provider with only opamp
params.ConfigProviderSettings = NewOpAmpConfigProviderSettings(opAmpPath)

return nil
}

func NewConfigProvider(locations []string) (otelcol.ConfigProvider, error) {
settings := NewConfigProviderSettings(locations)
return otelcol.NewConfigProvider(settings)
}

// see https://github.com/open-telemetry/opentelemetry-collector/blob/72011ca22dff6614d518768b3bb53a1193c6ad02/service/command.go#L38
// for the logic we're emulating here
// we only add the glob provider, everything else should be the same
func NewConfigProviderSettings(locations []string) otelcol.ConfigProviderSettings {
return otelcol.ConfigProviderSettings{
ResolverSettings: confmap.ResolverSettings{
URIs: locations,
ProviderFactories: []confmap.ProviderFactory{
fileprovider.NewFactory(),
envprovider.NewFactory(),
yamlprovider.NewFactory(),
httpprovider.NewFactory(),
httpsprovider.NewFactory(),
globprovider.NewFactory(),
},
ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
},
}
}

// NewOpAmpConfigProviderSettings is like NewConfigProviderSettings, but only
// the OpAmp config provider is configured.
func NewOpAmpConfigProviderSettings(location string) otelcol.ConfigProviderSettings {
Expand Down
38 changes: 16 additions & 22 deletions otelcolbuilder/cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,12 @@
package main // import "go.opentelemetry.io/collector/service"

import (
"errors"
"flag"
"strings"

"go.opentelemetry.io/collector/featuregate"
)

const (
configFlag = "config"
featureGatesFlag = "feature-gates"
configFlag = "config"
)

type configFlagValue struct {
Expand All @@ -52,29 +48,14 @@ const opAmpConfigFlag = "remote-config"
// opAmpConfig houses the contents of the flag
var opAmpConfig string

func flags(reg *featuregate.Registry) *flag.FlagSet {
func flags() *flag.FlagSet {
flagSet := new(flag.FlagSet)

cfgs := new(configFlagValue)
flagSet.Var(cfgs, configFlag, "Locations to the config file(s), note that only a"+
" single location can be set per flag entry e.g. `--config=file:/path/to/first --config=file:path/to/second`.")

flagSet.StringVar(&opAmpConfig, opAmpConfigFlag, "", "configure collector with opamp config file")

flagSet.Func("set",
"Set arbitrary component config property. The component has to be defined in the config file and the flag"+
" has a higher precedence. Array config properties are overridden and maps are joined. Example --set=processors.batch.timeout=2s",
func(s string) error {
idx := strings.Index(s, "=")
if idx == -1 {
// No need for more context, see TestSetFlag/invalid_set.
return errors.New("missing equal sign")
}
cfgs.sets = append(cfgs.sets, "yaml:"+strings.TrimSpace(strings.ReplaceAll(s[:idx], ".", "::"))+": "+strings.TrimSpace(s[idx+1:]))
return nil
})

reg.RegisterFlags(flagSet)
addOpampConfigFlag(flagSet)

return flagSet
}
Expand All @@ -83,3 +64,16 @@ func getConfigFlag(flagSet *flag.FlagSet) []string {
cfv := flagSet.Lookup(configFlag).Value.(*configFlagValue)
return append(cfv.values, cfv.sets...)
}

func getOpampConfigFlag(flagSet *flag.FlagSet) string {
opampPath := flagSet.Lookup(opAmpConfigFlag)
return opampPath.Value.String()
}

type CommonFlagSet interface {
StringVar(p *string, name string, value string, usage string)
}

func addOpampConfigFlag(flagSet CommonFlagSet) {
flagSet.StringVar(&opAmpConfig, opAmpConfigFlag, "", "configure collector with opamp config file")
}
2 changes: 1 addition & 1 deletion otelcolbuilder/cmd/main_windows.go.patch
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
+ }
+ cmd := otelcol.NewCommand(params)
+ // this is only here so that the flag can be recognized by the upstream parser and displayed in help
+ cmd.Flags().StringVarP(&opAmpConfig, "remote-config", "", "", "path to opamp config file")
+ addOpampConfigFlag(cmd.Flags())
+ if err := svc.Run("", NewSvcHandler(params)); err != nil {
if errors.Is(err, windows.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
// Per https://learn.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-startservicectrldispatchera#return-value
Expand Down

0 comments on commit 84421a2

Please sign in to comment.