diff --git a/check_speedtest.py b/check_speedtest.py index f38aab9..9991e3c 100755 --- a/check_speedtest.py +++ b/check_speedtest.py @@ -1,14 +1,65 @@ #!/usr/bin/env python3 import argparse +import statistics import sys import traceback import warnings -from cloudflarepycli import cloudflareclass +import cf_speedtest +import cf_speedtest.options as options +import urllib3 +from cf_speedtest.speedtest import run_standard_test import checker.nagios as nagios -from checker.linuxfabric.base import get_state from checker import print_icinga2_check_status +from checker.linuxfabric.base import get_state + + +def run_speedtest(): + # Set up the arguments for the speed test + argv = ["--percentile", "90", "--testpatience", "15"] + + urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + + parser = argparse.ArgumentParser() + parser_with_args = options.add_run_options(parser) + + args = parser_with_args.parse_args(argv) + percentile = args.percentile + VERIFY_SSL = args.verifyssl + OUTPUT_FILE = args.output + patience = args.testpatience + proxy = args.proxy + + # Taken from speed.cloudflare.com + # byte count for each test, ranging from 100KB to 250MB + measurement_sizes = \ + [ + 100_000, + 1_000_000, + 10_000_000, + 25_000_000, + 100_000_000, + 250_000_000, + ] + + def fake_print(*args, **kwargs): + return + + normal_print = __builtins__.print # silence the speedtest + __builtins__.print = fake_print + speeds = run_standard_test(measurement_sizes, percentile, True, patience) + __builtins__.print = normal_print + + # Extract the results + return { + 'download_speed': speeds['download_speed'] / 1_000_000, # Convert to Mbit/sec + 'upload_speed': speeds['upload_speed'] / 1_000_000, # Convert to Mbit/sec + 'percentile': f"{args.percentile}{'th percentile results:':<24}", + 'latency': cf_speedtest.speedtest.percentile(speeds['latency_measurements'], 50), # Median latency in ms + 'jitter': statistics.stdev(speeds['latency_measurements']), # Jitter in ms + 'raw': speeds + } def main(): @@ -34,38 +85,38 @@ def main(): """ with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) - speedtest_results = cloudflareclass.cloudflare(printit=False).runalltests() + speedtest_results = run_speedtest() - upload_speed_state = get_state(speedtest_results['90th_percentile_upload_speed']['value'], args.warn_up, args.critical_up, _operator='le') - download_speed_state = get_state(speedtest_results['90th_percentile_download_speed']['value'], args.warn_down, args.critical_down, _operator='le') - latency_state = get_state(speedtest_results['latency_ms']['value'], args.warn_latency, args.critical_latency, _operator='ge') + upload_speed_state = get_state(speedtest_results['upload_speed'], args.warn_up, args.critical_up, _operator='le') + download_speed_state = get_state(speedtest_results['download_speed'], args.warn_down, args.critical_down, _operator='le') + latency_state = get_state(speedtest_results['latency'], args.warn_latency, args.critical_latency, _operator='ge') exit_code = max(upload_speed_state, download_speed_state, latency_state) - text_result = f"upload: {speedtest_results['90th_percentile_upload_speed']['value']} Mbps, download: {speedtest_results['90th_percentile_download_speed']['value']} Mbps, latency: {speedtest_results['latency_ms']['value']} ms, jitter: {speedtest_results['Jitter_ms']['value']} ms" + text_result = f"upload: {speedtest_results['upload_speed']:.1f} Mbps, download: {speedtest_results['download_speed']:.1f} Mbps, latency: {speedtest_results['latency']:.1f} ms, jitter: {speedtest_results['jitter']:.1f} ms" perfdata = { 'upload': { - 'value': speedtest_results['90th_percentile_upload_speed']['value'] * 1e+6, - 'warn': args.warn_up * 1e+6, - 'crit': args.critical_up * 1e+6, + 'value': round(speedtest_results['upload_speed'] * 1e+6, 2), + 'warn': round(args.warn_up * 1e+6, 2), + 'crit': round(args.critical_up * 1e+6, 2), 'min': 0, 'unit': 'B' }, 'download': { - 'value': speedtest_results['90th_percentile_download_speed']['value'] * 1e+6, - 'warn': args.warn_down * 1e+6, - 'crit': args.critical_down * 1e+6, + 'value': round(speedtest_results['download_speed'] * 1e+6, 2), + 'warn': round(args.warn_down * 1e+6, 2), + 'crit': round(args.critical_down * 1e+6, 2), 'min': 0, 'unit': 'B' }, 'latency_ms': { - 'value': speedtest_results['latency_ms']['value'], - 'warn': args.warn_latency, - 'crit': args.critical_latency, + 'value': round(speedtest_results['latency'], 2), + 'warn': round(args.warn_latency, 2), + 'crit': round(args.critical_latency, 2), 'min': 0, 'unit': 'ms' }, 'jitter_ms': { - 'value': speedtest_results['Jitter_ms']['value'], + 'value': round(speedtest_results['jitter'], 2), 'min': 0, 'unit': 'ms' } diff --git a/requirements.txt b/requirements.txt index ff59795..535080b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,3 +16,4 @@ certifi~=2022.12.7 cloudflarepycli~=1.7.0 zfslib~=0.11.0 dnspython +cf-speedtest \ No newline at end of file