{ config, lib, pkgs, ... }: let inherit (lib) attrValues literalExpression mkEnableOption mkIf mkOption types ; cfg = config.services.metricbeat; settingsFormat = pkgs.formats.yaml {}; in { options = { services.metricbeat = { enable = mkEnableOption "metricbeat"; package = mkOption { type = types.package; default = pkgs.metricbeat; defaultText = literalExpression "pkgs.metricbeat"; example = literalExpression "pkgs.metricbeat7"; description = '' The metricbeat package to use ''; }; modules = mkOption { description = '' Metricbeat modules are responsible for reading metrics from the various sources. This is like <literal>services.metricbeat.settings.metricbeat.modules</literal>, but structured as an attribute set. This has the benefit that multiple NixOS modules can contribute settings to a single metricbeat module. A module can be specified multiple times by choosing a different <literal><name></literal> for each, but setting <xref linkend="opt-services.metricbeat.modules._name_.module"/> to the same value. See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html"/>. ''; default = {}; type = types.attrsOf (types.submodule ({ name, ... }: { freeformType = settingsFormat.type; options = { module = mkOption { type = types.str; default = name; description = '' The name of the module. Look for the value after <literal>module:</literal> on the individual module pages linked from <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html"/>. ''; }; }; })); example = { system = { metricsets = ["cpu" "load" "memory" "network" "process" "process_summary" "uptime" "socket_summary"]; enabled = true; period = "10s"; processes = [".*"]; cpu.metrics = ["percentages" "normalized_percentages"]; core.metrics = ["percentages"]; }; }; }; settings = mkOption { type = types.submodule { freeformType = settingsFormat.type; options = { name = mkOption { type = types.str; default = ""; description = '' Name of the beat. Defaults to the hostname. See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/configuration-general-options.html#_name"/>. ''; }; tags = mkOption { type = types.listOf types.str; default = []; description = '' Tags to place on the shipped metrics. See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/configuration-general-options.html#_tags_2"/>. ''; }; metricbeat.modules = mkOption { type = types.listOf settingsFormat.type; default = []; internal = true; description = '' The metric collecting modules. Use <xref linkend="opt-services.metricbeat.modules"/> instead. See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html"/>. ''; }; }; }; default = {}; description = '' Configuration for metricbeat. See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/configuring-howto-metricbeat.html"/> for supported values. ''; }; }; }; config = mkIf cfg.enable { assertions = [ { # empty modules would cause a failure at runtime assertion = cfg.settings.metricbeat.modules != []; message = "services.metricbeat: You must configure one or more modules."; } ]; services.metricbeat.settings.metricbeat.modules = attrValues cfg.modules; systemd.services.metricbeat = { description = "metricbeat metrics shipper"; wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = '' ${cfg.package}/bin/metricbeat \ -c ${settingsFormat.generate "metricbeat.yml" cfg.settings} \ --path.data $STATE_DIRECTORY \ --path.logs $LOGS_DIRECTORY \ ; ''; Restart = "always"; DynamicUser = true; ProtectSystem = "strict"; ProtectHome = "tmpfs"; StateDirectory = "metricbeat"; LogsDirectory = "metricbeat"; }; }; }; }