remappers/hostmetrics/cpu.go (200 lines of code) (raw):
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package hostmetrics
import (
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
"github.com/elastic/opentelemetry-lib/remappers/internal/remappedmetric"
)
func remapCPUMetrics(
src, out pmetric.MetricSlice,
_ pcommon.Resource,
mutator func(pmetric.NumberDataPoint),
) error {
var timestamp pcommon.Timestamp
var numCores int64
var totalPercent, idlePercent, systemPercent, userPercent, stealPercent,
iowaitPercent, nicePercent, irqPercent, softirqPercent float64
// iterate all metrics in the current scope and generate the additional Elastic
// system integration metrics.
for i := 0; i < src.Len(); i++ {
metric := src.At(i)
switch metric.Name() {
case "system.cpu.logical.count":
dp := metric.Sum().DataPoints().At(0)
if timestamp == 0 {
timestamp = dp.Timestamp()
}
numCores = dp.IntValue()
case "system.cpu.utilization":
dataPoints := metric.Gauge().DataPoints()
for j := 0; j < dataPoints.Len(); j++ {
dp := dataPoints.At(j)
if timestamp == 0 {
timestamp = dp.Timestamp()
}
value := dp.DoubleValue()
if state, ok := dp.Attributes().Get("state"); ok {
switch state.Str() {
case "idle":
idlePercent += value
case "system":
systemPercent += value
totalPercent += value
case "user":
userPercent += value
totalPercent += value
case "steal":
stealPercent += value
totalPercent += value
case "wait":
iowaitPercent += value
totalPercent += value
case "nice":
nicePercent += value
totalPercent += value
case "interrupt":
irqPercent += value
totalPercent += value
case "softirq":
softirqPercent += value
totalPercent += value
}
}
}
}
}
// Add all metrics that are independent of cpu logical count.
remappedmetric.Add(out, mutator,
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.total.pct",
Timestamp: timestamp,
DoubleValue: &totalPercent,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.idle.pct",
Timestamp: timestamp,
DoubleValue: &idlePercent,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.system.pct",
Timestamp: timestamp,
DoubleValue: &systemPercent,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.user.pct",
Timestamp: timestamp,
DoubleValue: &userPercent,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.steal.pct",
Timestamp: timestamp,
DoubleValue: &stealPercent,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.iowait.pct",
Timestamp: timestamp,
DoubleValue: &iowaitPercent,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.nice.pct",
Timestamp: timestamp,
DoubleValue: &nicePercent,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.irq.pct",
Timestamp: timestamp,
DoubleValue: &irqPercent,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.softirq.pct",
Timestamp: timestamp,
DoubleValue: &softirqPercent,
},
)
if numCores == 0 {
// system.cpu.logical.count is optional, and if it's not
// present we can't calculate the normalized values.
// This is not an error, so we just return early.
return nil
}
totalNorm := totalPercent / float64(numCores)
idleNorm := idlePercent / float64(numCores)
systemNorm := systemPercent / float64(numCores)
userNorm := userPercent / float64(numCores)
stealNorm := stealPercent / float64(numCores)
iowaitNorm := iowaitPercent / float64(numCores)
niceNorm := nicePercent / float64(numCores)
irqNorm := irqPercent / float64(numCores)
softirqNorm := softirqPercent / float64(numCores)
remappedmetric.Add(out, mutator,
remappedmetric.Metric{
DataType: pmetric.MetricTypeSum,
Name: "system.cpu.cores",
Timestamp: timestamp,
IntValue: &numCores,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeSum,
Name: "system.load.cores",
Timestamp: timestamp,
IntValue: &numCores,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.total.norm.pct",
Timestamp: timestamp,
DoubleValue: &totalNorm,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.idle.norm.pct",
Timestamp: timestamp,
DoubleValue: &idleNorm,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.system.norm.pct",
Timestamp: timestamp,
DoubleValue: &systemNorm,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.user.norm.pct",
Timestamp: timestamp,
DoubleValue: &userNorm,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.steal.norm.pct",
Timestamp: timestamp,
DoubleValue: &stealNorm,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.iowait.norm.pct",
Timestamp: timestamp,
DoubleValue: &iowaitNorm,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.nice.norm.pct",
Timestamp: timestamp,
DoubleValue: &niceNorm,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.irq.norm.pct",
Timestamp: timestamp,
DoubleValue: &irqNorm,
},
remappedmetric.Metric{
DataType: pmetric.MetricTypeGauge,
Name: "system.cpu.softirq.norm.pct",
Timestamp: timestamp,
DoubleValue: &softirqNorm,
},
)
return nil
}