@@ -58,6 +58,7 @@ const (
58
58
monitoringOutput = "monitoring"
59
59
defaultMonitoringNamespace = "default"
60
60
agentName = "elastic-agent"
61
+ edotCollectorName = "elastic-agent/collector"
61
62
metricBeatName = "metricbeat"
62
63
fileBeatName = "filebeat"
63
64
@@ -73,6 +74,9 @@ const (
73
74
// metricset stream failure threshold before the stream is marked as DEGRADED
74
75
// to avoid marking the agent degraded for transient errors, we set the default threshold to 5
75
76
defaultMetricsStreamFailureThreshold = uint (5 )
77
+
78
+ beatsMonitoringComponentInfoID = "beat/" + monitoringMetricsUnitID
79
+ httpMonitoringComponentInfoID = "http/" + monitoringMetricsUnitID
76
80
)
77
81
78
82
var (
@@ -84,10 +88,11 @@ var (
84
88
// BeatsMonitor provides config values for monitoring of agent clients (beats, endpoint, etc)
85
89
// by injecting the monitoring config into an existing fleet config
86
90
type BeatsMonitor struct {
87
- enabled bool // feature flag disabling whole v1 monitoring story
88
- config * monitoringConfig
89
- operatingSystem string
90
- agentInfo info.Agent
91
+ enabled bool // feature flag disabling whole v1 monitoring story
92
+ config * monitoringConfig
93
+ operatingSystem string
94
+ agentInfo info.Agent
95
+ isOtelRuntimeSubprocess bool
91
96
}
92
97
93
98
// componentInfo is the information necessary to generate monitoring configuration for a component. We don't just use
@@ -106,14 +111,15 @@ type monitoringConfig struct {
106
111
}
107
112
108
113
// New creates a new BeatsMonitor instance.
109
- func New (enabled bool , operatingSystem string , cfg * monitoringCfg.MonitoringConfig , agentInfo info.Agent ) * BeatsMonitor {
114
+ func New (enabled bool , operatingSystem string , cfg * monitoringCfg.MonitoringConfig , agentInfo info.Agent , isOtelRuntimeSubprocess bool ) * BeatsMonitor {
110
115
return & BeatsMonitor {
111
116
enabled : enabled ,
112
117
config : & monitoringConfig {
113
118
C : cfg ,
114
119
},
115
- operatingSystem : operatingSystem ,
116
- agentInfo : agentInfo ,
120
+ operatingSystem : operatingSystem ,
121
+ agentInfo : agentInfo ,
122
+ isOtelRuntimeSubprocess : isOtelRuntimeSubprocess ,
117
123
}
118
124
}
119
125
@@ -418,12 +424,12 @@ func (b *BeatsMonitor) getComponentInfos(components []component.Component, compo
418
424
if b .config .C .MonitorMetrics {
419
425
componentInfos = append (componentInfos ,
420
426
componentInfo {
421
- ID : fmt . Sprintf ( "beat/%s" , monitoringMetricsUnitID ) ,
427
+ ID : beatsMonitoringComponentInfoID ,
422
428
BinaryName : metricBeatName ,
423
429
RuntimeManager : component .RuntimeManager (b .config .C .RuntimeManager ),
424
430
},
425
431
componentInfo {
426
- ID : fmt . Sprintf ( "http/%s" , monitoringMetricsUnitID ) ,
432
+ ID : httpMonitoringComponentInfoID ,
427
433
BinaryName : metricBeatName ,
428
434
RuntimeManager : component .RuntimeManager (b .config .C .RuntimeManager ),
429
435
})
@@ -661,20 +667,28 @@ func (b *BeatsMonitor) getHttpStreams(
661
667
"namespace" : "agent" ,
662
668
"period" : metricsCollectionIntervalString ,
663
669
"index" : indexName ,
664
- "processors" : processorsForAgentHttpStream (monitoringNamespace , dataset , b .agentInfo ),
670
+ "processors" : processorsForAgentHttpStream (agentName , agentName , agentName , monitoringNamespace , dataset , b .agentInfo ),
665
671
}
666
672
if failureThreshold != nil {
667
673
agentStream [failureThresholdKey ] = * failureThreshold
668
674
}
669
675
httpStreams = append (httpStreams , agentStream )
670
676
677
+ var edotSubprocessEndpoints []interface {}
678
+
671
679
for _ , compInfo := range componentInfos {
672
680
binaryName := compInfo .BinaryName
673
681
if ! isSupportedMetricsBinary (binaryName ) {
674
682
continue
675
683
}
676
684
677
685
endpoints := []interface {}{PrefixedEndpoint (BeatsMonitoringEndpoint (compInfo .ID ))}
686
+ if compInfo .RuntimeManager == component .OtelRuntimeManager && compInfo .ID == httpMonitoringComponentInfoID && b .isOtelRuntimeSubprocess {
687
+ // when Otel runtime is running as subprocess, we need to monitor it as a separate stream, thus we utilise the already
688
+ // exposed endpoint of httpMonitoringComponentInfoID.
689
+ edotSubprocessEndpoints = endpoints
690
+ }
691
+
678
692
name := sanitizeName (binaryName )
679
693
680
694
// Do not create http streams if runtime-manager is otel and binary is of beat type
@@ -727,6 +741,30 @@ func (b *BeatsMonitor) getHttpStreams(
727
741
}
728
742
}
729
743
744
+ if edotSubprocessEndpoints != nil {
745
+ // Otel runtime subprocess metrics are collected using the same processors as the elastic-agent since we want only the
746
+ // system resources.
747
+ edotSubprocessStream := map [string ]any {
748
+ idKey : fmt .Sprintf ("%s-edot-collector" , monitoringMetricsUnitID ),
749
+ "data_stream" : map [string ]interface {}{
750
+ "type" : "metrics" ,
751
+ "dataset" : dataset ,
752
+ "namespace" : monitoringNamespace ,
753
+ },
754
+ "metricsets" : []interface {}{"json" },
755
+ "path" : "/stats" ,
756
+ "hosts" : edotSubprocessEndpoints ,
757
+ "namespace" : "agent" ,
758
+ "period" : metricsCollectionIntervalString ,
759
+ "index" : indexName ,
760
+ "processors" : processorsForAgentHttpStream (agentName , edotCollectorName , edotCollectorName , monitoringNamespace , dataset , b .agentInfo ),
761
+ }
762
+ if failureThreshold != nil {
763
+ edotSubprocessStream [failureThresholdKey ] = * failureThreshold
764
+ }
765
+ httpStreams = append (httpStreams , edotSubprocessStream )
766
+ }
767
+
730
768
return httpStreams
731
769
}
732
770
@@ -933,28 +971,28 @@ func processorsForHttpStream(binaryName, unitID, dataset string, agentInfo info.
933
971
}
934
972
935
973
// processorsForAgentHttpStream returns the processors used for the agent metric stream in the beats input.
936
- func processorsForAgentHttpStream (namespace , dataset string , agentInfo info.Agent ) []any {
974
+ func processorsForAgentHttpStream (binaryName , processName , unitID , namespace , dataset string , agentInfo info.Agent ) []any {
937
975
return []interface {}{
938
976
addDataStreamFieldsProcessor (dataset , namespace ),
939
977
addEventFieldsProcessor (dataset ),
940
- addElasticAgentFieldsProcessor (agentName , agentInfo ),
978
+ addElasticAgentFieldsProcessor (processName , agentInfo ),
941
979
addAgentFieldsProcessor (agentInfo .AgentID ()),
942
980
addCopyFieldsProcessor (httpCopyRules (), true , false ),
943
981
dropFieldsProcessor ([]any {"http" }, true ),
944
- addComponentFieldsProcessor (agentName , agentName ),
982
+ addComponentFieldsProcessor (binaryName , unitID ),
945
983
}
946
984
}
947
985
948
986
// addElasticAgentFieldsProcessor returns a processor definition that adds agent information in an `elastic_agent` field.
949
- func addElasticAgentFieldsProcessor (binaryName string , agentInfo info.Agent ) map [string ]any {
987
+ func addElasticAgentFieldsProcessor (processName string , agentInfo info.Agent ) map [string ]any {
950
988
return map [string ]any {
951
989
"add_fields" : map [string ]any {
952
990
"target" : "elastic_agent" ,
953
991
"fields" : map [string ]any {
954
992
"id" : agentInfo .AgentID (),
955
993
"version" : agentInfo .Version (),
956
994
"snapshot" : agentInfo .Snapshot (),
957
- "process" : binaryName ,
995
+ "process" : processName ,
958
996
},
959
997
},
960
998
}
0 commit comments