at 24.11-pre 9.5 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 = mkEnableOption "Datadog-agent v7 monitoring service"; 53 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 }; 62 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 }; 71 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 }; 82 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 }; 92 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 }; 99 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 }; 106 107 logLevel = mkOption { 108 description = "Logging verbosity."; 109 default = null; 110 type = types.nullOr (types.enum ["DEBUG" "INFO" "WARN" "ERROR"]); 111 }; 112 113 extraIntegrations = mkOption { 114 default = {}; 115 type = types.attrs; 116 117 description = '' 118 Extra integrations from the Datadog core-integrations 119 repository that should be built and included. 120 121 By default the included integrations are disk, mongo, network, 122 nginx and postgres. 123 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 ''; 128 129 example = literalExpression '' 130 { 131 ntp = pythonPackages: [ pythonPackages.ntplib ]; 132 } 133 ''; 134 }; 135 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 }; 144 145 enableLiveProcessCollection = mkOption { 146 description = '' 147 Whether to enable the live process collection agent. 148 ''; 149 default = false; 150 type = types.bool; 151 }; 152 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 }; 164 165 enableTraceAgent = mkOption { 166 description = '' 167 Whether to enable the trace agent. 168 ''; 169 default = false; 170 type = types.bool; 171 }; 172 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`. 178 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. 183 184 Refer to the implementation of this module (specifically the 185 definition of `defaultChecks`) for an example. 186 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 ''; 191 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 }; 204 205 default = {}; 206 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 }; 211 212 diskCheck = mkOption { 213 description = "Disk check config"; 214 type = types.attrs; 215 default = { 216 init_config = {}; 217 instances = [ { use_mount = "false"; } ]; 218 }; 219 }; 220 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 ]; 234 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 }; 242 243 users.groups.datadog.gid = config.ids.gids.datadog; 244 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 }; 270 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 }); 276 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 }); 285 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 }); 294 295 }; 296 297 environment.etc = etcfiles; 298 }; 299}