Skip to content

Commit 317fa29

Browse files
committed
Migrate the Hostmetrics<>System mapping code
1 parent df50afa commit 317fa29

File tree

8 files changed

+899
-0
lines changed

8 files changed

+899
-0
lines changed

hostmetrics/cpu.go

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package hostmetrics
2+
3+
import (
4+
"go.opentelemetry.io/collector/pdata/pcommon"
5+
"go.opentelemetry.io/collector/pdata/pmetric"
6+
)
7+
8+
func addCPUMetrics(metrics pmetric.MetricSlice, resource pcommon.Resource, dataset string) error {
9+
var timestamp pcommon.Timestamp
10+
var numCores int64
11+
var totalPercent, idlePercent, systemPercent, userPercent, stealPercent,
12+
iowaitPercent, nicePercent, irqPercent, softirqPercent float64
13+
14+
// iterate all metrics in the current scope and generate the additional Elastic system integration metrics
15+
for i := 0; i < metrics.Len(); i++ {
16+
metric := metrics.At(i)
17+
if metric.Name() == "system.cpu.logical.count" {
18+
dp := metric.Sum().DataPoints().At(0)
19+
if timestamp == 0 {
20+
timestamp = dp.Timestamp()
21+
}
22+
23+
numCores = dp.IntValue()
24+
} else if metric.Name() == "system.cpu.utilization" {
25+
dataPoints := metric.Gauge().DataPoints()
26+
for j := 0; j < dataPoints.Len(); j++ {
27+
dp := dataPoints.At(j)
28+
if timestamp == 0 {
29+
timestamp = dp.Timestamp()
30+
}
31+
32+
value := dp.DoubleValue()
33+
if state, ok := dp.Attributes().Get("state"); ok {
34+
switch state.Str() {
35+
case "idle":
36+
idlePercent += value
37+
case "system":
38+
systemPercent += value
39+
totalPercent += value
40+
case "user":
41+
userPercent += value
42+
totalPercent += value
43+
case "steal":
44+
stealPercent += value
45+
totalPercent += value
46+
case "wait":
47+
iowaitPercent += value
48+
totalPercent += value
49+
case "nice":
50+
nicePercent += value
51+
totalPercent += value
52+
case "interrupt":
53+
irqPercent += value
54+
totalPercent += value
55+
case "softirq":
56+
softirqPercent += value
57+
totalPercent += value
58+
}
59+
}
60+
}
61+
}
62+
}
63+
64+
totalNorm := totalPercent / float64(numCores)
65+
idleNorm := idlePercent / float64(numCores)
66+
systemNorm := systemPercent / float64(numCores)
67+
userNorm := userPercent / float64(numCores)
68+
stealNorm := stealPercent / float64(numCores)
69+
iowaitNorm := iowaitPercent / float64(numCores)
70+
niceNorm := nicePercent / float64(numCores)
71+
irqNorm := irqPercent / float64(numCores)
72+
softirqNorm := softirqPercent / float64(numCores)
73+
74+
addMetrics(metrics, resource, dataset,
75+
metric{
76+
dataType: pmetric.MetricTypeSum,
77+
name: "system.cpu.cores",
78+
timestamp: timestamp,
79+
intValue: &numCores,
80+
},
81+
metric{
82+
dataType: pmetric.MetricTypeGauge,
83+
name: "system.cpu.total.pct",
84+
timestamp: timestamp,
85+
doubleValue: &totalPercent,
86+
},
87+
metric{
88+
dataType: pmetric.MetricTypeGauge,
89+
name: "system.cpu.idle.pct",
90+
timestamp: timestamp,
91+
doubleValue: &idlePercent,
92+
},
93+
metric{
94+
dataType: pmetric.MetricTypeGauge,
95+
name: "system.cpu.system.pct",
96+
timestamp: timestamp,
97+
doubleValue: &systemPercent,
98+
},
99+
metric{
100+
dataType: pmetric.MetricTypeGauge,
101+
name: "system.cpu.user.pct",
102+
timestamp: timestamp,
103+
doubleValue: &userPercent,
104+
},
105+
metric{
106+
dataType: pmetric.MetricTypeGauge,
107+
name: "system.cpu.steal.pct",
108+
timestamp: timestamp,
109+
doubleValue: &stealPercent,
110+
},
111+
metric{
112+
dataType: pmetric.MetricTypeGauge,
113+
name: "system.cpu.wait.pct",
114+
timestamp: timestamp,
115+
doubleValue: &iowaitPercent,
116+
},
117+
metric{
118+
dataType: pmetric.MetricTypeGauge,
119+
name: "system.cpu.nice.pct",
120+
timestamp: timestamp,
121+
doubleValue: &nicePercent,
122+
},
123+
metric{
124+
dataType: pmetric.MetricTypeGauge,
125+
name: "system.cpu.irq.pct",
126+
timestamp: timestamp,
127+
doubleValue: &irqPercent,
128+
},
129+
metric{
130+
dataType: pmetric.MetricTypeGauge,
131+
name: "system.cpu.softirq.pct",
132+
timestamp: timestamp,
133+
doubleValue: &softirqPercent,
134+
},
135+
metric{
136+
dataType: pmetric.MetricTypeGauge,
137+
name: "system.cpu.total.norm.pct",
138+
timestamp: timestamp,
139+
doubleValue: &totalNorm,
140+
},
141+
metric{
142+
dataType: pmetric.MetricTypeGauge,
143+
name: "system.cpu.idle.norm.pct",
144+
timestamp: timestamp,
145+
doubleValue: &idleNorm,
146+
},
147+
metric{
148+
dataType: pmetric.MetricTypeGauge,
149+
name: "system.cpu.system.norm.pct",
150+
timestamp: timestamp,
151+
doubleValue: &systemNorm,
152+
},
153+
metric{
154+
dataType: pmetric.MetricTypeGauge,
155+
name: "system.cpu.user.norm.pct",
156+
timestamp: timestamp,
157+
doubleValue: &userNorm,
158+
},
159+
metric{
160+
dataType: pmetric.MetricTypeGauge,
161+
name: "system.cpu.steal.norm.pct",
162+
timestamp: timestamp,
163+
doubleValue: &stealNorm,
164+
},
165+
metric{
166+
dataType: pmetric.MetricTypeGauge,
167+
name: "system.cpu.wait.norm.pct",
168+
timestamp: timestamp,
169+
doubleValue: &iowaitNorm,
170+
},
171+
metric{
172+
dataType: pmetric.MetricTypeGauge,
173+
name: "system.cpu.nice.norm.pct",
174+
timestamp: timestamp,
175+
doubleValue: &niceNorm,
176+
},
177+
metric{
178+
dataType: pmetric.MetricTypeGauge,
179+
name: "system.cpu.irq.norm.pct",
180+
timestamp: timestamp,
181+
doubleValue: &irqNorm,
182+
},
183+
metric{
184+
dataType: pmetric.MetricTypeGauge,
185+
name: "system.cpu.softirq.norm.pct",
186+
timestamp: timestamp,
187+
doubleValue: &softirqNorm,
188+
},
189+
)
190+
191+
return nil
192+
}

