This repository has been archived by the owner on Jan 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathspeedtest.py
169 lines (145 loc) · 7.27 KB
/
speedtest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/usr/bin/env python3
import datetime
import json
import os
import subprocess # nosec B404
import time
import socket
import sys
from influxdb_client import InfluxDBClient
# Variables
influxdb_scheme = os.getenv("INFLUXDB_SCHEME", "http")
influxdb_host = os.getenv("INFLUXDB_HOST", "localhost")
influxdb_port = int(os.getenv("INFLUXDB_PORT", 8086))
influxdb_user = os.getenv("INFLUXDB_USER")
influxdb_pass = os.getenv("INFLUXDB_PASS")
influxdb_token = os.getenv("INFLUXDB_TOKEN")
influxdb_org = os.getenv("INFLUXDB_ORG", "-")
influxdb_db = os.getenv("INFLUXDB_DB")
sleepy_time = int(os.getenv("SLEEPY_TIME", 3600))
start_time = datetime.datetime.utcnow().isoformat()
default_hostname = socket.gethostname()
hostname = os.getenv("SPEEDTEST_HOST", default_hostname)
speedtest_server = os.getenv("SPEEDTEST_SERVER")
debug_mode = bool(os.getenv("DEBUG_MODE", False))
def db_check():
if debug_mode is True:
print("STATE: Debug mode is enabled, skipping the database check!")
else:
print("STATE: Running database check")
client_health = client.ping()
if client_health is True:
print("STATE: Connection", client_health)
elif client_health is False:
print("ERROR: Connection", client_health, " - Check scheme, host, port, user, pass, token, org, etc...")
sys.exit(1)
else:
print("ERROR: Something else went wrong")
sys.exit(1)
def speedtest():
db_check()
current_time = datetime.datetime.utcnow().isoformat()
print("STATE: Loop running at", current_time)
# Run Speedtest
# If the user specified a speedtest_server ID number, run a different command vs if they didn't specify an ID
if speedtest_server:
print("STATE: User specified speedtest server:", speedtest_server)
speedtest_server_arg = "--server-id="+speedtest_server
print("STATE: Speedtest running")
my_speed = subprocess.run(['/usr/bin/speedtest', '--accept-license', '--accept-gdpr', '--format=json', speedtest_server_arg], stdout=subprocess.PIPE, shell=False, text=True, check=True) # nosec B603
else:
print("STATE: User did not specify speedtest server, using a random server")
print("STATE: Speedtest running")
my_speed = subprocess.run(['/usr/bin/speedtest', '--accept-license', '--accept-gdpr', '--format=json'], stdout=subprocess.PIPE, shell=False, text=True, check=True) # nosec B603
# Convert the string into JSON, only getting the stdout and stripping the first/last characters
my_json = json.loads(my_speed.stdout.strip())
# Get the values from JSON and log them to the Docker logs
# Basic values
speed_down = my_json["download"]["bandwidth"]
speed_up = my_json["upload"]["bandwidth"]
ping_latency = my_json["ping"]["latency"]
ping_jitter = my_json["ping"]["jitter"]
result_url = my_json["result"]["url"]
# Advanced values
speedtest_server_id = my_json["server"]["id"]
speedtest_server_name = my_json["server"]["name"]
speedtest_server_location = my_json["server"]["location"]
speedtest_server_country = my_json["server"]["country"]
speedtest_server_host = my_json["server"]["host"]
# Print results to Docker logs
print("STATE: RESULTS ARE SAVED IN BYTES-PER-SECOND NOT MEGABITS-PER-SECOND")
print("STATE: Your download ", speed_down, "B/s")
print("STATE: Your upload ", speed_up, "B/s")
print("STATE: Your ping latency ", ping_latency, "ms")
print("STATE: Your ping jitter ", ping_jitter, "ms")
print("STATE: Your server info ", speedtest_server_id, speedtest_server_name, speedtest_server_location, speedtest_server_country, speedtest_server_host)
print("STATE: Your URL is ", result_url)
# This is ugly, but trying to get output in line protocol format (UNIX time is appended automatically)
# https://docs.influxdata.com/influxdb/v2.0/reference/syntax/line-protocol/
p = "speedtest," + "service=speedtest.net," + "host=" + str(hostname) + " download=" + str(speed_down) + ",upload=" + str(speed_up) + ",ping_latency=" + str(ping_latency) + ",ping_jitter=" + str(ping_jitter) + ",speedtest_server_id=" + str(speedtest_server_id) + ",speedtest_server_name=" + "\"" + str(speedtest_server_name) + "\"" + ",speedtest_server_location=" + "\"" + str(speedtest_server_location) + "\"" + ",speedtest_server_country=" + "\"" + str(speedtest_server_country) + "\"" + ",speedtest_server_host=" + "\"" + str(speedtest_server_host) + "\"" + ",result_url=" + "\"" + str(result_url) + "\""
# For troubleshooting the raw line protocol
# print(p)
if debug_mode is True:
print("STATE: Debug mode is enabled, skipping writing to the database!")
print(p)
else:
try:
print("STATE: Writing to database")
write_api = client.write_api()
write_api.write(bucket=influxdb_db, record=p)
write_api.__del__()
except Exception as err:
print("ERROR: Error writing to database")
print(err)
print("STATE: Sleeping for", sleepy_time, "seconds")
time.sleep(sleepy_time)
# Some logging
print("#####\nScript starting!\n#####")
print("STATE: Starting at", start_time)
print("STATE: Sleep time between runs set to", sleepy_time, "seconds")
# Check if variables are set
print("STATE: Checking environment variables...")
if debug_mode is True:
print("STATE: Debug mode is enabled, not checking for any variables!")
else:
if 'INFLUXDB_DB' in os.environ:
print("STATE: INFLUXDB_DB is set")
pass
else:
print("ERROR: INFLUXDB_DB is not set")
sys.exit(1)
if 'INFLUXDB_TOKEN' in os.environ:
print("STATE: INFLUXDB_TOKEN is set, so we must be talking to an InfluxDBv2 instance")
pass
# If token is set, then we are talking to an InfluxDBv2 instance, so INFLUXDB_ORG must also be set
if 'INFLUXDB_ORG' in os.environ:
print("STATE: INFLUXDB_ORG is set")
pass
else:
print("ERROR: INFLUXDB_TOKEN is set, but INFLUXDB_ORG is not set")
sys.exit(1)
else:
print("STATE: INFLUXDB_TOKEN is not set, so we must be talking to an InfluxDBv1 instance")
# If token is not set, then we are talking an InfluxDBv1 instance, so INFLUXDB_USER and INFLUXDB_PASS must also be set
if 'INFLUXDB_USER' in os.environ:
print("STATE: INFLUXDB_USER is set")
pass
else:
print("ERROR: INFLUXDB_USER is not set")
sys.exit(1)
if 'INFLUXDB_PASS' in os.environ:
print("STATE: INFLUXDB_PASS is set")
pass
else:
print("ERROR: INFLUXDB_PASS is not set")
sys.exit(1)
# If token is not set, influxdb_token must be a concatenation of influxdb_user:influxdb_pass when talking to an InfluxDBv1 instance
# https://docs.influxdata.com/influxdb/v1.8/tools/api/#apiv2query-http-endpoint
influxdb_token = f'{influxdb_user}:{influxdb_pass}'
# Instantiate the connection
connection_string = influxdb_scheme + "://" + influxdb_host + ":" + str(influxdb_port)
print("STATE: Database URL is... " + connection_string)
print("STATE: Connecting to InfluxDB...")
client = InfluxDBClient(url=connection_string, token=influxdb_token, org=influxdb_org)
while True:
speedtest()