@@ -8,38 +8,37 @@ import (
88 "time"
99)
1010
11- // ProcessExporterMetricSnapshot represents parsed process metrics from process_exporter
12- // This captures per-process group metrics (grouped by command name)
11+ // ProcessExporterMetricSnapshot represents a single process group metric snapshot
12+ // This is a flat structure matching NodeExporterMetricSnapshot pattern
13+ // Each process group (e.g., "nginx", "postgres") becomes one snapshot
1314type ProcessExporterMetricSnapshot struct {
14- Timestamp time.Time `json:"timestamp"`
15- Processes []ProcessMetric `json:"processes"`
15+ Timestamp time.Time `json:"timestamp"`
16+ Name string `json:"name"` // Process name (groupname from process_exporter)
17+ NumProcs int `json:"num_procs"` // Number of processes in this group
18+ CPUSecondsTotal float64 `json:"cpu_seconds_total"` // Total CPU time consumed (counter)
19+ MemoryBytes int64 `json:"memory_bytes"` // Resident memory (RSS) in bytes
1620}
1721
18- // ProcessMetric represents metrics for a single process group (e.g., all "nginx" processes)
19- type ProcessMetric struct {
20- Name string `json:"name"` // Process name (groupname from process_exporter)
21- NumProcs int `json:"num_procs"` // Number of processes in this group
22- CPUSecondsTotal float64 `json:"cpu_seconds_total"` // Total CPU time consumed (counter)
23- MemoryBytes int64 `json:"memory_bytes"` // Resident memory (RSS) in bytes
22+ // processData is a temporary struct used during parsing
23+ type processData struct {
24+ numProcs int
25+ cpuSecondsTotal float64
26+ memoryBytes int64
2427}
2528
2629// ParseProcessExporterMetrics parses Prometheus process_exporter text format
27- // Extracts per-process group metrics (CPU, memory, count )
30+ // Returns a slice of ProcessExporterMetricSnapshot (one per process group )
2831//
2932// Expected metrics from process_exporter:
3033// - namedprocess_namegroup_num_procs{groupname="nginx"} 4
3134// - namedprocess_namegroup_cpu_seconds_total{groupname="nginx"} 1234.56
3235// - namedprocess_namegroup_memory_bytes{groupname="nginx",memtype="resident"} 104857600
33- func ParseProcessExporterMetrics (data []byte ) (* ProcessExporterMetricSnapshot , error ) {
34- snapshot := & ProcessExporterMetricSnapshot {
35- Timestamp : time .Now ().UTC (),
36- Processes : []ProcessMetric {},
37- }
38-
36+ func ParseProcessExporterMetrics (data []byte ) ([]ProcessExporterMetricSnapshot , error ) {
37+ timestamp := time .Now ().UTC ()
3938 scanner := bufio .NewScanner (bytes .NewReader (data ))
4039
4140 // Track metrics per process group (groupname)
42- processMetrics := make (map [string ]* ProcessMetric )
41+ processMetrics := make (map [string ]* processData )
4342
4443 for scanner .Scan () {
4544 line := scanner .Text ()
@@ -60,18 +59,25 @@ func ParseProcessExporterMetrics(data []byte) (*ProcessExporterMetricSnapshot, e
6059 return nil , fmt .Errorf ("scanner error: %w" , err )
6160 }
6261
63- // Convert map to slice
64- for _ , pm := range processMetrics {
62+ // Convert map to slice of flat snapshots
63+ snapshots := []ProcessExporterMetricSnapshot {}
64+ for name , data := range processMetrics {
6565 // Only include processes that have at least 1 running instance
66- if pm .NumProcs > 0 {
67- snapshot .Processes = append (snapshot .Processes , * pm )
66+ if data .numProcs > 0 {
67+ snapshots = append (snapshots , ProcessExporterMetricSnapshot {
68+ Timestamp : timestamp ,
69+ Name : name ,
70+ NumProcs : data .numProcs ,
71+ CPUSecondsTotal : data .cpuSecondsTotal ,
72+ MemoryBytes : data .memoryBytes ,
73+ })
6874 }
6975 }
7076
71- return snapshot , nil
77+ return snapshots , nil
7278}
7379
74- func parseProcessLine (line string , processMetrics map [string ]* ProcessMetric ) error {
80+ func parseProcessLine (line string , processMetrics map [string ]* processData ) error {
7581 // Split metric name and value
7682 parts := strings .Fields (line )
7783 if len (parts ) < 2 {
@@ -107,26 +113,24 @@ func parseProcessLine(line string, processMetrics map[string]*ProcessMetric) err
107113
108114 // Ensure process metric entry exists
109115 if processMetrics [groupname ] == nil {
110- processMetrics [groupname ] = & ProcessMetric {
111- Name : groupname ,
112- }
116+ processMetrics [groupname ] = & processData {}
113117 }
114118
115119 pm := processMetrics [groupname ]
116120
117121 // Parse specific metrics
118122 switch metricName {
119123 case "namedprocess_namegroup_num_procs" :
120- pm .NumProcs = int (value )
124+ pm .numProcs = int (value )
121125
122126 case "namedprocess_namegroup_cpu_seconds_total" :
123- pm .CPUSecondsTotal = value
127+ pm .cpuSecondsTotal = value
124128
125129 case "namedprocess_namegroup_memory_bytes" :
126130 // Only use resident memory (RSS)
127131 memtype , ok := labels ["memtype" ]
128132 if ok && memtype == "resident" {
129- pm .MemoryBytes = int64 (value )
133+ pm .memoryBytes = int64 (value )
130134 }
131135 }
132136
0 commit comments