@@ -36,7 +36,13 @@ import (
3636
3737// This is a prefix we add to all names of Otel entities in the configuration. Its purpose is to avoid collisions with
3838// user-provided configuration
39- const OtelNamePrefix = "_agent-component/"
39+ const (
40+ OtelNamePrefix = "_agent-component/"
41+ BeatsAuthExtensionType = "beatsauth"
42+ outputOtelOverrideFieldName = "otel"
43+ outputOtelOverrideExporterFieldName = "exporter"
44+ outputOtelOverrideExtensionsFieldName = "extensions"
45+ )
4046
4147// BeatMonitoringConfigGetter is a function that returns the monitoring configuration for a beat receiver.
4248type (
@@ -183,7 +189,7 @@ func getExporterID(exporterType otelcomponent.Type, outputName string) otelcompo
183189// outputName here is name of the output defined in elastic-agent.yml. For ex: default, monitoring
184190func getBeatsAuthExtensionID (outputName string ) otelcomponent.ID {
185191 extensionName := fmt .Sprintf ("%s%s" , OtelNamePrefix , outputName )
186- return otelcomponent .NewIDWithName (otelcomponent .MustNewType ("beatsauth" ), extensionName )
192+ return otelcomponent .NewIDWithName (otelcomponent .MustNewType (BeatsAuthExtensionType ), extensionName )
187193}
188194
189195// getCollectorConfigForComponent returns the Otel collector config required to run the given component.
@@ -426,6 +432,12 @@ func unitToExporterConfig(unit component.Unit, exporterType otelcomponent.Type,
426432 return nil , nil , nil , fmt .Errorf ("error translating config for output: %s, unit: %s, error: %w" , outputName , unit .ID , err )
427433 }
428434
435+ // if there's an otel override config, extract it, we'll apply it after the conversion
436+ otelOverrideCfgC , err := extractOutputOtelOverrideConfig (outputCfgC )
437+ if err != nil {
438+ return nil , nil , nil , err
439+ }
440+
429441 // Config translation function can mutate queue settings defined under output config
430442 exporterConfig , err := configTranslationFunc (outputCfgC , logger )
431443 if err != nil {
@@ -443,6 +455,19 @@ func unitToExporterConfig(unit component.Unit, exporterType otelcomponent.Type,
443455 }
444456 }
445457
458+ // if there's an otel override section for the exporter, we should apply it
459+ exporterOverrideCfg , err := getOutputOtelOverrideExporterConfig (otelOverrideCfgC )
460+ if err != nil {
461+ return nil , nil , nil , err
462+ }
463+ koanfmaps .Merge (exporterOverrideCfg , exporterConfig )
464+
465+ // if there's an otel override section for extensions, extract it and apply it to individual extension configs
466+ extensionsOverrideCfg , err := getOutputOtelOverrideExtensionsConfig (otelOverrideCfgC )
467+ if err != nil {
468+ return nil , nil , nil , err
469+ }
470+
446471 // beatsauth extension is not tested with output other than elasticsearch
447472 if exporterType .String () == "elasticsearch" {
448473 // get extension ID
@@ -452,6 +477,10 @@ func unitToExporterConfig(unit component.Unit, exporterType otelcomponent.Type,
452477 return nil , nil , nil , fmt .Errorf ("error supporting http parameters for output: %s, unit: %s, error: %w" , outputName , unit .ID , err )
453478 }
454479
480+ if beatsauthOverrideCfg , found := extensionsOverrideCfg [BeatsAuthExtensionType ]; found {
481+ koanfmaps .Merge (beatsauthOverrideCfg , extensionConfig )
482+ }
483+
455484 // sets extensionCfg
456485 extensionCfg = map [string ]any {
457486 extensionID .String (): extensionConfig ,
@@ -519,16 +548,74 @@ func translateEsOutputToExporter(cfg *config.C, logger *logp.Logger) (map[string
519548 if err != nil {
520549 return nil , err
521550 }
522- // dynamic indexing works by default
523551
524- // we also want to use dynamic log ids
552+ // we want to use dynamic log ids
525553 esConfig ["logs_dynamic_id" ] = map [string ]any {"enabled" : true }
526554
527555 esConfig ["include_source_on_error" ] = true
528556
529557 return esConfig , nil
530558}
531559
560+ // extractOutputOtelOverrideConfig removes the configuration under the otel override key from the provided configuration
561+ // and returns it.
562+ func extractOutputOtelOverrideConfig (cfg * config.C ) (* config.C , error ) {
563+ if ! cfg .HasField (outputOtelOverrideFieldName ) {
564+ return nil , nil
565+ }
566+ otelCfg , err := cfg .Child (outputOtelOverrideFieldName , - 1 )
567+ if err != nil {
568+ return nil , err
569+ }
570+ _ , err = cfg .Remove (outputOtelOverrideFieldName , - 1 )
571+ if err != nil {
572+ return nil , err
573+ }
574+ return otelCfg , nil
575+ }
576+
577+ // getOutputOtelOverrideExporterConfig returns the exporter override configuration from the given otel override
578+ // configuration as a map[string]any. It does not modify the input.
579+ func getOutputOtelOverrideExporterConfig (otelOverrideCfg * config.C ) (map [string ]any , error ) {
580+ if otelOverrideCfg == nil {
581+ return nil , nil
582+ }
583+ if ! otelOverrideCfg .HasField (outputOtelOverrideExporterFieldName ) {
584+ return nil , nil
585+ }
586+ exporterCfgC , err := otelOverrideCfg .Child (outputOtelOverrideExporterFieldName , - 1 )
587+ if err != nil {
588+ return nil , err
589+ }
590+ exporterCfgMap := make (map [string ]any )
591+ err = exporterCfgC .Unpack (& exporterCfgMap )
592+ if err != nil {
593+ return nil , err
594+ }
595+ return exporterCfgMap , nil
596+ }
597+
598+ // getOutputOtelOverrideExporterConfig returns the override configuration for extensions from the given otel override
599+ // configuration. The return value is a map keyed by extension types, with configuration overrides as values.
600+ func getOutputOtelOverrideExtensionsConfig (otelOverrideCfg * config.C ) (map [string ]map [string ]any , error ) {
601+ if otelOverrideCfg == nil {
602+ return nil , nil
603+ }
604+ if ! otelOverrideCfg .HasField (outputOtelOverrideExtensionsFieldName ) {
605+ return nil , nil
606+ }
607+ extensionsCfgC , err := otelOverrideCfg .Child (outputOtelOverrideExtensionsFieldName , - 1 )
608+ if err != nil {
609+ return nil , err
610+ }
611+ extensionsCfgMap := make (map [string ]map [string ]any )
612+ err = extensionsCfgC .Unpack (& extensionsCfgMap )
613+ if err != nil {
614+ return nil , err
615+ }
616+ return extensionsCfgMap , nil
617+ }
618+
532619func BeatDataPath (componentId string ) string {
533620 return filepath .Join (paths .Run (), componentId )
534621}
0 commit comments