hostmetrics/hostmetrics.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package hostmetrics
2+
3+
import (
4+
"fmt"
5+
"path"
6+
"time"
7+
8+
"go.opentelemetry.io/collector/pdata/pcommon"
9+
"go.opentelemetry.io/collector/pdata/pmetric"
10+
)
11+
12+
var scraperToElasticDataset = map[string]string{
13+
"cpu": "system.cpu",
14+
"disk": "system.diskio",
15+
"filesystem": "system.filesystem",
16+
"load": "system.load",
17+
"memory": "system.memory",
18+
"network": "system.network",
19+
"paging": "system.memory",
20+
"processes": "system.process.summary",
21+
"process": "system.process",
22+
}
23+
24+
// AddElasticSystemMetrics computes additional metrics for compatibility with the Elastic system integration.
25+
// The `scopeMetrics` input should be metrics generated by a specific hostmetrics scraper.
26+
// `scopeMetrics` are modified in place.
27+
func AddElasticSystemMetrics(scopeMetrics pmetric.ScopeMetrics, resource pcommon.Resource, storage map[string]any) error {
28+
scope := scopeMetrics.Scope()
29+
scraper := path.Base(scope.Name())
30+
31+
dataset, ok := scraperToElasticDataset[scraper]
32+
if !ok {
33+
return fmt.Errorf("no dataset defined for scaper '%s'", scraper)
34+
}
35+
36+
currentTime := time.Now().UnixMilli()
37+
if lastScrape, ok := storage["lastScrape"]; ok {
38+
collectionPeriod := currentTime - lastScrape.(int64)
39+
scopeMetrics.Scope().Attributes().PutDouble("metricset.period", float64(collectionPeriod))
40+
}
41+
storage["lastScrape"] = currentTime
42+
43+
switch scraper {
44+
case "cpu":
45+
return addCPUMetrics(scopeMetrics.Metrics(), resource, dataset)
46+
case "memory":
47+
return addMemoryMetrics(scopeMetrics.Metrics(), resource, dataset)
48+
case "load":
49+
return addLoadMetrics(scopeMetrics.Metrics(), resource, dataset)
50+
case "process":
51+
return addProcessMetrics(scopeMetrics.Metrics(), resource, dataset)
52+
case "processes":
53+
return addProcessSummaryMetrics(scopeMetrics.Metrics(), resource, dataset)
54+
case "network":
55+
return addNetworkMetrics(scopeMetrics.Metrics(), resource, dataset)
56+
// case "disk":
57+
// return addDiskMetrics(scopeMetrics.Metrics(), resource, dataset)
58+
default:
59+
return fmt.Errorf("no matching transform function found for scope '%s'", scope.Name())
60+
}
61+
}

