From 5d844dd8993e6b1cf70b102a374c5aaf2d2e479c Mon Sep 17 00:00:00 2001 From: Todd Blake Date: Tue, 20 Aug 2024 22:10:49 -0400 Subject: [PATCH] 7.0 updates. All the same as 6.4 really, except I re-exported the template yml file --- .../Template_App_Speedtest_Wan/7.0/README.md | 91 ++ .../7.0/Template_App_Speedtest_Wan.yaml | 885 ++++++++++++++++++ .../7.0/dashboard.png | Bin 0 -> 64027 bytes .../7.0/record_speedtest.sh | 70 ++ .../Template_App_Speedtest_Wan/README.md | 2 +- 5 files changed, 1047 insertions(+), 1 deletion(-) create mode 100644 Applications/Template_App_Speedtest_Wan/7.0/README.md create mode 100755 Applications/Template_App_Speedtest_Wan/7.0/Template_App_Speedtest_Wan.yaml create mode 100644 Applications/Template_App_Speedtest_Wan/7.0/dashboard.png create mode 100755 Applications/Template_App_Speedtest_Wan/7.0/record_speedtest.sh diff --git a/Applications/Template_App_Speedtest_Wan/7.0/README.md b/Applications/Template_App_Speedtest_Wan/7.0/README.md new file mode 100644 index 000000000..8e3c7df34 --- /dev/null +++ b/Applications/Template_App_Speedtest_Wan/7.0/README.md @@ -0,0 +1,91 @@ +# Template_App_Speedtest_Wan +To store information from the ookla speedtest cli command into Zabbix. +# Author +Todd Blake +# Requirements: +* Zabbix version 6.4 or later +* the speedtest cli app from speedtest.net - https://www.speedtest.net/apps/cli (NOT the one from pypi) +* the timeout command to timeout a hanging speedtest command +* the zabbix_sender command for sending the data to zabbix +# Installation: +1. Import the Template_App_Speedtest_Wan.yaml template into your Zabbix instance (Configuration --> Templates --> Import), and apply the template to a host +2. Copy the record_speedtest.sh script to somewhere on your system, e.g. /usr/local/bin/record_speedtest.sh +3. Set the script to be executable, e.g. `chmod +x /usr/local/bin/record_speedtest.sh` +4. Edit the record_speedtest.sh script: + - Set the SPDHOST variable to the name of the host you've applied the template too within Zabbix + - Set the ZABSRV variable to the name/IP of your Zabbix server or proxy that the host is reporting too + - Optionally, set the PSKID and PSKFILE variables if you're using encryption in your Zabbix environment. + - Optionally, set the SPEEDTESTPARAMS variable to any additional needed speedtest parameters +5. Set the {$NO_SPDTST_DATA_SECS} macro to 300 seconds (5 minutes) more than the frequency of execution, in seconds. i.e. If you run it every 6 hours, set the macro to 21900 (6 hours * 60 minutes per hour * 60 seconds per minute, then add 300 seconds to that.) +6. Install a crontab entry to run this script on a schedule: + + `0 */6 * * * /usr/local/bin/record_speedtest.sh # feed speedtest info into zabbix every 6 hours` + +# Example Dashboard +![Example Dashboard](dashboard.png?raw=true "Example Dashboard") + +## Macros used + +|Macro|Default Value|Description| +|-----|-------------|-----------| +|{$NO_SPDTST_DATA_SECS}|21900 (6 hours and 5 minutes)|The number of seconds that Zabbix will alert when it's received no new speedtest data| +|{$BWIDTH_DL_ALERT}|209715200 (200Mbps)|The threshold for alerting if download bandwidth drops below this value| +|{$BWIDTH_UL_ALERT}|10485760 (10Mbps)|The threshold for alerting if upload bandwidth drops below this value| + +## Template links + +There are no template links in this template. + +## Discovery rules + +There are no discovery rules in this template. + +## Items collected + +|Name|Description|Type|Key and additional info| +|----|-----------|----|----| +|Speedtest - Download Bandwidth|The measured bandwidth in bits per second.|Dependent item|speedtest[download.bandwidth]| +|Speedtest - Download Bytes|The number of bytes downloaded in the test.|Dependent item|speedtest[download.bytes]| +|Speedtest - Download Latency (High)|The highest recorded latency during the download portion of the test.|Dependent item|speedtest[download.latency.high]| +|Speedtest - Download Latency (IQM)|The IQM (interquartile mean) of the latency recorded during the download portion of the test.|Dependent item|speedtest[download.latency.iqm]| +|Speedtest - Download Latency (Jitter)|The jitter recorded during the download portion of the test.|Dependent item|speedtest[download.latency.jitter]| +|Speedtest - Download Latency (Low)|The lowest recorded latency during the download portion of the test.|Dependent item|speedtest[download.latency.low]| +|Speedtest - Download Time Elapsed|The time to execute the download test.|Dependent item|speedtest[download.elapsed]| +|Speedtest - External IP|The external (internet) IP address of the system executing the test.|Dependent item|speedtest[interface.externalIp]| +|Speedtest - ISP|The ISP of the system executing the test.|Dependent item|speedtest[isp]| +|Speedtest - Internal IP|The internal (local) IP address of the system executing the test.|Dependent item|speedtest[interface.internalIp]| +|Speedtest - Is VPN?|Are we on a VPN while executing the test?|Dependent item|speedtest[interface.isVpn]| +|Speedtest - JSON|The raw JSON from the speedtest command. It's parsed out for all of the other fields except the run time.|Zabbix trapper|custom.speedtest[json]| +|Speedtest - MAC Address|The MAC address of the interface used when executing the test|Dependent item|speedtest[interface.macAddr]| +|Speedtest - Network Interface|The network interface used to execute the test|Dependent item|speedtest[interface.name]| +|Speedtest - Packet Loss|Packets lost during the test.|Dependent item|speedtest[packetLoss]| +|Speedtest - Ping Latency (Average)|The average recorded latency during the ping portion of the test.|Dependent item|speedtest[ping.latency]| +|Speedtest - Ping Latency (High)|The highest recorded latency during the ping portion of the test.|Dependent item|speedtest[ping.high]| +|Speedtest - Ping Latency (Jitter)|The recorded jitter during the ping portion of the test.|Dependent item|speedtest[ping.jitter]| +|Speedtest - Ping Latency (Low)|The lowest recorded latency during the ping portion of the test.|Dependent item|speedtest[ping.low]| +|Speedtest - Result ID|The ID at speedtest.net of the results.|Dependent item|speedtest[result.id]| +|Speedtest - Result URL|The URL at speedtest.net of the results.|Dependent item|speedtest[result.url]| +|Speedtest - Run time|The time the record_speedtest.sh script was executed.|Zabbix trapper|custom.speedtest[runtime]| +|Speedtest - Server Country|The country of the selected speedtest server.|Dependent item|speedtest[server.country]| +|Speedtest - Server Host|The hostname of the selected speedtest server.|Dependent item|speedtest[server.host]| +|Speedtest - Server ID|The speedtest ID of the selected speedtest server.|Dependent item|speedtest[server.id]| +|Speedtest - Server IP|The IP address of the selected speedtest server.|Dependent item|speedtest[server.ip]| +|Speedtest - Server Location|The geographical location (City, State in the US for example) of the selected speedtest server.|Dependent item|speedtest[server.location]| +|Speedtest - Server Name|The human readable speedtest.net name of the selected speedtest server.|Dependent item|speedtest[server.name]| +|Speedtest - Server Port|The TCP port used of the selected speedtest server.|Dependent item|speedtest[server.port]| +|Speedtest - Timestamp|The timestamp of the test recorded from speedtest.net.|Dependent item|speedtest[timestamp]| +|Speedtest - Upload Bandwidth|The measured bandwidth in bits per second.|Dependent item|speedtest[upload.bandwidth]| +|Speedtest - Upload Bytes|The number of bytes uploaded in the test.|Dependent item|speedtest[upload.bytes]| +|Speedtest - Upload Latency (High)|The highest recorded latency during the upload portion of the test.|Dependent item|speedtest[upload.latency.high]| +|Speedtest - Upload Latency (IQM)|The IQM (interquartile mean) of the latency recorded during the upload portion of the test.|Dependent item|speedtest[upload.latency.iqm]| +|Speedtest - Upload Latency (Jitter)|The jitter recorded during the upload portion of the test.|Dependent item|speedtest[upload.latency.jitter]| +|Speedtest - Upload Latency (Low)|The lowest recorded latency during the upload portion of the test.|Dependent item|speedtest[upload.latency.low]| +|Speedtest - Upload Time Elapsed|The time to execute the upload test.|Dependent item|speedtest[upload.elapsed]| + +## Triggers + +|Name|Description|Expression|Priority| +|----|-----------|----------|--------| +|No new speed test data received in the last {$NO_SPDTST_DATA_SECS} seconds|We haven't received any new JSON data from speedtest in the last {$NO_SPDTST_DATA_SECS} seconds.|nodata(/Template_App_Speedtest/custom.speedtest[json],{$NO_SPDTST_DATA_SECS})=1|High| +|Download bandwidth is less than {$BWIDTH_DL_ALERT}|The measured download bandwidth has dropped below {$BWIDTH_DL_ALERT}bps.|max(/Template_App_Speedtest_Wan/speedtest[download.bandwidth],#3)<{$BWIDTH_DL_ALERT}|Warning| +|Upload bandwidth is less than {$BWIDTH_UL_ALERT}|The measured upload bandwidth has dropped below {$BWIDTH_UL_ALERT}bps.|max(/Template_App_Speedtest_Wan/speedtest[upload.bandwidth],#3)<{$BWIDTH_UL_ALERT}|Warning| diff --git a/Applications/Template_App_Speedtest_Wan/7.0/Template_App_Speedtest_Wan.yaml b/Applications/Template_App_Speedtest_Wan/7.0/Template_App_Speedtest_Wan.yaml new file mode 100755 index 000000000..fbd27a283 --- /dev/null +++ b/Applications/Template_App_Speedtest_Wan/7.0/Template_App_Speedtest_Wan.yaml @@ -0,0 +1,885 @@ +zabbix_export: + version: '7.0' + template_groups: + - uuid: 7df96b18c230490a9a0a9e2307226338 + name: Templates + templates: + - uuid: 9daa55f388e94272af1cacad9807e847 + template: Template_App_Speedtest_Wan + name: Template_App_Speedtest_Wan + description: | + Template_App_Speedtest_Wan + https://github.com/zabbix/community-templates/tree/main/Applications/Template_App_Speedtest_Wan + + To store information from the ookla speedtest cli command into Zabbix. + + Requirements: + * Zabbix version 6.2 or later + * the speedtest cli app from speedtest.net - https://www.speedtest.net/apps/cli (NOT the one from pypi) + * the timeout command to timeout a hanging speedtest command + * the zabbix_sender command for sending the data to zabbix + groups: + - name: Templates + items: + - uuid: 5b0e301ec100482ba6185e88bea05b23 + name: 'Speedtest - JSON' + type: TRAP + key: 'custom.speedtest[json]' + delay: '0' + history: 1d + value_type: TEXT + trends: '0' + description: 'The raw JSON from the speedtest command. It''s parsed out for all of the other fields except the run time.' + tags: + - tag: Application + value: Speedtest + triggers: + - uuid: da54732cbc06492da25873a4617e6916 + expression: 'nodata(/Template_App_Speedtest_Wan/custom.speedtest[json],{$NO_SPDTST_DATA_SECS})=1' + name: 'No new speed test data received in the last {$NO_SPDTST_DATA_SECS} seconds' + priority: HIGH + description: 'We haven''t received any new JSON data from speedtest in the last {$NO_SPDTST_DATA_SECS} seconds.' + - uuid: d9bbc7332f7d418c9f446d0112e0d9a8 + name: 'Speedtest - Run time' + type: TRAP + key: 'custom.speedtest[runtime]' + delay: '0' + history: 1w + units: unixtime + description: 'The time the record_speedtest.sh script was executed.' + tags: + - tag: Application + value: Speedtest + - uuid: 2c14c429e1c94f06826c6dff2a667b8e + name: 'Speedtest - Download Bandwidth' + type: DEPENDENT + key: 'speedtest[download.bandwidth]' + delay: '0' + history: 1w + units: bps + description: 'The measured bandwidth in bits per second.' + preprocessing: + - type: JSONPATH + parameters: + - $.download.bandwidth + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '8' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + triggers: + - uuid: cbd066fd1ebb4357878aa45397012853 + expression: 'max(/Template_App_Speedtest_Wan/speedtest[download.bandwidth],{$BWIDTH_LOW_COUNT})<{$BWIDTH_DL_ALERT}' + name: 'Download bandwidth is less than {$BWIDTH_DL_ALERT}' + priority: WARNING + description: 'The measured download bandwidth has dropped below {$BWIDTH_DL_ALERT}bps.' + manual_close: 'YES' + - uuid: 74e02f936ec54eac82e79be3f8e514aa + name: 'Speedtest - Download Bytes' + type: DEPENDENT + key: 'speedtest[download.bytes]' + delay: '0' + history: 1w + units: B + description: 'The number of bytes downloaded in the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.download.bytes + error_handler: CUSTOM_VALUE + error_handler_params: '0' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 45bcc7edea6749d18322504cb98fe197 + name: 'Speedtest - Download Time Elapsed' + type: DEPENDENT + key: 'speedtest[download.elapsed]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The time to execute the download test.' + preprocessing: + - type: JSONPATH + parameters: + - $.download.elapsed + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 3706056ef63a44d1a29f98d281e94c3e + name: 'Speedtest - Download Latency (High)' + type: DEPENDENT + key: 'speedtest[download.latency.high]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The highest recorded latency during the download portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.download.latency.high + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 227dd77a34b8468c93f47fd825c7e8cf + name: 'Speedtest - Download Latency (IQM)' + type: DEPENDENT + key: 'speedtest[download.latency.iqm]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The IQM (interquartile mean) of the latency recorded during the download portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.download.latency.iqm + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 55de48e2814542cb97e4a7792f21b092 + name: 'Speedtest - Download Latency (Jitter)' + type: DEPENDENT + key: 'speedtest[download.latency.jitter]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The jitter recorded during the download portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.download.latency.jitter + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 2e9f1bcaf4a44a7cbaef11d6fcd731c2 + name: 'Speedtest - Download Latency (Low)' + type: DEPENDENT + key: 'speedtest[download.latency.low]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The lowest recorded latency during the download portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.download.latency.low + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 9104aa05b181443b8ff3d151a10a22ef + name: 'Speedtest - External IP' + type: DEPENDENT + key: 'speedtest[interface.externalIp]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The external (internet) IP address of the system executing the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.interface.externalIp + error_handler: CUSTOM_VALUE + error_handler_params: '-1.-1.-1.-1' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 346297b35c9247a28962ca6badeb794a + name: 'Speedtest - Internal IP' + type: DEPENDENT + key: 'speedtest[interface.internalIp]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The internal (local) IP address of the system executing the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.interface.internalIp + error_handler: CUSTOM_VALUE + error_handler_params: '-1.-1.-1.-1' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 96a9b03149434db98573f94a0194190e + name: 'Speedtest - Is VPN?' + type: DEPENDENT + key: 'speedtest[interface.isVpn]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'Are we on a VPN while executing the test?' + preprocessing: + - type: JSONPATH + parameters: + - $.interface.isVpn + error_handler: CUSTOM_ERROR + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: e1ec203ec4f24d66a8236cddf9e5902a + name: 'Speedtest - MAC Address' + type: DEPENDENT + key: 'speedtest[interface.macAddr]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The MAC address of the interface used when executing the test' + preprocessing: + - type: JSONPATH + parameters: + - $.interface.macAddr + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: e7685390f36d4ef0bd13e30995052836 + name: 'Speedtest - Network Interface' + type: DEPENDENT + key: 'speedtest[interface.name]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The network interface used to execute the test' + preprocessing: + - type: JSONPATH + parameters: + - $.interface.name + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 28218e064cd743e9bfacba18082c00b0 + name: 'Speedtest - ISP' + type: DEPENDENT + key: 'speedtest[isp]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The ISP of the system executing the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.isp + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: ff6e570e13644ff59193ea48fb4e02e4 + name: 'Speedtest - Packet Loss' + type: DEPENDENT + key: 'speedtest[packetLoss]' + delay: '0' + history: 1w + value_type: FLOAT + units: '%' + description: 'Packets lost during the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.packetLoss + error_handler: CUSTOM_VALUE + error_handler_params: '0' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: ca669dc101f342d78b4a995d1c56f443 + name: 'Speedtest - Ping Latency (High)' + type: DEPENDENT + key: 'speedtest[ping.high]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The highest recorded latency during the ping portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.ping.high + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: bb175a8af753409084491b212ac1dd76 + name: 'Speedtest - Ping Latency (Jitter)' + type: DEPENDENT + key: 'speedtest[ping.jitter]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The recorded jitter during the ping portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.ping.jitter + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 858dfc9a191a44deafdf0f79fd23284c + name: 'Speedtest - Ping Latency (Average)' + type: DEPENDENT + key: 'speedtest[ping.latency]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The average recorded latency during the ping portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.ping.latency + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 0b2834e0f7f242a4aa4701f1053b9322 + name: 'Speedtest - Ping Latency (Low)' + type: DEPENDENT + key: 'speedtest[ping.low]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The lowest recorded latency during the ping portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.ping.low + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 949003e3f0a6421c9d66bf4333eb80d1 + name: 'Speedtest - Result ID' + type: DEPENDENT + key: 'speedtest[result.id]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The ID at speedtest.net of the results.' + preprocessing: + - type: JSONPATH + parameters: + - $.result.id + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 3b09b2b31ca4447cb0482045de690a95 + name: 'Speedtest - Result URL' + type: DEPENDENT + key: 'speedtest[result.url]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The URL at speedtest.net of the results.' + preprocessing: + - type: JSONPATH + parameters: + - $.result.url + error_handler: CUSTOM_VALUE + error_handler_params: 'https://www.speedtest.net/' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: a9e6160c1f004fe7aca063bebf065c6d + name: 'Speedtest - Server Country' + type: DEPENDENT + key: 'speedtest[server.country]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The country of the selected speedtest server.' + preprocessing: + - type: JSONPATH + parameters: + - $.server.country + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: f5a1c26278a9485697d9a1482db4c15e + name: 'Speedtest - Server Host' + type: DEPENDENT + key: 'speedtest[server.host]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The hostname of the selected speedtest server.' + preprocessing: + - type: JSONPATH + parameters: + - $.server.host + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 32df3f9d535943189e03aeb85822a7cb + name: 'Speedtest - Server ID' + type: DEPENDENT + key: 'speedtest[server.id]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The speedtest ID of the selected speedtest server.' + preprocessing: + - type: JSONPATH + parameters: + - $.server.id + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: d9f33a38e35f49f1bef47f5b3e1fef8d + name: 'Speedtest - Server IP' + type: DEPENDENT + key: 'speedtest[server.ip]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The IP address of the selected speedtest server.' + preprocessing: + - type: JSONPATH + parameters: + - $.server.ip + error_handler: CUSTOM_VALUE + error_handler_params: '-1.-1.-1.-1' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: e5a2ed142f684f798c9af57e0e2dfcbc + name: 'Speedtest - Server Location' + type: DEPENDENT + key: 'speedtest[server.location]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The geographical location (City, State in the US for example) of the selected speedtest server.' + preprocessing: + - type: JSONPATH + parameters: + - $.server.location + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: f963f823f08740fc8d7d64ac5438a4cc + name: 'Speedtest - Server Name' + type: DEPENDENT + key: 'speedtest[server.name]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The human readable speedtest.net name of the selected speedtest server.' + preprocessing: + - type: JSONPATH + parameters: + - $.server.name + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 731abaeccbc24f71a5d9ec439b701c78 + name: 'Speedtest - Server Port' + type: DEPENDENT + key: 'speedtest[server.port]' + delay: '0' + history: 1w + value_type: CHAR + trends: '0' + description: 'The TCP port used of the selected speedtest server.' + preprocessing: + - type: JSONPATH + parameters: + - $.server.port + error_handler: CUSTOM_VALUE + error_handler_params: UNKNOWN + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 3b79f1537a0946059557cb65fb215b08 + name: 'Speedtest - Timestamp' + type: DEPENDENT + key: 'speedtest[timestamp]' + delay: '0' + history: 1w + units: unixtime + description: 'The timestamp of the test recorded from speedtest.net.' + preprocessing: + - type: JSONPATH + parameters: + - $.timestamp + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: JAVASCRIPT + parameters: + - 'return Date.parse(value)' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: cfe669566b2c49c6811498ea10507f39 + name: 'Speedtest - Upload Bandwidth' + type: DEPENDENT + key: 'speedtest[upload.bandwidth]' + delay: '0' + history: 1w + units: bps + description: 'The measured bandwidth in bits per second.' + preprocessing: + - type: JSONPATH + parameters: + - $.upload.bandwidth + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '8' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + triggers: + - uuid: e6b2a85551304792ab02cacdb2acaac6 + expression: 'max(/Template_App_Speedtest_Wan/speedtest[upload.bandwidth],#3)<{$BWIDTH_UL_ALERT}' + name: 'Upload bandwidth is less than {$BWIDTH_UL_ALERT}' + priority: WARNING + description: 'The measured upload bandwidth has dropped below {$BWIDTH_UL_ALERT}bps.' + - uuid: a13d7a41d91e43cebd523b61ed3ebb90 + name: 'Speedtest - Upload Bytes' + type: DEPENDENT + key: 'speedtest[upload.bytes]' + delay: '0' + history: 1w + units: B + description: 'The number of bytes uploaded in the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.upload.bytes + error_handler: CUSTOM_VALUE + error_handler_params: '0' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: b208d693bc1145e69718bca9cf1b313c + name: 'Speedtest - Upload Time Elapsed' + type: DEPENDENT + key: 'speedtest[upload.elapsed]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The time to execute the upload test.' + preprocessing: + - type: JSONPATH + parameters: + - $.upload.elapsed + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 99c0bdf65f49423ca48e223b48ec59f2 + name: 'Speedtest - Upload Latency (High)' + type: DEPENDENT + key: 'speedtest[upload.latency.high]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The highest recorded latency during the upload portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.upload.latency.high + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 9a990fd1fbbe40228eb7fd44729825bf + name: 'Speedtest - Upload Latency (IQM)' + type: DEPENDENT + key: 'speedtest[upload.latency.iqm]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The IQM (interquartile mean) of the latency recorded during the upload portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.upload.latency.iqm + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: b75e2582d5994a92bdaf7ae810423a3d + name: 'Speedtest - Upload Latency (Jitter)' + type: DEPENDENT + key: 'speedtest[upload.latency.jitter]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The jitter recorded during the upload portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.upload.latency.jitter + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + - uuid: 4ff34fc06d484b8a96b88cfb3436f579 + name: 'Speedtest - Upload Latency (Low)' + type: DEPENDENT + key: 'speedtest[upload.latency.low]' + delay: '0' + history: 1w + value_type: FLOAT + units: s + description: 'The lowest recorded latency during the upload portion of the test.' + preprocessing: + - type: JSONPATH + parameters: + - $.upload.latency.low + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: MULTIPLIER + parameters: + - '.001' + master_item: + key: 'custom.speedtest[json]' + tags: + - tag: Application + value: Speedtest + macros: + - macro: '{$BWIDTH_DL_ALERT}' + value: '209715200' + description: 'The threshold for alerting if download bandwidth drops below this value' + - macro: '{$BWIDTH_LOW_COUNT}' + value: '#3' + description: 'How many times the bandwidth needs to drop below the {$BWIDTH_DL_ALERT} threshold before we alert.' + - macro: '{$BWIDTH_UL_ALERT}' + value: '10485760' + description: 'The threshold for alerting if upload bandwidth drops below this value' + - macro: '{$NO_SPDTST_DATA_SECS}' + value: '21900' + description: 'The number of seconds that Zabbix will alert when it''s received no new speedtest data' + dashboards: + - uuid: 9c9a7a29f56c4b4caae1589dea6c7ad7 + name: 'Internet Bandwidth & Latency' + pages: + - widgets: + - type: graph + width: '72' + height: '5' + fields: + - type: GRAPH + name: graphid + value: + host: Template_App_Speedtest_Wan + name: 'Internet Bandwidth' + - type: STRING + name: reference + value: AAABE + - type: graph + 'y': '5' + width: '72' + height: '5' + fields: + - type: GRAPH + name: graphid + value: + host: Template_App_Speedtest_Wan + name: 'Internet Latency' + - type: STRING + name: reference + value: AAABF + graphs: + - uuid: 893328bbf0d14bcebcee0fbbb66e8086 + name: 'Internet Bandwidth' + graph_items: + - sortorder: '1' + color: 199C0D + item: + host: Template_App_Speedtest_Wan + key: 'speedtest[download.bandwidth]' + - sortorder: '2' + color: F63100 + item: + host: Template_App_Speedtest_Wan + key: 'speedtest[upload.bandwidth]' + - uuid: 6ca6efdc34a14c96bb5a2fe0baab7771 + name: 'Internet Latency' + graph_items: + - color: 2774A4 + yaxisside: RIGHT + item: + host: Template_App_Speedtest_Wan + key: 'speedtest[ping.latency]' + - sortorder: '1' + color: F7941D + yaxisside: RIGHT + item: + host: Template_App_Speedtest_Wan + key: 'speedtest[ping.jitter]' diff --git a/Applications/Template_App_Speedtest_Wan/7.0/dashboard.png b/Applications/Template_App_Speedtest_Wan/7.0/dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..4beb8d4c7f041b43cbc7903fa0eb506035f0b6e6 GIT binary patch literal 64027 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 QhmyO^PoPYR#;#HS1`|XLdH?_b literal 0 HcmV?d00001 diff --git a/Applications/Template_App_Speedtest_Wan/7.0/record_speedtest.sh b/Applications/Template_App_Speedtest_Wan/7.0/record_speedtest.sh new file mode 100755 index 000000000..091a5f654 --- /dev/null +++ b/Applications/Template_App_Speedtest_Wan/7.0/record_speedtest.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# Agent Encryption +PSKID="" +PSKFILE="" + +# Zabbix Server hostname or IP address +ZABSRV="x.x.x.x" + +# Speedtest Host, the name of the host you've applied the template too as it's named in the Zabbix web UI +SPDHOST="name of the host you've applied the template too" + +# Optional Speedtest CLI Params +SPEEDTESTPARAMS="" + +# program locations +SPEEDTEST="$(which speedtest)" +TIMEOUT="$(which timeout)" +ZABBIX_SENDER="$(which zabbix_sender)" +DATE="$(which date)" +MKTEMP="$(which mktemp)" +STAT="$(which stat)" +CAT="$(which cat)" +EGREP="$(which egrep)" +RM="$(which rm)" + +# timeout to run speedtest +TIMEOUTTIME=300 + +test -z "$SPEEDTEST" && echo "speedtest binary not found" && exit +test -z "$TIMEOUT" && echo "timeout binary not found" && exit +test -z "$ZABBIX_SENDER" && echo "zabbix_sender binary not found" && exit +test -z "$DATE" && echo "date binary not found" && exit +test -z "$MKTEMP" && echo "mktemp binary not found" && exit +test -z "$STAT" && echo "stat binary not found" && exit +test -z "$CAT" && echo "cat binary not found" && exit +test -z "$EGREP" && echo "egrep binary not found" && exit +test -z "$RM" && echo "rm binary not found" && exit + +if [ "$($SPEEDTEST -V | $EGREP -c 'Speedtest by Ookla')" -lt 1 ];then + echo "The speedtest binary needs to be from Ookla." + echo "Please visit https://www.speedtest.net/apps/cli" + exit +fi + +# Temporary speedtest output +OUTFILE=$($MKTEMP) + +# what time is it? +NOW=$($DATE +%s) + +$TIMEOUT $TIMEOUTTIME $SPEEDTEST $SPEEDTESTPARAMS -f json 2>/dev/null > $OUTFILE +if [ $($STAT -c %s $OUTFILE) -le 100 ];then + echo "ERROR running speedtest - output file too small - $OUTFILE" + echo "You may want to try running $SPEEDTEST -f json manually" + echo "and/or checking the contents of $OUTFILE" + exit +fi + +F="$($CAT $OUTFILE)" + +# do we have PSKID and PSKFILE? +if [ -f "$PSKFILE" -a -n "$PSKID" ];then + $ZABBIX_SENDER --tls-connect psk --tls-psk-identity "$PSKID" --tls-psk-file "$PSKFILE" -z "$ZABSRV" -s "$SPDHOST" -k "custom.speedtest[runtime]" -o "$NOW" > /dev/null 2>&1 + $ZABBIX_SENDER --tls-connect psk --tls-psk-identity "$PSKID" --tls-psk-file "$PSKFILE" -z "$ZABSRV" -s "$SPDHOST" -k "custom.speedtest[json]" -o "$F" > /dev/null 2>&1 +else + $ZABBIX_SENDER -z "$ZABSRV" -s "$SPDHOST" -k "custom.speedtest[runtime]" -o "$NOW" > /dev/null 2>&1 + $ZABBIX_SENDER -z "$ZABSRV" -s "$SPDHOST" -k "custom.speedtest[json]" -o "$F" > /dev/null 2>&1 +fi +$RM -f $OUTFILE diff --git a/Applications/Template_App_Speedtest_Wan/README.md b/Applications/Template_App_Speedtest_Wan/README.md index 446190f54..2e0f3a1d8 100644 --- a/Applications/Template_App_Speedtest_Wan/README.md +++ b/Applications/Template_App_Speedtest_Wan/README.md @@ -1,4 +1,4 @@ # Template_App_Speedtest_Wan -To store speedtest results inside of Zabbix. The latest version is for [Zabbix 6.4](6.4) +To store speedtest results inside of Zabbix. The latest version is for [Zabbix 7.0](7.0) # Author Todd Blake