about summary refs log tree commit diff
path: root/modules/services/logging
diff options
context:
space:
mode:
authorShea Levy <shea@shealevy.com>2012-07-11 11:22:16 -0400
committerShea Levy <shea@shealevy.com>2012-07-11 11:22:16 -0400
commit3039caf5ad3657ffd8bc84929ffc9eca44d18292 (patch)
tree3236011379e4a3f33f7e210ef0f7ec832ad10dde /modules/services/logging
parentb7398794ed7805002e57bb37d59bdcb777d623c9 (diff)
downloadnixlib-3039caf5ad3657ffd8bc84929ffc9eca44d18292.tar
nixlib-3039caf5ad3657ffd8bc84929ffc9eca44d18292.tar.gz
nixlib-3039caf5ad3657ffd8bc84929ffc9eca44d18292.tar.bz2
nixlib-3039caf5ad3657ffd8bc84929ffc9eca44d18292.tar.lz
nixlib-3039caf5ad3657ffd8bc84929ffc9eca44d18292.tar.xz
nixlib-3039caf5ad3657ffd8bc84929ffc9eca44d18292.tar.zst
nixlib-3039caf5ad3657ffd8bc84929ffc9eca44d18292.zip
Add logstash module.
Since the logstash config file seemed very similar to a nixexpr, I decided
to map directly from nixexprs to logstash configs. I didn't realize until
too far in that this solution was probably way over-engineered, but it
works.
Diffstat (limited to 'modules/services/logging')
-rw-r--r--modules/services/logging/logstash.nix152
1 files changed, 152 insertions, 0 deletions
diff --git a/modules/services/logging/logstash.nix b/modules/services/logging/logstash.nix
new file mode 100644
index 000000000000..f8b0d353cad6
--- /dev/null
+++ b/modules/services/logging/logstash.nix
@@ -0,0 +1,152 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.services.logstash;
+
+  listToConfig = list: "[ " + (concatStringsSep ", " (map exprToConfig list)) + " ]";
+
+  hashToConfig = attrs:
+    let
+      attrNameToConfigList = name:
+        [ (exprToConfig name)  (exprToConfig (getAttr name attrs)) ];
+    in
+      "[ " +
+      (concatStringsSep ", " (map attrNameToConfigList (attrNames attrs))) +
+      " ]";
+
+  valueToConfig = name: value: 
+    if (isAttrs value) && ((!(value ? __type)) || value.__type == "repeated")
+      then ''
+        ${name} {
+          ${exprToConfig value}
+        }
+      ''
+      else "${name} => ${exprToConfig value}";
+
+  repeatedAttrsToConfig = names: values:
+      concatStringsSep "\n" (zipListsWith valueToConfig names values);
+
+  attrsToConfig = attrs:
+    let
+      attrToConfig = name: valueToConfig name (getAttr name attrs);
+    in
+      concatStringsSep "\n" (map attrToConfig (attrNames attrs));
+
+  exprToConfig = expr:
+    let
+      isCustomType = expr: (isAttrs expr) && (expr ? __type);
+
+      isFloat = expr: (isCustomType expr) && (expr.__type == "float");
+
+      isHash = expr: (isCustomType expr) && (expr.__type == "hash");
+
+      isRepeatedAttrs = expr: (isCustomType expr) && (expr.__type == "repeated");
+    in
+      if builtins.isBool expr then (if expr then "true" else "false") else
+      if builtins.isString expr then ''"${expr}"'' else
+      if builtins.isInt expr then toString expr else
+      if isFloat expr then expr.value else
+      if isList expr then listToConfig expr else
+      if isHash expr then hashToConfig expr.value else
+      if isRepeatedAttrs expr then repeatedAttrsToConfig expr.names expr.values
+      else attrsToConfig expr;
+
+  mergeConfigs = configs:
+    let
+      op = attrs: newAttrs:
+        let
+          isRepeated = newAttrs ? __type && newAttrs.__type == "repeated";
+        in {
+            names = attrs.names ++
+              (if isRepeated then newAttrs.names else attrNames newAttrs);
+
+            values = attrs.values ++
+              (if isRepeated then newAttrs.values else attrValues newAttrs);
+          };
+    in (foldl op { names = []; values = []; } configs) //
+      { __type = "repeated"; };
+
+in
+
+{
+  ###### interface
+
+  options = {
+    services.logstash = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Enable logstash.
+        '';
+      };
+
+      inputConfig = mkOption {
+        default = {};
+        description = ''
+          An attr set representing a logstash configuration's input section.
+          logstash configs are name-value pairs, where values can be bools,
+          strings, numbers, arrays, hashes, or other name-value pairs,
+          and names are strings that can be repeated. name-value pairs with no
+          repeats are represented by attr sets. name-value pairs with repeats
+          are represented by an attrset with attr "__type" = "repeated" and
+          attrs "names" and "values" as matching lists pairing name and value.
+          bools, strings, ints, and arrays are mapped directly. Floats are
+          represented as an attrset with attr "__type" = "float" and attr value
+          set to the string representation of the float. Hashes are represented
+          with attr "__type" = "hash" and attr value set to an attr set
+          corresponding to the hash.
+        '';
+        merge = mergeConfigs;
+      };
+
+      filterConfig = mkOption {
+        default = {};
+        description = ''
+          An attr set representing a logstash configuration's filter section.
+          See inputConfig description for details.
+        '';
+        merge = mergeConfigs;
+      };
+
+      outputConfig = mkOption {
+        default = {};
+        description = ''
+          An attr set representing a logstash configuration's output section.
+          See inputConfig description for details.
+        '';
+        merge = mergeConfigs;
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    # Always log to stdout
+    services.logstash.outputConfig = { stdout = {}; };
+
+    jobs.logstash = with pkgs; {
+      description = "Logstash daemon";
+
+      path = [ jre ];
+
+      exec = "java -jar ${logstash} agent -f ${writeText "logstash.conf" ''
+        input {
+          ${exprToConfig cfg.inputConfig}
+        }
+
+        filter {
+          ${exprToConfig cfg.filterConfig}
+        }
+
+        output {
+          ${exprToConfig cfg.outputConfig}
+        }
+      ''}";
+    };
+  };
+}