hostmetrics/load.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package hostmetrics
2+
3+
import (
4+
"go.opentelemetry.io/collector/pdata/pcommon"
5+
"go.opentelemetry.io/collector/pdata/pmetric"
6+
)
7+
8+
func addLoadMetrics(metrics pmetric.MetricSlice, resource pcommon.Resource, dataset string) error {
9+
var timestamp pcommon.Timestamp
10+
var l1, l5, l15 float64
11+
12+
for i := 0; i < metrics.Len(); i++ {
13+
metric := metrics.At(i)
14+
if metric.Name() == "system.cpu.load_average.1m" {
15+
dp := metric.Gauge().DataPoints().At(0)
16+
if timestamp == 0 {
17+
timestamp = dp.Timestamp()
18+
}
19+
l1 = dp.DoubleValue()
20+
} else if metric.Name() == "system.cpu.load_average.5m" {
21+
dp := metric.Gauge().DataPoints().At(0)
22+
if timestamp == 0 {
23+
timestamp = dp.Timestamp()
24+
}
25+
l5 = dp.DoubleValue()
26+
} else if metric.Name() == "system.cpu.load_average.15m" {
27+
dp := metric.Gauge().DataPoints().At(0)
28+
if timestamp == 0 {
29+
timestamp = dp.Timestamp()
30+
}
31+
l15 = dp.DoubleValue()
32+
}
33+
}
34+
35+
addMetrics(metrics, resource, dataset,
36+
metric{
37+
dataType: pmetric.MetricTypeGauge,
38+
name: "system.load.1",
39+
timestamp: timestamp,
40+
doubleValue: &l1,
41+
},
42+
metric{
43+
dataType: pmetric.MetricTypeGauge,
44+
name: "system.load.5",
45+
timestamp: timestamp,
46+
doubleValue: &l5,
47+
},
48+
metric{
49+
dataType: pmetric.MetricTypeGauge,
50+
name: "system.load.15",
51+
timestamp: timestamp,
52+
doubleValue: &l15,
53+
},
54+
)
55+
56+
return nil
57+
}

0 commit comments

Comments
 (0)