diff --git a/modules/system/README.md b/modules/system/README.md index 4a16669..7b4e923 100644 --- a/modules/system/README.md +++ b/modules/system/README.md @@ -1,3 +1,4 @@ # System Modules - [node-exporter](./node-exporter/) +- [windows-exporter](./windows-exporter/) diff --git a/modules/system/windows-exporter/README.md b/modules/system/windows-exporter/README.md new file mode 100644 index 0000000..aef0d14 --- /dev/null +++ b/modules/system/windows-exporter/README.md @@ -0,0 +1,99 @@ +# Windows Exporter Module + +Handles scraping Windows Exporter metrics. + +## Components + +- [`local`](#local) +- [`scrape`](#scrape) + +### `local` + +#### Arguments + +| Name | Optional | Default | Description | +| :----- | :------- | :------ | :------------------------------------- | +| `collectors` | `true` | `["cpu", "cs", "logical_disk", "net", "os", "service", "system", "textfile", "time", "diskdrive"]` | The of the port to scrape metrics from | +| `timeout` | `true` | `4m` | Timeout for collecting metrics | +| `textfile_directory` | `true` | `C:\Program Files\GrafanaLabs\Alloy\textfile_imports` | The directory containing files to be ingested | +| `iis_app_exclude` | `true` | `""` | Regular Expression of applications to ignore | +| `iis_app_include` | `true` | `".*"` | Regular Expression of applications to report on | +| `iis_site_exclude` | `true` | `""` | Regular Expression of sites to ignore | +| `iis_site_include` | `true` | `".*"` | Regular Expression of sites to report on | +| `logical_disk_exclude` | `true` | `""` | Regular Expression of volumes to exclude | +| `logical_disk_include` | `true` | `".+"` | Regular Expression of volumes to include | +| `process_exclude` | `true` | `""` | Regular Expression of processes to exclude | +| `process_include` | `true` | `".*"` | Regular Expression of processes to include | +| `service_wql_where_clause` | `true` | `""` | WQL 'where' clause to use in WMI metrics query.| + +#### Exports + +| Name | Type | Description | +| :------- | :------------------ | :------------------------- | +| `output` | `list(map(string))` | List of discovered targets | + +--- + +### `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/node_exporter` | The job label to add for all mimir metric | +| `keep_metrics` | _no_ | [see code](metrics.alloy#L176) | A regular expression of metrics to keep | +| `drop_metrics` | _no_ | [see code](metrics.alloy#L169) | A regular expression 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://node_exporter.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 + +### `local` + +The following example will configure Alloy to scrape Windows metrics on the local machine. + +```river +import.git "windows_exporter" { + repository = "https://github.com/grafana/alloy-modules.git" + revision = "main" + path = "modules/system/windows-exporter/metrics.river" + pull_frequency = "15m" +} + +// get the targets +windows_exporter.local "targets" {} + +// scrape the targets +windows_exporter.scrape "metrics" { + targets = windows_exporter.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/system/windows-exporter/metrics.alloy b/modules/system/windows-exporter/metrics.alloy new file mode 100644 index 0000000..9133319 --- /dev/null +++ b/modules/system/windows-exporter/metrics.alloy @@ -0,0 +1,190 @@ +/* +Module: job-windows-exporter +Description: Integrates and Scrapes Windows Exporter Metrics utilized in the Windows Integration in Grafana Cloud +*/ + +declare "local" { + argument "collectors" { + comment = "The collectors to enable for the windows exporter integration. Default Collectors are: cpu, cs, logical_disk, net, os, system, textfile, time, diskdrive" + optional = true + } + + // timeout attribute on prometheus.windows.exporter component currently throws an error - will look into this more + argument "timeout" { + comment = "Timeout for collecting metrics. Default is 4m" + optional = true + } + + // issue with escape characters when specifying windows paths, this argument currently does nothing. + argument "textfile_directory" { + comment = "The directory containing the files to be ingested." + optional = true + } + + argument "iis_app_exclude" { + comment = "Regular expression of applications to ignore." + optional = true + } + + argument "iis_app_include" { + comment = "Regular expression of applications to report on." + optional = true + } + + argument "iis_site_exclude" { + comment = "Regular expression of sites to ignore" + optional = true + } + + argument "iis_site_include" { + comment = "Regular expression of sites to report on." + optional = true + } + + argument "logical_disk_exclude" { + comment = "Regular expression of volumes to exclude" + optional = true + } + + argument "logical_disk_include" { + comment = "Regular expression of volumes to include" + optional = true + } + + // does nothing unless the `process` collector is enabled + argument "process_exclude" { + comment = "Regular expression of processes to exclude. " + optional = true + } + + // does nothing unless the `process` collector is enabled + argument "process_include" { + comment = "Regular expression of processes to include" + optional = true + } + + // does nothing unless the `services` collector is enabled + argument "service_wql_where_clause" { + comment = "" + optional = true + } + + prometheus.exporter.windows "local" { + enabled_collectors = coalesce(argument.collectors.value, ["cpu", "cs", "logical_disk", "net", "os", "system", "textfile", "time", "diskdrive"]) + + iis { + app_exclude = coalesce(argument.iis_app_exclude.value, "") + app_include = coalesce(argument.iis_app_include.value, ".*") + site_exclude = coalesce(argument.iis_site_exclude.value, "") + site_include = coalesce(argument.iis_site_include.value, ".*") + } + + logical_disk { + exclude = coalesce(argument.logical_disk_exclude.value, "") + include = coalesce(argument.logical_disk_include.value, ".+") + } + + // process collector must be enabled for this to do anything + process { + exclude = coalesce(argument.process_exclude.value, "") + include = coalesce(argument.process_include.value, ".*") + } + + // service collector must be enabled for this to do anything + service { + where_clause = coalesce(argument.service_wql_where_clause.value, "") + } + + } + + export "output" { + value = prometheus.exporter.windows.local.targets + } +} + +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 windows_exporter metric (default: integrations/windows_exporter)" + default = "integrations/windows_exporter" + optional = true + } + + argument "keep_metrics" { + comment = "A regular expression of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regular expression 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://node_exporter.com/docs/agent/latest/flow/concepts/clustering/ + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + prometheus.scrape "windows_exporter" { + job_name = coalesce(argument.job_label.value, "integrations/windows_exporter") + forward_to = [prometheus.relabel.windows_exporter.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) + } + } + + prometheus.relabel "windows_exporter" { + 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)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + action = "keep" + regex = coalesce(argument.keep_metrics.value, "(up|windows_cpu_interrupts_total|windows_cpu_time_total|windows_cs_hostname|windows_cs_logical_processors|windows_cs_physical_memory_bytes|windows_disk_drive_status|windows_logical_disk_avg_read_requests_queued|windows_logical_disk_avg_write_requests_queued|windows_logical_disk_free_bytes|windows_logical_disk_idle_seconds_total|windows_logical_disk_read_bytes_total|windows_logical_disk_read_seconds_total|windows_logical_disk_reads_total|windows_logical_disk_size_bytes|windows_logical_disk_write_bytes_total|windows_logical_disk_write_seconds_total|windows_logical_disk_writes_total|windows_net_bytes_received_total|windows_net_bytes_sent_total|windows_net_packets_outbound_discarded_total|windows_net_packets_outbound_errors_total|windows_net_packets_received_discarded_total|windows_net_packets_received_errors_total|windows_net_packets_received_unknown_total|windows_os_info|windows_os_paging_limit_bytes|windows_os_physical_memory_free_bytes|windows_os_timezone|windows_service_status|windows_system_context_switches_total|windows_system_processor_queue_length|windows_system_system_up_time|windows_time_computed_time_offset_seconds|windows_time_ntp_round_trip_delay_seconds)") + source_labels = ["__name__"] + } + + // replace job label value with module default (integrations/windows_exporter) or passed in argument value + // windows_exporter defaults this value to integrations/windows + // Grafana Cloud Windows Integration expects job label to be integrations/windows_exporter + rule { + action = "replace" + target_label = "job" + replacement = argument.job_label.value + } + } +}