@@ -36,6 +36,8 @@ import (
36
36
"github.com/aws/amazon-cloudwatch-agent/cfg/envconfig"
37
37
"github.com/aws/amazon-cloudwatch-agent/cmd/amazon-cloudwatch-agent/internal"
38
38
"github.com/aws/amazon-cloudwatch-agent/extension/agenthealth/handler/useragent"
39
+ "github.com/aws/amazon-cloudwatch-agent/internal/mapstructure"
40
+ "github.com/aws/amazon-cloudwatch-agent/internal/merge/confmap"
39
41
"github.com/aws/amazon-cloudwatch-agent/internal/version"
40
42
cwaLogger "github.com/aws/amazon-cloudwatch-agent/logger"
41
43
"github.com/aws/amazon-cloudwatch-agent/logs"
@@ -46,6 +48,7 @@ import (
46
48
"github.com/aws/amazon-cloudwatch-agent/service/defaultcomponents"
47
49
"github.com/aws/amazon-cloudwatch-agent/service/registry"
48
50
"github.com/aws/amazon-cloudwatch-agent/tool/paths"
51
+ "github.com/aws/amazon-cloudwatch-agent/translator/tocwconfig/toyamlconfig"
49
52
)
50
53
51
54
const (
@@ -62,7 +65,7 @@ var fTest = flag.Bool("test", false, "enable test mode: gather metrics, print th
62
65
var fTestWait = flag .Int ("test-wait" , 0 , "wait up to this many seconds for service inputs to complete in test mode" )
63
66
var fSchemaTest = flag .Bool ("schematest" , false , "validate the toml file schema" )
64
67
var fTomlConfig = flag .String ("config" , "" , "configuration file to load" )
65
- var fOtelConfig = flag . String ( "otelconfig" , paths . YamlConfigPath , "YAML configuration file to run OTel pipeline" )
68
+ var fOtelConfigs configprovider. OtelConfigFlags
66
69
var fEnvConfig = flag .String ("envconfig" , "" , "env configuration file to load" )
67
70
var fConfigDirectory = flag .String ("config-directory" , "" ,
68
71
"directory containing additional *.conf files" )
@@ -184,7 +187,7 @@ func reloadLoop(
184
187
_ = f .Close ()
185
188
}
186
189
}
187
- log .Fatalf ("E! [telegraf] Error running agent: %v" , err )
190
+ log .Fatalf ("E! Error running agent: %v" , err )
188
191
}
189
192
}
190
193
}
@@ -312,35 +315,65 @@ func runAgent(ctx context.Context,
312
315
// Always run logAgent as goroutine regardless of whether starting OTEL or Telegraf.
313
316
go logAgent .Run (ctx )
314
317
315
- // If OTEL config does not exist, then ASSUME just monitoring logs.
318
+ // If only the default CWAgent config yaml is provided and does not exist, then ASSUME
319
+ // just monitoring logs since this is the default when no OTEL config flag is provided.
316
320
// So just start Telegraf.
317
- _ , err = os .Stat (* fOtelConfig )
318
- if errors .Is (err , os .ErrNotExist ) {
319
- useragent .Get ().SetComponents (& otelcol.Config {}, c )
320
- return ag .Run (ctx )
321
+ if len (fOtelConfigs ) == 1 && fOtelConfigs [0 ] == paths .YamlConfigPath {
322
+ _ , err = os .Stat (fOtelConfigs [0 ])
323
+ if errors .Is (err , os .ErrNotExist ) {
324
+ useragent .Get ().SetComponents (& otelcol.Config {}, c )
325
+ return ag .Run (ctx )
326
+ }
321
327
}
322
328
}
323
329
// Else start OTEL and rely on adapter package to start the logfile plugin.
324
- yamlConfigPath := * fOtelConfig
325
330
level := cwaLogger .ConvertToAtomicLevel (wlog .LogLevel ())
326
331
logger , loggerOptions := cwaLogger .NewLogger (writer , level )
327
- providerSettings := configprovider .GetSettings (yamlConfigPath , logger )
332
+
333
+ uris := fOtelConfigs
334
+ // merge configs together
335
+ if len (uris ) > 1 {
336
+ log .Printf ("D! Merging multiple OTEL configurations: %s" , uris )
337
+ result := confmap .New ()
338
+ for _ , path := range fOtelConfigs {
339
+ conf , err := confmap .LoadConf (path )
340
+ if err != nil {
341
+ return fmt .Errorf ("failed to load OTEL configs: %w" , err )
342
+ }
343
+ if err = result .Merge (conf ); err != nil {
344
+ return fmt .Errorf ("failed to merge OTEL configs: %w" , err )
345
+ }
346
+ }
347
+ _ = os .Setenv (envconfig .CWAgentMergedOtelConfig , toyamlconfig .ToYamlConfig (result .ToStringMap ()))
348
+ uris = []string {"env:" + envconfig .CWAgentMergedOtelConfig }
349
+ } else {
350
+ _ = os .Unsetenv (envconfig .CWAgentMergedOtelConfig )
351
+ }
352
+
353
+ providerSettings := configprovider .GetSettings (uris , logger )
328
354
provider , err := otelcol .NewConfigProvider (providerSettings )
329
355
if err != nil {
330
- log .Printf ("E! Error while initializing config provider: %v\n " , err )
331
- return err
356
+ return fmt .Errorf ("error while initializing config provider: %v" , err )
332
357
}
333
358
334
359
factories , err := components (c )
335
360
if err != nil {
336
- log .Printf ("E! Error while adapting telegraf input plugins: %v\n " , err )
337
- return err
361
+ return fmt .Errorf ("error while adapting telegraf input plugins: %v" , err )
338
362
}
339
363
340
364
cfg , err := provider .Get (ctx , factories )
341
365
if err != nil {
342
366
return err
343
367
}
368
+
369
+ if _ , ok := os .LookupEnv (envconfig .CWAgentMergedOtelConfig ); ok {
370
+ result , err := mapstructure .Marshal (cfg )
371
+ if err != nil {
372
+ return fmt .Errorf ("failed to marshal OTEL configuration: %v" , err )
373
+ }
374
+ log .Printf ("I! Merged OTEL configuration: \n %s\n " , toyamlconfig .ToYamlConfig (result ))
375
+ }
376
+
344
377
useragent .Get ().SetComponents (cfg , c )
345
378
346
379
params := getCollectorParams (factories , providerSettings , loggerOptions )
@@ -352,7 +385,10 @@ func runAgent(ctx context.Context,
352
385
// The config path below here is actually used that was set in the settings above.
353
386
// docs: https://github.com/open-telemetry/opentelemetry-collector/blob/93cbae436ae61b832279dbbb18a0d99214b7d305/otelcol/command.go#L63
354
387
// *************************************************************************************************
355
- e := []string {"--config=" + yamlConfigPath }
388
+ var e []string
389
+ for _ , uri := range uris {
390
+ e = append (e , "--config=" + uri )
391
+ }
356
392
cmd .SetArgs (e )
357
393
return cmd .Execute ()
358
394
}
@@ -422,7 +458,11 @@ func (p *program) Stop(_ service.Service) error {
422
458
}
423
459
424
460
func main () {
461
+ flag .Var (& fOtelConfigs , configprovider .OtelConfigFlagName , "YAML configuration files to run OTel pipeline" )
425
462
flag .Parse ()
463
+ if len (fOtelConfigs ) == 0 {
464
+ _ = fOtelConfigs .Set (paths .YamlConfigPath )
465
+ }
426
466
args := flag .Args ()
427
467
sectionFilters , inputFilters , outputFilters := []string {}, []string {}, []string {}
428
468
if * fSectionFilters != "" {
0 commit comments