From 2f08964d93606ebfbccfd9c593ba0f40a2b2464b Mon Sep 17 00:00:00 2001 From: Cyberes <64224601+Cyberes@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:16:52 -0700 Subject: [PATCH 1/2] add timeout-is-critical arg to nextcloud-stats When the nextcloud-stats check has timeout issues it tends to get buried in the dashboard since UNKNOWN is ranked a lower priority. The new timeout-is-critical arg makes any timeout return critical --- check-plugins/nextcloud-stats/nextcloud-stats | 52 +++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/check-plugins/nextcloud-stats/nextcloud-stats b/check-plugins/nextcloud-stats/nextcloud-stats index 2b66a224..607b347f 100755 --- a/check-plugins/nextcloud-stats/nextcloud-stats +++ b/check-plugins/nextcloud-stats/nextcloud-stats @@ -20,7 +20,7 @@ import lib.base # pylint: disable=C0413 import lib.human # pylint: disable=C0413 import lib.txt # pylint: disable=C0413 import lib.url # pylint: disable=C0413 -from lib.globals import STATE_OK, STATE_UNKNOWN # pylint: disable=C0413 +from lib.globals import STATE_OK, STATE_UNKNOWN, STATE_CRIT # pylint: disable=C0413 __author__ = 'Linuxfabrik GmbH, Zurich/Switzerland' __version__ = '2025100601' @@ -81,6 +81,15 @@ def parse_args(): default=DEFAULT_TIMEOUT, ) + parser.add_argument( + '--timeout-is-critical', + help='Return CRITICAL instead of UNKNOWN when a timeout occurs. ' + 'Default: %(default)s', + dest='TIMEOUT_IS_CRITICAL', + action='store_true', + default=False, + ) + parser.add_argument( '--url', help='Nextcloud API URL. ' @@ -125,15 +134,40 @@ def main(): 'OCS-APIRequest': 'true', } # and get the info from the API - jsonst = lib.base.coe( - lib.url.fetch( - url, - header=header, - insecure=args.INSECURE, - no_proxy=args.NO_PROXY, - timeout=args.TIMEOUT, - ) + fetch_result = lib.url.fetch( + url, + header=header, + insecure=args.INSECURE, + no_proxy=args.NO_PROXY, + timeout=args.TIMEOUT, ) + # lib.url.fetch returns (False, error_message) on error, or the content on success + if isinstance(fetch_result, tuple) and len(fetch_result) == 2 and not fetch_result[0]: + # This is an error + error_message = fetch_result[1] + # Check if this is a timeout error + timeout_exceptions = ( + 'timeout', + 'Timeout', + 'timed out', + 'Connection timeout', + 'Read timeout', + ) + error_str = str(error_message).lower() + is_timeout = any( + timeout_str.lower() in error_str + for timeout_str in timeout_exceptions + ) + if args.TIMEOUT_IS_CRITICAL and is_timeout: + lib.base.oao( + 'Connection timeout occurred while fetching Nextcloud API data.', + STATE_CRIT, + ) + # Let lib.base.coe() handle the error normally (will return UNKNOWN) + jsonst = lib.base.coe(fetch_result) + else: + # Success case + jsonst = lib.base.coe(fetch_result) try: result = json.loads(jsonst) except: From af6f97ffbc81a0547ca952c98a0431e0f6b1f1d3 Mon Sep 17 00:00:00 2001 From: Cyberes <64224601+Cyberes@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:56:36 -0700 Subject: [PATCH 2/2] make it failure-is-critical to CRIT on all errors --- check-plugins/nextcloud-stats/README.md | 29 +++++++++++-------- check-plugins/nextcloud-stats/nextcloud-stats | 24 ++++----------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/check-plugins/nextcloud-stats/README.md b/check-plugins/nextcloud-stats/README.md index a176a778..8f20b190 100644 --- a/check-plugins/nextcloud-stats/README.md +++ b/check-plugins/nextcloud-stats/README.md @@ -29,23 +29,26 @@ Tested with Nextcloud 15+. ```text usage: nextcloud-stats [-h] [-V] [--insecure] [--no-proxy] --password PASSWORD - [--timeout TIMEOUT] [--url URL] [--username USERNAME] + [--timeout TIMEOUT] [--failure-is-critical] [--url URL] + [--username USERNAME] This plugin lets you track the number of active users over time, the number of shares in various categories and some storage statistics against a Nextcloud server. options: - -h, --help show this help message and exit - -V, --version show program's version number and exit - --insecure This option explicitly allows to perform "insecure" SSL - connections. Default: False - --no-proxy Do not use a proxy. Default: False - --password PASSWORD Nextcloud API password. - --timeout TIMEOUT Network timeout in seconds. Default: 8 (seconds) - --url URL Nextcloud API URL. Default: http://localhost/nextcloud/ - ocs/v2.php/apps/serverinfo/api/v1/info - --username USERNAME Nextcloud API username. Default: admin + -h, --help show this help message and exit + -V, --version show program's version number and exit + --insecure This option explicitly allows to perform "insecure" SSL + connections. Default: False + --no-proxy Do not use a proxy. Default: False + --password PASSWORD Nextcloud API password. + --timeout TIMEOUT Network timeout in seconds. Default: 8 (seconds) + --failure-is-critical Return CRITICAL instead of UNKNOWN when any failure occurs + (timeout, connection error, etc.). Default: False + --url URL Nextcloud API URL. Default: http://localhost/nextcloud/ + ocs/v2.php/apps/serverinfo/api/v1/info + --username USERNAME Nextcloud API username. Default: admin ``` @@ -70,7 +73,9 @@ Output: ## States -* Always returns OK. +* Returns OK on success. +* Returns UNKNOWN on errors (such as connection failures, DNS resolution errors, authentication errors, and timeouts by default). +* Returns CRITICAL on any failure (timeout, connection error, etc.) when `--failure-is-critical` is used. ## Perfdata / Metrics diff --git a/check-plugins/nextcloud-stats/nextcloud-stats b/check-plugins/nextcloud-stats/nextcloud-stats index 607b347f..ba4981e8 100755 --- a/check-plugins/nextcloud-stats/nextcloud-stats +++ b/check-plugins/nextcloud-stats/nextcloud-stats @@ -82,10 +82,10 @@ def parse_args(): ) parser.add_argument( - '--timeout-is-critical', - help='Return CRITICAL instead of UNKNOWN when a timeout occurs. ' + '--failure-is-critical', + help='Return CRITICAL instead of UNKNOWN when any failure occurs (timeout, connection error, etc.). ' 'Default: %(default)s', - dest='TIMEOUT_IS_CRITICAL', + dest='FAILURE_IS_CRITICAL', action='store_true', default=False, ) @@ -145,24 +145,12 @@ def main(): if isinstance(fetch_result, tuple) and len(fetch_result) == 2 and not fetch_result[0]: # This is an error error_message = fetch_result[1] - # Check if this is a timeout error - timeout_exceptions = ( - 'timeout', - 'Timeout', - 'timed out', - 'Connection timeout', - 'Read timeout', - ) - error_str = str(error_message).lower() - is_timeout = any( - timeout_str.lower() in error_str - for timeout_str in timeout_exceptions - ) - if args.TIMEOUT_IS_CRITICAL and is_timeout: + if args.FAILURE_IS_CRITICAL: lib.base.oao( - 'Connection timeout occurred while fetching Nextcloud API data.', + 'Connection failure occurred while fetching Nextcloud API data: {}'.format(error_message), STATE_CRIT, ) + return # Exit early, oao() should have already exited but just in case # Let lib.base.coe() handle the error normally (will return UNKNOWN) jsonst = lib.base.coe(fetch_result) else: