-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Add Host Metrics receiver scaffolding #848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # Host Metrics Receiver | ||
|
|
||
| The Host Metrics receiver generates metrics about the host system. This is intended to be used when the collector is | ||
| deployed as an agent. | ||
|
|
||
| The categories of metrics scraped can be configured under the `scrapers` key, e.g. to scrape cpu, memory and disk metrics | ||
| (note not all of these are implemented yet): | ||
|
|
||
| ``` | ||
| hostmetrics: | ||
| default_collection_interval: 10s | ||
| scrapers: | ||
| cpu: | ||
| report_per_process: true | ||
| memory: | ||
| disk: | ||
| ``` | ||
|
|
||
| ## OS Support | ||
|
|
||
| The initial implementation of the Host Metrics receiver supports Windows only. It's intended that future iterations | ||
| of this receiver will support the collection of identical metrics (where possible) on other operating systems. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // 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. | ||
|
|
||
| package hostmetricsreceiver | ||
|
|
||
| import ( | ||
| "time" | ||
|
|
||
| "github.com/open-telemetry/opentelemetry-collector/config/configmodels" | ||
| "github.com/open-telemetry/opentelemetry-collector/receiver/hostmetricsreceiver/internal" | ||
| ) | ||
|
|
||
| // Config defines configuration for HostMetrics receiver. | ||
| type Config struct { | ||
| configmodels.ReceiverSettings `mapstructure:",squash"` | ||
|
|
||
| DefaultCollectionInterval time.Duration `mapstructure:"default_collection_interval"` | ||
| Scrapers map[string]internal.Config `mapstructure:"-"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // 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. | ||
|
|
||
| package hostmetricsreceiver | ||
|
|
||
| import ( | ||
| "path" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
|
|
||
| "github.com/open-telemetry/opentelemetry-collector/config" | ||
| ) | ||
|
|
||
| func TestLoadConfig(t *testing.T) { | ||
| factories, err := config.ExampleComponents() | ||
| require.NoError(t, err) | ||
|
|
||
| factory := NewFactory() | ||
| factories.Receivers[typeStr] = factory | ||
| _, err = config.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories) | ||
|
|
||
| require.Error(t, err) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| extensions: | ||
| zpages: | ||
| endpoint: 0.0.0.0:55679 | ||
|
|
||
| receivers: | ||
| hostmetrics: | ||
| default_collection_interval: 10s | ||
| scrapers: | ||
|
|
||
| exporters: | ||
| logging: | ||
| prometheus: | ||
| endpoint: 0.0.0.0:8889 | ||
|
|
||
| service: | ||
| pipelines: | ||
| metrics: | ||
| receivers: [hostmetrics] | ||
| exporters: [prometheus, logging] | ||
|
|
||
| extensions: [zpages] |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,147 @@ | ||||||
| // 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. | ||||||
|
|
||||||
| package hostmetricsreceiver | ||||||
|
|
||||||
| import ( | ||||||
| "context" | ||||||
| "errors" | ||||||
| "fmt" | ||||||
| "runtime" | ||||||
| "time" | ||||||
|
|
||||||
| "github.com/spf13/viper" | ||||||
|
|
||||||
| "github.com/open-telemetry/opentelemetry-collector/component" | ||||||
| "github.com/open-telemetry/opentelemetry-collector/config/configerror" | ||||||
| "github.com/open-telemetry/opentelemetry-collector/config/configmodels" | ||||||
| "github.com/open-telemetry/opentelemetry-collector/consumer" | ||||||
| "github.com/open-telemetry/opentelemetry-collector/receiver/hostmetricsreceiver/internal" | ||||||
| ) | ||||||
|
|
||||||
| // This file implements Factory for HostMetrics receiver. | ||||||
|
|
||||||
| const ( | ||||||
| // The value of "type" key in configuration. | ||||||
| typeStr = "hostmetrics" | ||||||
| scrapersKey = "scrapers" | ||||||
| ) | ||||||
|
|
||||||
| // Factory is the Factory for receiver. | ||||||
| type Factory struct { | ||||||
| ScraperFactories map[string]internal.Factory | ||||||
| } | ||||||
|
|
||||||
| // NewFactory creates a new factory | ||||||
| func NewFactory() *Factory { | ||||||
| return &Factory{ | ||||||
| ScraperFactories: map[string]internal.Factory{}, | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // Type gets the type of the Receiver config created by this Factory. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| func (f *Factory) Type() string { | ||||||
| return typeStr | ||||||
| } | ||||||
|
|
||||||
| // CustomUnmarshaler returns custom unmarshaler for this config. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| func (f *Factory) CustomUnmarshaler() component.CustomUnmarshaler { | ||||||
| return func(componentViperSection *viper.Viper, intoCfg interface{}) error { | ||||||
|
|
||||||
| // load the non-dynamic config normally | ||||||
|
|
||||||
| err := componentViperSection.Unmarshal(intoCfg) | ||||||
| if err != nil { | ||||||
| return err | ||||||
| } | ||||||
|
|
||||||
| cfg, ok := intoCfg.(*Config) | ||||||
| if !ok { | ||||||
| return fmt.Errorf("config type not hostmetrics.Config") | ||||||
| } | ||||||
|
|
||||||
| // dynamically load the individual collector configs based on the key name | ||||||
|
|
||||||
| cfg.Scrapers = map[string]internal.Config{} | ||||||
|
|
||||||
| scrapersViperSection := componentViperSection.Sub(scrapersKey) | ||||||
| if scrapersViperSection == nil || len(scrapersViperSection.AllKeys()) == 0 { | ||||||
| return fmt.Errorf("must specify at least one scraper when using hostmetrics receiver") | ||||||
| } | ||||||
|
|
||||||
| for key := range componentViperSection.GetStringMap(scrapersKey) { | ||||||
| factory, ok := f.ScraperFactories[key] | ||||||
| if !ok { | ||||||
| return fmt.Errorf("invalid hostmetrics scraper key: %s", key) | ||||||
| } | ||||||
|
|
||||||
| collectorCfg := factory.CreateDefaultConfig() | ||||||
| collectorViperSection := scrapersViperSection.Sub(key) | ||||||
| if collectorViperSection != nil { | ||||||
| err := collectorViperSection.UnmarshalExact(collectorCfg) | ||||||
| if err != nil { | ||||||
| return fmt.Errorf("error reading settings for hostmetric scraper type %q: %v", key, err) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| cfg.Scrapers[key] = collectorCfg | ||||||
| } | ||||||
|
|
||||||
| return nil | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // CreateDefaultConfig creates the default configuration for receiver. | ||||||
| func (f *Factory) CreateDefaultConfig() configmodels.Receiver { | ||||||
| return &Config{ | ||||||
| ReceiverSettings: configmodels.ReceiverSettings{ | ||||||
| TypeVal: typeStr, | ||||||
| NameVal: typeStr, | ||||||
| }, | ||||||
| DefaultCollectionInterval: 10 * time.Second, | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // CreateTraceReceiver creates a trace receiver based on provided config. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this should be |
||||||
| func (f *Factory) CreateTraceReceiver( | ||||||
| ctx context.Context, | ||||||
| params component.ReceiverCreateParams, | ||||||
| cfg configmodels.Receiver, | ||||||
| consumer consumer.TraceConsumer, | ||||||
| ) (component.TraceReceiver, error) { | ||||||
| // Host Metrics does not support traces | ||||||
| return nil, configerror.ErrDataTypeIsNotSupported | ||||||
| } | ||||||
|
|
||||||
| // CreateMetricsReceiver creates a metrics receiver based on provided config. | ||||||
| func (f *Factory) CreateMetricsReceiver( | ||||||
| ctx context.Context, | ||||||
| params component.ReceiverCreateParams, | ||||||
| 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) | ||||||
| if err != nil { | ||||||
| return nil, err | ||||||
| } | ||||||
|
|
||||||
| return hmr, nil | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| // 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. | ||
|
|
||
| package hostmetricsreceiver | ||
|
|
||
| import ( | ||
| "context" | ||
| "runtime" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "go.uber.org/zap" | ||
|
|
||
| "github.com/open-telemetry/opentelemetry-collector/component" | ||
| "github.com/open-telemetry/opentelemetry-collector/config/configcheck" | ||
| "github.com/open-telemetry/opentelemetry-collector/config/configerror" | ||
| ) | ||
|
|
||
| var creationParams = component.ReceiverCreateParams{Logger: zap.NewNop()} | ||
|
|
||
| func TestCreateDefaultConfig(t *testing.T) { | ||
| factory := &Factory{} | ||
| cfg := factory.CreateDefaultConfig() | ||
| assert.NotNil(t, cfg, "failed to create default config") | ||
| assert.NoError(t, configcheck.ValidateConfig(cfg)) | ||
| } | ||
|
|
||
| func TestCreateReceiver(t *testing.T) { | ||
| factory := &Factory{} | ||
| cfg := factory.CreateDefaultConfig() | ||
|
|
||
| tReceiver, err := factory.CreateTraceReceiver(context.Background(), creationParams, cfg, nil) | ||
|
|
||
| assert.Equal(t, err, configerror.ErrDataTypeIsNotSupported) | ||
| assert.Nil(t, tReceiver) | ||
|
|
||
| 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) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.