at 22.05-pre 9.3 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.datadog-agent; 7 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; 22 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; 30 31 defaultChecks = { 32 disk = cfg.diskCheck; 33 network = cfg.networkCheck; 34 }; 35 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); 43 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 }; 50in { 51 options.services.datadog-agent = { 52 enable = mkOption { 53 description = '' 54 Whether to enable the datadog-agent v7 monitoring service 55 ''; 56 default = false; 57 type = types.bool; 58 }; 59 60 package = mkOption { 61 default = pkgs.datadog-agent; 62 defaultText = literalExpression "pkgs.datadog-agent"; 63 description = '' 64 Which DataDog v7 agent package to use. Note that the provided 65 package is expected to have an overridable `pythonPackages`-attribute 66 which configures the Python environment with the Datadog 67 checks. 68 ''; 69 type = types.package; 70 }; 71 72 apiKeyFile = mkOption { 73 description = '' 74 Path to a file containing the Datadog API key to associate the 75 agent with your account. 76 ''; 77 example = "/run/keys/datadog_api_key"; 78 type = types.path; 79 }; 80 81 ddUrl = mkOption { 82 description = '' 83 Custom dd_url to configure the agent with. Useful if traffic to datadog 84 needs to go through a proxy. 85 Don't use this to point to another datadog site (EU) - use site instead. 86 ''; 87 default = null; 88 example = "http://haproxy.example.com:3834"; 89 type = types.nullOr types.str; 90 }; 91 92 site = mkOption { 93 description = '' 94 The datadog site to point the agent towards. 95 Set to datadoghq.eu to point it to their EU site. 96 ''; 97 default = null; 98 example = "datadoghq.eu"; 99 type = types.nullOr types.str; 100 }; 101 102 tags = mkOption { 103 description = "The tags to mark this Datadog agent"; 104 example = [ "test" "service" ]; 105 default = null; 106 type = types.nullOr (types.listOf types.str); 107 }; 108 109 hostname = mkOption { 110 description = "The hostname to show in the Datadog dashboard (optional)"; 111 default = null; 112 example = "mymachine.mydomain"; 113 type = types.nullOr types.str; 114 }; 115 116 logLevel = mkOption { 117 description = "Logging verbosity."; 118 default = null; 119 type = types.nullOr (types.enum ["DEBUG" "INFO" "WARN" "ERROR"]); 120 }; 121 122 extraIntegrations = mkOption { 123 default = {}; 124 type = types.attrs; 125 126 description = '' 127 Extra integrations from the Datadog core-integrations 128 repository that should be built and included. 129 130 By default the included integrations are disk, mongo, network, 131 nginx and postgres. 132 133 To include additional integrations the name of the derivation 134 and a function to filter its dependencies from the Python 135 package set must be provided. 136 ''; 137 138 example = literalExpression '' 139 { 140 ntp = pythonPackages: [ pythonPackages.ntplib ]; 141 } 142 ''; 143 }; 144 145 extraConfig = mkOption { 146 default = {}; 147 type = types.attrs; 148 description = '' 149 Extra configuration options that will be merged into the 150 main config file <filename>datadog.yaml</filename>. 151 ''; 152 }; 153 154 enableLiveProcessCollection = mkOption { 155 description = '' 156 Whether to enable the live process collection agent. 157 ''; 158 default = false; 159 type = types.bool; 160 }; 161 162 enableTraceAgent = mkOption { 163 description = '' 164 Whether to enable the trace agent. 165 ''; 166 default = false; 167 type = types.bool; 168 }; 169 170 checks = mkOption { 171 description = '' 172 Configuration for all Datadog checks. Keys of this attribute 173 set will be used as the name of the check to create the 174 appropriate configuration in `conf.d/$check.d/conf.yaml`. 175 176 The configuration is converted into JSON from the plain Nix 177 language configuration, meaning that you should write 178 configuration adhering to Datadog's documentation - but in Nix 179 language. 180 181 Refer to the implementation of this module (specifically the 182 definition of `defaultChecks`) for an example. 183 184 Note: The 'disk' and 'network' check are configured in 185 separate options because they exist by default. Attempting to 186 override their configuration here will have no effect. 187 ''; 188 189 example = { 190 http_check = { 191 init_config = null; # sic! 192 instances = [ 193 { 194 name = "some-service"; 195 url = "http://localhost:1337/healthz"; 196 tags = [ "some-service" ]; 197 } 198 ]; 199 }; 200 }; 201 202 default = {}; 203 204 # sic! The structure of the values is up to the check, so we can 205 # not usefully constrain the type further. 206 type = with types; attrsOf attrs; 207 }; 208 209 diskCheck = mkOption { 210 description = "Disk check config"; 211 type = types.attrs; 212 default = { 213 init_config = {}; 214 instances = [ { use_mount = "false"; } ]; 215 }; 216 }; 217 218 networkCheck = mkOption { 219 description = "Network check config"; 220 type = types.attrs; 221 default = { 222 init_config = {}; 223 # Network check only supports one configured instance 224 instances = [ { collect_connection_state = false; 225 excluded_interfaces = [ "lo" "lo0" ]; } ]; 226 }; 227 }; 228 }; 229 config = mkIf cfg.enable { 230 environment.systemPackages = [ datadogPkg pkgs.sysstat pkgs.procps pkgs.iproute2 ]; 231 232 users.users.datadog = { 233 description = "Datadog Agent User"; 234 uid = config.ids.uids.datadog; 235 group = "datadog"; 236 home = "/var/log/datadog/"; 237 createHome = true; 238 }; 239 240 users.groups.datadog.gid = config.ids.gids.datadog; 241 242 systemd.services = let 243 makeService = attrs: recursiveUpdate { 244 path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps pkgs.iproute2 ]; 245 wantedBy = [ "multi-user.target" ]; 246 serviceConfig = { 247 User = "datadog"; 248 Group = "datadog"; 249 Restart = "always"; 250 RestartSec = 2; 251 }; 252 restartTriggers = [ datadogPkg ] ++ map (x: x.source) (attrValues etcfiles); 253 } attrs; 254 in { 255 datadog-agent = makeService { 256 description = "Datadog agent monitor"; 257 preStart = '' 258 chown -R datadog: /etc/datadog-agent 259 rm -f /etc/datadog-agent/auth_token 260 ''; 261 script = '' 262 export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile}) 263 exec ${datadogPkg}/bin/agent run -c /etc/datadog-agent/datadog.yaml 264 ''; 265 serviceConfig.PermissionsStartOnly = true; 266 }; 267 268 dd-jmxfetch = lib.mkIf (lib.hasAttr "jmx" cfg.checks) (makeService { 269 description = "Datadog JMX Fetcher"; 270 path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ]; 271 serviceConfig.ExecStart = "${datadogPkg}/bin/dd-jmxfetch"; 272 }); 273 274 datadog-process-agent = lib.mkIf cfg.enableLiveProcessCollection (makeService { 275 description = "Datadog Live Process Agent"; 276 path = [ ]; 277 script = '' 278 export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile}) 279 ${pkgs.datadog-process-agent}/bin/process-agent --config /etc/datadog-agent/datadog.yaml 280 ''; 281 }); 282 283 datadog-trace-agent = lib.mkIf cfg.enableTraceAgent (makeService { 284 description = "Datadog Trace Agent"; 285 path = [ ]; 286 script = '' 287 export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile}) 288 ${datadogPkg}/bin/trace-agent -config /etc/datadog-agent/datadog.yaml 289 ''; 290 }); 291 292 }; 293 294 environment.etc = etcfiles; 295 }; 296}