Skip to content

Commit e4e6837

Browse files
committed
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.
1 parent 860ea0c commit e4e6837

File tree

6 files changed

+275
-99
lines changed

6 files changed

+275
-99
lines changed

Diff for: doc/10-Channels.md

+250-40
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,298 @@
11
# Channels
22

33
After Icinga Notifications decides to send a notification of any kind, it will be passed to a channel plugin.
4-
Such a channel plugin submits the notification event to a channel, e.g., email or a chat client.
4+
Such a plugin submits the notification event to a domain-specific channel, e.g., email or a chat client.
55

6-
Icinga Notifications comes packed with channel plugins, but also enables you to develop your own plugins.
6+
Icinga Notifications comes packed with channels, but also enables you to develop your own channels.
77

8-
To make those plugins available to Icinga Notifications, they must be placed in the
8+
To make those channels available to Icinga Notifications, they must be placed in the
99
[channels directory](03-Configuration.md#channels-directory),
1010
which is being done automatically for package installations.
11-
Afterwards they can be configured through Icinga Notifications Web.
11+
At startup, Icinga Notifications scans this directory, starts each channel once to query its configuration options
12+
and stores these options in the database.
13+
Using this information, Icinga Notifications Web allows channels to be configured,
14+
which are then started, configured, and lastly used to send notification events from Icinga Notifications.
1215

1316
## Technical Channel Description
1417

15-
Channel plugins are processes that run continuously and independently of each other. They receive many requests over
16-
their lifetime. They receive JSON-formatted requests on stdin and reply with JSON-formatted responses on stdout. The
17-
request and response structure is inspired by JSON-RPC.
18+
!!! warning
19+
20+
As this is still an early preview version, things might change.
21+
There may still be severe bugs and incompatible changes may happen without any notice.
22+
23+
Channel plugins are independent processes that run continuously, supervised by Icinga Notifications.
24+
They receive JSON-formatted requests on `stdin` and reply with JSON-formatted responses on `stdout`.
25+
The request and response structure is inspired by JSON-RPC.
26+
27+
Note that this documentation uses beautified JSON for ease of reading.
28+
29+
For logging or debugging, channels can write to `stderr`, which will be logged by Icinga Notifications.
1830

1931
### Request
2032

21-
The request must be in JSON format and should contain following keys:
33+
A channel receives a request as a JSON object with the following fields:
2234

2335
- `method`: The request method to call.
24-
- `params`: The params for request method.
36+
- `params`: Optional params for the request method.
2537
- `id`: Unsigned int value. Required to assign the response to its request as responses can be sent out of order.
2638

2739
Examples:
2840

41+
- Simple request without any `params`:
42+
```json
43+
{
44+
"method": "Simple",
45+
"id" : 1000
46+
}
47+
```
48+
- Request with `params` of different types:
49+
```json
50+
{
51+
"method": "WithParams",
52+
"params": {
53+
"foo": 23,
54+
"bar": "hello"
55+
},
56+
"id": 1000
57+
}
58+
```
59+
60+
### Response
61+
62+
Each request must be answered by the channel with a response JSON object of the following fields:
63+
64+
- `result`: The result as JSON format. Omitted when the method does not return a value, i.e., for setter calls, or an
65+
error has occurred.
66+
- `error`: The error message. Omitted when no error has occurred.
67+
- `id`: The request id.
68+
69+
In case of a present `error` value, the `result` field should be empty.
70+
Successfully responses without a `result` do only contain the `id` field.
71+
72+
Examples:
73+
74+
- Successfully response without a `result` message:
75+
```json
76+
{
77+
"id": 1000
78+
}
79+
```
80+
- Successfully response with a `result`:
81+
```json
82+
{
83+
"result": "hello world",
84+
"id": 1000
85+
}
86+
```
87+
- Response with an error:
88+
```json
89+
{
90+
"error": "unknown method: 'Foo'",
91+
"id": 1000
92+
}
93+
```
94+
95+
### Methods
96+
97+
The following methods must be implemented by a channel.
98+
99+
#### GetInfo
100+
101+
The parameterless `GetInfo` method returns information about the channel.
102+
103+
Its `result` is expected to be a JSON object with the `json` fields defined in the
104+
[`Info` type](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#Info).
105+
The `config_attrs` field must be an array of JSON objects according to the
106+
[`ConfigOption` type](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#ConfigOption).
107+
Those attributes define configuration options for the channel to be set via the `SetConfig` method.
108+
Furthermore, they are used to build the channel configuration UI in Icinga Notifications Web.
109+
110+
##### Example GetInfo Request
111+
29112
```json
30113
{
31-
"method": "Add",
32-
"params": {
33-
"num1": 5,
34-
"num2": 3
114+
"method": "GetInfo",
115+
"id" : 1
116+
}
117+
```
118+
119+
##### Example GetInfo Response
120+
121+
```json
122+
{
123+
"result": {
124+
"name": "Minified Webhook",
125+
"version": "0.0.0-gf369a11-dirty",
126+
"author": "Icinga GmbH",
127+
"config_attrs": [
128+
{
129+
"name": "url_template",
130+
"type": "string",
131+
"label": {
132+
"de_DE": "URL-Template",
133+
"en_US": "URL Template"
134+
},
135+
"help": {
136+
"de_DE": "URL, optional als Go-Template über das zu verarbeitende plugin.NotificationRequest.",
137+
"en_US": "URL, optionally as a Go template over the current plugin.NotificationRequest."
138+
},
139+
"required": true,
140+
"min": null,
141+
"max": null
142+
},
143+
{
144+
"name": "response_status_codes",
145+
"type": "string",
146+
"label": {
147+
"de_DE": "Antwort-Status-Codes",
148+
"en_US": "Response Status Codes"
149+
},
150+
"help": {
151+
"de_DE": "Kommaseparierte Liste erwarteter Status-Code der HTTP-Antwort, z.B.: 200,201,202,208,418",
152+
"en_US": "Comma separated list of expected HTTP response status code, e.g., 200,201,202,208,418"
153+
},
154+
"default": "200",
155+
"min": null,
156+
"max": null
157+
}
158+
]
35159
},
36-
"id": 2020
160+
"id": 1
37161
}
38162
```
39163

164+
#### SetConfig
165+
166+
The `SetConfig` method configures the channel and
167+
should be called at least once before sending the first notifications to initialize the channel plugin.
168+
169+
The passed JSON object in the request's `param` field reflects the objects from `GetInfo`'s `config_attrs`.
170+
Each object within the `config_attrs` array can be configured by using its `name` attribute as the key together with the
171+
desired configuration value, being of the specified type in the `type` field.
172+
173+
To illustrate, the URL template from the above output is configurable with the following JSON object passed in `params`:
174+
40175
```json
41176
{
42-
"method": "Foo",
177+
"url_template": "http://localhost:8000/update/{{.Incident.Id}}"
178+
}
179+
```
180+
181+
The response might carry an error if the configuration is invalid.
182+
183+
##### Example SetConfig Request
184+
185+
```json
186+
{
187+
"method": "SetConfig",
43188
"params": {
44-
"a": "value1",
45-
"b": "value2"
189+
"url_template": "http://localhost:8000/update/{{.Incident.Id}}",
190+
"response_status_codes": "200"
46191
},
47-
"id": 3030
192+
"id": 2
48193
}
49194
```
50195

51-
### Response
196+
##### Example GetInfo Response
52197

53-
The response is in JSON format and contains following keys:
198+
```json
199+
{
200+
"id": 2
201+
}
202+
```
54203

55-
- `result`: The result as JSON format. Omitted when the method does not return a value (e.g. setter calls) or an error
56-
has occurred.
57-
- `error`: The error message. Omitted when no error has occurred.
58-
- `id`: The request id. When result value is empty and no error is occurred, the response will only contain the request
59-
id.
204+
#### SendNotification
60205

61-
Examples:
206+
The `SendNotification` method requests the channel to dispatch notifications.
207+
208+
Within the request's `params`, a JSON object representing a
209+
[`NotificationRequest`](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#NotificationRequest)
210+
is expected.
211+
212+
The response might carry an error due to channel-specific reasons.
213+
214+
#### Example SendNotification Request
62215

63216
```json
64217
{
65-
"result": 8,
66-
"id": 2020
218+
"method": "SendNotification",
219+
"params": {
220+
"contact": {
221+
"full_name": "icingaadmin",
222+
"addresses": [
223+
{
224+
"type": "email",
225+
"address": "[email protected]"
226+
}
227+
]
228+
},
229+
"object": {
230+
"name": "dummy-816!random fortune",
231+
"url": "http://localhost/icingaweb2/icingadb/service?name=random%20fortune&host.name=dummy-816",
232+
"tags": {
233+
"host": "dummy-816",
234+
"service": "random fortune"
235+
},
236+
"extra_tags": {
237+
"hostgroup/app-mobile": "",
238+
"hostgroup/department-dev": "",
239+
"hostgroup/env-prod": "",
240+
"hostgroup/location-rome": "",
241+
"servicegroup/app-storage": "",
242+
"servicegroup/department-ps": "",
243+
"servicegroup/env-prod": "",
244+
"servicegroup/location-rome": ""
245+
}
246+
},
247+
"incident": {
248+
"id": 1437,
249+
"url": "http://localhost/icingaweb2/notifications/incident?id=1437",
250+
"severity": "crit"
251+
},
252+
"event": {
253+
"time": "2024-07-12T10:47:30.445439055Z",
254+
"type": "state",
255+
"username": "",
256+
"message": "Q:\tWhat looks like a cat, flies like a bat, brays like a donkey, and\n\tplays like a monkey?\nA:\tNothing."
257+
}
258+
},
259+
"id": 3
67260
}
68261
```
69262

263+
#### Example SendNotification Response
264+
70265
```json
71266
{
72-
"error": "unknown method: 'Foo'",
73-
"id": 3030
267+
"id": 3
74268
}
75269
```
76270

77-
### Methods
271+
## Writing Channel Plugins in Go
272+
273+
!!! warning
274+
275+
As this is still an early preview version, things might change.
276+
There may still be severe bugs and incompatible changes may happen without any notice.
277+
278+
!!! tip
279+
280+
Icinga Notifications comes with a Webhook channel plugin.
281+
Consider using this channel if your transport uses HTTP instead of writing a custom channel.
282+
283+
!!! tip
284+
285+
When developing custom channels, consider naming them with a unique prefix,
286+
as additional channels will get added to Icinga Notifications in the future.
287+
For example, name your channel `x_irc` or `my_irc` instead of `irc`.
78288

79-
Currently, the channel plugin include following three methods:
289+
Since Icinga Notifications and all of its channels are written in the Go programming language,
290+
libraries already used internally can be reused.
291+
In particular, the [`Plugin`](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#Plugin)
292+
interface must be implemented, requesting methods for all the RPC methods described above.
293+
The channel plugin's `main` function should call
294+
[`RunPlugin`](https://pkg.go.dev/github.com/icinga/icinga-notifications/pkg/plugin#RunPlugin),
295+
taking care about calling the RPC method implementations.
80296

81-
- `SetConfig`: Initialize the channel plugin with specified config as `params` key. The config is plugin specific
82-
therefore each plugin defines what is expected as config.
83-
[(example)](../internal/channel/examples/set-config.json)
84-
- `GetInfo`: Get the information about the channel e.g. Name. The `params` key has no effect and can be omitted.
85-
[(example)](../internal/channel/examples/get-info.json)
86-
- `SendNotification`: Send the notifications. The `params` key should contain the information about the contact to be
87-
notified, corresponding object, the incident and the triggered event.
88-
[(example)](../internal/channel/examples/send-notification.json)
297+
For concrete examples, there are the implemented channels in the Icinga Notifications repository under
298+
[`./cmd/channels`](https://github.com/Icinga/icinga-notifications/tree/main/cmd/channels).

Diff for: doc/20-HTTP-API.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ curl -v -u 'source-2:insecureinsecure' -d '@-' 'http://localhost:5680/process-ev
3535
"type": "state",
3636
"severity": "crit",
3737
"username": "",
38-
"message": "Something went somehwere very wrong."
38+
"message": "Something went somewhere very wrong."
3939
}
4040
EOF
4141
```

Diff for: internal/channel/examples/get-info.json

-4
This file was deleted.

Diff for: internal/channel/examples/send-notification.json

-38
This file was deleted.

0 commit comments

Comments
 (0)