diff options
Diffstat (limited to 'gnu/services/monitoring.scm')
| -rw-r--r-- | gnu/services/monitoring.scm | 571 |
1 files changed, 565 insertions, 6 deletions
diff --git a/gnu/services/monitoring.scm b/gnu/services/monitoring.scm index 8ba19ddd7ee..66bdc06d04a 100644 --- a/gnu/services/monitoring.scm +++ b/gnu/services/monitoring.scm | |||
| @@ -21,24 +21,39 @@ | |||
| 21 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | 21 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. |
| 22 | 22 | ||
| 23 | (define-module (gnu services monitoring) | 23 | (define-module (gnu services monitoring) |
| 24 | #:use-module (gnu services) | ||
| 25 | #:use-module (gnu services configuration) | ||
| 26 | #:use-module (gnu services shepherd) | ||
| 27 | #:use-module (gnu services web) | ||
| 28 | #:use-module (gnu packages admin) | 24 | #:use-module (gnu packages admin) |
| 25 | #:use-module (gnu packages bash) | ||
| 29 | #:use-module (gnu packages monitoring) | 26 | #:use-module (gnu packages monitoring) |
| 30 | #:use-module (gnu packages networking) | 27 | #:use-module (gnu packages networking) |
| 28 | #:use-module (gnu packages python) | ||
| 29 | #:use-module (gnu services configuration) | ||
| 30 | #:use-module (gnu services shepherd) | ||
| 31 | #:use-module (gnu services web) | ||
| 32 | #:use-module (gnu services) | ||
| 31 | #:use-module (gnu system shadow) | 33 | #:use-module (gnu system shadow) |
| 32 | #:use-module (guix gexp) | 34 | #:use-module (guix gexp) |
| 35 | #:use-module ((guix modules) #:select (source-module-closure)) | ||
| 33 | #:use-module (guix packages) | 36 | #:use-module (guix packages) |
| 37 | #:use-module ((guix profiles) #:select (packages->manifest | ||
| 38 | profile | ||
| 39 | profile-search-paths)) | ||
| 34 | #:use-module (guix records) | 40 | #:use-module (guix records) |
| 35 | #:use-module (guix utils) | 41 | #:use-module ((guix search-paths) #:select (search-path-specification-variable)) |
| 42 | #:use-module ((guix self) #:select (make-config.scm)) | ||
| 36 | #:use-module ((guix ui) #:select (display-hint G_)) | 43 | #:use-module ((guix ui) #:select (display-hint G_)) |
| 44 | #:use-module (guix utils) | ||
| 37 | #:use-module (ice-9 match) | 45 | #:use-module (ice-9 match) |
| 38 | #:use-module (ice-9 rdelim) | 46 | #:use-module (ice-9 rdelim) |
| 39 | #:use-module (srfi srfi-1) | 47 | #:use-module (srfi srfi-1) |
| 48 | #:use-module ((srfi srfi-2) #:select (and-let*)) | ||
| 40 | #:use-module (srfi srfi-26) | 49 | #:use-module (srfi srfi-26) |
| 41 | #:use-module (srfi srfi-35) | 50 | #:use-module (srfi srfi-35) |
| 51 | #:use-module ((srfi srfi-171) #:select (list-transduce | ||
| 52 | rcons | ||
| 53 | tconcatenate | ||
| 54 | tfilter | ||
| 55 | tmap)) | ||
| 56 | |||
| 42 | #:export (darkstat-configuration | 57 | #:export (darkstat-configuration |
| 43 | darkstat-service-type | 58 | darkstat-service-type |
| 44 | 59 | ||
| @@ -94,7 +109,49 @@ | |||
| 94 | zabbix-agent-service-type | 109 | zabbix-agent-service-type |
| 95 | zabbix-front-end-configuration | 110 | zabbix-front-end-configuration |
| 96 | zabbix-front-end-service-type | 111 | zabbix-front-end-service-type |
| 97 | %zabbix-front-end-configuration-nginx)) | 112 | %zabbix-front-end-configuration-nginx |
| 113 | |||
| 114 | collectd-plugin-generic | ||
| 115 | collectd-plugin-generic? | ||
| 116 | collectd-plugin-generic-load-plugin? | ||
| 117 | collectd-plugin-generic-name | ||
| 118 | collectd-plugin-generic-options | ||
| 119 | |||
| 120 | collectd-plugin-python | ||
| 121 | collectd-plugin-python? | ||
| 122 | collectd-plugin-python-load-plugin? | ||
| 123 | collectd-plugin-python-type-databases | ||
| 124 | collectd-plugin-python-type-packages | ||
| 125 | collectd-plugin-python-module-paths | ||
| 126 | collectd-plugin-python-log-traces? | ||
| 127 | collectd-plugin-python-log-interactive? | ||
| 128 | collectd-plugin-python-import | ||
| 129 | collectd-plugin-python-module | ||
| 130 | |||
| 131 | collectd-plugin? | ||
| 132 | |||
| 133 | %collectd-default-type-database | ||
| 134 | %collectd-pid-file | ||
| 135 | |||
| 136 | collectd-configuration | ||
| 137 | collectd-configuration? | ||
| 138 | collectd-configuration-collectd | ||
| 139 | collectd-configuration-base-directory | ||
| 140 | collectd-configuration-auto-load-plugins? | ||
| 141 | collectd-configuration-collect-internal-stats? | ||
| 142 | collectd-configuration-type-databases | ||
| 143 | collectd-configuration-interval | ||
| 144 | collectd-configuration-max-read-interval | ||
| 145 | collectd-configuration-timeout | ||
| 146 | collectd-configuration-read-threads | ||
| 147 | collectd-configuration-write-threads | ||
| 148 | collectd-configuration-write-queue-limit-high | ||
| 149 | collectd-configuration-write-queue-limit-low | ||
| 150 | collectd-configuration-host-name | ||
| 151 | collectd-configuration-fully-qualified-domain-name-lookup? | ||
| 152 | collectd-configuration-plugins | ||
| 153 | |||
| 154 | collectd-service-type)) | ||
| 98 | 155 | ||
| 99 | 156 | ||
| 100 | ;;; | 157 | ;;; |
| @@ -1186,3 +1243,505 @@ with Zabbix server."))) | |||
| 1186 | `((zabbix-front-end-configuration | 1243 | `((zabbix-front-end-configuration |
| 1187 | ,zabbix-front-end-configuration-fields)) | 1244 | ,zabbix-front-end-configuration-fields)) |
| 1188 | 'zabbix-front-end-configuration)) | 1245 | 'zabbix-front-end-configuration)) |
| 1246 | |||
| 1247 | |||
| 1248 | ;; | ||
| 1249 | ;; collectd | ||
| 1250 | ;; | ||
| 1251 | |||
| 1252 | (define *indent* (make-parameter "")) | ||
| 1253 | |||
| 1254 | (defmacro with-indent (. body) | ||
| 1255 | `(parameterize ((*indent* (string-append (*indent*) " "))) | ||
| 1256 | ,@body)) | ||
| 1257 | |||
| 1258 | (define seconds? integer?) | ||
| 1259 | |||
| 1260 | (define-maybe/no-serialization seconds) | ||
| 1261 | |||
| 1262 | (define list-of-string? (list-of string?)) | ||
| 1263 | |||
| 1264 | (define list-of-file-likes? (list-of file-like?)) | ||
| 1265 | |||
| 1266 | (define (collectd-serialize-list-of-file-likes name value) | ||
| 1267 | #~(string-join | ||
| 1268 | (map | ||
| 1269 | (lambda (v) (format #f "~a~a \"~a\"" #$name #$(*indent*) v)) | ||
| 1270 | '#$value) | ||
| 1271 | "\n" 'suffix)) | ||
| 1272 | |||
| 1273 | (define (collectd-serialize-file-like name value) | ||
| 1274 | (collectd-serialize-list-of-file-likes name (list value))) | ||
| 1275 | |||
| 1276 | (define list-of-packages? (list-of package?)) | ||
| 1277 | |||
| 1278 | (define (collectd-serialize-value value) | ||
| 1279 | (cond | ||
| 1280 | ;; Strings get quoted and escaped. | ||
| 1281 | ((string? value) | ||
| 1282 | (format #f "~s" value)) | ||
| 1283 | |||
| 1284 | ;; Keywords become unquoted strings (#:foo -> foo). | ||
| 1285 | ((keyword? value) | ||
| 1286 | (collectd-serialize-value | ||
| 1287 | (keyword->symbol value))) | ||
| 1288 | |||
| 1289 | ;; Booleans become bare words. | ||
| 1290 | ((eq? value #t) "true") | ||
| 1291 | ((eq? value #f) "false") | ||
| 1292 | |||
| 1293 | ;; Alists serialize to lines of KEY VALUE. | ||
| 1294 | ((alist? value) | ||
| 1295 | (apply string-append | ||
| 1296 | (map | ||
| 1297 | (generic-serialize-alist-entry collectd-serialize-field) | ||
| 1298 | value))) | ||
| 1299 | |||
| 1300 | ;; Lists get their elements serialized and joined with a space. | ||
| 1301 | ((list? value) (string-join (map collectd-serialize-value value) " ")) | ||
| 1302 | |||
| 1303 | ;; Other types (numbers etc) turn into bare strings. | ||
| 1304 | (else (object->string value)))) | ||
| 1305 | |||
| 1306 | (define (collectd-serialize-field name value) | ||
| 1307 | (if (and (list? value) (null-list? value)) | ||
| 1308 | "" | ||
| 1309 | (format #nil "~a~a ~a~%" (*indent*) name | ||
| 1310 | (collectd-serialize-value value)))) | ||
| 1311 | |||
| 1312 | (define (remap-names name-map serializer) | ||
| 1313 | "Renaming serializer. | ||
| 1314 | |||
| 1315 | Wraps `serializer', renaming fields according to `name-map', an alist of | ||
| 1316 | '((field-name . serialized-name))." | ||
| 1317 | (lambda (name value) | ||
| 1318 | (serializer (or (and=> (assoc name name-map) cdr) name) value))) | ||
| 1319 | |||
| 1320 | (define (collectd-make-load-plugin?-serializer plugin-name) | ||
| 1321 | (lambda (_ load-plugin?) | ||
| 1322 | (if load-plugin? | ||
| 1323 | (collectd-serialize-field "LoadPlugin" plugin-name) | ||
| 1324 | ""))) | ||
| 1325 | |||
| 1326 | ;; Generic plugin support. | ||
| 1327 | |||
| 1328 | (define-configuration/no-serialization collectd-plugin-generic | ||
| 1329 | (load-plugin? | ||
| 1330 | (boolean #t) | ||
| 1331 | "When @code{#t}, include a @code{LoadPlugin} directive in the | ||
| 1332 | configuration. This interacts with @code{auto-load-plugins?} in | ||
| 1333 | @code{collectd-configuration}; if @code{auto-load-plugins?} is @code{#f}, all | ||
| 1334 | plugins should set this to @code{#t}.") | ||
| 1335 | |||
| 1336 | (name | ||
| 1337 | string | ||
| 1338 | "The name of the plugin to configure. See @code{collect.conf(5)} for the | ||
| 1339 | list of plugins.") | ||
| 1340 | |||
| 1341 | (options | ||
| 1342 | (alist '()) | ||
| 1343 | "Configuration options for the plugin, as an alist. See | ||
| 1344 | @code{collect.conf(5)} for the available plugin options.")) | ||
| 1345 | |||
| 1346 | (define (collectd-serialize-plugin-generic _ value) | ||
| 1347 | (match-record value <collectd-plugin-generic> | ||
| 1348 | (name load-plugin? options) | ||
| 1349 | #~(string-join | ||
| 1350 | `("\n" | ||
| 1351 | ,#$((collectd-make-load-plugin?-serializer name) #nil load-plugin?) | ||
| 1352 | ,(string-append "<Plugin " #$name ">\n") | ||
| 1353 | ,#$(with-indent (collectd-serialize-value options)) | ||
| 1354 | "</Plugin>\n") | ||
| 1355 | ""))) | ||
| 1356 | |||
| 1357 | ;; Python plugin support. | ||
| 1358 | |||
| 1359 | (define (collectd-serialize-python-module name value) | ||
| 1360 | (apply string-append | ||
| 1361 | `(,(string-append (*indent*) "<Module " | ||
| 1362 | (collectd-serialize-value name) | ||
| 1363 | ">") | ||
| 1364 | "\n" | ||
| 1365 | ,@(with-indent | ||
| 1366 | (map | ||
| 1367 | (lambda (kvs) | ||
| 1368 | (collectd-serialize-field (car kvs) (cdr kvs))) | ||
| 1369 | value)) | ||
| 1370 | ,(string-append (*indent*) "</Module>")))) | ||
| 1371 | |||
| 1372 | (define collectd-plugin-python-remap | ||
| 1373 | '((module-paths . "ModulePath") | ||
| 1374 | (load-plugin? . "LoadPlugin") | ||
| 1375 | (log-traces? . "LogTraces") | ||
| 1376 | (interactive? . "Interactive") | ||
| 1377 | (type-databases . "TypesDB") | ||
| 1378 | (packages . "ModulePath") | ||
| 1379 | (module . "Import"))) | ||
| 1380 | |||
| 1381 | (define collectd-serialize-plugin-python-field | ||
| 1382 | (remap-names collectd-plugin-python-remap | ||
| 1383 | collectd-serialize-field)) | ||
| 1384 | |||
| 1385 | (define-configuration collectd-plugin-python | ||
| 1386 | (load-plugin? | ||
| 1387 | (boolean #t) | ||
| 1388 | "When @code{#t}, include a @code{LoadPlugin} directive in the | ||
| 1389 | configuration. This interacts with @code{auto-load-plugins?} in | ||
| 1390 | @code{collectd-configuration}; if @code{collectd-configuration}'s | ||
| 1391 | @code{auto-load-plugins?} is @code{#f}, all plugins should set this to | ||
| 1392 | @code{#t}." | ||
| 1393 | (serializer (collectd-make-load-plugin?-serializer "python"))) | ||
| 1394 | |||
| 1395 | (type-databases | ||
| 1396 | (list-of-file-likes '()) | ||
| 1397 | "One or more files that contain the data-set descriptions. See | ||
| 1398 | @code{types.db(5)} for a description of the format of these files." | ||
| 1399 | (serializer (remap-names collectd-plugin-python-remap | ||
| 1400 | collectd-serialize-list-of-file-likes))) | ||
| 1401 | |||
| 1402 | (packages | ||
| 1403 | (list-of-packages '()) | ||
| 1404 | "Packages to make available to the Python plugin. These can be | ||
| 1405 | dependencies of the plugin code, or may contain the plugin." | ||
| 1406 | (serializer empty-serializer)) | ||
| 1407 | |||
| 1408 | (module-paths | ||
| 1409 | (list-of-string '()) | ||
| 1410 | "Entries to prepend to @code{sys.path}." | ||
| 1411 | (serializer collectd-serialize-plugin-python-field)) | ||
| 1412 | |||
| 1413 | (log-traces? | ||
| 1414 | (boolean #f) | ||
| 1415 | "If a Python script throws an exception it will be logged by | ||
| 1416 | collectd with the name of the exception and the message. If you set | ||
| 1417 | this option to true it will also log the full stacktrace just like the | ||
| 1418 | default output of an interactive Python interpreter. This does not | ||
| 1419 | apply to the @code{CollectError} exception, which will never log a | ||
| 1420 | stacktrace. This should probably be set to false most of the time but | ||
| 1421 | is very useful for development and debugging of new modules." | ||
| 1422 | (serializer collectd-serialize-plugin-python-field)) | ||
| 1423 | |||
| 1424 | (interactive? | ||
| 1425 | (boolean #f) | ||
| 1426 | "This option will cause the module to launch an interactive Python | ||
| 1427 | interpreter that reads from and writes to the terminal. Note that collectd | ||
| 1428 | will terminate right after starting up if you try to run it as a daemon while | ||
| 1429 | this option is enabled so make sure to start collectd with the @code{-f} | ||
| 1430 | option. See the @code{collectd-python(5)} man page for more information on | ||
| 1431 | this option." | ||
| 1432 | (serializer collectd-serialize-plugin-python-field)) | ||
| 1433 | |||
| 1434 | (module | ||
| 1435 | string | ||
| 1436 | "The name of the Python module to import into the collectd Python | ||
| 1437 | process. The module must be available in @code{packages} or | ||
| 1438 | @code{module-paths}, and register a MPD callback." | ||
| 1439 | (serializer collectd-serialize-plugin-python-field)) | ||
| 1440 | |||
| 1441 | (module-options | ||
| 1442 | (alist '()) | ||
| 1443 | "Configuration options for the module." | ||
| 1444 | (serializer (lambda (_ value) (collectd-serialize-value value))))) | ||
| 1445 | |||
| 1446 | (define (collectd-serialize-plugin-python _ value) | ||
| 1447 | (define (serialize-fields fields) | ||
| 1448 | (list-transduce | ||
| 1449 | (base-transducer value) rcons | ||
| 1450 | (filter-configuration-fields collectd-plugin-python-fields fields))) | ||
| 1451 | |||
| 1452 | (match-record | ||
| 1453 | value <collectd-plugin-python> (module) | ||
| 1454 | #~(string-append | ||
| 1455 | "\n" | ||
| 1456 | #$@(serialize-fields '(load-plugin? type-databases)) | ||
| 1457 | "<Plugin python>\n" | ||
| 1458 | #$@(with-indent | ||
| 1459 | (append | ||
| 1460 | (serialize-fields '(log-traces? interactive? module-paths module)) | ||
| 1461 | (list (*indent*) "<Module " (collectd-serialize-value module) ">\n") | ||
| 1462 | (with-indent (serialize-fields '(module-options))) | ||
| 1463 | (list (*indent*) "</Module>\n"))) | ||
| 1464 | "</Plugin>\n"))) | ||
| 1465 | |||
| 1466 | (define (collectd-plugin? x) | ||
| 1467 | ;; XXX: Extend this if plugin-specific configuration records are | ||
| 1468 | ;; added. | ||
| 1469 | (or (collectd-plugin-generic? x) | ||
| 1470 | (collectd-plugin-python? x))) | ||
| 1471 | |||
| 1472 | (define list-of-collectd-plugins? (list-of collectd-plugin?)) | ||
| 1473 | |||
| 1474 | (define (collectd-serialize-plugin name value) | ||
| 1475 | ((match value | ||
| 1476 | ;; XXX: Extend this if plugin-specific configuration records are | ||
| 1477 | ;; added. | ||
| 1478 | ;; Note that these *must* return gexps, not strings, otherwise things | ||
| 1479 | ;; like type-databases won't work. | ||
| 1480 | (($ <collectd-plugin-generic>) collectd-serialize-plugin-generic) | ||
| 1481 | (($ <collectd-plugin-python>) collectd-serialize-plugin-python)) | ||
| 1482 | name value)) | ||
| 1483 | |||
| 1484 | (define (collectd-serialize-list-of-plugins name value) | ||
| 1485 | #~(string-append | ||
| 1486 | #$@(map | ||
| 1487 | (lambda (v) (collectd-serialize-plugin name v)) | ||
| 1488 | value))) | ||
| 1489 | |||
| 1490 | (define collectd-configuration-remap | ||
| 1491 | '((base-directory . "BaseDir") | ||
| 1492 | (auto-load-plugins? . "AutoLoadPlugin") | ||
| 1493 | (collect-internal-stats? . "CollectInternalStats") | ||
| 1494 | (type-databases . "TypesDB") | ||
| 1495 | (interval . "Interval") | ||
| 1496 | (max-read-interval . "MaxReadInterval") | ||
| 1497 | (timeout . "Timeout") | ||
| 1498 | (read-threads . "ReadThreads") | ||
| 1499 | (write-threads . "WriteThreads") | ||
| 1500 | (write-queue-limit-high . "WriteQueueLimitHigh") | ||
| 1501 | (write-queue-limit-low . "WriteQueueLimitLow") | ||
| 1502 | (host-name . "Hostname") | ||
| 1503 | (fully-qualified-domain-name-lookup? . "FQDNLookup"))) | ||
| 1504 | |||
| 1505 | (define collectd-configuration-serialize-field | ||
| 1506 | (remap-names collectd-configuration-remap | ||
| 1507 | collectd-serialize-field)) | ||
| 1508 | |||
| 1509 | (define %collectd-default-type-database | ||
| 1510 | (file-append collectd "/share/collectd/types.db")) | ||
| 1511 | |||
| 1512 | (define-configuration collectd-configuration | ||
| 1513 | (collectd | ||
| 1514 | (package collectd) | ||
| 1515 | "The collectd package to use." | ||
| 1516 | (serializer empty-serializer)) | ||
| 1517 | |||
| 1518 | (base-directory | ||
| 1519 | (string "/var/lib/collectd") | ||
| 1520 | "Sets the base directory. This is the directory beneath which all | ||
| 1521 | @acronym{RRD, round-robin database} files are created. Possibly more | ||
| 1522 | subdirectories are created. This is also the working directory for | ||
| 1523 | collectd." | ||
| 1524 | (serializer collectd-configuration-serialize-field)) | ||
| 1525 | |||
| 1526 | (auto-load-plugins? | ||
| 1527 | (boolean #f) | ||
| 1528 | "When set to @code{#f}, plugins must be loaded explicitly, by setting the | ||
| 1529 | @code{load-plugin?} field of each plugin configuration to @code{#t}. If a | ||
| 1530 | @code{<Plugin ...>} block is encountered and no configuration handling | ||
| 1531 | callback for this plugin has been registered, a warning is logged and the | ||
| 1532 | block is ignored. | ||
| 1533 | |||
| 1534 | When set to @code{#t}, each @code{<Plugin ...>} block acts as if it was | ||
| 1535 | immediately preceded by a @code{LoadPlugin} statement. @code{LoadPlugin} | ||
| 1536 | statements are still required for plugins that don't provide any | ||
| 1537 | configuration, e.g. the @code{Load} plugin." | ||
| 1538 | (serializer collectd-configuration-serialize-field)) | ||
| 1539 | |||
| 1540 | (collect-internal-stats? | ||
| 1541 | (boolean #f) | ||
| 1542 | "When @code{#t}, various statistics about the collectd daemon will | ||
| 1543 | be collected, with \"collectd\" as the plugin name." | ||
| 1544 | (serializer collectd-configuration-serialize-field)) | ||
| 1545 | |||
| 1546 | (type-databases | ||
| 1547 | (list-of-file-likes (list %collectd-default-type-database)) | ||
| 1548 | "One or more files that contain the data-set descriptions. See | ||
| 1549 | @code{types.db(5)} for a description of the format of these files." | ||
| 1550 | (serializer (remap-names collectd-configuration-remap | ||
| 1551 | collectd-serialize-list-of-file-likes))) | ||
| 1552 | |||
| 1553 | (interval | ||
| 1554 | (seconds 60) | ||
| 1555 | "Configures the interval in which to query the read plugins. | ||
| 1556 | Smaller values lead to a higher system load produced by | ||
| 1557 | collectd, while higher values lead to more coarse statistics. | ||
| 1558 | |||
| 1559 | Warning: You should set this once and then never touch it again. If | ||
| 1560 | you do, you will have to delete all your RRD files or know some | ||
| 1561 | serious RRDtool magic! (Assuming you're using the RRDtool or | ||
| 1562 | RRDCacheD plugin.)" | ||
| 1563 | (serializer collectd-configuration-serialize-field)) | ||
| 1564 | |||
| 1565 | (max-read-interval | ||
| 1566 | (seconds 86400) | ||
| 1567 | "A read plugin doubles the interval between queries after each | ||
| 1568 | failed attempt to get data. | ||
| 1569 | |||
| 1570 | This options limits the maximum value of the interval." | ||
| 1571 | (serializer collectd-configuration-serialize-field)) | ||
| 1572 | |||
| 1573 | (timeout | ||
| 1574 | maybe-integer | ||
| 1575 | "Consider a value list \"missing\" when no update has been read or | ||
| 1576 | received for @code{Iterations} iterations. By default, collectd considers | ||
| 1577 | a value list missing when no update has been received for twice the | ||
| 1578 | update interval. Since this setting uses iterations, the maximum | ||
| 1579 | allowed time without update depends on the @code{Interval} information | ||
| 1580 | contained in each value list. This is used in the @code{Threshold} | ||
| 1581 | configuration to dispatch notifications about missing values, see | ||
| 1582 | @code{collectd-threshold(5)} for details." | ||
| 1583 | (serializer collectd-configuration-serialize-field)) | ||
| 1584 | |||
| 1585 | (read-threads | ||
| 1586 | (integer 5) | ||
| 1587 | "Number of threads to start for reading plugins. You may want to | ||
| 1588 | increase this if you have more than five plugins that take a long time | ||
| 1589 | to read. Mostly those are plugins that do network-IO. Setting this to | ||
| 1590 | a value higher than the number of registered read callbacks is not | ||
| 1591 | recommended." | ||
| 1592 | (serializer collectd-configuration-serialize-field)) | ||
| 1593 | |||
| 1594 | (write-threads | ||
| 1595 | (integer 5) | ||
| 1596 | "Number of threads to start for dispatching value lists to write | ||
| 1597 | plugins. You may want to increase this if you have more than five | ||
| 1598 | plugins that may take relatively long to write to." | ||
| 1599 | (serializer collectd-configuration-serialize-field)) | ||
| 1600 | |||
| 1601 | (write-queue-limit-high | ||
| 1602 | maybe-integer | ||
| 1603 | "Metrics are read by the read threads and then put into a queue to | ||
| 1604 | be handled by the write threads. If one of the write plugins is | ||
| 1605 | slow (e.g. network timeouts, I/O saturation of the disk) this queue | ||
| 1606 | will grow. In order to avoid running into memory issues in such a | ||
| 1607 | case, you can limit the size of this queue. | ||
| 1608 | |||
| 1609 | If there are @code{write-queue-limit-high} metrics in the queue, any | ||
| 1610 | new metrics will be dropped. | ||
| 1611 | |||
| 1612 | If the number of metrics currently in the queue is between | ||
| 1613 | @code{write-queue-limit-low} and @code{write-queue-limit-high}, the | ||
| 1614 | metric is dropped with a probability that is proportional to the | ||
| 1615 | number of metrics in the queue (i.e. it increases linearly until it | ||
| 1616 | reaches 100%)." | ||
| 1617 | (serializer collectd-configuration-serialize-field)) | ||
| 1618 | |||
| 1619 | (write-queue-limit-low | ||
| 1620 | maybe-integer | ||
| 1621 | "If there are less than @code{write-queue-limit-low} metrics in the | ||
| 1622 | queue, all new metrics will be enqueued. | ||
| 1623 | |||
| 1624 | If @code{write-queue-limit-high} is set to non-zero and | ||
| 1625 | @code{write-queue-limit-low} is unset, the latter will default to half | ||
| 1626 | of @code{write-queue-limit-high}." | ||
| 1627 | (serializer collectd-configuration-serialize-field)) | ||
| 1628 | |||
| 1629 | (host-name | ||
| 1630 | maybe-string | ||
| 1631 | "Sets the hostname that identifies a host. If you omit this setting, | ||
| 1632 | the hostname will be determined using the @code{gethostname(2)} system | ||
| 1633 | call." | ||
| 1634 | (serializer collectd-configuration-serialize-field)) | ||
| 1635 | |||
| 1636 | (fully-qualified-domain-name-lookup? | ||
| 1637 | (boolean #t) | ||
| 1638 | "If @code{host-name} is determined automatically, this setting | ||
| 1639 | controls whether or not the daemon should try to figure out the | ||
| 1640 | @acronym{FQDN, fully qualified domain name}. This is done using a | ||
| 1641 | lookup of the name returned by @code{gethostname(2)}." | ||
| 1642 | (serializer collectd-configuration-serialize-field)) | ||
| 1643 | |||
| 1644 | (plugins | ||
| 1645 | (list-of-collectd-plugins '()) | ||
| 1646 | "Configurations for collectd plugins." | ||
| 1647 | (serializer collectd-serialize-list-of-plugins)) | ||
| 1648 | |||
| 1649 | (prefix collectd-)) | ||
| 1650 | |||
| 1651 | (define (collectd-configuration-python config) | ||
| 1652 | "Return the Python package collectd was built with, or #f." | ||
| 1653 | (and=> (assoc-ref (package-native-inputs | ||
| 1654 | (collectd-configuration-collectd config)) | ||
| 1655 | "python") | ||
| 1656 | car)) | ||
| 1657 | |||
| 1658 | (define (collectd-python-packages config) | ||
| 1659 | "Return a list of all packages in Python plugins." | ||
| 1660 | (append-map | ||
| 1661 | (lambda (plugin) | ||
| 1662 | (if (collectd-plugin-python? plugin) | ||
| 1663 | (collectd-plugin-python-packages plugin) | ||
| 1664 | '())) | ||
| 1665 | (collectd-configuration-plugins config))) | ||
| 1666 | |||
| 1667 | (define (collectd-profile-packages config) | ||
| 1668 | "Return packages to include in the profile for collectd." | ||
| 1669 | (let ((python (collectd-configuration-python config)) | ||
| 1670 | (python-packages (collectd-python-packages config))) | ||
| 1671 | (cons | ||
| 1672 | (collectd-configuration-collectd config) | ||
| 1673 | ;; Only include Python and packages if collectd has support. | ||
| 1674 | (if python | ||
| 1675 | (cons python python-packages) | ||
| 1676 | '())))) | ||
| 1677 | |||
| 1678 | (define (make-collectd-profile-wrapper config) | ||
| 1679 | "Return a gexp representing a wrapper for collectd, which runs it in a profile." | ||
| 1680 | (let* ((collectd (collectd-configuration-collectd config)) | ||
| 1681 | (packages (collectd-profile-packages config)) | ||
| 1682 | (collectd-profile (profile | ||
| 1683 | (content | ||
| 1684 | (packages->manifest packages))))) | ||
| 1685 | (computed-file | ||
| 1686 | "collectd-profile-wrapper" | ||
| 1687 | (with-imported-modules '((guix build utils)) | ||
| 1688 | #~(begin | ||
| 1689 | (use-modules (guix build utils)) | ||
| 1690 | (call-with-output-file #$output | ||
| 1691 | (lambda (output) | ||
| 1692 | (format output | ||
| 1693 | (string-append | ||
| 1694 | "#! ~a~%~%" | ||
| 1695 | ". ~a~%" | ||
| 1696 | "exec -a \"${0##*/}\" ~a \"$@\"~%") | ||
| 1697 | #$(file-append bash "/bin/bash") | ||
| 1698 | #$(file-append collectd-profile "/etc/profile") | ||
| 1699 | #$(file-append collectd "/sbin/collectd")))) | ||
| 1700 | (chmod #$output #o755)))))) | ||
| 1701 | |||
| 1702 | (define %collectd-pid-file "/var/run/collectd.pid") | ||
| 1703 | |||
| 1704 | (define (make-collectd-shepherd-service config) | ||
| 1705 | (let ((config-file | ||
| 1706 | (mixed-text-file | ||
| 1707 | "collectd.conf" | ||
| 1708 | (serialize-configuration config collectd-configuration-fields)))) | ||
| 1709 | (match-record config <collectd-configuration> (collectd) | ||
| 1710 | (shepherd-service | ||
| 1711 | (provision '(collectd)) | ||
| 1712 | (documentation "Run collectd.") | ||
| 1713 | (requirement '(user-processes networking)) | ||
| 1714 | (start | ||
| 1715 | #~(make-forkexec-constructor | ||
| 1716 | (list #$(make-collectd-profile-wrapper config) | ||
| 1717 | "-C" #$config-file | ||
| 1718 | "-B" ; Don't create base dir. | ||
| 1719 | "-P" #$%collectd-pid-file) | ||
| 1720 | #:pid-file #$%collectd-pid-file)) | ||
| 1721 | (stop #~(make-kill-destructor)))))) | ||
| 1722 | |||
| 1723 | (define (collectd-activation config) | ||
| 1724 | (match-record config <collectd-configuration> (base-directory) | ||
| 1725 | (with-imported-modules | ||
| 1726 | (source-module-closure '((guix build utils))) | ||
| 1727 | #~(begin | ||
| 1728 | (use-modules (guix build utils)) | ||
| 1729 | (mkdir-p #$base-directory))))) | ||
| 1730 | |||
| 1731 | (define collectd-service-type | ||
| 1732 | (service-type | ||
| 1733 | (name 'collectd) | ||
| 1734 | (description "Run collectd") | ||
| 1735 | (extensions | ||
| 1736 | (list | ||
| 1737 | (service-extension shepherd-root-service-type | ||
| 1738 | (compose list make-collectd-shepherd-service)) | ||
| 1739 | (service-extension activation-service-type | ||
| 1740 | collectd-activation))) | ||
| 1741 | (compose concatenate) | ||
| 1742 | (extend | ||
| 1743 | (lambda (config plugins) | ||
| 1744 | (collectd-configuration | ||
| 1745 | (inherit config) | ||
| 1746 | (plugins (append (collectd-configuration-plugins config) plugins))))) | ||
| 1747 | (default-value (collectd-configuration)))) | ||
