498 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			498 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ config, pkgs, lib, ... }:
 | 
						|
 | 
						|
with lib;
 | 
						|
 | 
						|
let
 | 
						|
  cfg = config.services.prometheus;
 | 
						|
  promUser = "prometheus";
 | 
						|
  promGroup = "prometheus";
 | 
						|
 | 
						|
  # Get a submodule without any embedded metadata:
 | 
						|
  _filter = x: filterAttrs (k: v: k != "_module") x;
 | 
						|
 | 
						|
  # Pretty-print JSON to a file
 | 
						|
  writePrettyJSON = name: x:
 | 
						|
    pkgs.runCommand name { } ''
 | 
						|
      echo '${builtins.toJSON x}' | ${pkgs.jq}/bin/jq . > $out
 | 
						|
    '';
 | 
						|
 | 
						|
  # This becomes the main config file
 | 
						|
  promConfig = {
 | 
						|
    global = cfg.globalConfig;
 | 
						|
    rule_files = cfg.ruleFiles ++ [
 | 
						|
      (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules))
 | 
						|
    ];
 | 
						|
    scrape_configs = cfg.scrapeConfigs;
 | 
						|
  };
 | 
						|
 | 
						|
  generatedPrometheusYml = writePrettyJSON "prometheus.yml" promConfig;
 | 
						|
 | 
						|
  prometheusYml =
 | 
						|
    if cfg.configText != null then
 | 
						|
      pkgs.writeText "prometheus.yml" cfg.configText
 | 
						|
    else generatedPrometheusYml;
 | 
						|
 | 
						|
  cmdlineArgs = cfg.extraFlags ++ [
 | 
						|
    "-storage.local.path=${cfg.dataDir}/metrics"
 | 
						|
    "-config.file=${prometheusYml}"
 | 
						|
    "-web.listen-address=${cfg.listenAddress}"
 | 
						|
    "-alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}"
 | 
						|
    "-alertmanager.timeout=${toString cfg.alertmanagerTimeout}s"
 | 
						|
    (optionalString (cfg.alertmanagerURL != []) "-alertmanager.url=${concatStringsSep "," cfg.alertmanagerURL}")
 | 
						|
  ];
 | 
						|
 | 
						|
  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 = {};
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  promTypes.scrape_config = types.submodule {
 | 
						|
    options = {
 | 
						|
      job_name = mkOption {
 | 
						|
        type = types.str;
 | 
						|
        description = ''
 | 
						|
          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
 | 
						|
              '';
 | 
						|
            };
 | 
						|
          };
 | 
						|
        });
 | 
						|
        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.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  promTypes.static_config = types.submodule {
 | 
						|
    options = {
 | 
						|
      targets = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        description = ''
 | 
						|
          The targets specified by the target group.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
      labels = mkOption {
 | 
						|
        type = types.attrsOf types.str;
 | 
						|
        default = {};
 | 
						|
        description = ''
 | 
						|
          Labels assigned to all metrics scraped from the targets.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  promTypes.dns_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 {
 | 
						|
        type = types.str;
 | 
						|
        default = "30s";
 | 
						|
        description = ''
 | 
						|
          The time after which the provided names are refreshed.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  promTypes.consul_sd_config = types.submodule {
 | 
						|
    options = {
 | 
						|
      server = 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";
 | 
						|
      };
 | 
						|
 | 
						|
      services = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        description = ''
 | 
						|
          A list of services for which targets are retrieved.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
      tag_separator = mkOption {
 | 
						|
        type = types.str;
 | 
						|
        default = ",";
 | 
						|
        description = ''
 | 
						|
          The string by which Consul tags are joined into the tag label.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  promTypes.file_sd_config = types.submodule {
 | 
						|
    options = {
 | 
						|
      files = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        description = ''
 | 
						|
          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.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  promTypes.relabel_config = types.submodule {
 | 
						|
    options = {
 | 
						|
      source_labels = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        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.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
in {
 | 
						|
  options = {
 | 
						|
    services.prometheus = {
 | 
						|
 | 
						|
      enable = mkOption {
 | 
						|
        type = types.bool;
 | 
						|
        default = false;
 | 
						|
        description = ''
 | 
						|
          Enable the Prometheus monitoring daemon.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      listenAddress = mkOption {
 | 
						|
        type = types.str;
 | 
						|
        default = "0.0.0.0:9090";
 | 
						|
        description = ''
 | 
						|
          Address to listen on for the web interface, API, and telemetry.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      dataDir = mkOption {
 | 
						|
        type = types.path;
 | 
						|
        default = "/var/lib/prometheus";
 | 
						|
        description = ''
 | 
						|
          Directory to store Prometheus metrics data.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      extraFlags = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        default = [];
 | 
						|
        description = ''
 | 
						|
          Extra commandline options when launching Prometheus.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      configText = mkOption {
 | 
						|
        type = types.nullOr types.lines;
 | 
						|
        default = null;
 | 
						|
        description = ''
 | 
						|
          If non-null, this option defines the text that is written to
 | 
						|
          prometheus.yml. If null, the contents of prometheus.yml is generated
 | 
						|
          from the structured config options.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      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
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      rules = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        default = [];
 | 
						|
        description = ''
 | 
						|
          Alerting and/or Recording rules to evaluate at runtime.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      ruleFiles = mkOption {
 | 
						|
        type = types.listOf types.path;
 | 
						|
        default = [];
 | 
						|
        description = ''
 | 
						|
          Any additional rules files to include in this configuration.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      scrapeConfigs = mkOption {
 | 
						|
        type = types.listOf promTypes.scrape_config;
 | 
						|
        default = [];
 | 
						|
        apply = x: map _filter x;
 | 
						|
        description = ''
 | 
						|
          A list of scrape configurations.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      alertmanagerURL = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        default = [];
 | 
						|
        description = ''
 | 
						|
          List of Alertmanager URLs to send notifications to.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      alertmanagerNotificationQueueCapacity = mkOption {
 | 
						|
        type = types.int;
 | 
						|
        default = 10000;
 | 
						|
        description = ''
 | 
						|
          The capacity of the queue for pending alert manager notifications.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      alertmanagerTimeout = mkOption {
 | 
						|
        type = types.int;
 | 
						|
        default = 10;
 | 
						|
        description = ''
 | 
						|
          Alert manager HTTP API timeout (in seconds).
 | 
						|
        '';
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  config = mkIf cfg.enable {
 | 
						|
    users.extraGroups.${promGroup}.gid = config.ids.gids.prometheus;
 | 
						|
    users.extraUsers.${promUser} = {
 | 
						|
      description = "Prometheus daemon user";
 | 
						|
      uid = config.ids.uids.prometheus;
 | 
						|
      group = promGroup;
 | 
						|
      home = cfg.dataDir;
 | 
						|
      createHome = true;
 | 
						|
    };
 | 
						|
    systemd.services.prometheus = {
 | 
						|
      wantedBy = [ "multi-user.target" ];
 | 
						|
      after    = [ "network.target" ];
 | 
						|
      script = ''
 | 
						|
        #!/bin/sh
 | 
						|
        exec ${pkgs.prometheus}/bin/prometheus \
 | 
						|
          ${concatStringsSep " \\\n  " cmdlineArgs}
 | 
						|
      '';
 | 
						|
      serviceConfig = {
 | 
						|
        User = promUser;
 | 
						|
        Restart  = "always";
 | 
						|
        WorkingDirectory = cfg.dataDir;
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
}
 |