vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / monitoring / datadog-agent.nix
blob04232b3c9346625947bd16310bb7f56527a9e616
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.datadog-agent;
8   ddConf = {
9     skip_ssl_validation = false;
10     confd_path          = "/etc/datadog-agent/conf.d";
11     additional_checksd  = "/etc/datadog-agent/checks.d";
12     use_dogstatsd       = true;
13   }
14   // optionalAttrs (cfg.logLevel != null) { log_level = cfg.logLevel; }
15   // optionalAttrs (cfg.hostname != null) { inherit (cfg) hostname; }
16   // optionalAttrs (cfg.ddUrl != null) { dd_url = cfg.ddUrl; }
17   // optionalAttrs (cfg.site != null) { site = cfg.site; }
18   // optionalAttrs (cfg.tags != null ) { tags = concatStringsSep ", " cfg.tags; }
19   // optionalAttrs (cfg.enableLiveProcessCollection) { process_config = { enabled = "true"; }; }
20   // optionalAttrs (cfg.enableTraceAgent) { apm_config = { enabled = true; }; }
21   // cfg.extraConfig;
23   # Generate Datadog configuration files for each configured checks.
24   # This works because check configurations have predictable paths,
25   # and because JSON is a valid subset of YAML.
26   makeCheckConfigs = entries: mapAttrs' (name: conf: {
27     name = "datadog-agent/conf.d/${name}.d/conf.yaml";
28     value.source = pkgs.writeText "${name}-check-conf.yaml" (builtins.toJSON conf);
29   }) entries;
31   defaultChecks = {
32     disk = cfg.diskCheck;
33     network = cfg.networkCheck;
34   };
36   # Assemble all check configurations and the top-level agent
37   # configuration.
38   etcfiles = with pkgs; with builtins;
39   { "datadog-agent/datadog.yaml" = {
40       source = writeText "datadog.yaml" (toJSON ddConf);
41     };
42   } // makeCheckConfigs (cfg.checks // defaultChecks);
44   # Apply the configured extraIntegrations to the provided agent
45   # package. See the documentation of `dd-agent/integrations-core.nix`
46   # for detailed information on this.
47   datadogPkg = cfg.package.override {
48     pythonPackages = pkgs.datadog-integrations-core cfg.extraIntegrations;
49   };
50 in {
51   options.services.datadog-agent = {
52     enable = mkEnableOption "Datadog-agent v7 monitoring service";
54     package = mkPackageOption pkgs "datadog-agent" {
55       extraDescription = ''
56         ::: {.note}
57         The provided package is expected to have an overridable `pythonPackages`-attribute
58         which configures the Python environment with the Datadog checks.
59         :::
60       '';
61     };
63     apiKeyFile = mkOption {
64       description = ''
65         Path to a file containing the Datadog API key to associate the
66         agent with your account.
67       '';
68       example = "/run/keys/datadog_api_key";
69       type = types.path;
70     };
72     ddUrl = mkOption {
73       description = ''
74         Custom dd_url to configure the agent with. Useful if traffic to datadog
75         needs to go through a proxy.
76         Don't use this to point to another datadog site (EU) - use site instead.
77       '';
78       default = null;
79       example = "http://haproxy.example.com:3834";
80       type = types.nullOr types.str;
81     };
83     site = mkOption {
84       description = ''
85         The datadog site to point the agent towards.
86         Set to datadoghq.eu to point it to their EU site.
87       '';
88       default = null;
89       example = "datadoghq.eu";
90       type = types.nullOr types.str;
91     };
93     tags = mkOption {
94       description = "The tags to mark this Datadog agent";
95       example = [ "test" "service" ];
96       default = null;
97       type = types.nullOr (types.listOf types.str);
98     };
100     hostname = mkOption {
101       description = "The hostname to show in the Datadog dashboard (optional)";
102       default = null;
103       example = "mymachine.mydomain";
104       type = types.nullOr types.str;
105     };
107     logLevel = mkOption {
108       description = "Logging verbosity.";
109       default = null;
110       type = types.nullOr (types.enum ["DEBUG" "INFO" "WARN" "ERROR"]);
111     };
113     extraIntegrations = mkOption {
114       default = {};
115       type    = types.attrs;
117       description = ''
118         Extra integrations from the Datadog core-integrations
119         repository that should be built and included.
121         By default the included integrations are disk, mongo, network,
122         nginx and postgres.
124         To include additional integrations the name of the derivation
125         and a function to filter its dependencies from the Python
126         package set must be provided.
127       '';
129       example = literalExpression ''
130         {
131           ntp = pythonPackages: [ pythonPackages.ntplib ];
132         }
133       '';
134     };
136     extraConfig = mkOption {
137       default = {};
138       type = types.attrs;
139       description = ''
140         Extra configuration options that will be merged into the
141         main config file {file}`datadog.yaml`.
142       '';
143      };
145     enableLiveProcessCollection = mkOption {
146       description = ''
147         Whether to enable the live process collection agent.
148       '';
149       default = false;
150       type = types.bool;
151     };
153     processAgentPackage = mkOption {
154       default = pkgs.datadog-process-agent;
155       defaultText = literalExpression "pkgs.datadog-process-agent";
156       description = ''
157         Which DataDog v7 agent package to use. Note that the provided
158         package is expected to have an overridable `pythonPackages`-attribute
159         which configures the Python environment with the Datadog
160         checks.
161       '';
162       type = types.package;
163     };
165     enableTraceAgent = mkOption {
166       description = ''
167         Whether to enable the trace agent.
168       '';
169       default = false;
170       type = types.bool;
171     };
173     checks = mkOption {
174       description = ''
175         Configuration for all Datadog checks. Keys of this attribute
176         set will be used as the name of the check to create the
177         appropriate configuration in `conf.d/$check.d/conf.yaml`.
179         The configuration is converted into JSON from the plain Nix
180         language configuration, meaning that you should write
181         configuration adhering to Datadog's documentation - but in Nix
182         language.
184         Refer to the implementation of this module (specifically the
185         definition of `defaultChecks`) for an example.
187         Note: The 'disk' and 'network' check are configured in
188         separate options because they exist by default. Attempting to
189         override their configuration here will have no effect.
190       '';
192       example = {
193         http_check = {
194           init_config = null; # sic!
195           instances = [
196             {
197               name = "some-service";
198               url = "http://localhost:1337/healthz";
199               tags = [ "some-service" ];
200             }
201           ];
202         };
203       };
205       default = {};
207       # sic! The structure of the values is up to the check, so we can
208       # not usefully constrain the type further.
209       type = with types; attrsOf attrs;
210     };
212     diskCheck = mkOption {
213       description = "Disk check config";
214       type = types.attrs;
215       default = {
216         init_config = {};
217         instances = [ { use_mount = "false"; } ];
218       };
219     };
221     networkCheck = mkOption {
222       description = "Network check config";
223       type = types.attrs;
224       default = {
225         init_config = {};
226         # Network check only supports one configured instance
227         instances = [ { collect_connection_state = false;
228           excluded_interfaces = [ "lo" "lo0" ]; } ];
229       };
230     };
231   };
232   config = mkIf cfg.enable {
233     environment.systemPackages = [ datadogPkg pkgs.sysstat pkgs.procps pkgs.iproute2 ];
235     users.users.datadog = {
236       description = "Datadog Agent User";
237       uid = config.ids.uids.datadog;
238       group = "datadog";
239       home = "/var/log/datadog/";
240       createHome = true;
241     };
243     users.groups.datadog.gid = config.ids.gids.datadog;
245     systemd.services = let
246       makeService = attrs: recursiveUpdate {
247         path = [ datadogPkg pkgs.sysstat pkgs.procps pkgs.iproute2 ];
248         wantedBy = [ "multi-user.target" ];
249         serviceConfig = {
250           User = "datadog";
251           Group = "datadog";
252           Restart = "always";
253           RestartSec = 2;
254         };
255         restartTriggers = [ datadogPkg ] ++  map (x: x.source) (attrValues etcfiles);
256       } attrs;
257     in {
258       datadog-agent = makeService {
259         description = "Datadog agent monitor";
260         preStart = ''
261           chown -R datadog: /etc/datadog-agent
262           rm -f /etc/datadog-agent/auth_token
263         '';
264         script = ''
265           export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
266           exec ${datadogPkg}/bin/agent run -c /etc/datadog-agent/datadog.yaml
267         '';
268         serviceConfig.PermissionsStartOnly = true;
269       };
271       dd-jmxfetch = lib.mkIf (lib.hasAttr "jmx" cfg.checks) (makeService {
272         description = "Datadog JMX Fetcher";
273         path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ];
274         serviceConfig.ExecStart = "${datadogPkg}/bin/dd-jmxfetch";
275       });
277       datadog-process-agent = lib.mkIf cfg.enableLiveProcessCollection (makeService {
278         description = "Datadog Live Process Agent";
279         path = [ ];
280         script = ''
281           export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
282           ${cfg.processAgentPackage}/bin/process-agent --config /etc/datadog-agent/datadog.yaml
283         '';
284       });
286       datadog-trace-agent = lib.mkIf cfg.enableTraceAgent (makeService {
287         description = "Datadog Trace Agent";
288         path = [ ];
289         script = ''
290           export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
291           ${datadogPkg}/bin/trace-agent --config /etc/datadog-agent/datadog.yaml
292         '';
293       });
295     };
297     environment.etc = etcfiles;
298   };