Refactor alert templates to use Laravel Blade templating engine (#8803)

* Initial start on new templating support

* further updates

* more updates

* More working version

* Last fixes

* Small updates

* modified test to look for dbname.

* Schema update

* Added fix for not being able to disable Philips Hue transport

* Updated sql file

* Updated db_schema

* Set myclabs/deep-copy to be 1.7.x version in composer

* Fixes from murrant

* Forced nikic/php-parser to version 3.1.x in composer

* Updated composer to use custom fork of string-blade-compiler + fixed transport use

* Updated to always use correct template

* Merged legacy and blade templating engines

* Removed template type + fixed test-alert.php

* Added more template placeholders

* Added ability to reference data in templates as $alert->X

* Updated docs for templates

* Updated db_schema.yaml

* Added $alert->builder

* Clarify the use of $alert->builder

* Fixed the use of $alert->transport

* renamed schema file

* Added template validation

* Small update to fix travis issue

* Add Docs text to title bar

* Updated amqp to new of version

* Consistency in alert rule and template title bars
This commit is contained in:
Neil Lathwood
2018-07-14 22:15:43 +01:00
committed by GitHub
parent b56380c261
commit ad6ec7f72a
28 changed files with 1121 additions and 587 deletions

View File

@@ -2,70 +2,66 @@ source: Alerting/Templates.md
# Templates
> This page is for installs running version 1.41 or later. You can find the older docs [here](Old_Templates.md)
Templates can be assigned to a single or a group of rules and can contain any kind of text. There is also a default template which is used for any rule that isn't associated with a template. This template can be found under `Alert Templates` page and can be edited. It also has an option revert it back to its default content.
The template-parser understands `if` and `foreach` controls and replaces certain placeholders with information gathered about the alert.
The templating engine in use is Laravel Blade. We will cover some of the basics here, however the official Laravel docs will have more information [here](https://laravel.com/docs/5.4/blade)
## Syntax
Controls:
- if-else (Else can be omitted):
`{if %placeholder == value}Some Text{else}Other Text{/if}`
`@if ($alert->placeholder == 'value') Some Text @else Other Text @endif`
- foreach-loop:
`{foreach %faults}Key: %key<br/>Value: %value{/foreach}`
`@foreach ($alert->faults as $key => $value) Key: $key<br/>Value: $value @endforeach`
Placeholders:
Placeholders are special variables that if used within the template will be replaced with the relevant data, I.e:
`The device %hostname has been up for %uptime seconds` would result in the following `The device localhost has been up for 30344 seconds`.
`The device {{ $alert->hostname }} has been up for {{ $alert->uptime }} seconds` would result in the following `The device localhost has been up for 30344 seconds`.
- Device ID: `%device_id`
- Hostname of the Device: `%hostname`
- sysName of the Device: `%sysName`
- sysDescr of the Device: `%sysDescr`
- hardware of the Device: `%hardware`
- Software version of the Device: `%version`
- location of the Device: `%location`
- uptime of the Device (in seconds): `%uptime`
- short uptime of the Device (28d 22h 30m 7s): `%uptime_short`
- long uptime of the Device (28 days, 22h 30m 7s): `%uptime_long`
- description (purpose db field) of the Device: `%description`
- notes of the Device: `%notes`
- notes of the alert: `%alert_notes`
- ping timestamp (if icmp enabled): `%ping_timestamp`
- ping loss (if icmp enabled): `%ping_loss`
- ping min (if icmp enabled): `%ping_min`
- ping max (if icmp enabled): `%ping_max`
- ping avg (if icmp enabled): `%ping_avg`
- Title for the Alert: `%title`
- Time Elapsed, Only available on recovery (`%state == 0`): `%elapsed`
- Alert-ID: `%id`
- Unique-ID: `%uid`
- Faults, Only available on alert (`%state != 0`), must be iterated in a foreach (`{foreach %faults}`). Holds all available information about the Fault, accessible in the format `%value.Column`, for example: `%value.ifDescr`. Special field `%value.string` has most Identification-information (IDs, Names, Descrs) as single string, this is the equivalent of the default used.
- State: `%state`
- Severity: `%severity`
- Rule: `%rule`
- Rule-Name: `%name`
- Timestamp: `%timestamp`
- Transport name: `%transport`
> When using placeholders to echo data, you need to wrap the placeholder in `{{ }}`. I.e `{{ $alert->hostname }}`.
- Contacts, must be iterated in a foreach, `%key` holds email and `%value` holds name: `%contacts`
- Device ID: `$alert->device_id`
- Hostname of the Device: `$alert->hostname`
- sysName of the Device: `$alert->sysName`
- sysDescr of the Device: `$alert->sysDescr`
- sysContact of the Device: `$alert->sysContact`
- OS of the Device: `$alert->os`
- Type of Device: `$alert->type`
- IP of the Device: `$alert->ip`
- hardware of the Device: `$alert->hardware`
- Software version of the Device: `$alert->version`
- location of the Device: `$alert->location`
- uptime of the Device (in seconds): `$alert->uptime`
- short uptime of the Device (28d 22h 30m 7s): `$alert->uptime_short`
- long uptime of the Device (28 days, 22h 30m 7s): `$alert->uptime_long`
- description (purpose db field) of the Device: `$alert->description`
- notes of the Device: `$alert->notes`
- notes of the alert: `$alert->alert_notes`
- ping timestamp (if icmp enabled): `$alert->ping_timestamp`
- ping loss (if icmp enabled): `$alert->ping_loss`
- ping min (if icmp enabled): `$alert->ping_min`
- ping max (if icmp enabled): `$alert->ping_max`
- ping avg (if icmp enabled): `$alert->ping_avg`
- Title for the Alert: `$alert->title`
- Time Elapsed, Only available on recovery (`$alert->state == 0`): `$alert->elapsed`
- Rule Builder (the actual rule) (use `{!! $alert->builder !!}`): `$alert->builder`
- Alert-ID: `$alert->id`
- Unique-ID: `$alert->uid`
- Faults, Only available on alert (`$alert->state != 0`), must be iterated in a foreach (`@foreach ($alert->faults as $key => $value) @endforeach`). Holds all available information about the Fault, accessible in the format `$value['Column']`, for example: `$value['ifDescr']`. Special field `$value['string']` has most Identification-information (IDs, Names, Descrs) as single string, this is the equivalent of the default used.
- State: `$alert->state`
- Severity: `$alert->severity`
- Rule: `$alert->rule`
- Rule-Name: `$alert->name`
- Timestamp: `$alert->timestamp`
- Transport name: `$alert->transport`
- Contacts, must be iterated in a foreach, `$key` holds email and `$value` holds name: `$alert->contacts`
Placeholders can be used within the subjects for templates as well although %faults is most likely going to be worthless.
> NOTE: Placeholder names which are contained within another need to be ordered correctly. As an example:
```text
Limit: %value.sensor_limit / %value.sensor_limit_low
```
Should be done as:
```text
Limit: %value.sensor_limit_low / %value.sensor_limit
```
Placeholders can be used within the subjects for templates as well although $faults is most likely going to be worthless.
The Default Template is a 'one-size-fit-all'. We highly recommend defining your own templates for your rules to include more specific information.
@@ -73,135 +69,138 @@ The Default Template is a 'one-size-fit-all'. We highly recommend defining your
Default Template:
```text
%title
Severity: %severity
{if %state == 0}Time elapsed: %elapsed{/if}
Timestamp: %timestamp
Unique-ID: %uid
Rule: {if %name}%name{else}%rule{/if}
{if %faults}Faults:
{foreach %faults} #%key: %value.string{/foreach}{/if}
Alert sent to: {foreach %contacts}%value <%key> {/foreach}
{{ $alert->title }}
Severity: {{ $alert->severity }}
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif
Timestamp: {{ $alert->timestamp }}
Unique-ID: {{ $alert->uid }}
Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif
@if ($alert->faults) Faults:
@foreach ($alert->faults as $key => $value)
#{{ $key }}: {{ $value['string'] }}
@endforeach
@endif
Alert sent to:
@foreach ($alert->contacts as $key => $value)
{{ $value }} <{{ $key }}>
@endforeach
```
Ports Utilization Template:
```text
%title
Device Name: %hostname
Severity: %severity
{if %state == 0}Time elapsed: %elapsed{/if}
Timestamp: %timestamp
Rule: {if %name}%name{else}%rule{/if}
{foreach %faults}
Physical Interface: %value.ifDescr
Interface Description: %value.ifAlias
Interface Speed: {calc (%value.ifSpeed/1000000000)} Gbs
Inbound Utilization: {calc ((%value.ifInOctets_rate*8)/%value.ifSpeed)*100}%
Outbound Utilization: {calc ((%value.ifOutOctets_rate*8)/%value.ifSpeed)*100}%
{/foreach}
{{ $alert->title }}
Device Name: {{ $alert->hostname }}
Severity: {{ $alert->severity }}
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif
Timestamp: {{ $alert->timestamp }}
Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif
@foreach ($alert->faults as $key => $value)
Physical Interface: $value['ifDescr']
Interface Description: $value['ifAlias']
Interface Speed: @php echo ($value['ifSpeed']/1000000000); @endphp Gbs
Inbound Utilization: @php echo (($value['ifInOctets_rate']*8)/$value['ifSpeed'])*100; @endphp%
Outbound Utilization: @php echo (($value['ifOutOctets_rate']*8)/$value['ifSpeed'])*100; @endphp%
@endforeach
```
Storage:
```text
{{ $alert->title }}
%title
Device Name: {{ $alert->hostname }}
Severity: {{ $alert->severity }}
Uptime: {{ $alert->uptime_short }}
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif
Timestamp: {{ $alert->timestamp }}
Location: {{ $alert->location }}
Description: {{ $alert->description }}
Features: {{ $alert->features }}
Purpose: {{ $alert->purpose }}
Notes: {{ $alert->notes }}
Device Name: %hostname
Severity: %severity
Uptime: %uptime_short
{if %state == 0}Time elapsed: %elapsed{/if}
Timestamp: %timestamp
Location: %location
Description: %description
Features: %features
Purpose: %purpose
Notes: %notes
Server: %sysName {foreach %faults}Mount Point: %value.storage_descr Percent Utilized: %value.storage_perc{/foreach}
Server: {{ $alert->sysName }} @foreach ($alert->faults as $key => $value)Mount Point: $value['storage_descr'] Percent Utilized: $value['storage_perc']@endforeach
```
Temperature Sensors:
```text
{{ $alert->title }}
%title
Device Name: {{ $alert->hostname }}
Severity: {{ $alert->severity }}
Timestamp: {{ $alert->timestamp }}
Uptime: {{ $alert->uptime_short }}
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif
Location: {{ $alert->location }}
Description: {{ $alert->description }}
Features: {{ $alert->features }}
Purpose: {{ $alert->purpose }}
Notes: {{ $alert->notes }}
Device Name: %hostname
Severity: %severity
Timestamp: %timestamp
Uptime: %uptime_short
{if %state == 0}Time elapsed: %elapsed{/if}
Location: %location
Description: %description
Features: %features
Purpose: %purpose
Notes: %notes
Rule: {if %name}%name{else}%rule{/if}
{if %faults}Faults:
{foreach %faults}
#%key: Temperature: %value.sensor_current°C
** {calc(%value.sensor_current-%value.sensor_limit)}°C over limit
Previous Measurement: %value.sensor_prev°C
High Temperature Limit: %value.sensor_limit°C
{/foreach}
{/if}
Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif
@if ($alert->faults) Faults:
@foreach ($faults as $key => $value)
#{{ $key }}: Temperature: $value['sensor_current']°C
** @php echo ($value['sensor_current']-$value['sensor_limit']); @endphp°C over limit
Previous Measurement: $value['sensor_prev']°C
High Temperature Limit: $value['sensor_limit']°C
@endforeach
@endif
```
Value Sensors:
```text
{{ $alert->title }}
%title
Device Name: {{ $alert->hostname }}
Severity: {{ $alert->severity }}
Timestamp: {{ $alert->timestamp }}
Uptime: {{ $alert->uptime_short }}
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif
Location: {{ $alert->location }}
Description: {{ $alert->description }}
Features: {{ $alert->features }}
Purpose: {{ $alert->purpose }}
Notes: {{ $alert->notes }}
Device Name: %hostname
Severity: %severity
Timestamp: %timestamp
Uptime: %uptime_short
{if %state == 0}Time elapsed: %elapsed{/if}
Location: %location
Description: %description
Features: %features
Purpose: %purpose
Notes: %notes
Rule: {if %name}%name{else}%rule{/if}
{if %faults}Faults:
{foreach %faults}
#%key: Sensor%value.sensor_current
** {calc(%value.sensor_current-%value.sensor_limit)}over limit
Previous Measurement: %value.sensor_prev
Limit: %value.sensor_limit
{/foreach}
{/if}
Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif
@if ($alert->faults) Faults:
@foreach ($alert->faults as $key => $value)
#{{ $key }}: Sensor {{ $value['sensor_current'] }}
** @php echo ($value['sensor_current']-$value['sensor_limit']); @endphp over limit
Previous Measurement: {{ $value['sensor_prev'] }}
Limit: {{ $value['sensor_limit'] }}
@endforeach
@endif
```
Memory Alert:
```text
%title
{{ $alert->title }}
Device Name: %hostname
Severity: %severity
Uptime: %uptime_short
{if %state == 0}Time elapsed: %elapsed{/if}
Timestamp: %timestamp
Location: %location
Description: %description
Notes: %notes
Device Name: {{ $alert->hostname }}
Severity: {{ $alert->severity }}
Uptime: {{ $alert->uptime_short }}
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif
Timestamp: {{ $alert->timestamp }}
Location: {{ $alert->location }}
Description: {{ $alert->description }}
Notes: {{ $alert->notes }}
Server: %hostname {foreach %faults}
Memory Description: %value.mempool_descr
Percent Utilized: %value.mempool_perc{/foreach}
Server: {{ $alert->hostname }}
@foreach ($alert->faults as $key => $value)
Memory Description: {{ $value['mempool_descr'] }}
Percent Utilized: {{ $value['mempool_perc'] }}
@endforeach
```
Conditional formatting example, will display a link to the host in email or just the hostname in any other transport:
```text
{if %transport == mail}<a href="https://my.librenms.install/device/device=%hostname/">%hostname</a>
{else}
%hostname
{/if}
@if ($alert->transport == mail)<a href="https://my.librenms.install/device/device={{ $alert->hostname }}/">{{ $alert->hostname }}</a>
@else
{{ $alert->hostname }}
@endif
```
Note the use of double-quotes. Single quotes (`'`) in templates will be escaped (replaced with `\'`) in the output and should therefore be avoided.
## Examples HTML
Note: To use HTML emails you must set HTML email to Yes in the WebUI under Global Settings > Alerting Settings > Email transport > Use HTML emails
@@ -215,43 +214,43 @@ $config['allow_unauth_graphs'] = true;
Service Alert:
```
<div style="font-family:Helvetica;">
<h2>{if %state == 1}<span style="color:red;">%severity{/if}
{if %state == 2}<span style="color:goldenrod;">acknowledged{/if}</span>
{if %state == 3}<span style="color:green;">recovering{/if}</span>
{if %state == 0}<span style="color:green;">recovered{/if}</span>
<h2>@if ($alert->state == 1) <span style="color:red;">{{ $alert->severity }} @endif
@if ($alert->state == 2) <span style="color:goldenrod;">acknowledged @endif</span>
@if ($alert->state == 3) <span style="color:green;">recovering @endif</span>
@if ($alert->state == 0) <span style="color:green;">recovered @endif</span>
</h2>
<b>Host:</b> %hostname<br>
<b>Duration:</b> %elapsed<br>
<b>Host:</b> {{ $alert->hostname }}<br>
<b>Duration:</b> {{ $alert->elapsed }}<br>
<br>
{if %faults}
{foreach %faults}<b>%value.service_desc - %value.service_type</b><br>
%value.service_message<br>
@if ($alert->faults)
@foreach ($alert->faults as $key => $value)<b>$value['service_desc'] - $value['service_type']</b><br>
$value['service_message']<br>
<br>
{/foreach}
{/if}
@endforeach
@endif
</div>
```
Processor Alert with Graph:
```
%title <br>
Severity: %severity <br>
{if %state == 0}Time elapsed: %elapsed{/if}
Timestamp: %timestamp <br>
Alert-ID: %id <br>
Rule: {if %name}%name{else}%rule{/if} <br>
{if %faults}Faults:
{foreach %faults}
#%key: %value.string <br>
{/foreach}
{if %faults}<b>Faults:</b><br>
{foreach %faults}<img src="https://server/graph.php?device=%value.device_id&type=device_processor&width=459&height=213&lazy_w=552&from=end-72h%22/%3E<br>
https://server/graphs/id=%value.device_id/type=device_processor/<br>
{/foreach}
{{ $alert->title }} <br>
Severity: {{ $alert->severity }} <br>
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif
Timestamp: {{ $alert->timestamp }} <br>
Alert-ID: {{ $alert->id }} <br>
Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif <br>
@if ($alert->faults) Faults:
@foreach ($alert->faults as $key => $value)
#{{ $key }}: {{ $value['string'] }}<br>
@endforeach
@if ($alert->faults) <b>Faults:</b><br>
@foreach ($alert->faults as $key => $value)<img src="https://server/graph.php?device={{ $value['device_id'] }}&type=device_processor&width=459&height=213&lazy_w=552&from=end-72h><br>
https://server/graphs/id={{ $value['device_id'] }}/type=device_processor/<br>
@endforeach
Template: CPU alert <br>
{/if}
{/if}
@endif
@endif
```
## Included