Hands up if you use www.speedtest.net ?
Speedtest.net® by OOKLA is the de-facto standard for measuring Internet connectivity and the performance and availability of your Internet connection. But did you know it has a command-line interface? This means that it can easily be integrated with Zabbix.
Small and medium sized enterprises, schools, not-for-profit organisations largely depend on the same Internet provision that we use at home. The only difference is likely to be that with a “business grade” Internet connection you’ll probably have a defined service level in terms of performance and availability.
Nobius shows you how
This article shows how Zabbix and OOKLA can work together in harmony to give you a straightforward view of your Internet performance and availability.
We assume that you have basic familiarity with Zabbix and Linux.
We should also mention that this is a very BASIC configuration. There are some steps that are crude to say the least but the objective here is to show conceptually how it can be done. This guide is published as a “kickstart” guide only. We strongly encourage you to seek further knowledge and understanding rather than blindly following my words.
Let’s start by listing the “ingredients” we’ll need….
- Zabbix
We used a straightforward 4.4.0 virtual appliance for simplicity. Definitely not recommended for serious monitoring, but it works as an example. - Internet Access from Your Zabbix Server
We’re going to set this up using the Zabbix Server to run Speedtest. You can also configure things so that Speedtest runs from a Zabbix proxy – useful if you want to monitor Internet connectivity at remote locations. - The Speedtest® CLI
This can be downloaded from here. Download the version for your OS. The Zabbix appliance VM we’re using is based on Ubuntu Xenial.
That’s the ingredients.
I’m going to assume you’ve got Zabbix running and you’ve installed the Speedtest® CLI on your Zabbix server.
First, check Speedtest works OK on your Zabbix server by running: appliance@zabbix:~$ speedtest -h
N.B. The first time you run Speedtest CLI you’ll be asked to accept some licensing and GDPR notices. These messages only appear the first time you run Speedtest.
After accepting the licensing information, you should see something like this:
Notice the ‘-f’ parameter. This tells Speedtest how to show the output. This is an important feature because Zabbix can handle JSON directly.
- If you run
appliance@zabbix:~$ speedtest -f json
you get something like this;
which is pretty much perfect for what we’ll need, even though it looks complicated. - Now the fun bit starts. We’re going to configure Speedtest CLI as a UserParameter in Zabbix. This will allow us to use the output to generate various Zabbix items. Remember a Zabbix item can only contain one value but the output when we run Speedtest CLI will give us multiple values. To handle this, we need to create an item containing the entire JSON output from the Speedtest CLI and then create dependent items to obtain individual metrics. Schematically, it looks like this;
With each dependent item being a child of the master item.
Only the master item actually executes the Speedtest CLI.
The steps to make it work
Step 1: Configure the UserParameter;
a) Edit (vi / vim) the /etc/zabbix/zabbix_agent.conf
file and find the “UserParameter” section:
b) Add the following line:
UserParameter=nobius.speedtest,sudo -u zabbix usr/bin/speedtest --accept-license --accept-gdpr -f json
c) In the same file, find the TimeOut section and change the Timeout parameter value to 30:
Save the file and restart the Zabbix agent.
Explainer for Step 1.
For step 1.b you might think that including the ‘sudo -u’ part is a little wrong. However, it seems that the writers of the Speedtest CLI® – OOKLA have some code in Speedtest CLI ® that causes it to crash when called by the Zabbix agent. This has been raised with OOKLA and we’re awaiting a response. This does mean though that we MUST perform Step 2.(below). Carefully.
In Step 1.c, we are increasing the Timeout value for processing. Running Speedtest CLI ® can take a few seconds – certainly more than the default of 3 seconds. In our test environment it takes on average 20 – 23 seconds.
Step 2: Make sure the zabbix agent can run the Speedtest CLI program.
a) Add the user zabbix to the sudoers files.
There are lots of ways to do this (it’s Linux after all) one way is to edit the /etc/sudoers file (use visudo NOT vi, vim or nano).
Add the following line at the end:
username ALL=(ALL) NOPASSWD:ALL
b) Important Step. When Speedtest CLI is run for the first time, it creates a directory structure in the home directory of the user running it. This needs to be replicated under the home directory of the zabbix user:
appliance@zabbix:~$ cd ~appliance | # Assuming you’re using the Zabbix appliance and logged on as appliance. |
appliance@zabbix:~$ ls -a . .. .bash_history .bash_logout .bashrc .config .profile .ssh .sudo_as_admin_successful | # If you’ve already run speedtest, you’ll see a directory called .config. This directory tree needs to be replicated in the home directory of the zabbix user. |
appliance@zabbix:~$ cp -R ~appliance/.config ~zabbix | # This creates the .config/ookla/speedtest-cli.json file. |
root@zabbix:~$ chown -R zabbix:zabbix ~zabbix/.config | Sudo into root and changes the ownership of the directories and files to zabbix:zabbix. |
Explainer for Step 2.
For Step 2.a we appreciate that this may not be the best way to do it. As we said, this is a simple route to working. The zabbix user itself does not have a login shell defined, which does mitigate this step a little.
For Step 2.b we manually recreated the structure of directory and files that are created by Speedtest CLI itself when executed for the first time. Zabbix doesn’t have a login shell defined and we didn’t want to set one up for obvious reasons.
Step 3. Test that the UserParameter is working
appliance@zabbix:~$ zabbix_get -s 127.0.0.1 -k nobius.speedtest should result in something like this:
{"type":"result","timestamp":"2020-02-03T22:11:08Z","ping":{"jitter":0.16400000000000001,"latency":18.266999999999999},"download":"bandwidth":8467913,"bytes":55840457,"elapsed":6615},"upload":"bandwidth":2332421,"bytes":32429585,"elapsed":15015},"packetLoss":0,"isp":"BT","interface":"internalIp":"192.168.146.129","name":"ens33","macAddr":"00:0C:29:6A:32:26","isVpn":false,"externalIp":"86.170.184.184"},"server":{"id":3504,"name":"TNP Ltd.","location":"Manchester","country":"Great Britain","host":"speedtest.tnp.net.uk","port":8080,"ip":"5.61.120.11"},"result":{"id":"2c00e1b4-fb2b-4424-a25fe2ca085a97b4","url":"https://www.speedtest.net/result/c/2c00e1b4-fb2b-4424-a25f-e2ca085a97b4"}}
You’ll be pleased to know that the rest of the process is done entirely within the Zabbix UI, but it’s probably worth doing a little recap…
So far we have:
- Installed the Speedtest CLI binary.
- Configured Zabbix to run the Speedtest CLI binary as a UserParameter.
- Configured the SpeedTest CLI so it runs in the context of the Zabbix agent.
We now need to configure the master Zabbix item and all the dependent items.
Step 4 In the Zabbix UI, create a new item (in our case for the Zabbix host) :
The important field here is the “Key”. This is set to the name of the UserParameter. Make a note of the item’s Name – you’ll need it for the dependent items.
Step 5 Now create the dependent items with some preprocessing:
The important field here is the Item Type. Make sure it is set to “Dependent Item”.
Also, make sure that the Master Item field is set to “Nobius Internet” – i.e. the Item you just created in step 4. Use the “Select” button to make it easier to find.
Step 6 Then select the Preprocessing tab :
The important field here is the JSONPath parameter. We can’t go into the nuances of JSON here but in simple terms, if you look carefully at the output of the Speedtest CLI, you’ll see a section that looks like this :
"ping":{"jitter":0.16400000000000001,"latency":18.266999999999999}
You can thing of “ping” as the section you want Zabbix to look at and the entry “latency” as the field within the section. Specifying “ping.latency” gives the value 18.2669999999999. In JSONPath terms, this is represented as $.ping.latency
.
If you wanted the value for jitter, you’d use $.ping.jitter
To create the remaining items, repeat sections 5 and 6 creating new item names and specifying new item keys.
Top Tip : We use http://www.jsonquerytool.com/ to figure out JSONPaths. Just paste your JSON into the input and enter your query to see whether you have the right JSONPath. We find this is quicker than using Zabbix’s built-in tests. Having said that we ALWAYS double check with the Zabbix JSONPath “test” dialogue.
For completeness, here’s the set of JSONPath parameters we used with the Speedtest CLI – it’s not all the values you can get, but it is the interesting ones….
$.ping.latency | The ping response time contained in the JSON from Speedtest CLI |
$.ping.jitter | The packet jitter rate measured by Speedtest CLI |
$.download.bytes | How many bytes were downloaded during the test |
$.upload.bytes | Bytes uploaded during the test |
$.packetloss | Number of data packets lost as measured by Speedtest CLI |
In summary, this is a crude and basic proof of concept on how to use the Speedtest CLI ® released by OOKLA with Zabbix. Nobius doesn’t warrant this guide or provide any guarantees as to suitability for a particular purpose.
There are a number of refinements that Nobius have made to this including graphs and maps that we use with our customers.
Feel free to use as you see fit and any comments are always appreciated. If you have questions, please contact us
The Nobius Team
Bloody great man!
It’s excellent tutorial. However I run into issues with SELinux on Fedora/Centos where occurred issued about sudo for zabbix-agent. Also Even after disabling selinux the speeedtest command run so long that zabbix didnt want to execute it (ofc after setting timeout to 30s). I changed the idea to run speedtest from crontab and in zabbix agent for that UserParameter=speedtest,cat /tmp/speedtest.json, in that case it can be read very fast and it’s not block zabbix-agent thread. Drawback is the timing between zabbix interval and crontab entry.
Cheers
Thanks Gregory. Interesting comment about your test taking >30s. Different connectivity in different places. I did need to update sudoers to get it to work which made me a little nervous. The reason I didn’t want to run from within crontab was that it introduced another component to the monitoring. I guess I just wanted to make it slightly more difficult for myself. As time has moved on, I think your approach makes a lot of sense especially when we can introduce Ansible into the equation so I can update multiple Zabbix proxies and do the test from multiple locations. Thanks for the feedback, really appreciate it.
Dave
David, What a create guide. I have followed it and it is very easy to follow, only I get to step 5 and then the wheels fall off.
I have not followed your naming convention. instead of ‘nobius.speedtest’ I used ‘speedtest-cli.latency’.
All steps 1 to 4 work like a dream. I even tested the jsonpath syntax with an online test portal to find out what value I should use for the jsonpath. The one you said in the example does not work.
In step 5 you use the key nobius.speedtest.latency.
I used speedtest-cli.latency
I then open the pre-processing tab and select JSONPATH and add the value ping.latency as you suggest, but this does not work. The error I get is as follows.
cannot extract value from json by path “ping.latency”: cannot parse as a valid JSON object: invalid object format, expected opening character ‘{‘ or ‘[‘ at: ‘ping.latency’
So I thought that because you are asking to extract a value from the JSONPATH, I assumed to try the following.
$.server.latency, exactly what I used to test with the online portal. This also produced an error.
cannot extract value from json by path “$.server.latency”: cannot parse as a valid JSON object: invalid object format, expected opening character ‘{‘ or ‘[‘ at: ‘$.server.latency’
Do you have any advice about what I am doing wrong.
Thanks
Lawrence
One further comment, in your tutorial you mention adding the UaerParameter into teh zabbix_agent.conf file. I have the zabbix agent installed but don’t have that file in place, I only had a zabbix-agentd.conf file. So that is where I placed the UserParameter.
Do you think this is what might be causing my issue?
LAwrence
Hi Lawrence, you’ll be glad to know tht’s not the cause of your issue. It’s a typo in my article. Thanks for pointing it out. I’ll update it accordingly.
Dave
Hi Lawrence,
I’ve reached out privately to ask you to send me a couple of screenshots so I can help. Once we’ve fixed the issue, I’ll update the article to fix any errors. Thanks for getting in touch, the feedback is very valuable to us.
Regards,
Dave
This article is great. I followed the same steps on a windows host using a Powershell script and it worked really well.
Was you able to create any triggers using these dependant items? I can’t seem to do so.
Hi Craig,
Sincere apologies for the (very) delayed answerto your question. Creating a trigger shouldn’t be a major problem – can you share where you’re having an issue, maybe a couple of screenshots, and we’ll take a look at it. Feel free to email me on David.Collier@nobius.co.uk.
Thanks for the feedback and once again my sincere apologies for the late response.
Dave
What was the typo in the steps? I can’t seem to get any of the dependent items to work other than upload speed