master
md 909 lines 49 KB
Rendered Raw
1 # External plugins
2
3 `plugins.d` is the Netdata internal plugin that collects metrics
4 from external processes, thus allowing Netdata to use **external plugins**.
5
6 ## Provided External Plugins
7
8 | plugin | language | O/S | description |
9 |:------------------------------------------------------------------------------------------------------:|:--------:|:--------------:|:----------------------------------------------------------------------------------------------------------------------------------------|
10 | [apps.plugin](/src/collectors/apps.plugin/README.md) | `C` | linux, freebsd | monitors the whole process tree on Linux and FreeBSD and breaks down system resource usage by **process**, **user** and **user group**. |
11 | [charts.d.plugin](/src/collectors/charts.d.plugin/README.md) | `BASH` | all | a **plugin orchestrator** for data collection modules written in `BASH` v4+. |
12 | [cups.plugin](/src/collectors/cups.plugin/README.md) | `C` | all | monitors **CUPS** |
13 | [ebpf.plugin](/src/collectors/ebpf.plugin/README.md) | `C` | linux | monitors different metrics on environments using kernel internal functions. |
14 | [go.d.plugin](/src/go/plugin/go.d/README.md) | `GO` | all | collects metrics from the system, applications, or third-party APIs. |
15 | [ioping.plugin](/src/collectors/ioping.plugin/README.md) | `C` | all | measures disk latency. |
16 | [freeipmi.plugin](/src/collectors/freeipmi.plugin/README.md) | `C` | linux | collects metrics from enterprise hardware sensors, on Linux servers. |
17 | [nfacct.plugin](/src/collectors/nfacct.plugin/README.md) | `C` | linux | collects netfilter firewall, connection tracker and accounting metrics using `libmnl` and `libnetfilter_acct`. |
18 | [xenstat.plugin](/src/collectors/xenstat.plugin/README.md) | `C` | linux | collects XenServer and XCP-ng metrics using `lxenstat`. |
19 | [perf.plugin](/src/collectors/perf.plugin/README.md) | `C` | linux | collects CPU performance metrics using performance monitoring units (PMU). |
20 | [python.d.plugin](/src/collectors/python.d.plugin/README.md) | `python` | all | a **plugin orchestrator** for data collection modules written in `python` v2 or v3 (both are supported). |
21 | [slabinfo.plugin](/src/collectors/slabinfo.plugin/README.md) | `C` | linux | collects kernel internal cache objects (SLAB) metrics. |
22
23 Plugin orchestrators may also be described as **modular plugins**. They are modular since they accept custom made modules to be included. Writing modules for these plugins is easier than accessing the native Netdata API directly. You will find modules already available for each orchestrator under the directory of the particular modular plugin (e.g. under python.d.plugin for the python orchestrator).
24 Each of these modular plugins has each own methods for defining modules. Please check the examples and their documentation.
25
26 ## Motivation
27
28 This plugin allows Netdata to use **external plugins** for data collection:
29
30 1. external data collection plugins may be written in any computer language.
31
32 2. external data collection plugins may use O/S capabilities or `setuid` to
33 run with escalated privileges (compared to the `netdata` daemon).
34 The communication between the external plugin and Netdata is unidirectional
35 (from the plugin to Netdata), so that Netdata cannot manipulate an external
36 plugin running with escalated privileges.
37
38 ## Operation
39
40 Each of the external plugins is expected to run forever.
41 Netdata will start it when it starts and stop it when it exits.
42
43 If the external plugin exits or crashes, Netdata will log an error.
44 If the external plugin exits or crashes without pushing metrics to Netdata, Netdata will not start it again.
45
46 - Plugins that exit with any value other than zero, will be disabled. Plugins that exit with zero, will be restarted after some time.
47 - Plugins may also be disabled by Netdata if they output things that Netdata does not understand.
48
49 The `stdout` of external plugins is connected to Netdata to receive metrics,
50 with the API defined below.
51
52 The `stderr` of external plugins is connected to Netdata's `error.log`.
53
54 Plugins can create any number of charts with any number of dimensions each. Each chart can have its own characteristics independently of the others generated by the same plugin. For example, one chart may have an update frequency of 1 second, another may have 5 seconds and a third may have 10 seconds.
55
56 ## Configuration
57
58 Netdata will supply the environment variables `NETDATA_USER_CONFIG_DIR` (for user supplied) and `NETDATA_STOCK_CONFIG_DIR` (for Netdata supplied) configuration files to identify the directory where configuration files are stored. It is up to the plugin to read the configuration it needs.
59
60 The `netdata.conf` section `[plugins]` section contains a list of all the plugins found at the system where Netdata runs, with a boolean setting to enable them or not.
61
62 Example:
63
64 ```
65 [plugins]
66 # enable running new plugins = yes
67 # check for new plugins every = 60
68
69 # charts.d = yes
70 # ioping = yes
71 # python.d = yes
72 ```
73
74 The setting `enable running new plugins` sets the default behavior for all external plugins. It can be
75 overridden for distinct plugins by modifying the appropriate plugin value configuration to either `yes` or `no`.
76
77 The setting `check for new plugins every` sets the interval between scans of the directory
78 `/usr/libexec/netdata/plugins.d`. New plugins can be added any time, and Netdata will detect them in a timely manner.
79
80 For each of the external plugins enabled, another `netdata.conf` section
81 is created, in the form of `[plugin:NAME]`, where `NAME` is the name of the external plugin.
82 This section allows controlling the update frequency of the plugin and provide
83 additional command line arguments to it.
84
85 For example, for `apps.plugin` the following section is available:
86
87 ```
88 [plugin:apps]
89 # update every = 1
90 # command options =
91 ```
92
93 - `update every` controls the granularity of the external plugin.
94 - `command options` allows giving additional command line options to the plugin.
95
96 Netdata will provide to the external plugins the environment variable `NETDATA_UPDATE_EVERY`, in seconds (the default is 1). This is the **minimum update frequency** for all charts. A plugin that is updating values more frequently than this, is just wasting resources.
97
98 Netdata will call the plugin with just one command line parameter: the number of seconds the user requested this plugin to update its data (by default is also 1).
99
100 Other than the above, the plugin configuration is up to the plugin.
101
102 Keep in mind, that the user may use Netdata configuration to overwrite chart and dimension parameters. This is transparent to the plugin.
103
104 ### Autoconfiguration
105
106 Plugins should attempt to autoconfigure themselves when possible.
107
108 For example, if your plugin wants to monitor `squid`, you can search for it on port `3128` or `8080`. If any succeeds, you can proceed. If it fails you can output an error (on stderr) saying that you cannot find `squid` running and giving instructions about the plugin configuration. Then you can stop (exit with non-zero value), so that Netdata will not attempt to start the plugin again.
109
110 ## External Plugins API
111
112 Any program that can print a few values to its standard output can become a Netdata external plugin.
113
114 Netdata parses lines starting with:
115
116 - `CHART` - create or update a chart
117 - `DIMENSION` - add or update a dimension to the chart just created
118 - `VARIABLE` - define a variable (to be used in health calculations)
119 - `CLABEL` - add a label to a chart
120 - `CLABEL_COMMIT` - commit added labels to the chart
121 - `FUNCTION` - define a function that can be called later to execute it
122 - `BEGIN` - initialize data collection for a chart
123 - `SET` - set the value of a dimension for the initialized chart
124 - `END` - complete data collection for the initialized chart
125 - `FLUSH` - ignore the last collected values
126 - `DISABLE` - disable this plugin
127 - `FUNCTION` - define functions
128 - `FUNCTION_PROGRESS` - report the progress of a function execution
129 - `FUNCTION_RESULT_BEGIN` - to initiate the transmission of function results
130 - `FUNCTION_RESULT_END` - to end the transmission of function result
131 - `CONFIG` - to define dynamic configuration entities
132
133 a single program can produce any number of charts with any number of dimensions each.
134
135 Charts can be added any time (not just the beginning).
136
137 Netdata may send the following commands to the plugin's `stdin`:
138
139 - `FUNCTION` - to call a specific function, with all parameters inline
140 - `FUNCTION_PAYLOAD` - to call a specific function, with a payload of parameters
141 - `FUNCTION_PAYLOAD_END` - to end the payload of parameters
142 - `FUNCTION_CANCEL` - to cancel a running function transaction - no response is required
143 - `FUNCTION_PROGRESS` - to report that a user asked the progress of running function call - no response is required
144
145 ### Command line parameters
146
147 The plugin **MUST** accept just **one** parameter: **the number of seconds it is
148 expected to update the values for its charts**. The value passed by Netdata
149 to the plugin is controlled via its configuration file (so there is no need
150 for the plugin to handle this configuration option).
151
152 The external plugin can overwrite the update frequency. For example, the server may
153 request per second updates, but the plugin may ignore it and update its charts
154 every 5 seconds.
155
156 ### Environment variables
157
158 There are a few environment variables that are set by `netdata` and are
159 available for the plugin to use.
160
161 | variable | description |
162 |:--------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
163 | `NETDATA_USER_CONFIG_DIR` | The directory where all Netdata-related user configuration should be stored. If the plugin requires custom user configuration, this is the place the user has saved it (normally under `/etc/netdata`). |
164 | `NETDATA_STOCK_CONFIG_DIR` | The directory where all Netdata -related stock configuration should be stored. If the plugin is shipped with configuration files, this is the place they can be found (normally under `/usr/lib/netdata/conf.d`). |
165 | `NETDATA_STOCK_DATA_DIR` | The directory where immutable Netdata stock data files are stored. Plugins can use this for packaged data assets such as MMDB files (normally under `/usr/share/netdata`). |
166 | `NETDATA_PLUGINS_DIR` | The directory where all Netdata plugins are stored. |
167 | `NETDATA_USER_PLUGINS_DIRS` | The list of directories where custom plugins are stored. |
168 | `NETDATA_WEB_DIR` | The directory where the web files of Netdata are saved. |
169 | `NETDATA_CACHE_DIR` | The directory where the cache files of Netdata are stored. Use this directory if the plugin requires a place to store data. A new directory should be created for the plugin for this purpose, inside this directory. |
170 | `NETDATA_LOG_DIR` | The directory where the log files are stored. By default the `stderr` output of the plugin will be saved in the `error.log` file of Netdata. |
171 | `NETDATA_HOST_PREFIX` | This is used in environments where system directories like `/sys` and `/proc` have to be accessed at a different path. |
172 | `NETDATA_DEBUG_FLAGS` | This is a number (probably in hex starting with `0x`), that enables certain Netdata debugging features. Check **\[[Tracing Options]]** for more information. |
173 | `NETDATA_UPDATE_EVERY` | The minimum number of seconds between chart refreshes. This is like the **internal clock** of Netdata (it is user configurable, defaulting to `1`). There is no meaning for a plugin to update its values more frequently than this number of seconds. |
174 | `NETDATA_INVOCATION_ID` | A random UUID in compact form, representing the unique invocation identifier of Netdata. When running under systemd, Netdata uses the `INVOCATION_ID` set by systemd. |
175 | `NETDATA_LOG_METHOD` | One of `syslog`, `journal`, `stderr` or `none`, indicating the preferred log method of external plugins. |
176 | `NETDATA_LOG_FORMAT` | One of `journal`, `logfmt` or `json`, indicating the format of the logs. Plugins can use the Netdata `systemd-cat-native` command to log always in `journal` format, and have it automatically converted to the format expected by netdata. |
177 | `NETDATA_LOG_LEVEL` | One of `emergency`, `alert`, `critical`, `error`, `warning`, `notice`, `info`, `debug`. Plugins are expected to log events with the given priority and the more important ones. |
178 | `NETDATA_SYSLOG_FACILITY` | Set only when the `NETDATA_LOG_METHOD` is `syslog`. Possible values are `auth`, `authpriv`, `cron`, `daemon`, `ftp`, `kern`, `lpr`, `mail`, `news`, `syslog`, `user`, `uucp` and `local0` to `local7` |
179 | `NETDATA_ERRORS_THROTTLE_PERIOD` | The log throttling period in seconds. |
180 | `NETDATA_ERRORS_PER_PERIOD` | The allowed number of log events per period. |
181 | `NETDATA_SYSTEMD_JOURNAL_PATH` | When `NETDATA_LOG_METHOD` is set to `journal`, this is the systemd-journald socket path to use. |
182
183 ### The output of the plugin
184
185 The plugin should output instructions for Netdata to its output (`stdout`). Since this uses pipes, please make sure you flush stdout after every iteration.
186
187 #### DISABLE
188
189 `DISABLE` will disable this plugin. This will prevent Netdata from restarting the plugin. You can also exit with the value `1` to have the same effect.
190
191 #### HOST_DEFINE
192
193 `HOST_DEFINE` defines a new (or updates an existing) virtual host.
194
195 The template is:
196
197 > HOST_DEFINE machine_guid hostname
198
199 where:
200
201 - `machine_guid`
202
203 uniquely identifies the host, this is what will be needed to add charts to the host.
204
205 - `hostname`
206
207 is the hostname of the virtual host
208
209 #### HOST_LABEL
210
211 `HOST_LABEL` adds a key-value pair to the virtual host labels. It has to be given between `HOST_DEFINE` and `HOST_DEFINE_END`.
212
213 The template is:
214
215 > HOST_LABEL key value
216
217 where:
218
219 - `key`
220
221 uniquely identifies the key of the label
222
223 - `value`
224
225 is the value associated with this key
226
227 There are a few special keys that are used to define the system information of the monitored system:
228
229 - `_cloud_provider_type`
230 - `_cloud_instance_type`
231 - `_cloud_instance_region`
232 - `_os_name`
233 - `_os_version`
234 - `_kernel_version`
235 - `_system_cores`
236 - `_system_cpu_freq`
237 - `_system_ram_total`
238 - `_system_disk_space`
239 - `_architecture`
240 - `_virtualization`
241 - `_container`
242 - `_container_detection`
243 - `_virt_detection`
244 - `_is_k8s_node`
245 - `_install_type`
246 - `_prebuilt_arch`
247 - `_prebuilt_dist`
248
249 #### HOST_DEFINE_END
250
251 `HOST_DEFINE_END` commits the host information, creating a new host entity, or updating an existing one with the same `machine_guid`.
252
253 #### HOST
254
255 `HOST` switches data collection between hosts.
256
257 The template is:
258
259 > HOST machine_guid
260
261 where:
262
263 - `machine_guid`
264
265 is the UUID of the host to switch to. After this command, every other command following it is assumed to be associated with this host.
266 Setting machine_guid to `localhost` switches data collection to the local host.
267
268 #### CHART
269
270 `CHART` defines a new chart.
271
272 the template is:
273
274 > CHART type.id name title units \[family \[context \[charttype \[priority \[update_every \[options \[plugin [module]]]]]]]]
275
276 where:
277
278 - `type.id`
279
280 uniquely identifies the chart,
281 this is what will be needed to add values to the chart
282
283 the `type` part controls the menu the charts will appear in
284
285 - `name`
286
287 is the name that will be presented to the user instead of `id` in `type.id`. This means that only the `id` part of
288 `type.id` is changed. When a name has been given, the chart is indexed (and can be referred) as both `type.id` and
289 `type.name`. You can set name to `''`, or `null`, or `(null)` to disable it. If a chart with the same name already
290 exists, a serial number is automatically attached to the name to avoid naming collisions.
291
292 - `title`
293
294 the text above the chart
295
296 - `units`
297
298 the label of the vertical axis of the chart,
299 all dimensions added to a chart should have the same units
300 of measurement
301
302 - `family`
303
304 is used to group charts together
305 (for example all eth0 charts should say: eth0),
306 if empty or missing, the `id` part of `type.id` will be used
307
308 this controls the sub-menu on the dashboard
309
310 - `context`
311
312 the context is giving the template of the chart. For example, if multiple charts present the same information for a different family, they should have the same `context`
313
314 this is used for looking up rendering information for the chart (colors, sizes, informational texts) and also apply alerts to it
315
316 - `charttype`
317
318 one of `line`, `area`, `stacked` or `heatmap`,
319 if empty or missing, the `line` will be used
320
321 - `priority`
322
323 is the relative priority of the charts as rendered on the web page,
324 lower numbers make the charts appear before the ones with higher numbers,
325 if empty or missing, `1000` will be used
326
327 - `update_every`
328
329 overwrite the update frequency set by the server,
330 if empty or missing, the user configured value will be used
331
332 - `options`
333
334 a space separated list of options, enclosed in quotes. The following options are currently supported: `obsolete` to mark a chart as obsolete (Netdata will hide it and delete it after some time), `store_first` to make Netdata store the first collected value, assuming there was an invisible previous value set to zero (this is used by statsd charts - if the first data collected value of incremental dimensions is not zero based, unrealistic spikes will appear with this option set) and `hidden` to perform all operations on a chart, but do not offer it on dashboards (the chart will be send to external databases). `CHART` options have been added in Netdata v1.7 and the `hidden` option was added in 1.10.
335
336 (for CHART options see above; DIMENSION-specific options are described below)
337
338 #### DIMENSION options
339
340 Additional option: `type=float` (default `type=int`).
341 - `type=int` (default): values parsed as 64-bit integers; wrap/reset detection applies for incremental counters.
342 - `type=float`: values parsed as double; incremental/delta-incremental allowed but wrap detection uses simple drop detection (no uint64 wrap math).
343 Older parents without `FLOATBASELINE` capability will truncate baselines to int when streaming/replicating.
344
345 - `plugin` and `module`
346
347 both are just names that are used to let the user identify the plugin and the module that generated the chart. If `plugin` is unset or empty, Netdata will automatically set the filename of the plugin that generated the chart. `module` has not default.
348
349 #### DIMENSION
350
351 `DIMENSION` defines a new dimension for the chart
352
353 the template is:
354
355 > DIMENSION id \[name \[algorithm \[multiplier \[divisor [options]]]]]
356
357 where:
358
359 - `id`
360
361 the `id` of this dimension (it is a text value, not numeric),
362 this will be needed later to add values to the dimension
363
364 We suggest to avoid using `.` in dimension ids. External databases expect metrics to be `.` separated and people will get confused if a dimension id contains a dot.
365
366 - `name`
367
368 the name of the dimension as it will appear at the legend of the chart,
369 if empty or missing the `id` will be used
370
371 - `algorithm`
372
373 one of:
374
375 - `absolute`
376
377 the value is to drawn as-is (interpolated to second boundary),
378 if `algorithm` is empty, invalid or missing, `absolute` is used
379
380 - `incremental`
381
382 the value increases over time,
383 the difference from the last value is presented in the chart,
384 the server interpolates the value and calculates a per second figure
385
386 - `percentage-of-absolute-row`
387
388 the % of this value compared to the total of all dimensions
389
390 - `percentage-of-incremental-row`
391
392 the % of this value compared to the incremental total of
393 all dimensions
394
395 - `multiplier`
396
397 an integer value to multiply the collected value,
398 if empty or missing, `1` is used
399
400 - `divisor`
401
402 an integer value to divide the collected value,
403 if empty or missing, `1` is used
404
405 - `options`
406
407 a space separated list of options, enclosed in quotes. Options supported: `obsolete` to mark a dimension as obsolete (Netdata will delete it after some time) and `hidden` to make this dimension hidden, it will take part in the calculations but will not be presented in the chart.
408
409 #### VARIABLE
410
411 > VARIABLE [SCOPE] name = value
412
413 `VARIABLE` defines a variable that can be used in alerts. This is to used for setting constants (like the max connections a server may accept).
414
415 Variables support 2 scopes:
416
417 - `GLOBAL` or `HOST` to define the variable at the host level.
418 - `LOCAL` or `CHART` to define the variable at the chart level. Use chart-local variables when the same variable may exist for different charts (i.e. Netdata monitors 2 mysql servers, and you need to set the `max_connections` each server accepts). Using chart-local variables is the ideal to build alert templates.
419
420 The position of the `VARIABLE` line, sets its default scope (in case you do not specify a scope). So, defining a `VARIABLE` before any `CHART`, or between `END` and `BEGIN` (outside any chart), sets `GLOBAL` scope, while defining a `VARIABLE` just after a `CHART` or a `DIMENSION`, or within the `BEGIN` - `END` block of a chart, sets `LOCAL` scope.
421
422 These variables can be set and updated at any point.
423
424 Variable names should use alphanumeric characters, the `.` and the `_`.
425
426 The `value` is floating point (Netdata used `long double`).
427
428 Variables are transferred to upstream Netdata servers (streaming and database replication).
429
430 #### CLABEL
431
432 > CLABEL name value source
433
434 `CLABEL` defines a label used to organize and identify a chart.
435
436 Name and value accept characters according to the following table:
437
438 | Character | Symbol | Label Name | Label Value |
439 |---------------------|:------:|:----------:|:-----------:|
440 | UTF-8 character | UTF-8 | _ | keep |
441 | Lower case letter | [a-z] | keep | keep |
442 | Upper case letter | [A-Z] | keep | [a-z] |
443 | Digit | [0-9] | keep | keep |
444 | Underscore | _ | keep | keep |
445 | Minus | - | keep | keep |
446 | Plus | + | _ | keep |
447 | Colon | : | _ | keep |
448 | Semicolon | ; | _ | : |
449 | Equal | = | _ | : |
450 | Period | . | keep | keep |
451 | Comma | , | . | . |
452 | Slash | / | keep | keep |
453 | Backslash | \ | / | / |
454 | At | @ | _ | keep |
455 | Space | ' ' | _ | keep |
456 | Opening parenthesis | ( | _ | keep |
457 | Closing parenthesis | ) | _ | keep |
458 | Anything else | | _ | _ |
459
460 The `source` is an integer field that can have the following values:
461 - `1`: The value was set automatically.
462 - `2`: The value was set manually.
463 - `4`: This is a K8 label.
464 - `8`: This is a label defined using `netdata` Agent-Cloud link.
465
466 #### CLABEL_COMMIT
467
468 `CLABEL_COMMIT` indicates that all labels were defined and the chart can be updated.
469
470 #### FUNCTION
471
472 The plugin can register functions to Netdata, like this:
473
474 > FUNCTION [GLOBAL] "name and parameters of the function" timeout "help string for users" "tags" "access" priority version
475
476 - Tags currently recognized are either `top` or `logs` (or both, space separated).
477 - Access is one of `any`, `member`, or `admin`:
478 - `any` to offer the function to all users of Netdata, even if they are not authenticated.
479 - `member` to offer the function to all authenticated members of Netdata.
480 - `admin` to offer the function only to authenticated administrators.
481 - Priority defines the position of the function relative to the other functions (default is 100).
482 - Version defines the version of the function (default is 0).
483
484 Users can use a function to ask for more information from the collector. Netdata maintains a registry of functions in 2 levels:
485
486 - per node
487 - per chart
488
489 Both node and chart functions are exactly the same, but chart functions allow Netdata to relate functions with charts and therefore present a context-sensitive menu of functions related to the chart the user is using.
490
491 Users can get a list of all the registered functions using the `/api/v1/functions` endpoint of Netdata and call functions using the `/api/v1/function` API call of Netdata.
492
493 Once a function is called, the plugin will receive at its standard input a command that looks like this:
494
495 ```
496 FUNCTION transaction_id timeout "name and parameters of the function as one quoted parameter" "user permissions value" "source of request"
497 ```
498
499 When the function to be called is to receive a payload of parameters, the call looks like this:
500
501 ```
502 FUNCTION_PAYLOAD transaction_id timeout "name and parameters of the function as one quoted parameter" "user permissions value" "source of request" "content/type"
503 body of the payload, formatted according to content/type
504 FUNCTION PAYLOAD END
505 ```
506
507 In this case, Netdata will send:
508
509 - A line starting with `FUNCTION_PAYLOAD` together with the required metadata for the function, like the transaction id, the function name and its parameters, the timeout and the content type. This line ends with a newline.
510 - Then, the payload itself (which may or may not have newlines in it). The payload should be parsed according to the content type parameter.
511 - Finally, a line starting with `FUNCTION_PAYLOAD_END`, so it is expected like `\nFUNCTION_PAYLOAD_END\n`.
512
513 Note 1: The plugins.d protocol allows parameters without single or double quotes if they don't contain spaces. However, the plugin should be able to parse parameters even if they are enclosed in single or double quotes. If the first character of a parameter is a single quote, its last character should also be a single quote too, and similarly for double quotes.
514
515 Note 2: Netdata always sends the function and its parameters enclosed in double quotes. If the function command and its parameters contain quotes, they are converted to single quotes.
516
517 The plugin is expected to parse and validate `name and parameters of the function as one quotes parameter`. Netdata allows the user interface to manipulate this string by appending more parameters.
518
519 If the plugin rejects the request, it should respond with this:
520
521 ```
522 FUNCTION_RESULT_BEGIN transaction_id 400 application/json
523 {
524 "status": 400,
525 "error_message": "description of the rejection reasons"
526 }
527 FUNCTION_RESULT_END
528 ```
529
530 If the plugin prepares a response, it should send (via its standard output, together with the collected data, but not interleaved with them):
531
532 ```
533 FUNCTION_RESULT_BEGIN transaction_id http_response_code content_type expiration
534 ```
535
536 Where:
537
538 - `transaction_id` is the transaction id that Netdata sent for this function execution
539 - `http_response_code` is the http error code Netdata should respond with, 200 is the "ok" response
540 - `content_type` is the content type of the response
541 - `expiration` is the absolute timestamp (number, unix epoch) this response expires
542
543 Immediately after this, all text is assumed to be the response content.
544 The content is text and line oriented. The maximum line length accepted is 15kb. Longer lines will be truncated.
545 The type of the context itself depends on the plugin and the UI.
546
547 To terminate the message, Netdata seeks a line with just this:
548
549 ```
550 FUNCTION_RESULT_END
551 ```
552
553 This defines the end of the message. `FUNCTION_RESULT_END` should appear in a line alone, without any other text, so it is wise to add `\n` before and after it.
554
555 After this line, Netdata resumes processing collected metrics from the plugin.
556
557 The maximum uncompressed payload size Netdata will accept is 100MB.
558
559 ##### Function naming conventions
560
561 Function names can follow a **colon-separated hierarchical naming convention** to organize related functions under a common namespace. This is particularly useful for plugins that expose multiple related functions.
562
563 The recommended format for module-level functions is:
564
565 ```
566 module:method
567 ```
568
569 Where:
570 - `module` is the collector or module name (e.g., `mysql`, `postgres`, `snmp`)
571 - `method` is the specific function/operation (e.g., `top-queries`, `deadlock-info`, `interfaces`)
572
573 Examples:
574 - `mysql:top-queries` - Top queries function for MySQL collector
575 - `mysql:deadlock-info` - Deadlock information for MySQL collector
576 - `postgres:top-queries` - Top queries function for PostgreSQL collector
577 - `snmp:interfaces` - Network interfaces function for SNMP collector
578
579 This naming convention:
580 - Groups related functions under a single module namespace
581 - Allows collectors to expose multiple methods
582 - Improves discoverability in the Functions API
583 - Follows the same colon-separator pattern used by [Dynamic Configuration (DynCfg)](#config) for consistency
584
585 :::note
586
587 This naming convention is distinct from DynCfg configuration IDs. DynCfg commands are sent through the special `config` function (e.g., `config go.d:mysql:local get`), while module functions use their own unique names directly (e.g.,
588 `mysql:top-queries`).
589
590 :::
591
592 ##### Functions cancellation
593
594 Netdata is able to detect when a user made an API request, but abandoned it before it was completed. If this happens to an API called for a function served by the plugin, Netdata will generate a `FUNCTION_CANCEL` request to let the plugin know that it can stop processing the query.
595
596 After receiving such a command, the plugin **must still send a response for the original function request**, to wake up any waiting threads before they timeout. The http response code is not important, since the response will be discarded, however for auditing reasons we suggest to send back a 499 http response code. This is not a standard response code according to the HTTP protocol, but web servers like `nginx` are using it to indicate that a request was abandoned by a user.
597
598 ##### Functions progress
599
600 When a request takes too long to be processed, Netdata allows the plugin to report progress to Netdata, which in turn will report progress to the caller.
601
602 The plugin can send `FUNCTION_PROGRESS` like this:
603
604 ```
605 FUNCTION_PROGRESS transaction_id done all
606 ```
607
608 Where:
609
610 - `transaction_id` is the transaction id of the function request
611 - `done` is an integer value indicating the amount of work done
612 - `all` is an integer value indicating the total amount of work to be done
613
614 Netdata supports two kinds of progress:
615 - progress as a percentage, which is calculated as `done * 100 / all`
616 - progress without knowing the total amount of work to be done, which is enabled when the plugin reports `all` as zero.
617
618 ##### Functions timeout
619
620 All functions calls specify a timeout, at which all the intermediate routing nodes (parents, web server threads) will time out and abort the call.
621
622 However, all intermediate routing nodes are configured to extend the timeout when the caller asks for progress. This works like this:
623
624 When a progress request is received, if the expected timeout of the request is less than or equal to 10 seconds, the expected timeout is extended by 10 seconds.
625
626 Usually, the user interface asks for a progress every second. So, during the last 10 seconds of the timeout, every progress request made shifts the timeout 10 seconds to the future.
627
628 To accomplish this, when Netdata receives a progress request by a user, it generates progress requests to the plugin, updating all the intermediate nodes to extend their timeout if necessary.
629
630 The plugin will receive progress requests like this:
631
632 ```
633 FUNCTION_PROGRESS transaction_id
634 ```
635
636 There is no need to respond to this command. It is only there to let the plugin know that a user is still waiting for the query to finish.
637
638 #### CONFIG
639
640 `CONFIG` commands sent from the plugin to Netdata define dynamic configuration entities. These configurable entities are exposed to the user interface, allowing users to change configuration at runtime.
641
642 Dynamically configurations made this way are saved to disk by Netdata and are replayed automatically when Netdata or the plugin restarts.
643
644 `CONFIG` commands look like this:
645
646 ```
647 CONFIG id action ...
648 ```
649
650 Where:
651
652 - `id` is a unique identifier for the configurable entity. This should by design be unique across Netdata. It should be something like `plugin:module:jobs`, e.g. `go.d:postgresql:jobs:masterdb`. This is assumed to be colon-separated with the last part (`masterdb` in our example), being the one displayed to users when there ano conflicts under the same configuration path.
653 - `action` can be:
654 - `create`, to declare the dynamic configuration entity
655 - `delete`, to delete the dynamic configuration entity - this does not delete user configuration, we if an entity with the same id is created in the future, the saved configuration will be given to it.
656 - `status`, to update the dynamic configuration entity status
657
658 > IMPORTANT:<br/>
659 > The plugin should blindly create, delete and update the status of its dynamic configuration entities, without any special logic applied to it. Netdata needs to be updated of what is actually happening at the plugin. Keep in mind that creating dynamic configuration entities triggers responses from Netdata, depending on its type and status. Re-creating a job, triggers the same responses every time, so make sure you create jobs only when you add jobs.
660
661 When the `action` is `create`, the following additional parameters are expected:
662
663 ```
664 CONFIG id action status type "path" source_type "source" "supported commands" "view permissions" "edit permissions"
665 ```
666
667 Where:
668
669 - `action` should be `create`
670 - `status` can be:
671 - `accepted`, the plugin accepted the configuration, but it is not running yet.
672 - `running`, the plugin accepted and runs the configuration.
673 - `failed`, the plugin tries to run the configuration but it fails.
674 - `incomplete`, the plugin needs additional settings to run this configuration. This is usually used for the cases the plugin discovered a job, but important information is missing for it to work.
675 - `disabled`, the configuration has been disabled by a user.
676 - `orphan`, the configuration is not claimed by any plugin. This is used internally by Netdata to mark the configuration nodes available, for which there is no plugin related to them. Do not use in plugins directly.
677 - `type` can be `single`, `template` or `job`:
678 - `single` is used when the configurable entity is fixed and users should never be able to add or delete it.
679 - `template` is used to define a template based on which users can add multiple configurations, like adding data collection jobs. So, the plugin defines the template of the jobs and users are presented with a `[+]` button to add such configuration jobs. The plugin can define multiple templates by giving different `id`s to them.
680 - `job` is used to define a job of a template. The plugin should always add all its jobs, independently of the way they have been discovered. It is important to note the relation between `template` and `job` when it comes it the `id`: The `id` of the template should be the prefix of the `job`'s `id`. For example, if the template is `go.d:postgresql:jobs`, then all its jobs be like `go.d:postgresql:jobs:jobname`.
681 - `path` is the absolute path of the configurable entity inside the tree of Netdata configurations. Usually, this is should be `/collectors`.
682 - `source` can be `internal`, `stock`, `user`, `discovered` or `dyncfg`:
683 - `internal` is used for configurations that are based on internal code settings
684 - `stock` is used for default configurations
685 - `discovered` is used for dynamic configurations the plugin discovers by its own
686 - `user` is used for user configurations, usually via a configuration file
687 - `dyncfg` is used for configuration received via this dynamic configuration mechanism
688 - `source` should provide more details about the exact source of the configuration, like `line@file`, or `user@ip`, etc.
689 - `supported_commands` is a space separated list of the following keywords, enclosed in single or double quotes. These commands are used by the user interface to determine the actions the users can take:
690 - `schema`, to expose the JSON schema for the user interface. This is mandatory for all configurable entities. When `schema` requests are received, Netdata will first attempt to load the schema from `/etc/netdata/schema.d/` and `/var/lib/netdata/conf.d/schema.d`. For jobs, it will serve the schema of their template. If no schema is found for the required `id`, the `schema` request will be forwarded to the plugin, which is expected to send back the relevant schema.
691 - `get`, to expose the current configuration values, according the schema defined. `templates` cannot support `get`, since they don't maintain any data.
692 - `update`, to receive configuration updates for this entity. `templates` cannot support `update`, since they don't maintain any data.
693 - `test`, like `update` but only test the configuration and report success or failure.
694 - `add`, to receive job creation commands for templates. Only `templates` should support this command.
695 - `remove`, to remove a configuration. Only `jobs` should support this command.
696 - `enable` and `disable`, to receive user requests to enable and disable this entity. Adding only one of `enable` or `disable` to the supported commands, Netdata will add both of them. The plugin should expose these commands on `templates` only when it wants to receive `enable` and `disable` commands for all the `jobs` of this `template`.
697 - `restart`, to restart a job.
698 - `view permissions` and `edit permissions` are bitmaps of the Netdata permission system to control access to the configuration. If set to zero, Netdata will require a signed in user with view and edit permissions to the Netdata's configuration system.
699
700 The plugin receives commands as if it had exposed a `FUNCTION` named `config`. Netdata formats all these calls like this:
701
702 ```
703 config id command
704 ```
705
706 Where `id` is the unique id of the configurable entity and `command` is one of the supported commands the plugin sent to Netdata.
707
708 The plugin will receive (for commands: `schema`, `get`, `remove`, `enable`, `disable` and `restart`):
709
710 ```
711 FUNCTION transaction_id timeout "config id command" "user permissions value" "source string"
712 ```
713
714 or (for commands: `update`, `add` and `test`):
715
716 ```
717 FUNCTION_PAYLOAD transaction_id timeout "config id command" "user permissions value" "source string" "content/type"
718 body of the payload formatted according to content/type
719 FUNCTION_PAYLOAD_END
720 ```
721
722 Once received, the plugin should process it and respond accordingly.
723
724 Immediately after the plugin adds a configuration entity, if the commands `enable` and `disable` are supported by it, Netdata will send either `enable` or `disable` for it, based on the last user action, which has been persisted to disk.
725
726 Plugin responses follow the same format `FUNCTIONS` do:
727
728 ```
729 FUNCTION_RESULT_BEGIN transaction_id http_response_code content/type expiration
730 body of the response formatted according to content/type
731 FUNCTION_RESULT_END
732 ```
733
734 Successful responses (HTTP response code 200) to `schema` and `get` should send back the relevant JSON object.
735 All other responses should have the following response body:
736
737 ```json
738 {
739 "status" : 404,
740 "message" : "some text"
741 }
742 ```
743
744 The user interface presents the message to users, even when the response is successful (HTTP code 200).
745
746 When responding to additions and updates, Netdata uses the following success response codes to derive additional information:
747
748 - `200`, responding with 200, means the configuration has been accepted and it is running.
749 - `202`, responding with 202, means the configuration has been accepted but it is not yet running. A subsequent `status` action will update it.
750 - `298`, responding with 298, means the configuration has been accepted but it is disabled for some reason (probably because it matches nothing or the contents are not useful - use the `message` to provide additional information).
751 - `299`, responding with 299, means the configuration has been accepted but a restart is required to apply it.
752
753 ## Data collection
754
755 data collection is defined as a series of `BEGIN` -> `SET` -> `END` lines
756
757 > BEGIN type.id [microseconds]
758
759 - `type.id`
760
761 is the unique identification of the chart (as given in `CHART`)
762
763 - `microseconds`
764
765 is the number of microseconds since the last update of the chart. It is optional.
766
767 Under heavy system load, the system may have some latency transferring
768 data from the plugins to Netdata via the pipe. This number improves
769 accuracy significantly, since the plugin is able to calculate the
770 duration between its iterations better than Netdata.
771
772 The first time the plugin is started, no microseconds should be given
773 to Netdata.
774
775 > SET id = value
776
777 - `id`
778
779 is the unique identification of the dimension (of the chart just began)
780
781 - `value`
782
783 is the collected value, only integer values are collected. If you want to push fractional values, multiply this value by 100 or 1000 and set the `DIMENSION` divider to 1000.
784
785 > END
786
787 END does not take any parameters, it commits the collected values for all dimensions to the chart. If a dimensions was not `SET`, its value will be empty for this commit.
788
789 More `SET` lines may appear to update all the dimensions of the chart.
790 All of them in one `BEGIN` -> `END` block.
791
792 All `SET` lines within a single `BEGIN` -> `END` block have to refer to the
793 same chart.
794
795 If more charts need to be updated, each chart should have its own
796 `BEGIN` -> `SET` -> `END` block.
797
798 If, for any reason, a plugin has issued a `BEGIN` but wants to cancel it,
799 it can issue a `FLUSH`. The `FLUSH` command will instruct Netdata to ignore
800 all the values collected since the last `BEGIN` command.
801
802 If a plugin does not behave properly (outputs invalid lines, or does not
803 follow these guidelines), will be disabled by Netdata.
804
805 ### collected values
806
807 Netdata will collect any **signed** value in the 64bit range:
808 `-9.223.372.036.854.775.808` to `+9.223.372.036.854.775.807`
809
810 If a value is not collected, leave it empty, like this:
811
812 `SET id =`
813
814 or do not output the line at all.
815
816 ## Modular Plugins
817
818 1. **python**, use `python.d.plugin`, there are many examples in the [python.d
819 directory](/src/collectors/python.d.plugin/README.md)
820
821 python is ideal for Netdata plugins. It is a simple, yet powerful way to collect data, it has a very small memory footprint, although it is not the most CPU efficient way to do it.
822
823 2. **BASH**, use `charts.d.plugin`, there are many examples in the [charts.d
824 directory](/src/collectors/charts.d.plugin/README.md)
825
826 BASH is the simplest scripting language for collecting values. It is the less efficient though in terms of CPU resources. You can use it to collect data quickly, but extensive use of it might use a lot of system resources.
827
828 3. **C**
829
830 Of course, C is the most efficient way of collecting data. This is why Netdata itself is written in C.
831
832 ## Writing Plugins Properly
833
834 There are a few rules for writing plugins properly:
835
836 1. Respect system resources
837
838 Pay special attention to efficiency:
839
840 - Initialize everything once, at the beginning. Initialization is not an expensive operation. Your plugin will most probably be started once and run forever. So, do whatever heavy operation is needed at the beginning, just once.
841 - Do the absolutely minimum while iterating to collect values repeatedly.
842 - If you need to connect to another server to collect values, avoid re-connects if possible. Connect just once, with keep-alive (for HTTP) enabled and collect values using the same connection.
843 - Avoid any CPU or memory heavy operation while collecting data. If you control memory allocation, avoid any memory allocation while iterating to collect values.
844 - Avoid running external commands when possible. If you are writing shell scripts avoid especially pipes (each pipe is another fork, a very expensive operation).
845
846 2. The best way to iterate at a constant pace is this pseudo code:
847
848 ```js
849 var update_every = argv[1] * 1000; /* seconds * 1000 = milliseconds */
850
851 readConfiguration();
852
853 if(!verifyWeCanCollectValues()) {
854 print("DISABLE");
855 exit(1);
856 }
857
858 createCharts(); /* print CHART and DIMENSION statements */
859
860 var loops = 0;
861 var last_run = 0;
862 var next_run = 0;
863 var dt_since_last_run = 0;
864 var now = 0;
865
866 while(true) {
867 /* find the current time in milliseconds */
868 now = currentTimeStampInMilliseconds();
869
870 /*
871 * find the time of the next loop
872 * this makes sure we are always aligned
873 * with the Netdata daemon
874 */
875 next_run = now - (now % update_every) + update_every;
876
877 /*
878 * wait until it is time
879 * it is important to do it in a loop
880 * since many wait functions can be interrupted
881 */
882 while( now < next_run ) {
883 sleepMilliseconds(next_run - now);
884 now = currentTimeStampInMilliseconds();
885 }
886
887 /* calculate the time passed since the last run */
888 if ( loops > 0 )
889 dt_since_last_run = (now - last_run) * 1000; /* in microseconds */
890
891 /* prepare for the next loop */
892 last_run = now;
893 loops++;
894
895 /* do your magic here to collect values */
896 collectValues();
897
898 /* send the collected data to Netdata */
899 printValues(dt_since_last_run); /* print BEGIN, SET, END statements */
900 }
901 ```
902
903 Using the above procedure, your plugin will be synchronized to start data collection on steps of `update_every`. There will be no need to keep track of latencies in data collection.
904
905 Netdata interpolates values to second boundaries, so even if your plugin is not perfectly aligned it does not matter. Netdata will find out. When your plugin works in increments of `update_every`, there will be no gaps in the charts due to the possible cumulative micro-delays in data collection. Gaps will only appear if the data collection is really delayed.
906
907 3. If you are not sure of memory leaks, exit every one hour. Netdata will re-start your process.
908
909 4. If possible, try to autodetect if your plugin should be enabled, without any configuration.