Support any OS in host metrics receiver & cpu scraper, and include all relevant cpu states for Linux (#902)
This commit is contained in:
parent
24c1569e97
commit
3a51f6090d
|
|
@ -16,9 +16,7 @@ package hostmetricsreceiver
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
|
|
@ -143,11 +141,6 @@ func (f *Factory) CreateMetricsReceiver(
|
|||
cfg configmodels.Receiver,
|
||||
consumer consumer.MetricsConsumer,
|
||||
) (component.MetricsReceiver, error) {
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
return nil, errors.New("hostmetrics receiver is currently only supported on windows")
|
||||
}
|
||||
|
||||
config := cfg.(*Config)
|
||||
|
||||
hmr, err := NewHostMetricsReceiver(ctx, params.Logger, config, f.scraperFactories, consumer)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ package hostmetricsreceiver
|
|||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -47,11 +46,6 @@ func TestCreateReceiver(t *testing.T) {
|
|||
|
||||
mReceiver, err := factory.CreateMetricsReceiver(context.Background(), creationParams, cfg, nil)
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, tReceiver)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, mReceiver)
|
||||
}
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, mReceiver)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,11 +49,6 @@ func TestGatherMetrics_EndToEnd(t *testing.T) {
|
|||
|
||||
receiver, err := NewHostMetricsReceiver(context.Background(), zap.NewNop(), config, factories, sink)
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
require.Error(t, err, "Expected error when creating a host metrics receiver with cpuscraper collector on a non-windows environment")
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err, "Failed to create metrics receiver: %v", err)
|
||||
|
||||
err = receiver.Start(context.Background(), componenttest.NewNopHost())
|
||||
|
|
@ -77,10 +72,10 @@ func assertMetricData(t *testing.T, got []pdata.Metrics) {
|
|||
// expect 1 metric
|
||||
assert.Equal(t, 1, metrics.Len())
|
||||
|
||||
// for cpu seconds metric, expect 5 timeseries with appropriate labels
|
||||
// for cpu seconds metric, expect a datapoint for each state label & core combination with at least 4 standard states
|
||||
hostCPUTimeMetric := metrics.At(0)
|
||||
internal.AssertDescriptorEqual(t, cpuscraper.MetricCPUSecondsDescriptor, hostCPUTimeMetric.MetricDescriptor())
|
||||
assert.Equal(t, 4*runtime.NumCPU(), hostCPUTimeMetric.Int64DataPoints().Len())
|
||||
assert.GreaterOrEqual(t, hostCPUTimeMetric.Int64DataPoints().Len(), runtime.NumCPU()*4)
|
||||
internal.AssertInt64MetricLabelExists(t, hostCPUTimeMetric, 0, cpuscraper.CPULabel)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 0, cpuscraper.StateLabel, cpuscraper.UserStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 1, cpuscraper.StateLabel, cpuscraper.SystemStateLabelValue)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ var (
|
|||
SystemStateLabelValue = "system"
|
||||
IdleStateLabelValue = "idle"
|
||||
InterruptStateLabelValue = "interrupt"
|
||||
NiceStateLabelValue = "nice"
|
||||
SoftIRQStateLabelValue = "softirq"
|
||||
StealStateLabelValue = "steal"
|
||||
WaitStateLabelValue = "wait"
|
||||
)
|
||||
|
||||
var MetricCPUSecondsDescriptor = metricCPUSecondsDescriptor()
|
||||
|
|
|
|||
|
|
@ -114,12 +114,9 @@ func initializeCPUSecondsMetric(metric pdata.Metric, startTime pdata.TimestampUn
|
|||
MetricCPUSecondsDescriptor.CopyTo(metric.MetricDescriptor())
|
||||
|
||||
idps := metric.Int64DataPoints()
|
||||
idps.Resize(4 * len(cpuTimes))
|
||||
idps.Resize(len(cpuTimes) * cpuStatesLen)
|
||||
for i, cpuTime := range cpuTimes {
|
||||
initializeCPUSecondsDataPoint(idps.At(4*i+0), startTime, cpuTime.CPU, UserStateLabelValue, int64(cpuTime.User))
|
||||
initializeCPUSecondsDataPoint(idps.At(4*i+1), startTime, cpuTime.CPU, SystemStateLabelValue, int64(cpuTime.System))
|
||||
initializeCPUSecondsDataPoint(idps.At(4*i+2), startTime, cpuTime.CPU, IdleStateLabelValue, int64(cpuTime.Idle))
|
||||
initializeCPUSecondsDataPoint(idps.At(4*i+3), startTime, cpuTime.CPU, InterruptStateLabelValue, int64(cpuTime.Irq))
|
||||
appendCPUStateTimes(idps, i*cpuStatesLen, startTime, cpuTime)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2020, OpenTelemetry Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
// +build linux
|
||||
|
||||
package cpuscraper
|
||||
|
||||
import (
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
|
||||
"github.com/open-telemetry/opentelemetry-collector/consumer/pdata"
|
||||
)
|
||||
|
||||
const cpuStatesLen = 8
|
||||
|
||||
func appendCPUStateTimes(idps pdata.Int64DataPointSlice, startIdx int, startTime pdata.TimestampUnixNano, cpuTime cpu.TimesStat) {
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+0), startTime, cpuTime.CPU, UserStateLabelValue, int64(cpuTime.User))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+1), startTime, cpuTime.CPU, SystemStateLabelValue, int64(cpuTime.System))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+2), startTime, cpuTime.CPU, IdleStateLabelValue, int64(cpuTime.Idle))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+3), startTime, cpuTime.CPU, InterruptStateLabelValue, int64(cpuTime.Irq))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+4), startTime, cpuTime.CPU, NiceStateLabelValue, int64(cpuTime.Nice))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+5), startTime, cpuTime.CPU, SoftIRQStateLabelValue, int64(cpuTime.Softirq))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+6), startTime, cpuTime.CPU, StealStateLabelValue, int64(cpuTime.Steal))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+7), startTime, cpuTime.CPU, WaitStateLabelValue, int64(cpuTime.Iowait))
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2020, OpenTelemetry Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
// +build !linux
|
||||
|
||||
package cpuscraper
|
||||
|
||||
import (
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
|
||||
"github.com/open-telemetry/opentelemetry-collector/consumer/pdata"
|
||||
)
|
||||
|
||||
const cpuStatesLen = 4
|
||||
|
||||
func appendCPUStateTimes(idps pdata.Int64DataPointSlice, startIdx int, startTime pdata.TimestampUnixNano, cpuTime cpu.TimesStat) {
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+0), startTime, cpuTime.CPU, UserStateLabelValue, int64(cpuTime.User))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+1), startTime, cpuTime.CPU, SystemStateLabelValue, int64(cpuTime.System))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+2), startTime, cpuTime.CPU, IdleStateLabelValue, int64(cpuTime.Idle))
|
||||
initializeCPUSecondsDataPoint(idps.At(startIdx+3), startTime, cpuTime.CPU, InterruptStateLabelValue, int64(cpuTime.Irq))
|
||||
}
|
||||
|
|
@ -37,10 +37,10 @@ func TestScrapeMetrics_MinimalData(t *testing.T) {
|
|||
// expect 1 metric
|
||||
assert.Equal(t, 1, metrics.Len())
|
||||
|
||||
// for cpu seconds metric, expect 4 timeseries with appropriate labels
|
||||
// for cpu seconds metric, expect a datapoint for each state label, including at least 4 standard states
|
||||
hostCPUTimeMetric := metrics.At(0)
|
||||
internal.AssertDescriptorEqual(t, MetricCPUSecondsDescriptor, hostCPUTimeMetric.MetricDescriptor())
|
||||
assert.Equal(t, 4, hostCPUTimeMetric.Int64DataPoints().Len())
|
||||
assert.GreaterOrEqual(t, hostCPUTimeMetric.Int64DataPoints().Len(), 4)
|
||||
internal.AssertInt64MetricLabelDoesNotExist(t, hostCPUTimeMetric, 0, CPULabel)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 0, StateLabel, UserStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 1, StateLabel, SystemStateLabelValue)
|
||||
|
|
@ -60,10 +60,10 @@ func TestScrapeMetrics_AllData(t *testing.T) {
|
|||
// expect 1 metric
|
||||
assert.Equal(t, 1, metrics.Len())
|
||||
|
||||
// for cpu seconds metric, expect 4*cores timeseries with appropriate labels
|
||||
// for cpu seconds metric, expect a datapoint for each state label & core combination with at least 4 standard states
|
||||
hostCPUTimeMetric := metrics.At(0)
|
||||
internal.AssertDescriptorEqual(t, MetricCPUSecondsDescriptor, hostCPUTimeMetric.MetricDescriptor())
|
||||
assert.Equal(t, 4*runtime.NumCPU(), hostCPUTimeMetric.Int64DataPoints().Len())
|
||||
assert.GreaterOrEqual(t, hostCPUTimeMetric.Int64DataPoints().Len(), runtime.NumCPU()*4)
|
||||
internal.AssertInt64MetricLabelExists(t, hostCPUTimeMetric, 0, CPULabel)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 0, StateLabel, UserStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 1, StateLabel, SystemStateLabelValue)
|
||||
|
|
@ -72,6 +72,30 @@ func TestScrapeMetrics_AllData(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestScrapeMetrics_Linux(t *testing.T) {
|
||||
if runtime.GOOS != "linux" {
|
||||
return
|
||||
}
|
||||
|
||||
createScraperAndValidateScrapedMetrics(t, &Config{}, func(t *testing.T, got []pdata.Metrics) {
|
||||
metrics := internal.AssertSingleMetricDataAndGetMetricsSlice(t, got)
|
||||
|
||||
// for cpu seconds metric, expect a datapoint for all 8 state labels
|
||||
hostCPUTimeMetric := metrics.At(0)
|
||||
internal.AssertDescriptorEqual(t, MetricCPUSecondsDescriptor, hostCPUTimeMetric.MetricDescriptor())
|
||||
assert.Equal(t, 8, hostCPUTimeMetric.Int64DataPoints().Len())
|
||||
internal.AssertInt64MetricLabelDoesNotExist(t, hostCPUTimeMetric, 0, CPULabel)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 0, StateLabel, UserStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 1, StateLabel, SystemStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 2, StateLabel, IdleStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 3, StateLabel, InterruptStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 4, StateLabel, NiceStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 5, StateLabel, SoftIRQStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 6, StateLabel, StealStateLabelValue)
|
||||
internal.AssertInt64MetricLabelHasValue(t, hostCPUTimeMetric, 7, StateLabel, WaitStateLabelValue)
|
||||
})
|
||||
}
|
||||
|
||||
func createScraperAndValidateScrapedMetrics(t *testing.T, config *Config, assertFn validationFn) {
|
||||
config.SetCollectionInterval(100 * time.Millisecond)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@ package cpuscraper
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"runtime"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
|
|
@ -55,11 +53,6 @@ func (f *Factory) CreateMetricsScraper(
|
|||
config internal.Config,
|
||||
consumer consumer.MetricsConsumer,
|
||||
) (internal.Scraper, error) {
|
||||
if runtime.GOOS != "windows" {
|
||||
return nil, errors.New("cpu scraper is currently only supported on windows")
|
||||
}
|
||||
|
||||
cfg := config.(*Config)
|
||||
|
||||
return NewCPUScraper(ctx, cfg, consumer)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ package cpuscraper
|
|||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -29,12 +28,6 @@ func TestCreateMetricsScraper(t *testing.T) {
|
|||
|
||||
scraper, err := factory.CreateMetricsScraper(context.Background(), zap.NewNop(), cfg, nil)
|
||||
|
||||
switch os := runtime.GOOS; os {
|
||||
case "windows":
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, scraper)
|
||||
default:
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, scraper)
|
||||
}
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, scraper)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue