Skip to content

Commit 40e2bb3

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

File tree

16 files changed

+579
-5
lines changed

16 files changed

+579
-5
lines changed

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ require (
2626
github.com/hashicorp/consul/api v1.2.0 // indirect
2727
github.com/jaegertracing/jaeger v1.17.0
2828
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024
29-
github.com/mitchellh/mapstructure v1.2.2
3029
github.com/open-telemetry/opentelemetry-proto v0.3.0
3130
github.com/openzipkin/zipkin-go v0.2.1
3231
github.com/orijtech/prometheus-go-metrics-exporter v0.0.4
@@ -48,15 +47,15 @@ require (
4847
github.com/spf13/cobra v0.0.6
4948
github.com/spf13/viper v1.6.2
5049
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 // indirect
51-
github.com/stretchr/testify v1.4.0
50+
github.com/stretchr/testify v1.5.1
5251
github.com/tcnksm/ghr v0.13.0
5352
github.com/uber-go/atomic v1.4.0 // indirect
5453
github.com/uber/jaeger-lib v2.2.0+incompatible
5554
github.com/uber/tchannel-go v1.10.0 // indirect
5655
go.opencensus.io v0.22.3
5756
go.uber.org/zap v1.10.0
5857
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
59-
golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b
58+
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4
6059
google.golang.org/api v0.10.0 // indirect
6160
google.golang.org/genproto v0.0.0-20200408120641-fbb3ad325eb7
6261
google.golang.org/grpc v1.28.1

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
10981098
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
10991099
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
11001100
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
1101+
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
1102+
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
11011103
github.com/subosito/gotenv v1.1.1/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
11021104
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
11031105
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
@@ -1327,8 +1329,8 @@ golang.org/x/sys v0.0.0-20200121082415-34d275377bf9/go.mod h1:h1NjWce9XRLGQEsW7w
13271329
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
13281330
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
13291331
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
1330-
golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b h1:h03Ur1RlPrGTjua4koYdpGl8W0eYo8p1uI9w7RPlkdk=
1331-
golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
1332+
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
1333+
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
13321334
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
13331335
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
13341336
golang.org/x/text v0.3.1-0.20180805044716-cb6730876b98/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

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/scraper"
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]scraper.Config `mapstructure:"scrapers"`
30+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
"github.com/open-telemetry/opentelemetry-collector/receiver/hostmetricsreceiver/scraper"
25+
)
26+
27+
func TestLoadConfig(t *testing.T) {
28+
factories, err := config.ExampleComponents()
29+
require.NoError(t, err)
30+
31+
collectorFactories, err := scraper.MakeScraperFactoryMap()
32+
require.NoError(t, err)
33+
34+
factory := &Factory{ScraperFactories: collectorFactories}
35+
factories.Receivers[typeStr] = factory
36+
_, err = config.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories)
37+
38+
require.Error(t, err)
39+
}
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: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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/scraper"
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]scraper.Factory
44+
}
45+
46+
// Type gets the type of the Receiver config created by this Factory.
47+
func (f *Factory) Type() string {
48+
return typeStr
49+
}
50+
51+
// CustomUnmarshaler returns custom unmarshaler for this config.
52+
func (f *Factory) CustomUnmarshaler() component.CustomUnmarshaler {
53+
return func(componentViperSection *viper.Viper, intoCfg interface{}) error {
54+
55+
// load the non-dynamic config normally
56+
57+
err := componentViperSection.UnmarshalExact(intoCfg)
58+
if err != nil {
59+
return err
60+
}
61+
62+
cfg, ok := intoCfg.(*Config)
63+
if !ok {
64+
return fmt.Errorf("config type not hostmetrics.Config")
65+
}
66+
67+
// dynamically load the individual collector configs based on the key name
68+
69+
cfg.Scrapers = map[string]scraper.Config{}
70+
71+
scrapersViperSection := componentViperSection.Sub(scrapersKey)
72+
if scrapersViperSection == nil || len(scrapersViperSection.AllKeys()) == 0 {
73+
return fmt.Errorf("must specify at least one scraper when using hostmetrics receiver")
74+
}
75+
76+
for key := range componentViperSection.GetStringMap(scrapersKey) {
77+
factory, ok := f.ScraperFactories[key]
78+
if !ok {
79+
return fmt.Errorf("invalid hostmetrics scraper key: %s", key)
80+
}
81+
82+
collectorCfg := factory.CreateDefaultConfig()
83+
collectorViperSection := scrapersViperSection.Sub(key)
84+
if collectorViperSection != nil {
85+
err := collectorViperSection.UnmarshalExact(collectorCfg)
86+
if err != nil {
87+
return fmt.Errorf("error reading settings for hostmetric scraper type %q: %v", key, err)
88+
}
89+
}
90+
91+
cfg.Scrapers[key] = collectorCfg
92+
}
93+
94+
return nil
95+
}
96+
}
97+
98+
// CreateDefaultConfig creates the default configuration for receiver.
99+
func (f *Factory) CreateDefaultConfig() configmodels.Receiver {
100+
return &Config{
101+
ReceiverSettings: configmodels.ReceiverSettings{
102+
TypeVal: typeStr,
103+
NameVal: typeStr,
104+
},
105+
DefaultCollectionInterval: 10 * time.Second,
106+
}
107+
}
108+
109+
// CreateTraceReceiver creates a trace receiver based on provided config.
110+
func (f *Factory) CreateTraceReceiver(
111+
ctx context.Context,
112+
params component.ReceiverCreateParams,
113+
cfg configmodels.Receiver,
114+
consumer consumer.TraceConsumer,
115+
) (component.TraceReceiver, error) {
116+
// Host Metrics does not support traces
117+
return nil, configerror.ErrDataTypeIsNotSupported
118+
}
119+
120+
// CreateMetricsReceiver creates a metrics receiver based on provided config.
121+
func (f *Factory) CreateMetricsReceiver(
122+
ctx context.Context,
123+
params component.ReceiverCreateParams,
124+
cfg configmodels.Receiver,
125+
consumer consumer.MetricsConsumer,
126+
) (component.MetricsReceiver, error) {
127+
128+
if runtime.GOOS != "windows" {
129+
return nil, errors.New("hostmetrics receiver is currently only supported on windows")
130+
}
131+
132+
config := cfg.(*Config)
133+
134+
hmr, err := NewHostMetricsReceiver(ctx, params.Logger, config, f.ScraperFactories, consumer)
135+
if err != nil {
136+
return nil, err
137+
}
138+
139+
return hmr, nil
140+
}
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)