1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.logstash;
7 pluginPath = lib.concatStringsSep ":" cfg.plugins;
8 havePluginPath = lib.length cfg.plugins > 0;
9 ops = lib.optionalString;
10 verbosityFlag = {
11 debug = "--debug";
12 info = "--verbose";
13 warn = ""; # intentionally empty
14 error = "--quiet";
15 fatal = "--silent";
16 }."${cfg.logLevel}";
17
18in
19
20{
21 ###### interface
22
23 options = {
24
25 services.logstash = {
26
27 enable = mkOption {
28 type = types.bool;
29 default = false;
30 description = "Enable logstash.";
31 };
32
33 package = mkOption {
34 type = types.package;
35 default = pkgs.logstash;
36 example = literalExample "pkgs.logstash";
37 description = "Logstash package to use.";
38 };
39
40 plugins = mkOption {
41 type = types.listOf types.path;
42 default = [ ];
43 example = literalExample "[ pkgs.logstash-contrib ]";
44 description = "The paths to find other logstash plugins in.";
45 };
46
47 logLevel = mkOption {
48 type = types.enum [ "debug" "info" "warn" "error" "fatal" ];
49 default = "warn";
50 description = "Logging verbosity level.";
51 };
52
53 watchdogTimeout = mkOption {
54 type = types.int;
55 default = 10;
56 description = "Set watchdog timeout value in seconds.";
57 };
58
59 filterWorkers = mkOption {
60 type = types.int;
61 default = 1;
62 description = "The quantity of filter workers to run.";
63 };
64
65 enableWeb = mkOption {
66 type = types.bool;
67 default = false;
68 description = "Enable the logstash web interface.";
69 };
70
71 address = mkOption {
72 type = types.str;
73 default = "0.0.0.0";
74 description = "Address on which to start webserver.";
75 };
76
77 port = mkOption {
78 type = types.str;
79 default = "9292";
80 description = "Port on which to start webserver.";
81 };
82
83 inputConfig = mkOption {
84 type = types.lines;
85 default = ''stdin { type => "example" }'';
86 description = "Logstash input configuration.";
87 example = ''
88 # Read from journal
89 pipe {
90 command => "${pkgs.systemd}/bin/journalctl -f -o json"
91 type => "syslog" codec => json {}
92 }
93 '';
94 };
95
96 filterConfig = mkOption {
97 type = types.lines;
98 default = ''noop {}'';
99 description = "logstash filter configuration.";
100 example = ''
101 if [type] == "syslog" {
102 # Keep only relevant systemd fields
103 # http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html
104 prune {
105 whitelist_names => [
106 "type", "@timestamp", "@version",
107 "MESSAGE", "PRIORITY", "SYSLOG_FACILITY",
108 ]
109 }
110 }
111 '';
112 };
113
114 outputConfig = mkOption {
115 type = types.lines;
116 default = ''stdout { debug => true debug_format => "json"}'';
117 description = "Logstash output configuration.";
118 example = ''
119 redis { host => "localhost" data_type => "list" key => "logstash" codec => json }
120 elasticsearch { embedded => true }
121 '';
122 };
123
124 };
125 };
126
127
128 ###### implementation
129
130 config = mkIf cfg.enable {
131 systemd.services.logstash = with pkgs; {
132 description = "Logstash Daemon";
133 wantedBy = [ "multi-user.target" ];
134 environment = { JAVA_HOME = jre; };
135 serviceConfig = {
136 ExecStart =
137 "${cfg.package}/bin/logstash agent " +
138 "-w ${toString cfg.filterWorkers} " +
139 ops havePluginPath "--pluginpath ${pluginPath} " +
140 "${verbosityFlag} " +
141 "--watchdog-timeout ${toString cfg.watchdogTimeout} " +
142 "-f ${writeText "logstash.conf" ''
143 input {
144 ${cfg.inputConfig}
145 }
146
147 filter {
148 ${cfg.filterConfig}
149 }
150
151 output {
152 ${cfg.outputConfig}
153 }
154 ''} " +
155 ops cfg.enableWeb "-- web -a ${cfg.address} -p ${cfg.port}";
156 };
157 };
158 };
159}