docker stats app (#12358)

* docker stat app support

* Add missing doc and app

* stylci

* styleci

* styleci

* Add test data

* add snmpsim

* Update docker.inc.php

test with use Number::Bi

* typo

* Add tests

* Add tests

Co-authored-by: Jellyfrog <Jellyfrog@users.noreply.github.com>
This commit is contained in:
Lucas Dousse
2021-03-07 20:26:44 +01:00
committed by GitHub
parent b340a3eec4
commit 49868ee1a6
12 changed files with 465 additions and 0 deletions

View File

@@ -92,6 +92,7 @@ by following the steps under the `SNMP Extend` heading.
1. [Certificate](#certificate) - Certificate extend
1. [C.H.I.P.](#chip) - SNMP extend
1. [DHCP Stats](#dhcp-stats) - SNMP extend
1. [Docker Stats](#docker-stats) - SNMP extend
1. [Entropy](#entropy) - SNMP extend
1. [EXIM Stats](#exim-stats) - SNMP extend
1. [Fail2ban](#fail2ban) - SNMP extend
@@ -468,6 +469,39 @@ The application should be auto-discovered as described at the top of
the page. If it is not, please follow the steps set out under `SNMP
Extend` heading top of page.
# Docker Stats
It allows you to know which container docker run and their stats.
This script require: jq
## SNMP Extend
1: Install jq
```
sudo apt install jq
```
2: Copy the shell script to the desired host.
```
wget https://github.com/librenms/librenms-agent/raw/master/snmp/docker-stats.sh -O /etc/snmp/docker-stats.sh
```
3: Run `chmod +x /etc/snmp/docker-stats.sh`
4: Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add:
```
extend docker /etc/snmp/docker-stats.sh
```
5: Restart snmpd on your host
```
systemctl restart snmpd
```
# Entropy
A small shell script that checks your system's available random entropy.

View File

@@ -0,0 +1,36 @@
<?php
$name = 'docker';
$app_id = $app['app_id'];
$colours = 'mega';
$dostack = 0;
$printtotal = 0;
$addarea = 1;
$transparency = 15;
$unitlen = 20;
$bigdescrlen = 25;
$smalldescrlen = 25;
if (isset($vars['container'])) {
$containers = [$vars['container']];
} else {
$containers = get_arrays_with_application($device, $app['app_id'], 'docker');
}
$int = 0;
while (isset($containers[$int])) {
$container_name = $containers[$int];
$rrd_filename = rrd_name($device['hostname'], ['app', $name, $app_id, $container_name]);
if (rrdtool_check_rrd_exists($rrd_filename)) {
$rrd_list[] = [
'filename' => $rrd_filename,
'descr' => $container_name,
'ds' => $rrdVar,
];
}
$int++;
}
require 'includes/html/graphs/generic_multi_line_exact_numbers.inc.php';

View File

@@ -0,0 +1,7 @@
<?php
$unit_text = 'CPU (%)';
$rrdVar = 'cpu_usage';
$divider = 100;
require 'docker-common.inc.php';

View File

@@ -0,0 +1,6 @@
<?php
$unit_text = 'Memory Limit';
$rrdVar = 'mem_limit';
require 'docker-common.inc.php';

View File

@@ -0,0 +1,7 @@
<?php
$unit_text = 'Memory (%)';
$rrdVar = 'mem_perc';
$divider = 100;
require 'docker-common.inc.php';

View File

@@ -0,0 +1,6 @@
<?php
$unit_text = 'Memory used';
$rrdVar = 'mem_used';
require 'docker-common.inc.php';

View File

@@ -0,0 +1,6 @@
<?php
$unit_text = 'PIDs (count)';
$rrdVar = 'pids';
require 'docker-common.inc.php';

View File

@@ -357,6 +357,13 @@ $graphs['voip-monitor'] = [
'memoryusage',
'openfiles',
];
$graphs['docker'] = [
'cpu_usage',
'pids',
'mem_limit',
'mem_used',
'mem_perc',
];
echo '<div class="panel panel-default">';
echo '<div class="panel-heading">';

View File

@@ -0,0 +1,60 @@
<?php
$domain_list = get_arrays_with_application($device, $app['app_id'], 'docker');
print_optionbar_start();
$link_array = [
'page' => 'device',
'device' => $device['device_id'],
'tab' => 'apps',
'app' => 'docker',
];
$containers_list = [];
foreach ($domain_list as $label) {
$container = $label;
if ($vars['container'] == $container) {
$label = sprintf('⚫ %s', $label);
}
array_push($containers_list, generate_link($label, $link_array, ['container' => $container]));
}
printf('%s | containers: %s', generate_link('All Containers', $link_array), implode(', ', $containers_list));
print_optionbar_end();
$graphs = [
'docker_pids' => 'PIDs',
'docker_mem_limit' => 'Container memory limit',
'docker_mem_used' => 'Container memory used',
'docker_cpu_usage' => 'Container CPU usage, %',
'docker_mem_perc' => 'Container Memory usage, %',
];
foreach ($graphs as $key => $text) {
$graph_type = $key;
$graph_array['height'] = '100';
$graph_array['width'] = '215';
$graph_array['to'] = time();
$graph_array['id'] = $app['app_id'];
$graph_array['type'] = 'application_' . $key;
if (isset($vars['container'])) {
$graph_array['container'] = $vars['container'];
}
echo '<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">' . $text . '</h3>
</div>
<div class="panel-body">
<div class="row">';
include 'includes/html/print-graphrow.inc.php';
echo '</div>';
echo '</div>';
echo '</div>';
}

View File

@@ -0,0 +1,69 @@
<?php
use LibreNMS\Exceptions\JsonAppException;
use LibreNMS\Exceptions\JsonAppMissingKeysException;
use LibreNMS\RRD\RrdDefinition;
use LibreNMS\Util\Number;
$name = 'docker';
$app_id = $app['app_id'];
$output = 'OK';
function convertToBytes(string $from): ?int
{
$units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'];
$number = substr($from, 0, -3);
$suffix = substr($from, -3);
//B or no suffix
if (is_numeric(substr($suffix, 0, 1))) {
return (int) $from;
}
$exponent = array_flip($units)[$suffix] ?? null;
if ($exponent === null) {
return null;
}
return $number * (1024 ** $exponent);
}
try {
$docker_data = json_app_get($device, $name, 1)['data'];
} catch (JsonAppMissingKeysException $e) {
$docker_data = $e->getParsedJson();
} catch (JsonAppException $e) {
echo PHP_EOL . $name . ':' . $e->getCode() . ':' . $e->getMessage() . PHP_EOL;
update_application($app, $e->getCode() . ':' . $e->getMessage(), []); // Set empty metrics and error message
return;
}
$rrd_name = ['app', $name, $app_id];
$rrd_def = RrdDefinition::make()
->addDataset('cpu_usage', 'GAUGE', 0, 100)
->addDataset('pids', 'GAUGE', 0)
->addDataset('mem_perc', 'GAUGE', 0, 100)
->addDataset('mem_used', 'GAUGE', 0)
->addDataset('mem_limit', 'GAUGE', 0);
$metrics = [];
foreach ($docker_data as $data) {
$container = $data['container'];
$rrd_name = ['app', $name, $app_id, $container];
$fields = [
'cpu_usage' => ((float) $data['cpu']) * 100,
'pids' => $data['pids'],
'mem_limit' => Number::formatBi($data['memory']['limit']),
'mem_used' => Number::formatBi($data['memory']['used']),
'mem_perc' => ((float) $data['memory']['perc']) * 100,
];
$metrics[$container] = $fields;
$tags = ['name' => $container, 'app_id' => $app_id, 'rrd_def' => $rrd_def, 'rrd_name' => $rrd_name];
data_update($device, 'app', $tags, $fields);
}
update_application($app, $output, $metrics);

View File

@@ -0,0 +1,219 @@
{
"applications": {
"discovery": {
"applications": [
{
"app_type": "docker",
"app_state": "UNKNOWN",
"discovered": 1,
"app_state_prev": null,
"app_status": "",
"app_instance": ""
}
],
"application_metrics": []
},
"poller": {
"applications": [
{
"app_type": "docker",
"app_state": "OK",
"discovered": 1,
"app_state_prev": "UNKNOWN",
"app_status": "",
"app_instance": ""
}
],
"application_metrics": [
{
"metric": "foobar_dashboard_1_cpu_usage",
"value": 1,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_dashboard_1_mem_limit",
"value": 15.36,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_dashboard_1_mem_perc",
"value": 4,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_dashboard_1_mem_used",
"value": 6.93,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_dashboard_1_pids",
"value": 6,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_laravel.test_1_cpu_usage",
"value": 9,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_laravel.test_1_mem_limit",
"value": 15.36,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_laravel.test_1_mem_perc",
"value": 17,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_laravel.test_1_mem_used",
"value": 26.67,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_laravel.test_1_pids",
"value": 4,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_meilisearch_1_cpu_usage",
"value": 0,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_meilisearch_1_mem_limit",
"value": 15.36,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_meilisearch_1_mem_perc",
"value": 7,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_meilisearch_1_mem_used",
"value": 10.86,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_meilisearch_1_pids",
"value": 15,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_mysql_1_cpu_usage",
"value": 33,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_mysql_1_mem_limit",
"value": 15.36,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_mysql_1_mem_perc",
"value": 90,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_mysql_1_mem_used",
"value": 141.3,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_mysql_1_pids",
"value": 38,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_redis_1_cpu_usage",
"value": 23,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_redis_1_mem_limit",
"value": 15.36,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_redis_1_mem_perc",
"value": 3,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_redis_1_mem_used",
"value": 5.06,
"value_prev": null,
"app_type": "docker"
},
{
"metric": "foobar_redis_1_pids",
"value": 5,
"value_prev": null,
"app_type": "docker"
}
]
}
},
"os": {
"discovery": {
"devices": [
{
"sysName": "<private>",
"sysObjectID": ".1.3.6.1.4.1.8072.3.2.10",
"sysDescr": "Linux server 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64",
"sysContact": "<private>",
"version": "3.10.0-693.5.2.el7.x86_64",
"hardware": "Generic x86 64-bit",
"features": null,
"os": "linux",
"type": "server",
"serial": null,
"icon": "linux.svg",
"location": "<private>"
}
]
},
"poller": {
"devices": [
{
"sysName": "<private>",
"sysObjectID": ".1.3.6.1.4.1.8072.3.2.10",
"sysDescr": "Linux server 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64",
"sysContact": "<private>",
"version": "3.10.0-693.5.2.el7.x86_64",
"hardware": "Generic x86 64-bit",
"features": null,
"os": "linux",
"type": "server",
"serial": null,
"icon": "linux.svg",
"location": "<private>"
}
]
}
}
}

View File

@@ -0,0 +1,8 @@
1.3.6.1.2.1.1.1.0|4|Linux server 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64
1.3.6.1.2.1.1.2.0|6|1.3.6.1.4.1.8072.3.2.10
1.3.6.1.2.1.1.3.0|67|77550514
1.3.6.1.2.1.1.4.0|4|<private>
1.3.6.1.2.1.1.5.0|4|<private>
1.3.6.1.2.1.1.6.0|4|<private>
1.3.6.1.4.1.8072.1.3.2.2.1.21.6.100.111.99.107.101.114|2|1
1.3.6.1.4.1.8072.1.3.2.3.1.2.6.100.111.99.107.101.114|4|{"version":"1","data":[{"container":"foobar_laravel.test_1","pids":4,"memory":{"used":"26.67MiB","limit":"15.36GiB","perc":"0.17%"},"cpu":"0.09%"},{"container":"foobar_dashboard_1","pids":6,"memory":{"used":"6.934MiB","limit":"15.36GiB","perc":"0.04%"},"cpu":"0.01%"},{"container":"foobar_meilisearch_1","pids":15,"memory":{"used":"10.86MiB","limit":"15.36GiB","perc":"0.07%"},"cpu":"0.00%"},{"container":"foobar_mysql_1","pids":38,"memory":{"used":"141.3MiB","limit":"15.36GiB","perc":"0.90%"},"cpu":"0.33%"},{"container":"foobar_redis_1","pids":5,"memory":{"used":"5.055MiB","limit":"15.36GiB","perc":"0.03%"},"cpu":"0.23%"}],"error":"0","errorString":""}