banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Services

banshee/services-collection/services/nginx/https/

stub-status

The connections, requests per second and dropped connections of an nginx server, from its stub_status page.

  • services
  • nginx
  • web
  • stub_status
  • http
  • https

by banshee1 installation1 version

v1Latest

Published on October 27, 2026. First version.

Keen 1.0.0 · 62 lines
// An nginx server, by its stub_status page over HTTP: the connections open, reading, writing and waiting, the
// requests per second, and the connections nginx accepted but could not handle (worker_connections reached).
// The page answers, in plain text:
//   Active connections: 291
//   server accepts handled requests
//    16630948 16630948 31070465
//   Reading: 6 Writing: 179 Waiting: 106
need('protocol:http');
$user = need('protocol:http:user', 'optional');
$password = need('protocol:http:password', 'optional');

$url = variable('nginx:url', 'text', array(
    'label' => 'Status page address',
    'help'  => 'The address of the stub_status page, http:// or https://, for instance https://www.example/nginx_status.',
));

output('connections', 'number', array('label' => 'Active connections'));
output('reading', 'number', array('label' => 'Connections reading a request'));
output('writing', 'number', array('label' => 'Connections writing a response'));
output('waiting', 'number', array('label' => 'Idle connections waiting'));
output('requests', 'number', array('label' => 'Requests', 'unit' => 'requests/s'));
output('dropped', 'number', array('label' => 'Connections dropped since start'));

watch.increase('dropped', 'Connections dropped', 'dropped', array('warning' => 0, 'window' => '1 h'));
watch.above('busy', 'Many active connections', 'connections', array('enabled' => false));
watch.habit('requests-unusual', 'Unusual request rate', 'requests', array('enabled' => false));

// A server that refuses the connection, or does not answer in time, is down: critical.
$answer = http.get($url, user=$user, password=$password, errors=$err);
if ($err['code'] == 'connection_refused' || $err['code'] == 'timeout') {
    fail('critical', 'nginx down', $err['text']);
}
if ($err['code'] != '') {
    fail('unreachable', 'nginx unreachable', $err['text']);
}
if ($answer['status'] == 401 || $answer['status'] == 403 || $answer['status'] == 404) {
    fail('misconfigured', 'nginx refuses the status page, code ' . $answer['status'],
        'See the stub_status location and its allow lines in the documentation.');
}
if ($answer['status'] != 200) {
    fail('unreachable', 'nginx answers the status page with code ' . $answer['status']);
}

$active = text.match($answer['body'], 'Active connections: *([0-9]+)');
$counts = text.match($answer['body'], '\n *([0-9]+) +([0-9]+) +([0-9]+)');
$states = text.match($answer['body'], 'Reading: *([0-9]+) +Writing: *([0-9]+) +Waiting: *([0-9]+)');
if (list.count($active) == 0 || list.count($counts) == 0 || list.count($states) == 0) {
    fail('misconfigured', 'The address does not serve an nginx stub_status page', $url);
}

// The requests per second, from the counter of this run and the previous one: none at the first run.
$requests = counter.rate('requests', $counts[3]);
if ($requests == '') {
    skip('First reading: the request rate comes at the next run');
}
value('connections', $active[1]);
value('reading', $states[1]);
value('writing', $states[2]);
value('waiting', $states[3]);
value('requests', number.round($requests, 2));
// accepts minus handled: the connections nginx closed at once, out of worker_connections.
value('dropped', $counts[1] - $counts[2]);