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