-
Notifications
You must be signed in to change notification settings - Fork 488
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
flow: Add otelcol.receiver.vcenter component #5715
Changes from 13 commits
e3baf8e
12d8ccf
ae785aa
d9fe9f9
abfb48a
93fa7c2
5f2cf69
c708425
a346827
5cfef4c
84b75ee
04be039
6465d15
1de1406
a8aceca
a747885
63385ea
80876f9
33a62aa
cf803c9
ea66d8f
f3ea19e
fa17b65
65f7233
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,57 @@ | ||
package otelcol | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"time" | ||
|
||
scraperhelper "go.opentelemetry.io/collector/receiver/scraperhelper" | ||
) | ||
|
||
var ( | ||
errNonPositiveInterval = errors.New("requires positive value") | ||
) | ||
|
||
// ScraperControllerArguments defines common settings for a scraper controller | ||
// configuration. | ||
type ScraperControllerArguments struct { | ||
CollectionInterval time.Duration `river:"collection_interval,attr,optional"` | ||
InitialDelay time.Duration `river:"initial_delay,attr,optional"` | ||
Timeout time.Duration `river:"timeout,attr,optional"` | ||
} | ||
|
||
// DefaultScraperControllerArguments holds default settings for ScraperControllerArguments. | ||
var DefaultScraperControllerArguments = ScraperControllerArguments{ | ||
CollectionInterval: time.Minute, | ||
InitialDelay: time.Second, | ||
Timeout: 0 * time.Second, | ||
} | ||
|
||
// SetToDefault implements river.Defaulter. | ||
func (args *ScraperControllerArguments) SetToDefault() { | ||
*args = DefaultScraperControllerArguments | ||
} | ||
|
||
// Convert converts args into the upstream type. | ||
func (args *ScraperControllerArguments) Convert() *scraperhelper.ScraperControllerSettings { | ||
if args == nil { | ||
return nil | ||
} | ||
|
||
return &scraperhelper.ScraperControllerSettings{ | ||
CollectionInterval: args.CollectionInterval, | ||
InitialDelay: args.InitialDelay, | ||
Timeout: args.Timeout, | ||
} | ||
} | ||
|
||
// Validate returns an error if args is invalid. | ||
func (args *ScraperControllerArguments) Validate() error { | ||
if args.CollectionInterval <= 0 { | ||
return fmt.Errorf(`"collection_interval": %w`, errNonPositiveInterval) | ||
} | ||
if args.Timeout < 0 { | ||
return fmt.Errorf(`"timeout": %w`, errNonPositiveInterval) | ||
} | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Package vcenter provides an otelcol.receiver.vcenter component. | ||
package vcenter | ||
|
||
import ( | ||
"fmt" | ||
"net/url" | ||
|
||
"github.com/grafana/agent/component" | ||
"github.com/grafana/agent/component/otelcol" | ||
"github.com/grafana/agent/component/otelcol/receiver" | ||
otel_service "github.com/grafana/agent/service/otel" | ||
"github.com/grafana/river/rivertypes" | ||
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver" | ||
otelcomponent "go.opentelemetry.io/collector/component" | ||
"go.opentelemetry.io/collector/config/configopaque" | ||
otelextension "go.opentelemetry.io/collector/extension" | ||
) | ||
|
||
func init() { | ||
component.Register(component.Registration{ | ||
Name: "otelcol.receiver.vcenter", | ||
Args: Arguments{}, | ||
NeedsServices: []string{otel_service.ServiceName}, | ||
|
||
Build: func(opts component.Options, args component.Arguments) (component.Component, error) { | ||
fact := vcenterreceiver.NewFactory() | ||
return receiver.New(opts, fact, args.(Arguments)) | ||
}, | ||
}) | ||
} | ||
|
||
// Arguments configures the otelcol.receiver.vcenter component. | ||
type Arguments struct { | ||
Endpoint string `river:"endpoint,attr"` | ||
Username string `river:"username,attr"` | ||
Password rivertypes.Secret `river:"password,attr"` | ||
|
||
ScraperControllerArguments otelcol.ScraperControllerArguments `river:",squash"` | ||
TLS otelcol.TLSClientArguments `river:"tls,block,optional"` | ||
|
||
// DebugMetrics configures component internal metrics. Optional. | ||
DebugMetrics otelcol.DebugMetricsArguments `river:"debug_metrics,block,optional"` | ||
|
||
// Output configures where to send received data. Required. | ||
Output *otelcol.ConsumerArguments `river:"output,block"` | ||
} | ||
|
||
var _ receiver.Arguments = Arguments{} | ||
|
||
var ( | ||
// DefaultArguments holds default values for Arguments. | ||
DefaultArguments = Arguments{ | ||
ScraperControllerArguments: otelcol.DefaultScraperControllerArguments, | ||
} | ||
ptodev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
// SetToDefault implements river.Defaulter. | ||
func (args *Arguments) SetToDefault() { | ||
*args = DefaultArguments | ||
} | ||
|
||
// Convert implements receiver.Arguments. | ||
func (args Arguments) Convert() (otelcomponent.Config, error) { | ||
return &vcenterreceiver.Config{ | ||
TLSClientSetting: *args.TLS.Convert(), | ||
ScraperControllerSettings: *args.ScraperControllerArguments.Convert(), | ||
Endpoint: args.Endpoint, | ||
Username: args.Username, | ||
Password: configopaque.String(args.Password), | ||
}, nil | ||
} | ||
|
||
// Validate checks to see if the supplied config will work for the receiver | ||
func (args Arguments) Validate() error { | ||
res, err := url.Parse(args.Endpoint) | ||
if err != nil { | ||
return fmt.Errorf("unable to parse url %s: %w", args.Endpoint, err) | ||
} | ||
|
||
if res.Scheme != "http" && res.Scheme != "https" { | ||
return fmt.Errorf("url scheme must be http or https") | ||
} | ||
return nil | ||
} | ||
|
||
// Extensions implements receiver.Arguments. | ||
func (args Arguments) Extensions() map[otelcomponent.ID]otelextension.Extension { | ||
return nil | ||
} | ||
|
||
// Exporters implements receiver.Arguments. | ||
func (args Arguments) Exporters() map[otelcomponent.DataType]map[otelcomponent.ID]otelcomponent.Component { | ||
return nil | ||
} | ||
|
||
// NextConsumers implements receiver.Arguments. | ||
func (args Arguments) NextConsumers() *otelcol.ConsumerArguments { | ||
return args.Output | ||
} | ||
|
||
// DebugMetricsConfig implements receiver.Arguments. | ||
func (args Arguments) DebugMetricsConfig() otelcol.DebugMetricsArguments { | ||
return args.DebugMetrics | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package vcenter | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/grafana/river" | ||
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestArguments_UnmarshalRiver(t *testing.T) { | ||
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. For unmarshal tests, I personally prefer the table driven approach. It allows you to add lots of tests with minimal overhead. For example, I'd use the If none of the config structs are internal, I'd go for specifying the OTel structs directly: |
||
in := ` | ||
endpoint = "http://localhost:1234" | ||
username = "user" | ||
password = "pass" | ||
collection_interval = "2m" | ||
|
||
output { /* no-op */ } | ||
` | ||
|
||
var args Arguments | ||
require.NoError(t, river.Unmarshal([]byte(in), &args)) | ||
args.Convert() | ||
ext, err := args.Convert() | ||
require.NoError(t, err) | ||
otelArgs, ok := (ext).(*vcenterreceiver.Config) | ||
|
||
require.True(t, ok) | ||
|
||
require.Equal(t, "user", otelArgs.Username) | ||
require.Equal(t, "pass", string(otelArgs.Password)) | ||
require.Equal(t, "http://localhost:1234", otelArgs.Endpoint) | ||
|
||
require.Equal(t, 2*time.Minute, otelArgs.ScraperControllerSettings.CollectionInterval) | ||
require.Equal(t, time.Second, otelArgs.ScraperControllerSettings.InitialDelay) | ||
require.Equal(t, 0*time.Second, otelArgs.ScraperControllerSettings.Timeout) | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
--- | ||
aliases: | ||
- /docs/grafana-cloud/agent/flow/reference/components/otelcol.receiver.vcenter/ | ||
- /docs/grafana-cloud/monitor-infrastructure/agent/flow/reference/components/otelcol.receiver.vcenter/ | ||
- /docs/grafana-cloud/monitor-infrastructure/integrations/agent/flow/reference/components/otelcol.receiver.vcenter/ | ||
canonical: https://grafana.com/docs/agent/latest/flow/reference/components/otelcol.receiver.vcenter/ | ||
title: otelcol.receiver.vcenter | ||
marctc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
description: Learn about otelcol.receiver.vcenter | ||
--- | ||
|
||
# otelcol.receiver.vcenter | ||
|
||
`otelcol.receiver.vcenter` accepts metrics from a | ||
vCenter or ESXi host running VMware vSphere APIs and | ||
forwards it to other `otelcol.*` components. | ||
|
||
> **NOTE**: `otelcol.receiver.vcenter` is a wrapper over the upstream | ||
> OpenTelemetry Collector `vcenter` receiver from the `otelcol-contrib` | ||
> distribution. Bug reports or feature requests will be redirected to the | ||
> upstream repository, if necessary. | ||
|
||
Multiple `otelcol.receiver.vcenter` components can be specified by giving them | ||
different labels. | ||
|
||
Make sure that you fulfill the [prerequisites](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/receiver/vcenterreceiver/README.md#prerequisites) before using this component. | ||
marctc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The full list of metrics that can be collected can be found [here](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/receiver/vcenterreceiver/documentation.md) | ||
marctc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Usage | ||
|
||
```river | ||
otelcol.receiver.vcenter "LABEL" { | ||
endpoint = "VCENTER_ENDPOINT" | ||
username = "VCENTER_USERNAME" | ||
password = "VCENTER_PASSWORD" | ||
|
||
output { | ||
metrics = [...] | ||
} | ||
} | ||
``` | ||
|
||
## Arguments | ||
|
||
`otelcol.receiver.vcenter` supports the following arguments: | ||
|
||
|
||
Name | Type | Description | Default | Required | ||
---- | ---- | ----------- | ------- | -------- | ||
`endpoint` | `string` | Endpoint to a vCenter Server or ESXi host which has the SDK path enabled. | | yes | ||
`username` | `string` | Username to use for authentication. | | yes | ||
`password` | `string` | Password to use for authentication. | | yes | ||
`collection_interval` | `duration` | Defines how often to collect metrics. | `"1m"` | no | ||
`initial_delay` | `duration` | Defines how long this receiver waits before starting. | `"1s"` | no | ||
`timeout` | `duration` | Defines the timeout for the underlying HTTP client. | `"0s"` | no | ||
|
||
`endpoint` has the format `<protocol>://<hostname>`. For example, `https://vcsa.hostname.localnet`. | ||
|
||
## Blocks | ||
marctc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The following blocks are supported inside the definition of | ||
`otelcol.receiver.vcenter`: | ||
|
||
Hierarchy | Block | Description | Required | ||
--------- | ----- | ----------- | -------- | ||
tls | [tls][] | Configures TLS for the HTTP client. | no | ||
debug_metrics | [debug_metrics][] | Configures the metrics that this component generates to monitor its state. | no | ||
output | [output][] | Configures where to send received telemetry data. | yes | ||
|
||
[tls]: #tls-block | ||
[debug_metrics]: #debug_metrics-block | ||
[output]: #output-block | ||
|
||
### tls block | ||
|
||
The `tls` block configures TLS settings used for a server. If the `tls` block | ||
isn't provided, TLS won't be used for connections to the server. | ||
|
||
{{< docs/shared lookup="flow/reference/components/otelcol-tls-config-block.md" source="agent" version="<AGENT VERSION>" >}} | ||
|
||
### debug_metrics block | ||
|
||
{{< docs/shared lookup="flow/reference/components/otelcol-debug-metrics-block.md" source="agent" version="<AGENT VERSION>" >}} | ||
|
||
### output block | ||
|
||
{{< docs/shared lookup="flow/reference/components/output-block.md" source="agent" version="<AGENT VERSION>" >}} | ||
|
||
## Exported fields | ||
|
||
`otelcol.receiver.vcenter` does not export any fields. | ||
|
||
## Component health | ||
|
||
`otelcol.receiver.vcenter` is only reported as unhealthy if given an invalid | ||
configuration. | ||
|
||
## Debug information | ||
|
||
`otelcol.receiver.vcenter` does not expose any component-specific debug | ||
information. | ||
|
||
## Example | ||
|
||
This example forwards received telemetry data through a batch processor before | ||
finally sending it to an OTLP-capable endpoint: | ||
|
||
```river | ||
otelcol.receiver.vcenter "default" { | ||
endpoint = "http://localhost:15672" | ||
username = "otelu" | ||
password = "password" | ||
|
||
output { | ||
metrics = [otelcol.processor.batch.default.input] | ||
logs = [otelcol.processor.batch.default.input] | ||
traces = [otelcol.processor.batch.default.input] | ||
} | ||
} | ||
|
||
otelcol.processor.batch "default" { | ||
output { | ||
metrics = [otelcol.exporter.otlp.default.input] | ||
logs = [otelcol.exporter.otlp.default.input] | ||
traces = [otelcol.exporter.otlp.default.input] | ||
} | ||
} | ||
|
||
otelcol.exporter.otlp "default" { | ||
client { | ||
endpoint = env("OTLP_ENDPOINT") | ||
} | ||
} |
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.
Seems like "timeout" can be 0, whereas "collection interval" cannot? In that case the error message for timeout should be a bit different, to say the value should not be negative?