diff options
Diffstat (limited to 'nixos/modules/services/monitoring/prometheus/default.nix')
-rw-r--r-- | nixos/modules/services/monitoring/prometheus/default.nix | 600 |
1 files changed, 341 insertions, 259 deletions
diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix index 25385be9704..d8384e0d35b 100644 --- a/nixos/modules/services/monitoring/prometheus/default.nix +++ b/nixos/modules/services/monitoring/prometheus/default.nix @@ -22,9 +22,6 @@ let workingDir = stateDirBase + stateDir; workingDir2 = stateDirBase + cfg2.stateDir; - # Get a submodule without any embedded metadata: - _filter = x: filterAttrs (k: v: k != "_module") x; - # a wrapper that verifies that the configuration is valid promtoolCheck = what: name: file: pkgs.runCommand "${name}-${what}-checked" { buildInputs = [ cfg.package ]; } '' @@ -50,11 +47,11 @@ let # This becomes the main config file for Prometheus 1 promConfig = { - global = cfg.globalConfig; + global = filterValidPrometheus cfg.globalConfig; rule_files = map (promtoolCheck "check-rules" "rules") (cfg.ruleFiles ++ [ (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules)) ]); - scrape_configs = cfg.scrapeConfigs; + scrape_configs = filterValidPrometheus cfg.scrapeConfigs; }; generatedPrometheusYml = writePrettyJSON "prometheus.yml" promConfig; @@ -77,11 +74,11 @@ let # This becomes the main config file for Prometheus 2 promConfig2 = { - global = cfg2.globalConfig; + global = filterValidPrometheus cfg2.globalConfig; rule_files = map (prom2toolCheck "check rules" "rules") (cfg2.ruleFiles ++ [ (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg2.rules)) ]); - scrape_configs = cfg2.scrapeConfigs; + scrape_configs = filterValidPrometheus cfg2.scrapeConfigs; alerting = optionalAttrs (cfg2.alertmanagerURL != []) { alertmanagers = [{ static_configs = [{ @@ -108,41 +105,52 @@ let ] ++ optional (cfg2.webExternalUrl != null) "--web.external-url=${cfg2.webExternalUrl}"; + filterValidPrometheus = filterAttrsListRecursive (n: v: !(n == "_module" || v == null)); + filterAttrsListRecursive = pred: x: + if isAttrs x then + listToAttrs ( + concatMap (name: + let v = x.${name}; in + if pred name v then [ + (nameValuePair name (filterAttrsListRecursive pred v)) + ] else [] + ) (attrNames x) + ) + else if isList x then + map (filterAttrsListRecursive pred) x + else x; + + mkDefOpt = type : defaultStr : description : mkOpt type (description + '' + + Defaults to <literal>${defaultStr}</literal> in prometheus + when set to <literal>null</literal>. + ''); + + mkOpt = type : description : mkOption { + type = types.nullOr type; + default = null; + inherit description; + }; + promTypes.globalConfig = types.submodule { options = { - scrape_interval = mkOption { - type = types.str; - default = "1m"; - description = '' - How frequently to scrape targets by default. - ''; - }; - - scrape_timeout = mkOption { - type = types.str; - default = "10s"; - description = '' - How long until a scrape request times out. - ''; - }; - - evaluation_interval = mkOption { - type = types.str; - default = "1m"; - description = '' - How frequently to evaluate rules by default. - ''; - }; - - external_labels = mkOption { - type = types.attrsOf types.str; - description = '' - The labels to add to any time series or alerts when - communicating with external systems (federation, remote - storage, Alertmanager). - ''; - default = {}; - }; + scrape_interval = mkDefOpt types.str "1m" '' + How frequently to scrape targets by default. + ''; + + scrape_timeout = mkDefOpt types.str "10s" '' + How long until a scrape request times out. + ''; + + evaluation_interval = mkDefOpt types.str "1m" '' + How frequently to evaluate rules by default. + ''; + + external_labels = mkOpt (types.attrsOf types.str) '' + The labels to add to any time series or alerts when + communicating with external systems (federation, remote + storage, Alertmanager). + ''; }; }; @@ -154,129 +162,127 @@ let The job name assigned to scraped metrics by default. ''; }; - scrape_interval = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - How frequently to scrape targets from this job. Defaults to the - globally configured default. - ''; - }; - scrape_timeout = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Per-target timeout when scraping this job. Defaults to the - globally configured default. - ''; - }; - metrics_path = mkOption { - type = types.str; - default = "/metrics"; - description = '' - The HTTP resource path on which to fetch metrics from targets. - ''; - }; - honor_labels = mkOption { - type = types.bool; - default = false; - description = '' - Controls how Prometheus handles conflicts between labels - that are already present in scraped data and labels that - Prometheus would attach server-side ("job" and "instance" - labels, manually configured target labels, and labels - generated by service discovery implementations). - - If honor_labels is set to "true", label conflicts are - resolved by keeping label values from the scraped data and - ignoring the conflicting server-side labels. - - If honor_labels is set to "false", label conflicts are - resolved by renaming conflicting labels in the scraped data - to "exported_<original-label>" (for example - "exported_instance", "exported_job") and then attaching - server-side labels. This is useful for use cases such as - federation, where all labels specified in the target should - be preserved. - ''; - }; - scheme = mkOption { - type = types.enum ["http" "https"]; - default = "http"; - description = '' - The URL scheme with which to fetch metrics from targets. - ''; - }; - params = mkOption { - type = types.attrsOf (types.listOf types.str); - default = {}; - description = '' - Optional HTTP URL parameters. - ''; - }; - basic_auth = mkOption { - type = types.nullOr (types.submodule { - options = { - username = mkOption { - type = types.str; - description = '' - HTTP username - ''; - }; - password = mkOption { - type = types.str; - description = '' - HTTP password - ''; - }; + scrape_interval = mkOpt types.str '' + How frequently to scrape targets from this job. Defaults to the + globally configured default. + ''; + + scrape_timeout = mkOpt types.str '' + Per-target timeout when scraping this job. Defaults to the + globally configured default. + ''; + + metrics_path = mkDefOpt types.str "/metrics" '' + The HTTP resource path on which to fetch metrics from targets. + ''; + + honor_labels = mkDefOpt types.bool "false" '' + Controls how Prometheus handles conflicts between labels + that are already present in scraped data and labels that + Prometheus would attach server-side ("job" and "instance" + labels, manually configured target labels, and labels + generated by service discovery implementations). + + If honor_labels is set to "true", label conflicts are + resolved by keeping label values from the scraped data and + ignoring the conflicting server-side labels. + + If honor_labels is set to "false", label conflicts are + resolved by renaming conflicting labels in the scraped data + to "exported_<original-label>" (for example + "exported_instance", "exported_job") and then attaching + server-side labels. This is useful for use cases such as + federation, where all labels specified in the target should + be preserved. + ''; + + honor_timestamps = mkDefOpt types.bool "true" '' + honor_timestamps controls whether Prometheus respects the timestamps present + in scraped data. + + If honor_timestamps is set to <literal>true</literal>, the timestamps of the metrics exposed + by the target will be used. + + If honor_timestamps is set to <literal>false</literal>, the timestamps of the metrics exposed + by the target will be ignored. + ''; + + scheme = mkDefOpt (types.enum ["http" "https"]) "http" '' + The URL scheme with which to fetch metrics from targets. + ''; + + params = mkOpt (types.attrsOf (types.listOf types.str)) '' + Optional HTTP URL parameters. + ''; + + basic_auth = mkOpt (types.submodule { + options = { + username = mkOption { + type = types.str; + description = '' + HTTP username + ''; }; - }); - default = null; - apply = x: mapNullable _filter x; - description = '' - Optional http login credentials for metrics scraping. - ''; - }; - dns_sd_configs = mkOption { - type = types.listOf promTypes.dns_sd_config; - default = []; - apply = x: map _filter x; - description = '' - List of DNS service discovery configurations. - ''; - }; - consul_sd_configs = mkOption { - type = types.listOf promTypes.consul_sd_config; - default = []; - apply = x: map _filter x; - description = '' - List of Consul service discovery configurations. - ''; - }; - file_sd_configs = mkOption { - type = types.listOf promTypes.file_sd_config; - default = []; - apply = x: map _filter x; - description = '' - List of file service discovery configurations. - ''; - }; - static_configs = mkOption { - type = types.listOf promTypes.static_config; - default = []; - apply = x: map _filter x; - description = '' - List of labeled target groups for this job. - ''; - }; - relabel_configs = mkOption { - type = types.listOf promTypes.relabel_config; - default = []; - apply = x: map _filter x; - description = '' - List of relabel configurations. - ''; - }; + password = mkOption { + type = types.str; + description = '' + HTTP password + ''; + }; + }; + }) '' + Optional http login credentials for metrics scraping. + ''; + + bearer_token = mkOpt types.str '' + Sets the `Authorization` header on every scrape request with + the configured bearer token. It is mutually exclusive with + <option>bearer_token_file</option>. + ''; + + bearer_token_file = mkOpt types.str '' + Sets the `Authorization` header on every scrape request with + the bearer token read from the configured file. It is mutually + exclusive with <option>bearer_token</option>. + ''; + + tls_config = mkOpt promTypes.tls_config '' + Configures the scrape request's TLS settings. + ''; + + proxy_url = mkOpt types.str '' + Optional proxy URL. + ''; + + ec2_sd_configs = mkOpt (types.listOf promTypes.ec2_sd_config) '' + List of EC2 service discovery configurations. + ''; + + dns_sd_configs = mkOpt (types.listOf promTypes.dns_sd_config) '' + List of DNS service discovery configurations. + ''; + + consul_sd_configs = mkOpt (types.listOf promTypes.consul_sd_config) '' + List of Consul service discovery configurations. + ''; + + file_sd_configs = mkOpt (types.listOf promTypes.file_sd_config) '' + List of file service discovery configurations. + ''; + + static_configs = mkOpt (types.listOf promTypes.static_config) '' + List of labeled target groups for this job. + ''; + + relabel_configs = mkOpt (types.listOf promTypes.relabel_config) '' + List of relabel configurations. + ''; + + sample_limit = mkDefOpt types.int "0" '' + Per-scrape limit on number of scraped samples that will be accepted. + If more than this number of samples are present after metric relabelling + the entire scrape will be treated as failed. 0 means no limit. + ''; }; }; @@ -298,64 +304,137 @@ let }; }; - promTypes.dns_sd_config = types.submodule { + promTypes.ec2_sd_config = types.submodule { options = { - names = mkOption { - type = types.listOf types.str; - description = '' - A list of DNS SRV record names to be queried. - ''; - }; - refresh_interval = mkOption { + region = mkOption { type = types.str; - default = "30s"; description = '' - The time after which the provided names are refreshed. + The AWS Region. ''; }; + endpoint = mkOpt types.str '' + Custom endpoint to be used. + ''; + + access_key = mkOpt types.str '' + The AWS API key id. If blank, the environment variable + <literal>AWS_ACCESS_KEY_ID</literal> is used. + ''; + + secret_key = mkOpt types.str '' + The AWS API key secret. If blank, the environment variable + <literal>AWS_SECRET_ACCESS_KEY</literal> is used. + ''; + + profile = mkOpt types.str '' + Named AWS profile used to connect to the API. + ''; + + role_arn = mkOpt types.str '' + AWS Role ARN, an alternative to using AWS API keys. + ''; + + refresh_interval = mkDefOpt types.str "60s" '' + Refresh interval to re-read the instance list. + ''; + + port = mkDefOpt types.int "80" '' + The port to scrape metrics from. If using the public IP + address, this must instead be specified in the relabeling + rule. + ''; + + filters = mkOpt (types.listOf promTypes.filter) '' + Filters can be used optionally to filter the instance list by other criteria. + ''; }; }; - promTypes.consul_sd_config = types.submodule { + promTypes.filter = types.submodule { options = { - server = mkOption { + name = mkOption { type = types.str; - description = "Consul server to query."; - }; - token = mkOption { - type = types.nullOr types.str; - description = "Consul token"; - }; - datacenter = mkOption { - type = types.nullOr types.str; - description = "Consul datacenter"; - }; - scheme = mkOption { - type = types.nullOr types.str; - description = "Consul scheme"; - }; - username = mkOption { - type = types.nullOr types.str; - description = "Consul username"; - }; - password = mkOption { - type = types.nullOr types.str; - description = "Consul password"; + description = '' + See <link xlink:href="https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html">this list</link> + for the available filters. + ''; }; - services = mkOption { + value = mkOption { type = types.listOf types.str; + default = []; description = '' - A list of services for which targets are retrieved. + Value of the filter. ''; }; - tag_separator = mkOption { - type = types.str; - default = ","; + }; + }; + + promTypes.dns_sd_config = types.submodule { + options = { + names = mkOption { + type = types.listOf types.str; description = '' - The string by which Consul tags are joined into the tag label. + A list of DNS SRV record names to be queried. ''; }; + + refresh_interval = mkDefOpt types.str "30s" '' + The time after which the provided names are refreshed. + ''; + }; + }; + + promTypes.consul_sd_config = types.submodule { + options = { + server = mkDefOpt types.str "localhost:8500" '' + Consul server to query. + ''; + + token = mkOpt types.str "Consul token"; + + datacenter = mkOpt types.str "Consul datacenter"; + + scheme = mkDefOpt types.str "http" "Consul scheme"; + + username = mkOpt types.str "Consul username"; + + password = mkOpt types.str "Consul password"; + + tls_config = mkOpt promTypes.tls_config '' + Configures the Consul request's TLS settings. + ''; + + services = mkOpt (types.listOf types.str) '' + A list of services for which targets are retrieved. + ''; + + tags = mkOpt (types.listOf types.str) '' + An optional list of tags used to filter nodes for a given + service. Services must contain all tags in the list. + ''; + + node_meta = mkOpt (types.attrsOf types.str) '' + Node metadata used to filter nodes for a given service. + ''; + + tag_separator = mkDefOpt types.str "," '' + The string by which Consul tags are joined into the tag label. + ''; + + allow_stale = mkOpt types.bool '' + Allow stale Consul results + (see <link xlink:href="https://www.consul.io/api/index.html#consistency-modes"/>). + + Will reduce load on Consul. + ''; + + refresh_interval = mkDefOpt types.str "30s" '' + The time after which the provided names are refreshed. + + On large setup it might be a good idea to increase this value + because the catalog will change all the time. + ''; }; }; @@ -367,67 +446,74 @@ let Patterns for files from which target groups are extracted. Refer to the Prometheus documentation for permitted filename patterns and formats. - - ''; - }; - refresh_interval = mkOption { - type = types.str; - default = "30s"; - description = '' - Refresh interval to re-read the files. ''; }; + + refresh_interval = mkDefOpt types.str "5m" '' + Refresh interval to re-read the files. + ''; }; }; promTypes.relabel_config = types.submodule { options = { - source_labels = mkOption { - type = with types; nullOr (listOf str); - default = null; - description = '' - The source labels select values from existing labels. Their content - is concatenated using the configured separator and matched against - the configured regular expression. - ''; - }; - separator = mkOption { - type = types.str; - default = ";"; - description = '' - Separator placed between concatenated source label values. - ''; - }; - target_label = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Label to which the resulting value is written in a replace action. - It is mandatory for replace actions. - ''; - }; - regex = mkOption { - type = types.str; - default = "(.*)"; - description = '' - Regular expression against which the extracted value is matched. - ''; - }; - replacement = mkOption { - type = types.str; - default = "$1"; - description = '' - Replacement value against which a regex replace is performed if the - regular expression matches. - ''; - }; - action = mkOption { - type = types.enum ["replace" "keep" "drop"]; - default = "replace"; - description = '' - Action to perform based on regex matching. - ''; - }; + source_labels = mkOpt (types.listOf types.str) '' + The source labels select values from existing labels. Their content + is concatenated using the configured separator and matched against + the configured regular expression. + ''; + + separator = mkDefOpt types.str ";" '' + Separator placed between concatenated source label values. + ''; + + target_label = mkOpt types.str '' + Label to which the resulting value is written in a replace action. + It is mandatory for replace actions. + ''; + + regex = mkDefOpt types.str "(.*)" '' + Regular expression against which the extracted value is matched. + ''; + + modulus = mkOpt types.int '' + Modulus to take of the hash of the source label values. + ''; + + replacement = mkDefOpt types.str "$1" '' + Replacement value against which a regex replace is performed if the + regular expression matches. + ''; + + action = mkDefOpt (types.enum ["replace" "keep" "drop"]) "replace" '' + Action to perform based on regex matching. + ''; + + }; + }; + + promTypes.tls_config = types.submodule { + options = { + ca_file = mkOpt types.str '' + CA certificate to validate API server certificate with. + ''; + + cert_file = mkOpt types.str '' + Certificate file for client cert authentication to the server. + ''; + + key_file = mkOpt types.str '' + Key file for client cert authentication to the server. + ''; + + server_name = mkOpt types.str '' + ServerName extension to indicate the name of the server. + http://tools.ietf.org/html/rfc4366#section-3.1 + ''; + + insecure_skip_verify = mkOpt types.bool '' + Disable validation of the server certificate. + ''; }; }; @@ -500,7 +586,6 @@ in { globalConfig = mkOption { type = promTypes.globalConfig; default = {}; - apply = _filter; description = '' Parameters that are valid in all configuration contexts. They also serve as defaults for other configuration sections @@ -526,7 +611,6 @@ in { scrapeConfigs = mkOption { type = types.listOf promTypes.scrape_config; default = []; - apply = x: map _filter x; description = '' A list of scrape configurations. ''; @@ -624,7 +708,6 @@ in { globalConfig = mkOption { type = promTypes.globalConfig; default = {}; - apply = _filter; description = '' Parameters that are valid in all configuration contexts. They also serve as defaults for other configuration sections @@ -650,7 +733,6 @@ in { scrapeConfigs = mkOption { type = types.listOf promTypes.scrape_config; default = []; - apply = x: map _filter x; description = '' A list of scrape configurations. ''; |