-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Increase details of Channels documentation
With a release approaching, the Channels documentation got more information about how the Channel system actually work and how to build your own channels. The internal/changes/examples JSON files were inlined to ease the readability and updated, as they contained partially outdated information. For the pkg/plugin part, some API documentation was added as this might get used by external users.
- Loading branch information
Showing
6 changed files
with
291 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,312 @@ | ||
# Channels | ||
|
||
After Icinga Notifications decides to send a notification of any kind, it will be passed to a channel plugin. | ||
Such a channel plugin submits the notification event to a channel, e.g., email or a chat client. | ||
Such a plugin submits the notification event to a domain-specific channel, e.g., email or a chat client. | ||
|
||
Icinga Notifications comes packed with channel plugins, but also enables you to develop your own plugins. | ||
Icinga Notifications comes packed with channels, but also enables you to develop your own channels. | ||
|
||
To make those plugins available to Icinga Notifications, they must be placed in the | ||
To make those channels available to Icinga Notifications, they must be placed in the | ||
[channels directory](03-Configuration.md#channels-directory), | ||
which is being done automatically for package installations. | ||
Afterwards they can be configured through Icinga Notifications Web. | ||
At startup, Icinga Notifications scans this directory, starts each channel once to query its configuration options | ||
and stores these options in the database. | ||
Using this information, Icinga Notifications Web allows channels to be configured, | ||
which are then started, configured, and lastly used to send notification events from Icinga Notifications. | ||
|
||
## Technical Channel Description | ||
|
||
Channel plugins are processes that run continuously and independently of each other. They receive many requests over | ||
their lifetime. They receive JSON-formatted requests on stdin and reply with JSON-formatted responses on stdout. The | ||
request and response structure is inspired by JSON-RPC. | ||
!!! warning | ||
|
||
As this is still an early preview version, things might change. | ||
There may still be severe bugs and incompatible changes may happen without any notice. | ||
|
||
Channel plugins are independent processes that run continuously, supervised by Icinga Notifications. | ||
They receive JSON-formatted requests on `stdin` and reply with JSON-formatted responses on `stdout`. | ||
For logging or debugging, channels can write to `stderr`, which will be logged by Icinga Notifications. | ||
|
||
The request and response structure is inspired by JSON-RPC. | ||
The anatomy of requests and responses is described below. | ||
Note that fields with a type marked as optional must be omitted in the JSON object if they do not have a value. | ||
|
||
This documentation uses beautified JSON for ease of reading. | ||
|
||
### Request | ||
|
||
The request must be in JSON format and should contain following keys: | ||
A channel receives a request as a JSON object with the following fields: | ||
|
||
- `method`: The request method to call. | ||
- `params`: The params for request method. | ||
- `id`: Unsigned int value. Required to assign the response to its request as responses can be sent out of order. | ||
| Field | Description | Type | | ||
|----------|-------------------------------|------------------------------------------------------------------------| | ||
| `method` | Request method to call. | String | | ||
| `params` | Params for the request method | Optional JSON object, mapping parameter keys (string) to values (any). | | ||
| `id` | Unique identifier. | Unsigned integer | | ||
|
||
Examples: | ||
|
||
- Simple request without any `params`: | ||
```json | ||
{ | ||
"method": "Simple", | ||
"id" : 1000 | ||
} | ||
``` | ||
- Request with `params` of different types: | ||
```json | ||
{ | ||
"method": "WithParams", | ||
"params": { | ||
"foo": 23, | ||
"bar": "hello" | ||
}, | ||
"id": 1000 | ||
} | ||
``` | ||
|
||
### Response | ||
|
||
Each request must be answered by the channel with a response JSON object of the following fields: | ||
|
||
| Field | Description | Type | | ||
|----------|-------------------------------------|---------------------------| | ||
| `result` | Output of a successful method call. | Optional JSON value (any) | | ||
| `error` | Error message. | Optional string | | ||
| `id` | Request id. | Unsigned integer | | ||
|
||
The `result` field may be omitted if the method does not return a value, i.e., for setter calls. | ||
|
||
In case of a present `error` value, the `result` field must be omitted. | ||
Thus, a successful responses without a `result` contains just an `id` field. | ||
|
||
The `id` field in a response must match those of its request, allowing Icinga Notifications to link those two. | ||
This is necessary as responses may be created out of order. | ||
|
||
Examples: | ||
|
||
- Successful response without a `result` message: | ||
```json | ||
{ | ||
"id": 1000 | ||
} | ||
``` | ||
- Successful response with a `result`: | ||
```json | ||
{ | ||
"result": "hello world", | ||
"id": 1000 | ||
} | ||
``` | ||
- Response with an error: | ||
```json | ||
{ | ||
"error": "unknown method: 'Foo'", | ||
"id": 1000 | ||
} | ||
``` | ||
|
||
### Methods | ||
|
||
The following methods must be implemented by a channel. | ||
|
||
#### GetInfo | ||
|
||
The parameterless `GetInfo` method returns information about the channel. | ||
|
||
Its `result` is expected to be a JSON object with the `json` fields defined in the | ||
[`Info` type](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#Info). | ||
The `config_attrs` field must be an array of JSON objects according to the | ||
[`ConfigOption` type](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#ConfigOption). | ||
Those attributes define configuration options for the channel to be set via the `SetConfig` method. | ||
Furthermore, they are used for channel configuration in Icinga Notifications Web. | ||
|
||
##### Example GetInfo Request | ||
|
||
```json | ||
{ | ||
"method": "Add", | ||
"params": { | ||
"num1": 5, | ||
"num2": 3 | ||
"method": "GetInfo", | ||
"id" : 1 | ||
} | ||
``` | ||
|
||
##### Example GetInfo Response | ||
|
||
```json | ||
{ | ||
"result": { | ||
"name": "Minified Webhook", | ||
"version": "0.0.0-gf369a11-dirty", | ||
"author": "Icinga GmbH", | ||
"config_attrs": [ | ||
{ | ||
"name": "url_template", | ||
"type": "string", | ||
"label": { | ||
"de_DE": "URL-Template", | ||
"en_US": "URL Template" | ||
}, | ||
"help": { | ||
"de_DE": "URL, optional als Go-Template über das zu verarbeitende plugin.NotificationRequest.", | ||
"en_US": "URL, optionally as a Go template over the current plugin.NotificationRequest." | ||
}, | ||
"required": true, | ||
"min": null, | ||
"max": null | ||
}, | ||
{ | ||
"name": "response_status_codes", | ||
"type": "string", | ||
"label": { | ||
"de_DE": "Antwort-Status-Codes", | ||
"en_US": "Response Status Codes" | ||
}, | ||
"help": { | ||
"de_DE": "Kommaseparierte Liste erwarteter Status-Code der HTTP-Antwort, z.B.: 200,201,202,208,418", | ||
"en_US": "Comma separated list of expected HTTP response status code, e.g., 200,201,202,208,418" | ||
}, | ||
"default": "200", | ||
"min": null, | ||
"max": null | ||
} | ||
] | ||
}, | ||
"id": 2020 | ||
"id": 1 | ||
} | ||
``` | ||
|
||
#### SetConfig | ||
|
||
The `SetConfig` method configures the channel. | ||
|
||
The Icinga Notifications daemon is going to call this method at least once before sending the first notifications | ||
to initialize the channel plugin. | ||
|
||
The passed JSON object in the request's `param` field reflects the objects from `GetInfo`'s `config_attrs`. | ||
Each object within the `config_attrs` array must be configurable by using its `name` attribute as the key together with | ||
the desired configuration value, being of the specified type in the `type` field. | ||
|
||
To illustrate, the URL template from the above output is configurable with the following JSON object passed in `params`: | ||
|
||
```json | ||
{ | ||
"url_template": "http://localhost:8000/update/{{.Incident.Id}}" | ||
} | ||
``` | ||
|
||
If the channel plugin successfully configured itself, a response without an `result` must be returned. | ||
Otherwise, an `error` must be returned. | ||
|
||
##### Example SetConfig Request | ||
|
||
```json | ||
{ | ||
"method": "Foo", | ||
"method": "SetConfig", | ||
"params": { | ||
"a": "value1", | ||
"b": "value2" | ||
"url_template": "http://localhost:8000/update/{{.Incident.Id}}", | ||
"response_status_codes": "200" | ||
}, | ||
"id": 3030 | ||
"id": 2 | ||
} | ||
``` | ||
|
||
### Response | ||
##### Example GetInfo Response | ||
|
||
```json | ||
{ | ||
"id": 2 | ||
} | ||
``` | ||
|
||
The response is in JSON format and contains following keys: | ||
#### SendNotification | ||
|
||
- `result`: The result as JSON format. Omitted when the method does not return a value (e.g. setter calls) or an error | ||
has occurred. | ||
- `error`: The error message. Omitted when no error has occurred. | ||
- `id`: The request id. When result value is empty and no error is occurred, the response will only contain the request | ||
id. | ||
The `SendNotification` method requests the channel to dispatch notifications. | ||
|
||
Examples: | ||
Within the request's `params`, a JSON object representing a | ||
[`NotificationRequest`](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#NotificationRequest) | ||
is passed. | ||
|
||
If the channel cannot dispatch a notification, an `error` must be returned. | ||
This may be due to channel-specific reasons, such as an email channel where the SMTP server is unavailable. | ||
|
||
#### Example SendNotification Request | ||
|
||
```json | ||
{ | ||
"result": 8, | ||
"id": 2020 | ||
"method": "SendNotification", | ||
"params": { | ||
"contact": { | ||
"full_name": "icingaadmin", | ||
"addresses": [ | ||
{ | ||
"type": "email", | ||
"address": "[email protected]" | ||
} | ||
] | ||
}, | ||
"object": { | ||
"name": "dummy-816!random fortune", | ||
"url": "http://localhost/icingaweb2/icingadb/service?name=random%20fortune&host.name=dummy-816", | ||
"tags": { | ||
"host": "dummy-816", | ||
"service": "random fortune" | ||
}, | ||
"extra_tags": { | ||
"hostgroup/app-mobile": "", | ||
"hostgroup/department-dev": "", | ||
"hostgroup/env-prod": "", | ||
"hostgroup/location-rome": "", | ||
"servicegroup/app-storage": "", | ||
"servicegroup/department-ps": "", | ||
"servicegroup/env-prod": "", | ||
"servicegroup/location-rome": "" | ||
} | ||
}, | ||
"incident": { | ||
"id": 1437, | ||
"url": "http://localhost/icingaweb2/notifications/incident?id=1437", | ||
"severity": "crit" | ||
}, | ||
"event": { | ||
"time": "2024-07-12T10:47:30.445439055Z", | ||
"type": "state", | ||
"username": "", | ||
"message": "Q:\tWhat looks like a cat, flies like a bat, brays like a donkey, and\n\tplays like a monkey?\nA:\tNothing." | ||
} | ||
}, | ||
"id": 3 | ||
} | ||
``` | ||
|
||
#### Example SendNotification Response | ||
|
||
```json | ||
{ | ||
"error": "unknown method: 'Foo'", | ||
"id": 3030 | ||
"id": 3 | ||
} | ||
``` | ||
|
||
### Methods | ||
## Writing Channel Plugins in Go | ||
|
||
!!! warning | ||
|
||
As this is still an early preview version, things might change. | ||
There may still be severe bugs and incompatible changes may happen without any notice. | ||
|
||
!!! tip | ||
|
||
Icinga Notifications comes with a Webhook channel plugin. | ||
Consider using this channel if your transport uses HTTP instead of writing a custom channel. | ||
|
||
!!! tip | ||
|
||
When developing custom channels, consider naming them with a unique prefix, | ||
as additional channels will get added to Icinga Notifications in the future. | ||
For example, name your channel `x_irc` or `my_irc` instead of `irc`. | ||
|
||
Currently, the channel plugin include following three methods: | ||
Since Icinga Notifications and all of its channels are written in the Go programming language, | ||
libraries already used internally can be reused. | ||
In particular, the [`Plugin`](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#Plugin) | ||
interface must be implemented, requesting methods for all the RPC methods described above. | ||
The channel plugin's `main` function should call | ||
[`RunPlugin`](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#RunPlugin), | ||
taking care about calling the RPC method implementations. | ||
|
||
- `SetConfig`: Initialize the channel plugin with specified config as `params` key. The config is plugin specific | ||
therefore each plugin defines what is expected as config. | ||
[(example)](../internal/channel/examples/set-config.json) | ||
- `GetInfo`: Get the information about the channel e.g. Name. The `params` key has no effect and can be omitted. | ||
[(example)](../internal/channel/examples/get-info.json) | ||
- `SendNotification`: Send the notifications. The `params` key should contain the information about the contact to be | ||
notified, corresponding object, the incident and the triggered event. | ||
[(example)](../internal/channel/examples/send-notification.json) | ||
For concrete examples, there are the implemented channels in the Icinga Notifications repository under | ||
[`./cmd/channels`](https://github.com/Icinga/icinga-notifications/tree/main/cmd/channels). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.