Skip to content

Commit f640aa5

Browse files
james-bebbingtonwyTrivail
authored andcommitted
Disable process scraper for any non Linux/Windows OS (open-telemetry#1328)
1 parent adf08ab commit f640aa5

File tree

9 files changed

+134
-79
lines changed

9 files changed

+134
-79
lines changed

receiver/hostmetricsreceiver/example_config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ receivers:
1212
disk:
1313
filesystem:
1414
network:
15+
processes:
1516
swap:
1617

1718
exporters:

receiver/hostmetricsreceiver/hostmetrics_receiver.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"fmt"
2020
"time"
2121

22-
"github.com/pkg/errors"
2322
"go.opencensus.io/trace"
2423
"go.uber.org/zap"
2524

@@ -58,7 +57,7 @@ func newHostMetricsReceiver(
5857
for key, cfg := range config.Scrapers {
5958
hostMetricsScraper, ok, err := createHostMetricsScraper(ctx, logger, key, cfg, factories)
6059
if err != nil {
61-
errors.Wrapf(err, "failed to create scraper for key %q", key)
60+
return nil, fmt.Errorf("failed to create scraper for key %q: %w", key, err)
6261
}
6362

6463
if ok {
@@ -68,7 +67,7 @@ func newHostMetricsReceiver(
6867

6968
resourceMetricsScraper, ok, err := createResourceMetricsScraper(ctx, logger, key, cfg, resourceFactories)
7069
if err != nil {
71-
errors.Wrapf(err, "failed to create resource scraper for key %q", key)
70+
return nil, fmt.Errorf("failed to create resource scraper for key %q: %w", key, err)
7271
}
7372

7473
if ok {

receiver/hostmetricsreceiver/hostmetrics_receiver_test.go

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"time"
2323

2424
"github.com/stretchr/testify/assert"
25+
"github.com/stretchr/testify/mock"
2526
"github.com/stretchr/testify/require"
2627
"go.uber.org/zap"
2728

@@ -103,10 +104,13 @@ func TestGatherMetrics_EndToEnd(t *testing.T) {
103104
networkscraper.TypeStr: &networkscraper.Config{},
104105
processesscraper.TypeStr: &processesscraper.Config{},
105106
swapscraper.TypeStr: &swapscraper.Config{},
106-
processscraper.TypeStr: &processscraper.Config{},
107107
},
108108
}
109109

110+
if runtime.GOOS == "linux" || runtime.GOOS == "windows" {
111+
config.Scrapers[processscraper.TypeStr] = &processscraper.Config{}
112+
}
113+
110114
receiver, err := newHostMetricsReceiver(context.Background(), zap.NewNop(), config, factories, resourceFactories, sink)
111115

112116
require.NoError(t, err, "Failed to create metrics receiver: %v", err)
@@ -120,7 +124,7 @@ func TestGatherMetrics_EndToEnd(t *testing.T) {
120124
cancelFn()
121125

122126
const tick = 50 * time.Millisecond
123-
const waitFor = 5 * time.Second
127+
const waitFor = time.Second
124128
require.Eventuallyf(t, func() bool {
125129
got := sink.AllMetrics()
126130
if len(got) == 0 {
@@ -154,6 +158,10 @@ func assertIncludesStandardMetrics(t *testing.T, got pdata.Metrics) {
154158
}
155159

156160
func assertIncludesResourceMetrics(t *testing.T, got pdata.Metrics) {
161+
if runtime.GOOS != "linux" && runtime.GOOS != "windows" {
162+
return
163+
}
164+
157165
md := pdatautil.MetricsToInternalMetrics(got)
158166

159167
// get the superset of metrics returned by all resource metrics (excluding the first)
@@ -197,31 +205,33 @@ const mockResourceTypeStr = "mockresource"
197205

198206
type mockConfig struct{}
199207

200-
type mockFactory struct{}
201-
type mockScraper struct{}
208+
type mockFactory struct{ mock.Mock }
209+
type mockScraper struct{ mock.Mock }
202210

203-
func (*mockFactory) CreateDefaultConfig() internal.Config { return &mockConfig{} }
204-
func (*mockFactory) CreateMetricsScraper(ctx context.Context, logger *zap.Logger, cfg internal.Config) (internal.Scraper, error) {
205-
return &mockScraper{}, nil
211+
func (m *mockFactory) CreateDefaultConfig() internal.Config { return &mockConfig{} }
212+
func (m *mockFactory) CreateMetricsScraper(ctx context.Context, logger *zap.Logger, cfg internal.Config) (internal.Scraper, error) {
213+
args := m.MethodCalled("CreateMetricsScraper")
214+
return args.Get(0).(internal.Scraper), args.Error(1)
206215
}
207216

208-
func (*mockScraper) Initialize(ctx context.Context) error { return nil }
209-
func (*mockScraper) Close(ctx context.Context) error { return nil }
210-
func (*mockScraper) ScrapeMetrics(ctx context.Context) (pdata.MetricSlice, error) {
217+
func (m *mockScraper) Initialize(ctx context.Context) error { return nil }
218+
func (m *mockScraper) Close(ctx context.Context) error { return nil }
219+
func (m *mockScraper) ScrapeMetrics(ctx context.Context) (pdata.MetricSlice, error) {
211220
return pdata.NewMetricSlice(), errors.New("err1")
212221
}
213222

214-
type mockResourceFactory struct{}
215-
type mockResourceScraper struct{}
223+
type mockResourceFactory struct{ mock.Mock }
224+
type mockResourceScraper struct{ mock.Mock }
216225

217-
func (*mockResourceFactory) CreateDefaultConfig() internal.Config { return &mockConfig{} }
218-
func (*mockResourceFactory) CreateMetricsScraper(ctx context.Context, logger *zap.Logger, cfg internal.Config) (internal.ResourceScraper, error) {
219-
return &mockResourceScraper{}, nil
226+
func (m *mockResourceFactory) CreateDefaultConfig() internal.Config { return &mockConfig{} }
227+
func (m *mockResourceFactory) CreateMetricsScraper(ctx context.Context, logger *zap.Logger, cfg internal.Config) (internal.ResourceScraper, error) {
228+
args := m.MethodCalled("CreateMetricsScraper")
229+
return args.Get(0).(internal.ResourceScraper), args.Error(1)
220230
}
221231

222-
func (*mockResourceScraper) Initialize(ctx context.Context) error { return nil }
223-
func (*mockResourceScraper) Close(ctx context.Context) error { return nil }
224-
func (*mockResourceScraper) ScrapeMetrics(ctx context.Context) (pdata.ResourceMetricsSlice, error) {
232+
func (m *mockResourceScraper) Initialize(ctx context.Context) error { return nil }
233+
func (m *mockResourceScraper) Close(ctx context.Context) error { return nil }
234+
func (m *mockResourceScraper) ScrapeMetrics(ctx context.Context) (pdata.ResourceMetricsSlice, error) {
225235
return pdata.NewResourceMetricsSlice(), errors.New("err2")
226236
}
227237

@@ -236,9 +246,38 @@ func TestGatherMetrics_ScraperKeyConfigError(t *testing.T) {
236246
require.Error(t, err)
237247
}
238248

249+
func TestGatherMetrics_CreateMetricsScraperError(t *testing.T) {
250+
mFactory := &mockFactory{}
251+
mFactory.On("CreateMetricsScraper").Return(&mockScraper{}, errors.New("err1"))
252+
var mockFactories = map[string]internal.ScraperFactory{mockTypeStr: mFactory}
253+
var mockResourceFactories = map[string]internal.ResourceScraperFactory{}
254+
255+
sink := &exportertest.SinkMetricsExporter{}
256+
config := &Config{Scrapers: map[string]internal.Config{mockTypeStr: &mockConfig{}}}
257+
_, err := newHostMetricsReceiver(context.Background(), zap.NewNop(), config, mockFactories, mockResourceFactories, sink)
258+
require.Error(t, err)
259+
}
260+
261+
func TestGatherMetrics_CreateMetricsResourceScraperError(t *testing.T) {
262+
mResourceFactory := &mockResourceFactory{}
263+
mResourceFactory.On("CreateMetricsScraper").Return(&mockResourceScraper{}, errors.New("err1"))
264+
var mockFactories = map[string]internal.ScraperFactory{}
265+
var mockResourceFactories = map[string]internal.ResourceScraperFactory{mockTypeStr: mResourceFactory}
266+
267+
sink := &exportertest.SinkMetricsExporter{}
268+
config := &Config{Scrapers: map[string]internal.Config{mockTypeStr: &mockConfig{}}}
269+
_, err := newHostMetricsReceiver(context.Background(), zap.NewNop(), config, mockFactories, mockResourceFactories, sink)
270+
require.Error(t, err)
271+
}
272+
239273
func TestGatherMetrics_Error(t *testing.T) {
240-
var mockFactories = map[string]internal.ScraperFactory{mockTypeStr: &mockFactory{}}
241-
var mockResourceFactories = map[string]internal.ResourceScraperFactory{mockResourceTypeStr: &mockResourceFactory{}}
274+
mFactory := &mockFactory{}
275+
mFactory.On("CreateMetricsScraper").Return(&mockScraper{}, nil)
276+
mResourceFactory := &mockResourceFactory{}
277+
mResourceFactory.On("CreateMetricsScraper").Return(&mockResourceScraper{}, nil)
278+
279+
var mockFactories = map[string]internal.ScraperFactory{mockTypeStr: mFactory}
280+
var mockResourceFactories = map[string]internal.ResourceScraperFactory{mockResourceTypeStr: mResourceFactory}
242281

243282
sink := &exportertest.SinkMetricsExporter{}
244283

@@ -313,8 +352,8 @@ func Benchmark_ScrapeNetworkMetrics(b *testing.B) {
313352
benchmarkScrapeMetrics(b, cfg)
314353
}
315354

316-
func Benchmark_ScrapeProcessMetrics(b *testing.B) {
317-
cfg := &Config{Scrapers: map[string]internal.Config{processscraper.TypeStr: (&processscraper.Factory{}).CreateDefaultConfig()}}
355+
func Benchmark_ScrapeProcessesMetrics(b *testing.B) {
356+
cfg := &Config{Scrapers: map[string]internal.Config{processesscraper.TypeStr: (&processesscraper.Factory{}).CreateDefaultConfig()}}
318357
benchmarkScrapeMetrics(b, cfg)
319358
}
320359

@@ -323,6 +362,15 @@ func Benchmark_ScrapeSwapMetrics(b *testing.B) {
323362
benchmarkScrapeMetrics(b, cfg)
324363
}
325364

365+
func Benchmark_ScrapeProcessMetrics(b *testing.B) {
366+
if runtime.GOOS != "linux" && runtime.GOOS != "windows" {
367+
b.Skip("skipping test on non linux/windows")
368+
}
369+
370+
cfg := &Config{Scrapers: map[string]internal.Config{processscraper.TypeStr: (&processscraper.Factory{}).CreateDefaultConfig()}}
371+
benchmarkScrapeMetrics(b, cfg)
372+
}
373+
326374
func Benchmark_ScrapeSystemMetrics(b *testing.B) {
327375
cfg := &Config{
328376
Scrapers: map[string]internal.Config{
@@ -351,9 +399,12 @@ func Benchmark_ScrapeSystemAndProcessMetrics(b *testing.B) {
351399
networkscraper.TypeStr: &networkscraper.Config{},
352400
processesscraper.TypeStr: &processesscraper.Config{},
353401
swapscraper.TypeStr: &swapscraper.Config{},
354-
processscraper.TypeStr: &processscraper.Config{},
355402
},
356403
}
357404

405+
if runtime.GOOS == "linux" || runtime.GOOS == "windows" {
406+
cfg.Scrapers[processscraper.TypeStr] = &processscraper.Config{}
407+
}
408+
358409
benchmarkScrapeMetrics(b, cfg)
359410
}

receiver/hostmetricsreceiver/internal/scraper/processscraper/factory.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ package processscraper
1616

1717
import (
1818
"context"
19+
"errors"
20+
"runtime"
1921

2022
"go.uber.org/zap"
2123

@@ -45,6 +47,10 @@ func (f *Factory) CreateMetricsScraper(
4547
_ *zap.Logger,
4648
config internal.Config,
4749
) (internal.ResourceScraper, error) {
50+
if runtime.GOOS != "linux" && runtime.GOOS != "windows" {
51+
return nil, errors.New("process scraper only available on Linux or Windows")
52+
}
53+
4854
cfg := config.(*Config)
4955
ps, err := newProcessScraper(cfg)
5056
if err != nil {

receiver/hostmetricsreceiver/internal/scraper/processscraper/factory_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package processscraper
1616

1717
import (
1818
"context"
19+
"runtime"
1920
"testing"
2021

2122
"github.com/stretchr/testify/assert"
@@ -34,6 +35,11 @@ func TestCreateMetricsScraper(t *testing.T) {
3435

3536
scraper, err := factory.CreateMetricsScraper(context.Background(), zap.NewNop(), cfg)
3637

37-
assert.NoError(t, err)
38-
assert.NotNil(t, scraper)
38+
if runtime.GOOS == "linux" || runtime.GOOS == "windows" {
39+
assert.NoError(t, err)
40+
assert.NotNil(t, scraper)
41+
} else {
42+
assert.Error(t, err)
43+
assert.Nil(t, scraper)
44+
}
3945
}

receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper_linux.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,33 @@ func appendCPUTimeStateDataPoints(ddps pdata.DoubleDataPointSlice, startTime pda
2929
initializeCPUTimeDataPoint(ddps.At(1), startTime, cpuTime.System, systemStateLabelValue)
3030
initializeCPUTimeDataPoint(ddps.At(2), startTime, cpuTime.Iowait, waitStateLabelValue)
3131
}
32+
33+
func getProcessExecutable(proc processHandle) (*executableMetadata, error) {
34+
name, err := proc.Name()
35+
if err != nil {
36+
return nil, err
37+
}
38+
39+
exe, err := proc.Exe()
40+
if err != nil {
41+
return nil, err
42+
}
43+
44+
executable := &executableMetadata{name: name, path: exe}
45+
return executable, nil
46+
}
47+
48+
func getProcessCommand(proc processHandle) (*commandMetadata, error) {
49+
cmdline, err := proc.CmdlineSlice()
50+
if err != nil {
51+
return nil, err
52+
}
53+
54+
var cmd string
55+
if len(cmdline) > 0 {
56+
cmd = cmdline[0]
57+
}
58+
59+
command := &commandMetadata{command: cmd, commandLineSlice: cmdline}
60+
return command, nil
61+
}

receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper_notwindows.go

Lines changed: 0 additions & 47 deletions
This file was deleted.

receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper_others.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,15 @@ import (
2222
"go.opentelemetry.io/collector/consumer/pdata"
2323
)
2424

25-
const cpuStatesLen = 2
25+
const cpuStatesLen = 0
2626

2727
func appendCPUTimeStateDataPoints(ddps pdata.DoubleDataPointSlice, startTime pdata.TimestampUnixNano, cpuTime *cpu.TimesStat) {
28-
initializeCPUTimeDataPoint(ddps.At(0), startTime, cpuTime.User, userStateLabelValue)
29-
initializeCPUTimeDataPoint(ddps.At(1), startTime, cpuTime.System, systemStateLabelValue)
28+
}
29+
30+
func getProcessExecutable(proc processHandle) (*executableMetadata, error) {
31+
return nil, nil
32+
}
33+
34+
func getProcessCommand(proc processHandle) (*commandMetadata, error) {
35+
return nil, nil
3036
}

receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
//+build linux windows
16+
1517
package processscraper
1618

1719
import (
1820
"context"
1921
"errors"
22+
"fmt"
2023
"runtime"
2124
"strings"
2225
"testing"
@@ -107,7 +110,7 @@ func getMetric(t *testing.T, descriptor pdata.MetricDescriptor, rms pdata.Resour
107110
}
108111
}
109112

110-
require.Failf(t, "no metric with name %s was returned", descriptor.Name())
113+
require.Fail(t, fmt.Sprintf("no metric with name %s was returned", descriptor.Name()))
111114
return pdata.NewMetric()
112115
}
113116

0 commit comments

Comments
 (0)