Skip to content

Commit c4ba9b4

Browse files
Add Host Metrics receiver scaffolding - currently only supported on Windows
1 parent 5e3b4e2 commit c4ba9b4

File tree

14 files changed

+558
-6
lines changed

14 files changed

+558
-6
lines changed

receiver/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Supported trace receivers (sorted alphabetically):
1212
- [Zipkin Receiver](#zipkin)
1313

1414
Supported metric receivers (sorted alphabetically):
15+
- [Host Metrics Receiver](#hostmetrics)
1516
- [OpenCensus Receiver](#opencensus)
1617
- [Prometheus Receiver](#prometheus)
1718
- [VM Metrics Receiver](#vmmetrics)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Host Metrics Receiver
2+
3+
The Host Metrics receiver generates metrics about the host system. This is intended to be used when the collector is
4+
deployed as an agent.
5+
6+
The categories of metrics scraped can be configured under the `scrapers` key, e.g. to scrape cpu, memory and disk metrics
7+
(note not all of these are implemented yet):
8+
9+
```
10+
hostmetrics:
11+
default_collection_interval: 10s
12+
scrapers:
13+
cpu:
14+
report_per_process: true
15+
memory:
16+
disk:
17+
```
18+
19+
## OS Support
20+
21+
The initial implementation of the Host Metrics receiver supports Windows only. It's intended that future iterations
22+
of this receiver will support the collection of identical metrics (where possible) on other operating systems.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2020, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package hostmetricsreceiver
16+
17+
import (
18+
"time"
19+
20+
"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
21+
"github.com/open-telemetry/opentelemetry-collector/receiver/hostmetricsreceiver/internal"
22+
)
23+
24+
// Config defines configuration for HostMetrics receiver.
25+
type Config struct {
26+
configmodels.ReceiverSettings `mapstructure:",squash"`
27+
28+
DefaultCollectionInterval time.Duration `mapstructure:"default_collection_interval"`
29+
Scrapers map[string]internal.Config `mapstructure:"scrapers"`
30+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2020, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package hostmetricsreceiver
16+
17+
import (
18+
"path"
19+
"testing"
20+
21+
"github.com/stretchr/testify/require"
22+
23+
"github.com/open-telemetry/opentelemetry-collector/config"
24+
)
25+
26+
func TestLoadConfig(t *testing.T) {
27+
factories, err := config.ExampleComponents()
28+
require.NoError(t, err)
29+
30+
factory := NewFactory()
31+
factories.Receivers[typeStr] = factory
32+
_, err = config.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories)
33+
34+
require.Error(t, err)
35+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
extensions:
2+
zpages:
3+
endpoint: 0.0.0.0:55679
4+
5+
receivers:
6+
hostmetrics:
7+
default_collection_interval: 10s
8+
scrapers:
9+
cpu:
10+
11+
exporters:
12+
logging:
13+
prometheus:
14+
endpoint: 0.0.0.0:8889
15+
16+
service:
17+
pipelines:
18+
metrics:
19+
receivers: [hostmetrics]
20+
exporters: [prometheus, logging]
21+
22+
extensions: [zpages]
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2020, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package hostmetricsreceiver
16+
17+
import (
18+
"context"
19+
"errors"
20+
"fmt"
21+
"runtime"
22+
"time"
23+
24+
"github.com/spf13/viper"
25+
26+
"github.com/open-telemetry/opentelemetry-collector/component"
27+
"github.com/open-telemetry/opentelemetry-collector/config/configerror"
28+
"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
29+
"github.com/open-telemetry/opentelemetry-collector/consumer"
30+
"github.com/open-telemetry/opentelemetry-collector/receiver/hostmetricsreceiver/internal"
31+
)
32+
33+
// This file implements Factory for HostMetrics receiver.
34+
35+
const (
36+
// The value of "type" key in configuration.
37+
typeStr = "hostmetrics"
38+
scrapersKey = "scrapers"
39+
)
40+
41+
// Factory is the Factory for receiver.
42+
type Factory struct {
43+
ScraperFactories map[string]internal.Factory
44+
}
45+
46+
// NewFactory creates a new factory
47+
func NewFactory() *Factory {
48+
return &Factory{
49+
ScraperFactories: map[string]internal.Factory{},
50+
}
51+
}
52+
53+
// Type gets the type of the Receiver config created by this Factory.
54+
func (f *Factory) Type() string {
55+
return typeStr
56+
}
57+
58+
// CustomUnmarshaler returns custom unmarshaler for this config.
59+
func (f *Factory) CustomUnmarshaler() component.CustomUnmarshaler {
60+
return func(componentViperSection *viper.Viper, intoCfg interface{}) error {
61+
62+
// load the non-dynamic config normally
63+
64+
err := componentViperSection.UnmarshalExact(intoCfg)
65+
if err != nil {
66+
return err
67+
}
68+
69+
cfg, ok := intoCfg.(*Config)
70+
if !ok {
71+
return fmt.Errorf("config type not hostmetrics.Config")
72+
}
73+
74+
// dynamically load the individual collector configs based on the key name
75+
76+
cfg.Scrapers = map[string]internal.Config{}
77+
78+
scrapersViperSection := componentViperSection.Sub(scrapersKey)
79+
if scrapersViperSection == nil || len(scrapersViperSection.AllKeys()) == 0 {
80+
return fmt.Errorf("must specify at least one scraper when using hostmetrics receiver")
81+
}
82+
83+
for key := range componentViperSection.GetStringMap(scrapersKey) {
84+
factory, ok := f.ScraperFactories[key]
85+
if !ok {
86+
return fmt.Errorf("invalid hostmetrics scraper key: %s", key)
87+
}
88+
89+
collectorCfg := factory.CreateDefaultConfig()
90+
collectorViperSection := scrapersViperSection.Sub(key)
91+
if collectorViperSection != nil {
92+
err := collectorViperSection.UnmarshalExact(collectorCfg)
93+
if err != nil {
94+
return fmt.Errorf("error reading settings for hostmetric scraper type %q: %v", key, err)
95+
}
96+
}
97+
98+
cfg.Scrapers[key] = collectorCfg
99+
}
100+
101+
return nil
102+
}
103+
}
104+
105+
// CreateDefaultConfig creates the default configuration for receiver.
106+
func (f *Factory) CreateDefaultConfig() configmodels.Receiver {
107+
return &Config{
108+
ReceiverSettings: configmodels.ReceiverSettings{
109+
TypeVal: typeStr,
110+
NameVal: typeStr,
111+
},
112+
DefaultCollectionInterval: 10 * time.Second,
113+
}
114+
}
115+
116+
// CreateTraceReceiver creates a trace receiver based on provided config.
117+
func (f *Factory) CreateTraceReceiver(
118+
ctx context.Context,
119+
params component.ReceiverCreateParams,
120+
cfg configmodels.Receiver,
121+
consumer consumer.TraceConsumer,
122+
) (component.TraceReceiver, error) {
123+
// Host Metrics does not support traces
124+
return nil, configerror.ErrDataTypeIsNotSupported
125+
}
126+
127+
// CreateMetricsReceiver creates a metrics receiver based on provided config.
128+
func (f *Factory) CreateMetricsReceiver(
129+
ctx context.Context,
130+
params component.ReceiverCreateParams,
131+
cfg configmodels.Receiver,
132+
consumer consumer.MetricsConsumer,
133+
) (component.MetricsReceiver, error) {
134+
135+
if runtime.GOOS != "windows" {
136+
return nil, errors.New("hostmetrics receiver is currently only supported on windows")
137+
}
138+
139+
config := cfg.(*Config)
140+
141+
hmr, err := NewHostMetricsReceiver(ctx, params.Logger, config, f.ScraperFactories, consumer)
142+
if err != nil {
143+
return nil, err
144+
}
145+
146+
return hmr, nil
147+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2020, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package hostmetricsreceiver
16+
17+
import (
18+
"context"
19+
"runtime"
20+
"testing"
21+
22+
"github.com/stretchr/testify/assert"
23+
"go.uber.org/zap"
24+
25+
"github.com/open-telemetry/opentelemetry-collector/component"
26+
"github.com/open-telemetry/opentelemetry-collector/config/configcheck"
27+
"github.com/open-telemetry/opentelemetry-collector/config/configerror"
28+
)
29+
30+
var creationParams = component.ReceiverCreateParams{Logger: zap.NewNop()}
31+
32+
func TestCreateDefaultConfig(t *testing.T) {
33+
factory := &Factory{}
34+
cfg := factory.CreateDefaultConfig()
35+
assert.NotNil(t, cfg, "failed to create default config")
36+
assert.NoError(t, configcheck.ValidateConfig(cfg))
37+
}
38+
39+
func TestCreateReceiver(t *testing.T) {
40+
factory := &Factory{}
41+
cfg := factory.CreateDefaultConfig()
42+
43+
tReceiver, err := factory.CreateTraceReceiver(context.Background(), creationParams, cfg, nil)
44+
45+
assert.Equal(t, err, configerror.ErrDataTypeIsNotSupported)
46+
assert.Nil(t, tReceiver)
47+
48+
mReceiver, err := factory.CreateMetricsReceiver(context.Background(), creationParams, cfg, nil)
49+
50+
if runtime.GOOS != "windows" {
51+
assert.NotNil(t, err)
52+
assert.Nil(t, tReceiver)
53+
} else {
54+
assert.Nil(t, err)
55+
assert.NotNil(t, mReceiver)
56+
}
57+
}

0 commit comments

Comments
 (0)