Skip to content

Commit

Permalink
flow: add a prometheus.exporter.cadvisor component (#5307)
Browse files Browse the repository at this point in the history
Signed-off-by: Paschalis Tsilias <[email protected]>
Signed-off-by: erikbaranowski <[email protected]>
Co-authored-by: Mischa Thompson <[email protected]>
Co-authored-by: Clayton Cornell <[email protected]>
Co-authored-by: erikbaranowski <[email protected]>
  • Loading branch information
4 people authored Oct 4, 2023
1 parent 04c013d commit 2fd6eb6
Show file tree
Hide file tree
Showing 16 changed files with 453 additions and 154 deletions.
23 changes: 12 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ Main (unreleased)

- New Grafana Agent Flow components:

- `otelcol.connector.spanlogs` creates logs from spans. It is the flow mode equivalent
to static mode's `automatic_logging` processor. (@ptodev)
- `otelcol.connector.servicegraph` creates service graph metrics from spans. It is the
flow mode equivalent to static mode's `service_graphs` processor. (@ptodev)
- `otelcol.processor.k8sattributes` adds Kubernetes metadata as resource attributes
to spans, logs, and metrics. (@acr92)
- `discovery.consulagent` discovers scrape targets from Consul Agent. (@wildum)
- `discovery.kuma` discovers scrape targets from the Kuma control plane. (@tpaschalis)
- `discovery.linode` discovers scrape targets from the Linode API. (@captncraig)
Expand All @@ -46,16 +40,23 @@ Main (unreleased)
- `discovery.serverset` discovers Serversets stored in Zookeeper. (@thampiotr)
- `discovery.scaleway` discovers scrape targets from Scaleway virtual
instances and bare-metal machines. (@rfratto)
- `prometheus.exporter.azure` collects metrics from Azure. (@wildum)
- `discovery.dockerswarm` discovers scrape targets from Docker Swarm. (@wildum)
- `otelcol.connector.servicegraph` creates service graph metrics from spans. It is the
flow mode equivalent to static mode's `service_graphs` processor. (@ptodev)
- `otelcol.connector.spanlogs` creates logs from spans. It is the flow mode equivalent
to static mode's `automatic_logging` processor. (@ptodev)
- `otelcol.processor.k8sattributes` adds Kubernetes metadata as resource attributes
to spans, logs, and metrics. (@acr92)
- `otelcol.processor.probabilistic_sampler` samples logs and traces based on configuration options. (@mar4uk)
- `remote.kubernetes.configmap` loads a configmap's data for use in other components (@captncraig)
- `remote.kubernetes.secret` loads a secret's data for use in other components (@captncraig)
- `prometheus.exporter.agent` - scrape agent's metrics. (@hainenber)
- `prometheus.exporter.vsphere` - scrape vmware vsphere metrics. (@marctc)
- `otelcol.processor.transform` transforms OTLP telemetry data using the
OpenTelemetry Transformation Language (OTTL). It is most commonly used
for transformations on attributes.
- `remote.kubernetes.configmap` loads a configmap's data for use in other components (@captncraig)
- `remote.kubernetes.secret` loads a secret's data for use in other components (@captncraig)
- `prometheus.exporter.agent` exposes the agent's internal metrics. (@hainenber)
- `prometheus.exporter.azure` collects metrics from Azure. (@wildum)
- `prometheus.exporter.cadvisor` exposes cAdvisor metrics. (@tpaschalis)
- `prometheus.exporter.vsphere` exposes vmware vsphere metrics. (@marctc)

- Flow: allow the HTTP server to be configured with TLS in the config file
using the new `http` config block. (@rfratto)
Expand Down
1 change: 1 addition & 0 deletions component/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ import (
_ "github.com/grafana/agent/component/prometheus/exporter/apache" // Import prometheus.exporter.apache
_ "github.com/grafana/agent/component/prometheus/exporter/azure" // Import prometheus.exporter.azure
_ "github.com/grafana/agent/component/prometheus/exporter/blackbox" // Import prometheus.exporter.blackbox
_ "github.com/grafana/agent/component/prometheus/exporter/cadvisor" // Import prometheus.exporter.cadvisor
_ "github.com/grafana/agent/component/prometheus/exporter/cloudwatch" // Import prometheus.exporter.cloudwatch
_ "github.com/grafana/agent/component/prometheus/exporter/consul" // Import prometheus.exporter.consul
_ "github.com/grafana/agent/component/prometheus/exporter/dnsmasq" // Import prometheus.exporter.dnsmasq
Expand Down
109 changes: 109 additions & 0 deletions component/prometheus/exporter/cadvisor/cadvisor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package cadvisor

import (
"time"

"github.com/grafana/agent/component"
"github.com/grafana/agent/component/prometheus/exporter"
"github.com/grafana/agent/pkg/integrations"
"github.com/grafana/agent/pkg/integrations/cadvisor"
)

func init() {
component.Register(component.Registration{
Name: "prometheus.exporter.cadvisor",
Args: Arguments{},
Exports: exporter.Exports{},
NeedsServices: exporter.RequiredServices(),
Build: exporter.New(createExporter, "cadvisor"),
})
}

func createExporter(opts component.Options, args component.Arguments, defaultInstanceKey string) (integrations.Integration, string, error) {
a := args.(Arguments)
return integrations.NewIntegrationWithInstanceKey(opts.Logger, a.Convert(), defaultInstanceKey)
}

// DefaultArguments holds non-zero default options for Arguments when it is
// unmarshaled from river.
var DefaultArguments = Arguments{
StoreContainerLabels: true,
AllowlistedContainerLabels: []string{""},
EnvMetadataAllowlist: []string{""},
RawCgroupPrefixAllowlist: []string{""},
ResctrlInterval: 0,
StorageDuration: 2 * time.Minute,

ContainerdHost: "/run/containerd/containerd.sock",
ContainerdNamespace: "k8s.io",

// TODO(@tpaschalis) Do we need the default cert/key/ca since tls is disabled by default?
DockerHost: "unix:///var/run/docker.sock",
UseDockerTLS: false,
DockerTLSCert: "cert.pem",
DockerTLSKey: "key.pem",
DockerTLSCA: "ca.pem",

DockerOnly: false,
}

// Arguments configures the prometheus.exporter.cadvisor component.
type Arguments struct {
StoreContainerLabels bool `river:"store_container_labels,attr,optional"`
AllowlistedContainerLabels []string `river:"allowlisted_container_labels,attr,optional"`
EnvMetadataAllowlist []string `river:"env_metadata_allowlist,attr,optional"`
RawCgroupPrefixAllowlist []string `river:"raw_cgroup_prefix_allowlist,attr,optional"`
PerfEventsConfig string `river:"perf_events_config,attr,optional"`
ResctrlInterval time.Duration `river:"resctrl_interval,attr,optional"`
DisabledMetrics []string `river:"disabled_metrics,attr,optional"`
EnabledMetrics []string `river:"enabled_metrics,attr,optional"`
StorageDuration time.Duration `river:"storage_duration,attr,optional"`
ContainerdHost string `river:"containerd_host,attr,optional"`
ContainerdNamespace string `river:"containerd_namespace,attr,optional"`
DockerHost string `river:"docker_host,attr,optional"`
UseDockerTLS bool `river:"use_docker_tls,attr,optional"`
DockerTLSCert string `river:"docker_tls_cert,attr,optional"`
DockerTLSKey string `river:"docker_tls_key,attr,optional"`
DockerTLSCA string `river:"docker_tls_ca,attr,optional"`
DockerOnly bool `river:"docker_only,attr,optional"`
}

// SetToDefault implements river.Defaulter.
func (a *Arguments) SetToDefault() {
*a = DefaultArguments
}

// Convert returns the upstream-compatible configuration struct.
func (a *Arguments) Convert() *cadvisor.Config {
if len(a.AllowlistedContainerLabels) == 0 {
a.AllowlistedContainerLabels = []string{""}
}
if len(a.RawCgroupPrefixAllowlist) == 0 {
a.RawCgroupPrefixAllowlist = []string{""}
}
if len(a.EnvMetadataAllowlist) == 0 {
a.EnvMetadataAllowlist = []string{""}
}

cfg := &cadvisor.Config{
StoreContainerLabels: a.StoreContainerLabels,
AllowlistedContainerLabels: a.AllowlistedContainerLabels,
EnvMetadataAllowlist: a.EnvMetadataAllowlist,
RawCgroupPrefixAllowlist: a.RawCgroupPrefixAllowlist,
PerfEventsConfig: a.PerfEventsConfig,
ResctrlInterval: int64(a.ResctrlInterval), // TODO(@tpaschalis) This is so that the cadvisor package can re-cast back to time.Duration. Can we make it use time.Duration directly instead?
DisabledMetrics: a.DisabledMetrics,
EnabledMetrics: a.EnabledMetrics,
StorageDuration: a.StorageDuration,
Containerd: a.ContainerdHost,
ContainerdNamespace: a.ContainerdNamespace,
Docker: a.DockerHost,
DockerTLS: a.UseDockerTLS,
DockerTLSCert: a.DockerTLSCert,
DockerTLSKey: a.DockerTLSKey,
DockerTLSCA: a.DockerTLSCA,
DockerOnly: a.DockerOnly,
}

return cfg
}
95 changes: 95 additions & 0 deletions component/prometheus/exporter/cadvisor/cadvisor_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package cadvisor

import (
"testing"
"time"

"github.com/grafana/agent/pkg/integrations/cadvisor"
"github.com/grafana/river"
"github.com/stretchr/testify/require"
)

func TestUnmarshalRiver(t *testing.T) {
riverCfg := `
store_container_labels = true
allowlisted_container_labels = ["label1", "label2"]
env_metadata_allowlist = ["env1", "env2"]
raw_cgroup_prefix_allowlist = ["prefix1", "prefix2"]
perf_events_config = "perf_events_config"
resctrl_interval = "1s"
disabled_metrics = ["metric1", "metric2"]
enabled_metrics = ["metric3", "metric4"]
storage_duration = "2s"
containerd_host = "containerd_host"
containerd_namespace = "containerd_namespace"
docker_host = "docker_host"
use_docker_tls = true
docker_tls_cert = "docker_tls_cert"
docker_tls_key = "docker_tls_key"
docker_tls_ca = "docker_tls_ca"
`
var args Arguments
err := river.Unmarshal([]byte(riverCfg), &args)
require.NoError(t, err)
expected := Arguments{
StoreContainerLabels: true,
AllowlistedContainerLabels: []string{"label1", "label2"},
EnvMetadataAllowlist: []string{"env1", "env2"},
RawCgroupPrefixAllowlist: []string{"prefix1", "prefix2"},
PerfEventsConfig: "perf_events_config",
ResctrlInterval: 1 * time.Second,
DisabledMetrics: []string{"metric1", "metric2"},
EnabledMetrics: []string{"metric3", "metric4"},
StorageDuration: 2 * time.Second,
ContainerdHost: "containerd_host",
ContainerdNamespace: "containerd_namespace",
DockerHost: "docker_host",
UseDockerTLS: true,
DockerTLSCert: "docker_tls_cert",
DockerTLSKey: "docker_tls_key",
DockerTLSCA: "docker_tls_ca",
}
require.Equal(t, expected, args)
}

func TestConvert(t *testing.T) {
args := Arguments{
StoreContainerLabels: true,
AllowlistedContainerLabels: []string{"label1", "label2"},
EnvMetadataAllowlist: []string{"env1", "env2"},
RawCgroupPrefixAllowlist: []string{"prefix1", "prefix2"},
PerfEventsConfig: "perf_events_config",
ResctrlInterval: 1 * time.Second,
DisabledMetrics: []string{"metric1", "metric2"},
EnabledMetrics: []string{"metric3", "metric4"},
StorageDuration: 2 * time.Second,
ContainerdHost: "containerd_host",
ContainerdNamespace: "containerd_namespace",
DockerHost: "docker_host",
UseDockerTLS: true,
DockerTLSCert: "docker_tls_cert",
DockerTLSKey: "docker_tls_key",
DockerTLSCA: "docker_tls_ca",
}

res := args.Convert()
expected := &cadvisor.Config{
StoreContainerLabels: true,
AllowlistedContainerLabels: []string{"label1", "label2"},
EnvMetadataAllowlist: []string{"env1", "env2"},
RawCgroupPrefixAllowlist: []string{"prefix1", "prefix2"},
PerfEventsConfig: "perf_events_config",
ResctrlInterval: int64(1 * time.Second),
DisabledMetrics: []string{"metric1", "metric2"},
EnabledMetrics: []string{"metric3", "metric4"},
StorageDuration: 2 * time.Second,
Containerd: "containerd_host",
ContainerdNamespace: "containerd_namespace",
Docker: "docker_host",
DockerTLS: true,
DockerTLSCert: "docker_tls_cert",
DockerTLSKey: "docker_tls_key",
DockerTLSCA: "docker_tls_ca",
}
require.Equal(t, expected, res)
}
3 changes: 3 additions & 0 deletions converter/internal/staticconvert/internal/build/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/grafana/agent/pkg/integrations/apache_http"
"github.com/grafana/agent/pkg/integrations/azure_exporter"
"github.com/grafana/agent/pkg/integrations/blackbox_exporter"
"github.com/grafana/agent/pkg/integrations/cadvisor"
"github.com/grafana/agent/pkg/integrations/cloudwatch_exporter"
int_config "github.com/grafana/agent/pkg/integrations/config"
"github.com/grafana/agent/pkg/integrations/consul_exporter"
Expand Down Expand Up @@ -126,6 +127,8 @@ func (b *IntegrationsV1ConfigBuilder) appendIntegrations() {
exports = b.appendWindowsExporter(itg)
case *azure_exporter.Config:
exports = b.appendAzureExporter(itg)
case *cadvisor.Config:
exports = b.appendCadvisorExporter(itg)
}

if len(exports.Targets) > 0 {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package build

import (
"fmt"
"time"

"github.com/grafana/agent/component/discovery"
"github.com/grafana/agent/component/prometheus/exporter/cadvisor"
"github.com/grafana/agent/converter/internal/common"
"github.com/grafana/agent/converter/internal/prometheusconvert"
cadvisor_integration "github.com/grafana/agent/pkg/integrations/cadvisor"
)

func (b *IntegrationsV1ConfigBuilder) appendCadvisorExporter(config *cadvisor_integration.Config) discovery.Exports {
args := toCadvisorExporter(config)
compLabel := common.LabelForParts(b.globalCtx.LabelPrefix, config.Name())
b.f.Body().AppendBlock(common.NewBlockWithOverride(
[]string{"prometheus", "exporter", "cadvisor"},
compLabel,
args,
))

return prometheusconvert.NewDiscoveryExports(fmt.Sprintf("prometheus.exporter.cadvisor.%s.targets", compLabel))
}

func toCadvisorExporter(config *cadvisor_integration.Config) *cadvisor.Arguments {
return &cadvisor.Arguments{

StoreContainerLabels: config.StoreContainerLabels,
AllowlistedContainerLabels: config.AllowlistedContainerLabels,
EnvMetadataAllowlist: config.EnvMetadataAllowlist,
RawCgroupPrefixAllowlist: config.RawCgroupPrefixAllowlist,
PerfEventsConfig: config.PerfEventsConfig,
ResctrlInterval: time.Duration(config.ResctrlInterval),
DisabledMetrics: config.DisabledMetrics,
EnabledMetrics: config.EnabledMetrics,
StorageDuration: config.StorageDuration,
ContainerdHost: config.Containerd,
ContainerdNamespace: config.ContainerdNamespace,
DockerHost: config.Docker,
UseDockerTLS: config.DockerTLS,
DockerTLSCert: config.DockerTLSCert,
DockerTLSKey: config.DockerTLSKey,
DockerTLSCA: config.DockerTLSCA,
DockerOnly: config.DockerOnly,
}
}
21 changes: 17 additions & 4 deletions converter/internal/staticconvert/testdata/integrations.river
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,9 @@ prometheus.scrape "integrations_snmp" {
}

prometheus.exporter.azure "integrations_azure_exporter" {
subscriptions = ["subId"]
resource_type = "Microsoft.Dashboard/grafana"
metrics = ["HttpRequestCount"]
included_resource_tags = ["owner"]
subscriptions = ["subId"]
resource_type = "Microsoft.Dashboard/grafana"
metrics = ["HttpRequestCount"]
}

prometheus.scrape "integrations_azure_exporter" {
Expand All @@ -91,6 +90,20 @@ prometheus.scrape "integrations_azure_exporter" {
}
}

prometheus.exporter.cadvisor "integrations_cadvisor" { }

prometheus.scrape "integrations_cadvisor" {
targets = prometheus.exporter.cadvisor.integrations_cadvisor.targets
forward_to = [prometheus.remote_write.integrations.receiver]
job_name = "integrations/cadvisor"

tls_config {
ca_file = "/something7.cert"
cert_file = "/something8.cert"
key_file = "/something9.cert"
}
}

prometheus.exporter.cloudwatch "integrations_cloudwatch_exporter" {
sts_region = "us-east-2"
fips_disabled = false
Expand Down
2 changes: 2 additions & 0 deletions converter/internal/staticconvert/testdata/integrations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,5 @@ integrations:
resource_type: "Microsoft.Dashboard/grafana"
metrics:
- "HttpRequestCount"
cadvisor:
enabled: true
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
(Error) unsupported prefer_server_cipher_suites server config was provided.
(Error) unsupported wal_directory metrics config was provided. use the run command flag --storage.path for Flow mode instead.
(Error) unsupported integration agent was provided.
(Error) unsupported integration cadvisor was provided.
(Warning) disabled integrations do nothing and are not included in the output: node_exporter.
(Error) unsupported traces config was provided.
(Error) unsupported agent_management config was provided.
4 changes: 1 addition & 3 deletions converter/internal/staticconvert/testdata/unsupported.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ metrics:
integrations:
agent:
enabled: true
cadvisor:
enabled: true
mssql:
enabled: true
scrape_integration: false
Expand Down Expand Up @@ -61,4 +59,4 @@ logs:
- name: log_config

agent_management:
host: host_name
host: host_name
Loading

0 comments on commit 2fd6eb6

Please sign in to comment.