at 18.09-beta 7.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.datadog-agent; 7 8 ddConf = { 9 dd_url = "https://app.datadoghq.com"; 10 skip_ssl_validation = "no"; 11 api_key = ""; 12 confd_path = "/etc/datadog-agent/conf.d"; 13 additional_checksd = "/etc/datadog-agent/checks.d"; 14 use_dogstatsd = true; 15 } 16 // optionalAttrs (cfg.logLevel != null) { log_level = cfg.logLevel; } 17 // optionalAttrs (cfg.hostname != null) { inherit (cfg) hostname; } 18 // optionalAttrs (cfg.tags != null ) { tags = concatStringsSep ", " cfg.tags; } 19 // cfg.extraConfig; 20 21 # Generate Datadog configuration files for each configured checks. 22 # This works because check configurations have predictable paths, 23 # and because JSON is a valid subset of YAML. 24 makeCheckConfigs = entries: mapAttrsToList (name: conf: { 25 source = pkgs.writeText "${name}-check-conf.yaml" (builtins.toJSON conf); 26 target = "datadog-agent/conf.d/${name}.d/conf.yaml"; 27 }) entries; 28 29 defaultChecks = { 30 disk = cfg.diskCheck; 31 network = cfg.networkCheck; 32 }; 33 34 # Assemble all check configurations and the top-level agent 35 # configuration. 36 etcfiles = with pkgs; with builtins; [{ 37 source = writeText "datadog.yaml" (toJSON ddConf); 38 target = "datadog-agent/datadog.yaml"; 39 }] ++ makeCheckConfigs (cfg.checks // defaultChecks); 40 41 # Apply the configured extraIntegrations to the provided agent 42 # package. See the documentation of `dd-agent/integrations-core.nix` 43 # for detailed information on this. 44 datadogPkg = cfg.package.overrideAttrs(_: { 45 python = (pkgs.datadog-integrations-core cfg.extraIntegrations).python; 46 }); 47in { 48 options.services.datadog-agent = { 49 enable = mkOption { 50 description = '' 51 Whether to enable the datadog-agent v6 monitoring service 52 ''; 53 default = false; 54 type = types.bool; 55 }; 56 57 package = mkOption { 58 default = pkgs.datadog-agent; 59 defaultText = "pkgs.datadog-agent"; 60 description = '' 61 Which DataDog v6 agent package to use. Note that the provided 62 package is expected to have an overridable `python`-attribute 63 which configures the Python environment with the Datadog 64 checks. 65 ''; 66 type = types.package; 67 }; 68 69 apiKeyFile = mkOption { 70 description = '' 71 Path to a file containing the Datadog API key to associate the 72 agent with your account. 73 ''; 74 example = "/run/keys/datadog_api_key"; 75 type = types.path; 76 }; 77 78 tags = mkOption { 79 description = "The tags to mark this Datadog agent"; 80 example = [ "test" "service" ]; 81 default = null; 82 type = types.nullOr (types.listOf types.str); 83 }; 84 85 hostname = mkOption { 86 description = "The hostname to show in the Datadog dashboard (optional)"; 87 default = null; 88 example = "mymachine.mydomain"; 89 type = types.uniq (types.nullOr types.string); 90 }; 91 92 logLevel = mkOption { 93 description = "Logging verbosity."; 94 default = null; 95 type = types.nullOr (types.enum ["DEBUG" "INFO" "WARN" "ERROR"]); 96 }; 97 98 extraIntegrations = mkOption { 99 default = {}; 100 type = types.attrs; 101 102 description = '' 103 Extra integrations from the Datadog core-integrations 104 repository that should be built and included. 105 106 By default the included integrations are disk, mongo, network, 107 nginx and postgres. 108 109 To include additional integrations the name of the derivation 110 and a function to filter its dependencies from the Python 111 package set must be provided. 112 ''; 113 114 example = { 115 ntp = (pythonPackages: [ pythonPackages.ntplib ]); 116 }; 117 }; 118 119 extraConfig = mkOption { 120 default = {}; 121 type = types.attrs; 122 description = '' 123 Extra configuration options that will be merged into the 124 main config file <filename>datadog.yaml</filename>. 125 ''; 126 }; 127 128 checks = mkOption { 129 description = '' 130 Configuration for all Datadog checks. Keys of this attribute 131 set will be used as the name of the check to create the 132 appropriate configuration in `conf.d/$check.d/conf.yaml`. 133 134 The configuration is converted into JSON from the plain Nix 135 language configuration, meaning that you should write 136 configuration adhering to Datadog's documentation - but in Nix 137 language. 138 139 Refer to the implementation of this module (specifically the 140 definition of `defaultChecks`) for an example. 141 142 Note: The 'disk' and 'network' check are configured in 143 separate options because they exist by default. Attempting to 144 override their configuration here will have no effect. 145 ''; 146 147 example = { 148 http_check = { 149 init_config = null; # sic! 150 instances = [ 151 { 152 name = "some-service"; 153 url = "http://localhost:1337/healthz"; 154 tags = [ "some-service" ]; 155 } 156 ]; 157 }; 158 }; 159 160 default = {}; 161 162 # sic! The structure of the values is up to the check, so we can 163 # not usefully constrain the type further. 164 type = with types; attrsOf attrs; 165 }; 166 167 diskCheck = mkOption { 168 description = "Disk check config"; 169 type = types.attrs; 170 default = { 171 init_config = {}; 172 instances = [ { use-mount = "no"; } ]; 173 }; 174 }; 175 176 networkCheck = mkOption { 177 description = "Network check config"; 178 type = types.attrs; 179 default = { 180 init_config = {}; 181 # Network check only supports one configured instance 182 instances = [ { collect_connection_state = false; 183 excluded_interfaces = [ "lo" "lo0" ]; } ]; 184 }; 185 }; 186 }; 187 config = mkIf cfg.enable { 188 environment.systemPackages = [ datadogPkg pkgs.sysstat pkgs.procps ]; 189 190 users.extraUsers.datadog = { 191 description = "Datadog Agent User"; 192 uid = config.ids.uids.datadog; 193 group = "datadog"; 194 home = "/var/log/datadog/"; 195 createHome = true; 196 }; 197 198 users.extraGroups.datadog.gid = config.ids.gids.datadog; 199 200 systemd.services = let 201 makeService = attrs: recursiveUpdate { 202 path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps ]; 203 wantedBy = [ "multi-user.target" ]; 204 serviceConfig = { 205 User = "datadog"; 206 Group = "datadog"; 207 Restart = "always"; 208 RestartSec = 2; 209 PrivateTmp = true; 210 }; 211 restartTriggers = [ datadogPkg ] ++ map (etc: etc.source) etcfiles; 212 } attrs; 213 in { 214 datadog-agent = makeService { 215 description = "Datadog agent monitor"; 216 preStart = '' 217 chown -R datadog: /etc/datadog-agent 218 rm -f /etc/datadog-agent/auth_token 219 ''; 220 script = '' 221 export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile}) 222 exec ${datadogPkg}/bin/agent start -c /etc/datadog-agent/datadog.yaml 223 ''; 224 serviceConfig.PermissionsStartOnly = true; 225 }; 226 227 dd-jmxfetch = lib.mkIf (lib.hasAttr "jmx" cfg.checks) (makeService { 228 description = "Datadog JMX Fetcher"; 229 path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ]; 230 serviceConfig.ExecStart = "${datadogPkg}/bin/dd-jmxfetch"; 231 }); 232 }; 233 234 environment.etc = etcfiles; 235 }; 236}