diff --git a/modules/integrations/agent/README.md b/modules/integrations/agent/README.md new file mode 100644 index 0000000..bac08b7 --- /dev/null +++ b/modules/integrations/agent/README.md @@ -0,0 +1,168 @@ +# Agent Module + +Handles scraping Grafana Agent metrics. + +## Components + +- [kubernetes](#kubernetes) +- [local](#local) +- [scrape](#scrape) + +### kubernetes + +Handles discovery of kubernetes targets and exports them, this component does not perform any scraping at all and is not required to be used for kubernetes, as a custom service discovery and targets can be defined and passed to `agent.scrape` + +#### Arguments + +| Name | Required | Default | Description | +| :----------- | :------- | :----------------------------------------- | :---------- | +| `namespaces` | _no_ | `[]` | The namespaces to look for targets in, the default (`[]`) is all namespaces | +| `selectors` | _no_ | `["app.kubernetes.io/name=grafana-agent"]` | The label selectors to use to find matching targets | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `app` | Derived from the pod label value of `app.kubernetes.io/name`, `k8s-app`, or `app` | +| `component` | Derived from the pod label value of `app.kubernetes.io/component`, `k8s-component`, or `component | +| `container` | The name of the container, usually `haproxy` | +| `namespace` | The namespace the target was found in. | +| `pod` | The full name of the pod | +| `source` | Constant value of `kubernetes`, denoting where the results came from, this can be useful for LBAC | +| `workload` | Kubernetes workload, a combination of `__meta_kubernetes_pod_controller_kind` and `__meta_kubernetes_pod_controller_name`, i.e. `ReplicaSet/my-app` | +--- + +### local + +#### Arguments + +| Name | Optional | Default | Description | +| :----- | :------- | :------ | :------------------------------------- | +| `port` | `true` | `12345` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :------------------------- | +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :------- | :------------------------------------------------------------------------------------------- | +| `source` | Constant value of `local`, denoting where the results came from, this can be useful for LBAC | + +--- + +### scrape + +#### Arguments + +| Name | Required | Default | Description | +| :---------------- | :------- | :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `targets` | _yes_ | `list(map(string))` | List of targets to scrape | +| `forward_to` | _yes_ | `list(MetricsReceiver)` | Must be a where scraped should be forwarded to | +| `job_label` | _no_ | `integrations/agent` | The job label to add for all mimir metric | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | +| `keep_metrics` | _no_ | [see code](module.river#L228) | A regex of metrics to keep | +| `drop_metrics` | _no_ | [see code](module.river#L235) | A regex of metrics to drop | +| `scrape_interval` | _no_ | `60s` | How often to scrape metrics from the targets | +| `scrape_timeout` | _no_ | `10s` | How long before a scrape times out | +| `max_cache_size` | _no_ | `100000` | The maximum number of elements to hold in the relabeling cache. This should be at least 2x-5x your largest scrape target or samples appended rate. | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---- | :--------------------------------------------- | +| `job` | Set to the value of `argument.job_label.value` | + +--- + +## Usage + +### Kubernetes + +The following example will scrape all agents in cluster. + +```river +import.git "agent" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/agent/module.river" + pull_frequency = "15m" +} + +// get the targets +agent.kubernetes "targets" {} + +// scrape the targets +agent.scrape "metrics" { + targets = agent.kubernetes.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "local_primary" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` + +### Local + +The following example will scrape the agent for metrics on the local machine. + +```river +import.git "agent" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/agent/module.river" + pull_frequency = "15m" +} + +// get the targets +agent.local "targets" {} + +// scrape the targets +agent.scrape "metrics" { + targets = agent.local.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "default" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` diff --git a/modules/integrations/agent/metrics.river b/modules/integrations/agent/metrics.river new file mode 100644 index 0000000..10ab4e8 --- /dev/null +++ b/modules/integrations/agent/metrics.river @@ -0,0 +1,304 @@ +/* +Module: job-agent +Description: Scrapes grafana agent + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ +declare "kubernetes" { + // arguments for kubernetes discovery + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"app.kubernetes.io/name=grafana-agent\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: http-metrics)" + optional = true + } + + // grafana agent service discovery for all of the pods + discovery.kubernetes "agent" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.field_selectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app.kubernetes.io/name=grafana-agent"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // grafana agent relabelings (pre-scrape) + discovery.relabel "kubernetes" { + targets = discovery.kubernetes.agent.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "metrics") + "@Running@true@false" + action = "keep" + } + + // set the namespace label + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + // set the pod label + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + // set the container label + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + // set a workload label + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.kubernetes.output + } +} + +declare "local" { + + argument "port_name" { + comment = "The port to use (default: 12345)" + optional = true + } + + // arguments for local (static) + discovery.relabel "local" { + targets = [ + { + "__address__" = "localhost" + format("%s", coalesce(argument.port.value, "12345")), + "source" = "local", + }, + ] + } + + export "output" { + value = discovery.relabel.local.output + } +} + +declare "scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all grafana-agent metric (default: integrations/agent)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // grafana agent scrape job + prometheus.scrape "agent" { + job_name = coalesce(argument.job_label.value, "integrations/agent") + forward_to = [prometheus.relabel.agent.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // grafana-agent metric relabelings (post-scrape) + prometheus.relabel "agent" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(up|log_.+|(agent_(build_info|tcp_connections|wal_(samples_appended_total|storage_active_series))|go_(gc_duration_seconds_count|goroutines|memstats_heap_inuse_bytes)|process_(cpu_seconds_total|start_time_seconds)|prometheus_(remote_storage_(enqueue_retries_total|highest_timestamp_in_seconds|queue_highest_sent_timestamp_seconds|samples_(dropped_total|failed_total|pending|retried_total|total)|sent_batch_duration_seconds_(bucket|count|sum)|shard_(capacity|s(_desired|_max|_min))|succeeded_samples_total)|sd_discovered_targets|target_(interval_length_seconds_(count|sum)|scrapes_(exceeded_sample_limit_total|sample_(duplicate_timestamp_total|out_of_bounds_total|out_of_order_total)))|target_sync_length_seconds_sum|wal_watcher_current_segment)|traces_(exporter_send_failed_spans|exporter_sent_spans|loadbalancer_(backend_outcome|num_backends)|receiver_(accepted_spans|refused_spans))))") + action = "keep" + } + + // remove the component_id label from any metric that starts with log_bytes or log_lines, these are custom metrics that are generated + // as part of the log annotation modules in this repo + rule { + action = "replace" + source_labels = ["__name__"] + regex = "^log_(bytes|lines).+" + replacement = "" + target_label = "component_id" + } + + // set the namespace label to that of the exported_namespace + rule { + action = "replace" + source_labels = ["__name__", "exported_namespace"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "namespace" + } + + // set the pod label to that of the exported_pod + rule { + action = "replace" + source_labels = ["__name__", "exported_pod"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "pod" + } + + // set the container label to that of the exported_container + rule { + action = "replace" + source_labels = ["__name__", "exported_container"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "container" + } + + // set the job label to that of the exported_job + rule { + action = "replace" + source_labels = ["__name__", "exported_job"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "job" + } + + // set the instance label to that of the exported_instance + rule { + action = "replace" + source_labels = ["__name__", "exported_instance"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "instance" + } + + rule { + action = "labeldrop" + regex = "exported_(namespace|pod|container|job|instance)" + } + } +} diff --git a/modules/integrations/cert-manager/README.md b/modules/integrations/cert-manager/README.md new file mode 100644 index 0000000..d62bc29 --- /dev/null +++ b/modules/integrations/cert-manager/README.md @@ -0,0 +1,168 @@ +# Memcached Module + +Handles scraping Memcached metrics. + +## Components + +- [kubernetes](#kubernetes) +- [local](#local) +- [scrape](#scrape) + +### kubernetes + +Handles discovery of kubernetes targets and exports them, this component does not perform any scraping at all and is not required to be used for kubernetes, as a custom service discovery and targets can be defined and passed to `cert_manager.scrape` + +#### Arguments + +| Name | Required | Default | Description | +| :----------- | :------- | :---------------------------------------- | :-------------------------------------------------------------------------- | +| `namespaces` | _no_ | `[]` | The namespaces to look for targets in, the default (`[]`) is all namespaces | +| `selectors` | _no_ | `["app.kubernetes.io/name=cert-manager"]` | The label selectors to use to find matching targets | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :------------------------- | +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `app` | Derived from the pod label value of `app.kubernetes.io/name`, `k8s-app`, or `app` | +| `component` | Derived from the pod label value of `app.kubernetes.io/component`, `k8s-component`, or `component | +| `container` | The name of the container, usually `haproxy` | +| `namespace` | The namespace the target was found in. | +| `pod` | The full name of the pod | +| `source` | Constant value of `kubernetes`, denoting where the results came from, this can be useful for LBAC | +| `workload` | Kubernetes workload, a combination of `__meta_kubernetes_pod_controller_kind` and `__meta_kubernetes_pod_controller_name`, i.e. `ReplicaSet/my-app` | + +--- + +### local + +#### Arguments + +| Name | Optional | Default | Description | +| :----- | :------- | :------ | :------------------------------------- | +| `port` | `true` | `9402` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :------- | :------------------------------------------------------------------------------------------- | +| `source` | Constant value of `local`, denoting where the results came from, this can be useful for LBAC | + +--- + +### scrape + +#### Arguments + +| Name | Required | Default | Description | +| :---------------- | :------- | :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `targets` | _yes_ | `list(map(string))` | List of targets to scrape | +| `forward_to` | _yes_ | `list(MetricsReceiver)` | Must be a where scraped should be forwarded to | +| `job_label` | _no_ | `integrations/cert-manager` | The job label to add for all mimir metric | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | +| `keep_metrics` | _no_ | [see code](module.river#L228) | A regex of metrics to keep | +| `drop_metrics` | _no_ | [see code](module.river#L235) | A regex of metrics to drop | +| `scrape_interval` | _no_ | `60s` | How often to scrape metrics from the targets | +| `scrape_timeout` | _no_ | `10s` | How long before a scrape times out | +| `max_cache_size` | _no_ | `100000` | The maximum number of elements to hold in the relabeling cache. This should be at least 2x-5x your largest scrape target or samples appended rate. | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---- | :-----------| +| `job` | Set to the value of `argument.job_label.value` | + +--- + +## Usage + +### Kubernetes + +The following example will scrape all cert_manager instances in cluster. + +```river +import.git "cert_manager" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/cert_manager/module.river" + pull_frequency = "15m" +} + +// get the targets +cert_manager.kubernetes "targets" {} + +// scrape the targets +cert_manager.scrape "metrics" { + targets = cert_manager.kubernetes.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "local_primary" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` + +### Local + +The following example will scrape cert_manager for metrics on the local machine. + +```river +import.git "cert_manager" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/cert_manager/module.river" + pull_frequency = "15m" +} + +// get the targets +cert_manager.local "targets" {} + +// scrape the targets +cert_manager.scrape "metrics" { + targets = cert_manager.local.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "default" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` diff --git a/modules/integrations/cert-manager/metrics.river b/modules/integrations/cert-manager/metrics.river new file mode 100644 index 0000000..478ba97 --- /dev/null +++ b/modules/integrations/cert-manager/metrics.river @@ -0,0 +1,217 @@ +/* +Module: job-cert-manager +Description: Scrapes cert-manager + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ +declare "kubernetes" { + // arguments for kubernetes discovery + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"app.kubernetes.io/name=cert-manager\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: http-metrics)" + optional = true + } + + // cert-manager service discovery for all of the pods + discovery.kubernetes "cert_manager" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.field_selectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app.kubernetes.io/name=cert-manager"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // cert-manager relabelings (pre-scrape) + discovery.relabel "kubernetes" { + targets = discovery.kubernetes.cert-manager.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "metrics") + "@Running@true@false" + action = "keep" + } + + // set the namespace label + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + // set the pod label + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + // set the container label + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + // set a workload label + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.kubernetes.output + } +} + +declare "scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all cert-manager metric (default: integrations/cert-manager)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // cert-manager scrape job + prometheus.scrape "cert_manager" { + job_name = coalesce(argument.job_label.value, "integrations/cert-manager") + forward_to = [prometheus.relabel.cert-manager.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // cert-manager metric relabelings (post-scrape) + prometheus.relabel "cert_manager" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(up|(certmanager_(certificate_(expiration_timestamp_seconds|ready_status)|clock_time_seconds|controller_sync_call_count|http_acme_client_request_(count|duration_seconds_(count|sum)))|container_(cpu_(cfs_(periods|throttled_periods)_total|usage_seconds_total)|memory_usage_bytes|network_(receive|transmit)_bytes_total)|kube_pod_container_resource_(limits|requests)_(cpu_cores|memory_bytes)))") + action = "keep" + } + } +} diff --git a/modules/integrations/consul/README.md b/modules/integrations/consul/README.md new file mode 100644 index 0000000..eb643d2 --- /dev/null +++ b/modules/integrations/consul/README.md @@ -0,0 +1,167 @@ +# Consul Module + +Handles scraping Consul metrics. + +## Components + +- [kubernetes](#kubernetes) +- [local](#local) +- [scrape](#scrape) + +### kubernetes + +Handles discovery of kubernetes targets and exports them, this component does not perform any scraping at all and is not required to be used for kubernetes, as a custom service discovery and targets can be defined and passed to `consul.scrape` + +#### Arguments + +| Name | Required | Default | Description | +| :----------- | :------- | :------------------------------------- | :-------------------------------------------------------------------------- | +| `namespaces` | _no_ | `[]` | The namespaces to look for targets in, the default (`[]`) is all namespaces | +| `selectors` | _no_ | `["app=consul"]` | The label selectors to use to find matching targets | +| `port_name` | _no_ | `metrics` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `app` | Derived from the pod label value of `app.kubernetes.io/name`, `k8s-app`, or `app` | +| `component` | Derived from the pod label value of `app.kubernetes.io/component`, `k8s-component`, or `component | +| `container` | The name of the container, usually `haproxy` | +| `namespace` | The namespace the target was found in. | +| `pod` | The full name of the pod | +| `source` | Constant value of `kubernetes`, denoting where the results came from, this can be useful for LBAC | +| `workload` | Kubernetes workload, a combination of `__meta_kubernetes_pod_controller_kind` and `__meta_kubernetes_pod_controller_name`, i.e. `ReplicaSet/my-app` | +--- + +### local + +#### Arguments + +| Name | Optional | Default | Description | +| :----- | :------- | :------ | :------------------------------------- | +| `port` | `true` | `20200` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :------- | :------------------------------------------------------------------------------------------- | +| `source` | Constant value of `local`, denoting where the results came from, this can be useful for LBAC | + +--- + +### scrape + +#### Arguments + +| Name | Required | Default | Description | +| :---------------- | :------- | :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `targets` | _yes_ | `list(map(string))` | List of targets to scrape | +| `forward_to` | _yes_ | `list(MetricsReceiver)` | Must be a where scraped should be forwarded to | +| `job_label` | _no_ | `integrations/consul` | The job label to add for all mimir metric | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | +| `keep_metrics` | _no_ | [see code](module.river#L228) | A regex of metrics to keep | +| `drop_metrics` | _no_ | [see code](module.river#L235) | A regex of metrics to drop | +| `scrape_interval` | _no_ | `60s` | How often to scrape metrics from the targets | +| `scrape_timeout` | _no_ | `10s` | How long before a scrape times out | +| `max_cache_size` | _no_ | `100000` | The maximum number of elements to hold in the relabeling cache. This should be at least 2x-5x your largest scrape target or samples appended rate. | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---- | :-----------| +| `job` | Set to the value of `argument.job_label.value` | + +--- + +## Usage + +### Kubernetes + +The following example will scrape all consul instances in cluster. + +```river +import.git "consul" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/consul/module.river" + pull_frequency = "15m" +} + +// get the targets +consul.kubernetes "targets" {} + +// scrape the targets +consul.scrape "metrics" { + targets = consul.kubernetes.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "local_primary" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` + +### Local + +The following example will scrape consul for metrics on the local machine. + +```river +import.git "consul" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/consul/module.river" + pull_frequency = "15m" +} + +// get the targets +consul.local "targets" {} + +// scrape the targets +consul.scrape "metrics" { + targets = consul.local.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "default" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` diff --git a/modules/integrations/consul/metrics.river b/modules/integrations/consul/metrics.river new file mode 100644 index 0000000..100afdd --- /dev/null +++ b/modules/integrations/consul/metrics.river @@ -0,0 +1,238 @@ +/* +Module: job-consul +Description: Scrapes consul + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ +declare "kubernetes" { + // arguments for kubernetes discovery + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"app=consul\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: metrics)" + optional = true + } + + // consul service discovery for all of the pods + discovery.kubernetes "consul" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.fieldselectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app=consul"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // consul relabelings (pre-scrape) + discovery.relabel "kubernetes" { + targets = discovery.kubernetes.consul.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "metrics") + "@Running@true@false" + action = "keep" + } + + // set the namespace label + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + // set the pod label + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + // set the container label + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + // set a workload label + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.kubernetes.output + } +} + +declare "local" { + argument "port" { + comment = "The port to use (default: 9150)" + optional = true + } + + // arguments for local (static) + discovery.relabel "local" { + targets = [ + { + "__address__" = "localhost" + format("%s", coalesce(argument.port.value, "9150")), + "source" = "local", + }, + ] + } + + export "output" { + value = discovery.relabel.local.output + } +} + +declare "scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all consul metric (default: integrations/consul)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // consul scrape job + prometheus.scrape "consul" { + job_name = coalesce(argument.job_label.value, "integrations/consul") + forward_to = [prometheus.relabel.consul.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // consul metric relabelings (post-scrape) + prometheus.relabel "consul" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(up|consul_(commands_total|connections_total|current_(bytes|connections|items)|items_(evicted_total|total)|max_connections|read_bytes_total|up|uptime_seconds|version|written_bytes_total))") + action = "keep" + } + } +} diff --git a/modules/integrations/etcd/README.md b/modules/integrations/etcd/README.md new file mode 100644 index 0000000..0caaacc --- /dev/null +++ b/modules/integrations/etcd/README.md @@ -0,0 +1,167 @@ +# Etcd Module + +Handles scraping Etcd metrics. + +## Components + +- [kubernetes](#kubernetes) +- [local](#local) +- [scrape](#scrape) + +### kubernetes + +Handles discovery of kubernetes targets and exports them, this component does not perform any scraping at all and is not required to be used for kubernetes, as a custom service discovery and targets can be defined and passed to `etcd.scrape` + +#### Arguments + +| Name | Required | Default | Description | +| :----------- | :------- | :------------------------------------- | :-------------------------------------------------------------------------- | +| `namespaces` | _no_ | `[]` | The namespaces to look for targets in, the default (`[]`) is all namespaces | +| `selectors` | _no_ | `["app.kubernetes.io/component=etcd"]` | The label selectors to use to find matching targets | +| `port_name` | _no_ | `metrics` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `app` | Derived from the pod label value of `app.kubernetes.io/name`, `k8s-app`, or `app` | +| `component` | Derived from the pod label value of `app.kubernetes.io/component`, `k8s-component`, or `component | +| `container` | The name of the container, usually `haproxy` | +| `namespace` | The namespace the target was found in. | +| `pod` | The full name of the pod | +| `source` | Constant value of `kubernetes`, denoting where the results came from, this can be useful for LBAC | +| `workload` | Kubernetes workload, a combination of `__meta_kubernetes_pod_controller_kind` and `__meta_kubernetes_pod_controller_name`, i.e. `ReplicaSet/my-app` | +--- + +### local + +#### Arguments + +| Name | Optional | Default | Description | +| :----- | :------- | :------ | :------------------------------------- | +| `port` | `true` | `2379` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :------- | :------------------------------------------------------------------------------------------- | +| `source` | Constant value of `local`, denoting where the results came from, this can be useful for LBAC | + +--- + +### scrape + +#### Arguments + +| Name | Required | Default | Description | +| :---------------- | :------- | :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `targets` | _yes_ | `list(map(string))` | List of targets to scrape | +| `forward_to` | _yes_ | `list(MetricsReceiver)` | Must be a where scraped should be forwarded to | +| `job_label` | _no_ | `integrations/etcd` | The job label to add for all mimir metric | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | +| `keep_metrics` | _no_ | [see code](module.river#L228) | A regex of metrics to keep | +| `drop_metrics` | _no_ | [see code](module.river#L235) | A regex of metrics to drop | +| `scrape_interval` | _no_ | `60s` | How often to scrape metrics from the targets | +| `scrape_timeout` | _no_ | `10s` | How long before a scrape times out | +| `max_cache_size` | _no_ | `100000` | The maximum number of elements to hold in the relabeling cache. This should be at least 2x-5x your largest scrape target or samples appended rate. | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---- | :-----------| +| `job` | Set to the value of `argument.job_label.value` | + +--- + +## Usage + +### Kubernetes + +The following example will scrape all etcd instances in cluster. + +```river +import.git "etcd" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/etcd/module.river" + pull_frequency = "15m" +} + +// get the targets +etcd.kubernetes "targets" {} + +// scrape the targets +etcd.scrape "metrics" { + targets = etcd.kubernetes.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "local_primary" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` + +### Local + +The following example will scrape etcd for metrics on the local machine. + +```river +import.git "etcd" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/etcd/module.river" + pull_frequency = "15m" +} + +// get the targets +etcd.local "targets" {} + +// scrape the targets +etcd.scrape "metrics" { + targets = etcd.local.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "default" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` diff --git a/modules/integrations/etcd/metrics.river b/modules/integrations/etcd/metrics.river new file mode 100644 index 0000000..d9298ab --- /dev/null +++ b/modules/integrations/etcd/metrics.river @@ -0,0 +1,238 @@ +/* +Module: job-etcd +Description: Scrapes etcd + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ +declare "kubernetes" { + // arguments for kubernetes discovery + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"app.kubernetes.io/component=etcd\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: metrics)" + optional = true + } + + // etcd service discovery for all of the pods + discovery.kubernetes "etcd" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.fieldselectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app.kubernetes.io/component=etcd"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // etcd relabelings (pre-scrape) + discovery.relabel "kubernetes" { + targets = discovery.kubernetes.etcd.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "metrics") + "@Running@true@false" + action = "keep" + } + + // set the namespace label + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + // set the pod label + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + // set the container label + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + // set a workload label + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.kubernetes.output + } +} + +declare "local" { + argument "port" { + comment = "The port to use (default: 9150)" + optional = true + } + + // arguments for local (static) + discovery.relabel "local" { + targets = [ + { + "__address__" = "localhost" + format("%s", coalesce(argument.port.value, "9150")), + "source" = "local", + }, + ] + } + + export "output" { + value = discovery.relabel.local.output + } +} + +declare "scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all etcd metric (default: integrations/etcd)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // etcd scrape job + prometheus.scrape "etcd" { + job_name = coalesce(argument.job_label.value, "integrations/etcd") + forward_to = [prometheus.relabel.etcd.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // etcd metric relabelings (post-scrape) + prometheus.relabel "etcd" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(up|etcd_(commands_total|connections_total|current_(bytes|connections|items)|items_(evicted_total|total)|max_connections|read_bytes_total|up|uptime_seconds|version|written_bytes_total))") + action = "keep" + } + } +} diff --git a/modules/integrations/gitlab/README.md b/modules/integrations/gitlab/README.md new file mode 100644 index 0000000..8194a01 --- /dev/null +++ b/modules/integrations/gitlab/README.md @@ -0,0 +1,166 @@ +# Gitlab Exporter Module + +Handles scraping Gitlab Exporter metrics. + +## Components + +- [kubernetes](#kubernetes) +- [local](#local) +- [scrape](#scrape) + +### kubernetes + +Handles discovery of kubernetes targets and exports them, this component does not perform any scraping at all and is not required to be used for kubernetes, as a custom service discovery and targets can be defined and passed to `gitlab.scrape` + +#### Arguments + +| Name | Required | Default | Description | +| :----------- | :------- | :-------------------------------------------------------- | :-------------------------------------------------------------------------- | +| `namespaces` | _no_ | `[]` | The namespaces to look for targets in, the default (`[]`) is all namespaces | +| `selectors` | _no_ | `["app.kubernetes.io/name=gitlab-ci-pipelines-exporter"]` | The label selectors to use to find matching targets | +| `port_name` | _no_ | `metrics` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---------- | :------------------------------------------------------------------------------------------------ | +| `app` | Derived from the pod label value of `app.kubernetes.io/name`, `k8s-app`, or `app` | +| `component` | Derived from the pod label value of `app.kubernetes.io/component`, `k8s-component`, or `component | +| `namespace` | The namespace the target was found in. | +| `service` | The full name of the service | +| `source` | Constant value of `kubernetes`, denoting where the results came from, this can be useful for LBAC | + +--- + +### local + +#### Arguments + +| Name | Optional | Default | Description | +| :----- | :------- | :------ | :------------------------------------- | +| `port` | `true` | `9168` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :------- | :------------------------------------------------------------------------------------------- | +| `source` | Constant value of `local`, denoting where the results came from, this can be useful for LBAC | + +--- + +### scrape + +#### Arguments + +| Name | Required | Default | Description | +| :---------------- | :------- | :----------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `targets` | _yes_ | `list(map(string))` | List of targets to scrape | +| `forward_to` | _yes_ | `list(MetricsReceiver)` | Must be a where scraped should be forwarded to | +| `job_label` | _no_ | `integrations/gitlab` | The job label to add for all mimir metric | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | +| `keep_metrics` | _no_ | [see code](module.river#L228) | A regex of metrics to keep | +| `drop_metrics` | _no_ | [see code](module.river#L235) | A regex of metrics to drop | +| `scrape_interval` | _no_ | `60s` | How often to scrape metrics from the targets | +| `scrape_timeout` | _no_ | `10s` | How long before a scrape times out | +| `max_cache_size` | _no_ | `100000` | The maximum number of elements to hold in the relabeling cache. This should be at least 2x-5x your largest scrape target or samples appended rate. | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---- | :-----------| +| `job` | Set to the value of `argument.job_label.value` | + +--- + +## Usage + +### Kubernetes + +The following example will scrape all gitlab instances in cluster. + +```river +import.git "gitlab" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/gitlab/module.river" + pull_frequency = "15m" +} + +// get the targets +gitlab.kubernetes "targets" {} + +// scrape the targets +gitlab.scrape "metrics" { + targets = gitlab.kubernetes.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "local_primary" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` + +### Local + +The following example will scrape gitlab for metrics on the local machine. + +```river +import.git "gitlab" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/gitlab/module.river" + pull_frequency = "15m" +} + +// get the targets +gitlab.local "targets" {} + +// scrape the targets +gitlab.scrape "metrics" { + targets = gitlab.local.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "default" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` diff --git a/modules/integrations/gitlab/metrics.river b/modules/integrations/gitlab/metrics.river new file mode 100644 index 0000000..6d2a1ae --- /dev/null +++ b/modules/integrations/gitlab/metrics.river @@ -0,0 +1,210 @@ +/* +Module: job-gitlab +Description: Scrapes gitlab + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ +declare "kubernetes" { + // arguments for kubernetes discovery + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"app.kubernetes.io/name=gitlab-ci-pipelines-exporter\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: http)" + optional = true + } + + // gitlab service discovery for all of the pods + discovery.kubernetes "gitlab" { + role = "service" + + selectors { + role = "service" + field = join(coalesce(argument.fieldselectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app.kubernetes.io/name=gitlab-ci-pipelines-exporter"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // gitlab relabelings (pre-scrape) + discovery.relabel "kubernetes" { + targets = discovery.kubernetes.gitlab.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = ["__meta_kubernetes_service_port_name"] + regex = coalesce(argument.port_name.value, "http") + action = "keep" + } + + // set the namespace label + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + // set the pod label + rule { + source_labels = ["__meta_kubernetes_service_name"] + target_label = "service" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_service_label_app_kubernetes_io_name", + "__meta_kubernetes_service_label_k8s_app", + "__meta_kubernetes_service_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_service_label_app_kubernetes_io_component", + "__meta_kubernetes_service_label_k8s_component", + "__meta_kubernetes_service_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.kubernetes.output + } +} + +declare "local" { + argument "port" { + comment = "The port to use (default: 9150)" + optional = true + } + + // arguments for local (static) + discovery.relabel "local" { + targets = [ + { + "__address__" = "localhost" + format("%s", coalesce(argument.port.value, "9168")), + "source" = "local", + }, + ] + } + + export "output" { + value = discovery.relabel.local.output + } +} + +declare "scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all gitlab metric (default: integrations/gitlab)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // gitlab scrape job + prometheus.scrape "gitlab" { + job_name = coalesce(argument.job_label.value, "integrations/gitlab") + forward_to = [prometheus.relabel.gitlab.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // gitlab metric relabelings (post-scrape) + prometheus.relabel "gitlab" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(up|(gitlab_ci_(active_jobs_sum|pipeline_size_builds_sum|runner_authentication_(failure|success)_total|trace_operations_total)|gitlab_rails_boot_time_seconds|http_request_duration_seconds_(count|sum)|http_requests_total|job_register_attempts_(failed_total|total)|pipelines_created_total|user_session_logins_total))") + action = "keep" + } + } +} diff --git a/modules/integrations/grafana/README.md b/modules/integrations/grafana/README.md new file mode 100644 index 0000000..613108a --- /dev/null +++ b/modules/integrations/grafana/README.md @@ -0,0 +1,168 @@ +# Grafana Module + +Handles scraping Grafana metrics. + +## Components + +- [kubernetes](#kubernetes) +- [local](#local) +- [scrape](#scrape) + +### kubernetes + +Handles discovery of kubernetes targets and exports them, this component does not perform any scraping at all and is not required to be used for kubernetes, as a custom service discovery and targets can be defined and passed to `grafana.scrape` + +#### Arguments + +| Name | Required | Default | Description | +| :----------- | :------- | :------------------------------------- | :-------------------------------------------------------------------------- | +| `namespaces` | _no_ | `[]` | The namespaces to look for targets in, the default (`[]`) is all namespaces | +| `selectors` | _no_ | `["app.kubernetes.io/name=grafana"]` | The label selectors to use to find matching targets | +| `port_name` | _no_ | `grafana` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `app` | Derived from the pod label value of `app.kubernetes.io/name`, `k8s-app`, or `app` | +| `component` | Derived from the pod label value of `app.kubernetes.io/component`, `k8s-component`, or `component | +| `container` | The name of the container, usually `haproxy` | +| `namespace` | The namespace the target was found in. | +| `pod` | The full name of the pod | +| `source` | Constant value of `kubernetes`, denoting where the results came from, this can be useful for LBAC | +| `workload` | Kubernetes workload, a combination of `__meta_kubernetes_pod_controller_kind` and `__meta_kubernetes_pod_controller_name`, i.e. `ReplicaSet/my-app` | + +--- + +### local + +#### Arguments + +| Name | Optional | Default | Description | +| :----- | :------- | :------ | :------------------------------------- | +| `port` | `true` | `3000` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :------- | :------------------------------------------------------------------------------------------- | +| `source` | Constant value of `local`, denoting where the results came from, this can be useful for LBAC | + +--- + +### scrape + +#### Arguments + +| Name | Required | Default | Description | +| :---------------- | :------- | :------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `targets` | _yes_ | `list(map(string))` | List of targets to scrape | +| `forward_to` | _yes_ | `list(MetricsReceiver)` | Must be a where scraped should be forwarded to | +| `job_label` | _no_ | `integrations/grafana` | The job label to add for all mimir metric | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | +| `keep_metrics` | _no_ | [see code](module.river#L228) | A regex of metrics to keep | +| `drop_metrics` | _no_ | [see code](module.river#L235) | A regex of metrics to drop | +| `scrape_interval` | _no_ | `60s` | How often to scrape metrics from the targets | +| `scrape_timeout` | _no_ | `10s` | How long before a scrape times out | +| `max_cache_size` | _no_ | `100000` | The maximum number of elements to hold in the relabeling cache. This should be at least 2x-5x your largest scrape target or samples appended rate. | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---- | :--------------------------------------------- | +| `job` | Set to the value of `argument.job_label.value` | + +--- + +## Usage + +### Kubernetes + +The following example will scrape all grafana instances in cluster. + +```river +import.git "grafana" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/grafana/module.river" + pull_frequency = "15m" +} + +// get the targets +grafana.kubernetes "targets" {} + +// scrape the targets +grafana.scrape "metrics" { + targets = grafana.kubernetes.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "local_primary" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` + +### Local + +The following example will scrape grafana for metrics on the local machine. + +```river +import.git "grafana" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/grafana/module.river" + pull_frequency = "15m" +} + +// get the targets +grafana.local "targets" {} + +// scrape the targets +grafana.scrape "metrics" { + targets = grafana.local.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "default" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` diff --git a/modules/integrations/grafana/metrics.river b/modules/integrations/grafana/metrics.river new file mode 100644 index 0000000..252e6be --- /dev/null +++ b/modules/integrations/grafana/metrics.river @@ -0,0 +1,238 @@ +/* +Module: job-grafana +Description: Scrapes grafana + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ +declare "kubernetes" { + // arguments for kubernetes discovery + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"app.kubernetes.io/name=grafana\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: grafana)" + optional = true + } + + // grafana service discovery for all of the pods + discovery.kubernetes "grafana" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.fieldselectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app.kubernetes.io/name=grafana"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // grafana relabelings (pre-scrape) + discovery.relabel "kubernetes" { + targets = discovery.kubernetes.grafana.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "grafana") + "@Running@true@false" + action = "keep" + } + + // set the namespace label + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + // set the pod label + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + // set the container label + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + // set a workload label + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.kubernetes.output + } +} + +declare "local" { + argument "port" { + comment = "The port to use (default: 3000)" + optional = true + } + + // arguments for local (static) + discovery.relabel "local" { + targets = [ + { + "__address__" = "localhost" + format("%s", coalesce(argument.port.value, "3000")), + "source" = "local", + }, + ] + } + + export "output" { + value = discovery.relabel.local.output + } +} + +declare "scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all grafana metric (default: integrations/grafana)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // grafana scrape job + prometheus.scrape "grafana" { + job_name = coalesce(argument.job_label.value, "integrations/grafana") + forward_to = [prometheus.relabel.grafana.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // grafana metric relabelings (post-scrape) + prometheus.relabel "grafana" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(.+)") + action = "keep" + } + } +} diff --git a/modules/integrations/haproxy/README.md b/modules/integrations/haproxy/README.md new file mode 100644 index 0000000..22b4f0f --- /dev/null +++ b/modules/integrations/haproxy/README.md @@ -0,0 +1,168 @@ +# HAProxy Module + +Handles scraping HAProxy metrics. + +## Components + +- [kubernetes](#kubernetes) +- [local](#local) +- [scrape](#scrape) + +### kubernetes + +Handles discovery of kubernetes targets and exports them, this component does not perform any scraping at all and is not required to be used for kubernetes, as a custom service discovery and targets can be defined and passed to `haproxy.scrape` + +#### Arguments + +| Name | Required | Default | Description | +| :----------- | :------- | :------------------------------------ | :-------------------------------------------------------------------------- | +| `namespaces` | _no_ | `[]` | The namespaces to look for targets in, the default (`[]`) is all namespaces | +| `selectors` | _no_ | `["app.kubernetes.io/name=haproxy"]` | The label selectors to use to find matching targets | +| `port_name` | _no_ | `prometheus` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `app` | Derived from the pod label value of `app.kubernetes.io/name`, `k8s-app`, or `app` | +| `component` | Derived from the pod label value of `app.kubernetes.io/component`, `k8s-component`, or `component | +| `container` | The name of the container, usually `haproxy` | +| `namespace` | The namespace the target was found in. | +| `pod` | The full name of the pod | +| `source` | Constant value of `kubernetes`, denoting where the results came from, this can be useful for LBAC | +| `workload` | Kubernetes workload, a combination of `__meta_kubernetes_pod_controller_kind` and `__meta_kubernetes_pod_controller_name`, i.e. `ReplicaSet/my-app` | + +--- + +### local + +#### Arguments + +| Name | Optional | Default | Description | +| :----- | :------- | :------ | :------------------------------------- | +| `port` | `true` | `8405` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :------- | :------------------------------------------------------------------------------------------- | +| `source` | Constant value of `local`, denoting where the results came from, this can be useful for LBAC | + +--- + +### scrape + +#### Arguments + +| Name | Required | Default | Description | +| :---------------- | :------- | :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `targets` | _yes_ | `list(map(string))` | List of targets to scrape | +| `forward_to` | _yes_ | `list(MetricsReceiver)` | Must be a where scraped should be forwarded to | +| `job_label` | _no_ | `integrations/haproxy` | The job label to add for all mimir metric | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | +| `keep_metrics` | _no_ | [see code](module.river#L228) | A regex of metrics to keep | +| `drop_metrics` | _no_ | [see code](module.river#L235) | A regex of metrics to drop | +| `scrape_interval` | _no_ | `60s` | How often to scrape metrics from the targets | +| `scrape_timeout` | _no_ | `10s` | How long before a scrape times out | +| `max_cache_size` | _no_ | `100000` | The maximum number of elements to hold in the relabeling cache. This should be at least 2x-5x your largest scrape target or samples appended rate. | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---- | :-----------| +| `job` | Set to the value of `argument.job_label.value` | + +--- + +## Usage + +### Kubernetes + +The following example will scrape all haproxy instances in cluster. + +```river +import.git "haproxy" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/haproxy/module.river" + pull_frequency = "15m" +} + +// get the targets +haproxy.kubernetes "targets" {} + +// scrape the targets +haproxy.scrape "metrics" { + targets = haproxy.kubernetes.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "local_primary" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` + +### Local + +The following example will scrape haproxy for metrics on the local machine. + +```river +import.git "haproxy" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/haproxy/module.river" + pull_frequency = "15m" +} + +// get the targets +haproxy.local "targets" {} + +// scrape the targets +haproxy.scrape "metrics" { + targets = haproxy.local.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "default" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` diff --git a/modules/integrations/haproxy/metrics.river b/modules/integrations/haproxy/metrics.river new file mode 100644 index 0000000..924249e --- /dev/null +++ b/modules/integrations/haproxy/metrics.river @@ -0,0 +1,238 @@ +/* +Module: job-haproxy +Description: Scrapes haproxy + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ +declare "kubernetes" { + // arguments for kubernetes discovery + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"app.kubernetes.io/component=haproxy\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: prometheus)" + optional = true + } + + // haproxy service discovery for all of the pods + discovery.kubernetes "haproxy" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.fieldselectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app.kubernetes.io/component=haproxy"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // haproxy relabelings (pre-scrape) + discovery.relabel "kubernetes" { + targets = discovery.kubernetes.haproxy.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "prometheus") + "@Running@true@false" + action = "keep" + } + + // set the namespace label + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + // set the pod label + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + // set the container label + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + // set a workload label + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.kubernetes.output + } +} + +declare "local" { + argument "port" { + comment = "The port to use (default: 8405)" + optional = true + } + + // arguments for local (static) + discovery.relabel "local" { + targets = [ + { + "__address__" = "localhost" + format("%s", coalesce(argument.port.value, "8405")), + "source" = "local", + }, + ] + } + + export "output" { + value = discovery.relabel.local.output + } +} + +declare "scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all haproxy metric (default: integrations/haproxy)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // haproxy scrape job + prometheus.scrape "haproxy" { + job_name = coalesce(argument.job_label.value, "integrations/haproxy") + forward_to = [prometheus.relabel.haproxy.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // haproxy metric relabelings (post-scrape) + prometheus.relabel "haproxy" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(up|haproxy_(blocked_clients|cluster_slots_(fail|pfail)|cluster_state|commands_(duration_seconds_total|total)|connected_(clients|slaves)|db_keys(_expiring)?|evicted_keys_total|keyspace_(hits|misses)_total|master_last_io_seconds_ago|memory_(fragmentation_ratio|max_bytes|used_(bytes|rss_bytes))|total_system_memory_bytes|up))") + action = "keep" + } + } +} diff --git a/modules/integrations/konnectivity-agent/README.md b/modules/integrations/konnectivity-agent/README.md new file mode 100644 index 0000000..d69bca7 --- /dev/null +++ b/modules/integrations/konnectivity-agent/README.md @@ -0,0 +1,142 @@ +# Konnectivity Agent Module + +Handles scraping Konnectivity Agent metrics. + +## Components + +- [kubernetes](#kubernetes) +- [local](#local) +- [scrape](#scrape) + +### kubernetes + +Handles discovery of kubernetes targets and exports them, this component does not perform any scraping at all and is not required to be used for kubernetes, as a custom service discovery and targets can be defined and passed to `konnectivity.scrape` + +#### Arguments + +| Name | Required | Default | Description | +| :----------------- | :------- | :--------------------------------------------- | :-------------------------------------------------------------------------- | +| `namespaces` | _no_ | `[]` | The namespaces to look for targets in, the default (`[]`) is all namespaces | +| `field_selectors` | _no_ | `[]` | The label selectors to use to find matching targets | +| `label_selectors` | _no_ | `["app.kubernetes.io/component=konnectivity"]` | The label selectors to use to find matching targets | +| `port_name` | _no_ | `metrics` | The of the port to scrape metrics from | + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :--------------------------| +| `output` | `list(map(string))` | List of discovered targets | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---------- | :------------------------------------------------------------------------------------------------ | +| `app` | Derived from the pod label value of `app.kubernetes.io/name`, `k8s-app`, or `app` | +| `namespace` | The namespace the target was found in. | +| `service` | The full name of the service | +| `source` | Constant value of `kubernetes`, denoting where the results came from, this can be useful for LBAC | + +--- + +### scrape + +#### Arguments + +| Name | Required | Default | Description | +| :---------------- | :------- | :-------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| `targets` | _yes_ | `list(map(string))` | List of targets to scrape | +| `forward_to` | _yes_ | `list(MetricsReceiver)` | Must be a where scraped should be forwarded to | +| `job_label` | _no_ | `integrations/konnectivity-agent` | The job label to add for all mimir metric | +| `port_name` | _no_ | `http-metrics` | The of the port to scrape metrics from | +| `keep_metrics` | _no_ | [see code](module.river#L228) | A regex of metrics to keep | +| `drop_metrics` | _no_ | [see code](module.river#L235) | A regex of metrics to drop | +| `scrape_interval` | _no_ | `60s` | How often to scrape metrics from the targets | +| `scrape_timeout` | _no_ | `10s` | How long before a scrape times out | +| `max_cache_size` | _no_ | `100000` | The maximum number of elements to hold in the relabeling cache. This should be at least 2x-5x your largest scrape target or samples appended rate. | +| `clustering` | _no_ | `false` | Whether or not [clustering](https://grafana.com/docs/agent/latest/flow/concepts/clustering/) should be enabled | + +#### Labels + +The following labels are automatically added to exported targets. + +| Label | Description | +| :---- | :-----------| +| `job` | Set to the value of `argument.job_label.value` | + +--- + +## Usage + +### Kubernetes + +The following example will scrape all konnectivity instances in cluster. + +```river +import.git "konnectivity" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/konnectivity/module.river" + pull_frequency = "15m" +} + +// get the targets +konnectivity.kubernetes "targets" {} + +// scrape the targets +konnectivity.scrape "metrics" { + targets = konnectivity.kubernetes.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "local_primary" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` + +### Local + +The following example will scrape konnectivity for metrics on the local machine. + +```river +import.git "konnectivity" { + repository = "https://github.com/grafana/agent-modules.git" + revision = "main" + path = "v2/integrations/konnectivity/module.river" + pull_frequency = "15m" +} + +// get the targets +konnectivity.local "targets" {} + +// scrape the targets +konnectivity.scrape "metrics" { + targets = konnectivity.local.targets.output + forward_to = [ + prometheus.remote_write.default.receiver, + ] +} + +// write the metrics +prometheus.remote_write "default" { + endpoint { + url = "http://mimir:9009/api/v1/push" + + basic_auth { + username = "example-user" + password = "example-password" + } + } +} +``` diff --git a/modules/integrations/konnectivity-agent/metrics.river b/modules/integrations/konnectivity-agent/metrics.river new file mode 100644 index 0000000..8d6903f --- /dev/null +++ b/modules/integrations/konnectivity-agent/metrics.river @@ -0,0 +1,218 @@ +/* +Module: job-etcd +Description: Scrapes etcd + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ + +declare "kubernetes" { + // arguments for kubernetes discovery + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [\"kube-system\"] is all namespaces)" + optional = true + } + + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"k8s-app=konnectivity-agent\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: metrics)" + optional = true + } + + // konnectivity service discovery for all of the pods + discovery.kubernetes "konnectivity" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.field_selectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["k8s-app=konnectivity-agent"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, ["kube-system"]) + } + } + + // konnectivity relabelings (pre-scrape) + discovery.relabel "konnectivity" { + targets = discovery.kubernetes.konnectivity.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "metrics") + "@Running@true@false" + action = "keep" + } + + // set the namespace label + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + // set the pod label + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + // set the container label + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + // set a workload label + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.konnectivity.output + } +} + +declare "scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all kube-konnectivity metrics (default: integrations/kubernetes/konnectivity-agent)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // konnectivity-agent scrape job + prometheus.scrape "konnectivity" { + job_name = coalesce(argument.job_label.value, "integrations/kubernetes/konnectivity-agent") + forward_to = [prometheus.relabel.konnectivity.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // konnectivity metric relabelings (post-scrape) + prometheus.relabel "konnectivity" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process|promhttp)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(.+)") + action = "keep" + } + } +} diff --git a/modules/integrations/kubernetes/metrics.river b/modules/integrations/kubernetes/metrics.river new file mode 100644 index 0000000..0ee80f6 --- /dev/null +++ b/modules/integrations/kubernetes/metrics.river @@ -0,0 +1,1191 @@ +/* +Module: job-cadvisor +Description: Scrapes cadvisor + +Note: Every argument except for "forward_to" is optional, and does have a defined default value. However, the values for these + arguments are not defined using the default = " ... " argument syntax, but rather using the coalesce(argument.value, " ... "). + This is because if the argument passed in from another consuming module is set to null, the default = " ... " syntax will + does not override the value passed in, where coalesce() will return the first non-null value. +*/ +declare "cadvisor" { + argument "field_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [\"metadata.name=kubernetes\"])" + optional = true + } + + argument "label_selectors" { + // Docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + comment = "The label selectors to use to find matching targets (default: [])" + optional = true + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all cadvisor metric (default: integrations/kubernetes/cadvisor)" + optional = true + } + + argument "keep_metrics" { + comment = "A regex of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regex of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + // Docs: https://grafana.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + // cadvisor service discovery for all of the nodes + discovery.kubernetes "cadvisor" { + role = "node" + + selectors { + role = "node" + field = join(coalesce(argument.field_selectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, []), ",") + } + } + + // cadvisor relabelings (pre-scrape) + discovery.relabel "cadvisor" { + targets = discovery.kubernetes.cadvisor.targets + + // set the address to use the kubernetes service dns name + rule { + target_label = "__address__" + replacement = "kubernetes.default.svc.cluster.local:443" + } + + // set the metrics path to use the proxy path to the nodes cadvisor metrics endpoint + rule { + source_labels = ["__meta_kubernetes_node_name"] + regex = "(.+)" + replacement = "/api/v1/nodes/${1}/proxy/metrics/cadvisor" + target_label = "__metrics_path__" + } + + // set the node label + rule { + source_labels = ["__meta_kubernetes_node_name"] + target_label = "node" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_node_label_app_kubernetes_io_name", + "__meta_kubernetes_node_label_k8s_app", + "__meta_kubernetes_node_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + // cadvisor scrape job + prometheus.scrape "cadvisor" { + job_name = coalesce(argument.job_label.value, "integrations/kubernetes/cadvisor") + forward_to = [prometheus.relabel.cadvisor.receiver] + targets = discovery.relabel.cadvisor.output + scheme = "https" + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + bearer_token_file = "/var/run/secrets/kubernetes.io/serviceaccount/token" + + tls_config { + ca_file = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" + insecure_skip_verify = false + server_name = "kubernetes" + } + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // cadvisor metric relabelings (post-scrape) + prometheus.relabel "cadvisor" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, "(up|container_(cpu_(cfs_(periods|throttled_periods)_total|usage_seconds_total)|fs_(reads|writes)(_bytes)?_total|memory_(cache|rss|swap|working_set_bytes)|network_(receive|transmit)_(bytes|packets(_dropped)?_total))|machine_memory_bytes)") + action = "keep" + } + + // Drop empty container labels, addressing https://github.com/google/cadvisor/issues/2688 + rule { + source_labels = ["__name__","container"] + separator = "@" + regex = "(container_cpu_.*|container_fs_.*|container_memory_.*)@" + action = "drop" + } + + // Drop empty image labels, addressing https://github.com/google/cadvisor/issues/2688 + rule { + source_labels = ["__name__","image"] + separator = "@" + regex = "(container_cpu_.*|container_fs_.*|container_memory_.*|container_network_.*)@" + action = "drop" + } + + // Normalizing unimportant labels (not deleting to continue satisfying