Package: alertbook
# alertbookAn Ansible-inspired Prometheus rules file compiler## InstallationThe recommended installation method is via `pip`:```pip install alertbook```For development use, clone this repository and install with the `-e`(development) flag in `pip`:```git clone https://github.com/kneitinger/alertbook.gitcd alertbookpip install -e .```## UsageThis program works in analogously to how `ansible-playbook` works.  A*rulebook* is like an `ansible` playbook, where variables are defined and thedesired rules are listed, each with conditions, or `conds`, under which theyshould be instantiated.A project layout might look something like:```alertbook_proj├── foo_cluster.yml└── rules├── DiskFailure└── DiskUsageHigh```By default, the `alertbook` command looks for rules in the `./rules` directory,and outputs compiled `*.rules` files to the `./out` directory, but these valuescan be modified with the `--rules-dir` and `--out-dir` command line arguments,respectively.### Rules_Note: this tool is currently only compatible with the rule format ofPrometheus versions less than 2.0_The rules files that `alertbook` expects look no different than the recordingand alert rules files that Prometheus already uses...in fact, files in thatformat can be included as is into an `alertbook` rules directory.  They canalso be augmented with variables (in the form `${foo}` that can be assigned ina rulebook. For example, the following rule,```ALERT DiskUsageOver${threshold}PercentIF node_filesystem_avail / node_filesystem_size < (100 - ${threshold}) / 100FOR 5mLABELS { severity = "${prio}" }ANNOTATIONS {description = "{{ $labels.instance }} disk usage has over {$threshold}%."}```parameterizes the disk usage percentage and alert priority with the`${threshold}` and `${prio}` variables, meaning that the same rule can be usedin a variety of contexts.### RulebooksA rulebook is a YAML file of the form.```---name: "Text to appear in compiled .rules file header"vars:some_ident: "in scope for all rules unless overwritten"rules:- file: path-relative-to-rules-dirconds:- some_var_in_rule_file: doopanother_var_in_rule_file: [8,16]- some_var_in_rule_file: floopanother_var_in_rule_file: 53```The `name` component is a purely cosmetic value that populates the header inthe output rules file's header.  The `vars` component allows you to defineglobal variables for the rulebook.The `rules` component is where all of the desired rules are listed, and theirvariables, if any, are instantiated.  Each entry has a `file` option, whichspecifies the path of the file relative to the default or user-specified rulesdirectory, and optionally, a `conds` list, where any remaining variables arespecified.#### ConditionsThe `conds` list can have many items (conditions), and each item may generate one ormore rules, depending on whether or not a variable is defined as an array.When a condition's variables only have single element values, `alertbook` fillsthe rule's variables in with those values, and adds it to the output text.When one or more of the condition's variables has an array value, `alertbook`creates a set of values equal to the Cartesian product of the condition'svariables and outputs one rule for each set.  See the **Example** section forfurther clarification.### Command```$ alertbook -husage: alertbook [-h] [-r DIR] [-o DIR] book [book ...]positional arguments:bookoptional arguments:-h, --help               show this help message and exit-r DIR, --rules-dir DIR  base directory of rules (default: './rules')-o DIR, --out-dir DIR    directory for compiled rules (default: './out')```### ExampleLet's use the following project structure```alertbook_proj├── foo_cluster.yml└── rules├── DiskFailure└── DiskUsageHigh```where,```$ cat foo_cluster.yml---name: Prometheus Alert Rules for foo clusterrules:- file: DiskFailureconds:- prio: lowhours: [8,16]- prio: highhours: 4- file: DiskUsageHighconds:- threshold: 85prio: high``````$ cat rules/DiskFailureALERT DiskWillFillIn{%hours}HoursIF predict_linear(node_filesystem_free[1h], ${hours}*3600) < 0FOR 5mLABELS { severity="${prio}" }``````$ cat rules/DiskUsageHighALERT DiskUsageOver${threshold}PercentIF node_filesystem_avail / node_filesystem_size < (100 - ${threshold}) / 100FOR 5mLABELS { severity = "${prio}" }ANNOTATIONS {description = "{{ $labels.instance }} disk usage has over {$threshold}%."}```if we examine the `rules` section of the `rulebook` we can see that we're using2 rules.The 2nd rule, `DiskUsageHigh`, is fairly straightforward, we are justpopulating the values of the variables in the rule file, one for diskpercentage, and one for alert priority.The 1st rule however has a it more going on:```- file: DiskFailureconds:- prio: lowhours: [8,16]- prio: highhours: 4```It's second condition is just like the `DiskUsageHigh` rule's form, but thefirst condition has an array.  Again, when `alertbook` encounters an array inone or more of a conditions variables, it constructs the Cartesian product ofthem and essentially generates one condition for each.  With that in mind, wecould interpret```conds:- foo: [bar, baz]floop: [doop,  boop]```as being equivalent to```conds:- foo: barfloop: doop- foo: barfloop: boop- foo: bazfloop: doop- foo: bazfloop: boop```When we run```alertbook foo_cluster```the following file is generated and output to `foo_cluster.rules` in the`./out` directory```########################################### Prometheus Alert Rules for foo cluster ############################################# DiskFailureALERT DiskWillFillIn{%hours}HoursIF predict_linear(node_filesystem_free[1h], 8*3600) < 0FOR 5mLABELS { severity="low" }ALERT DiskWillFillIn{%hours}HoursIF predict_linear(node_filesystem_free[1h], 16*3600) < 0FOR 5mLABELS { severity="low" }ALERT DiskWillFillIn{%hours}HoursIF predict_linear(node_filesystem_free[1h], 4*3600) < 0FOR 5mLABELS { severity="high" }## DiskUsageHighALERT DiskUsageOver70PercentIF node_filesystem_avail / node_filesystem_size < (100 - 70) / 100FOR 5mLABELS { severity = "low" }ANNOTATIONS {description = "{{ $labels.instance }} disk usage has over {$threshold}%."}ALERT DiskUsageOver85PercentIF node_filesystem_avail / node_filesystem_size < (100 - 85) / 100FOR 5mLABELS { severity = "high" }ANNOTATIONS {description = "{{ $labels.instance }} disk usage has over {$threshold}%."}```