Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0caebbfda | ||
|
|
3002990e43 | ||
|
|
7a35d300e0 | ||
|
|
599e0e376e | ||
|
|
b02c6d240f | ||
|
|
2b2dd14493 | ||
|
|
40b8b2aac6 | ||
|
|
b3ee0a5cc6 |
+49
@@ -0,0 +1,49 @@
|
|||||||
|
###########
|
||||||
|
# BUILDER #
|
||||||
|
###########
|
||||||
|
|
||||||
|
# pull official base image
|
||||||
|
FROM python:3.10-bookworm as BUILDER
|
||||||
|
|
||||||
|
# install Ookla's speedtest
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y speedtest-cli
|
||||||
|
|
||||||
|
# set environment variables
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE 1
|
||||||
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
|
||||||
|
# install dependencies
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --upgrade pip && \
|
||||||
|
pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt
|
||||||
|
|
||||||
|
#########
|
||||||
|
# FINAL #
|
||||||
|
#########
|
||||||
|
|
||||||
|
FROM python:3.10-bookworm
|
||||||
|
|
||||||
|
# create home direcroty and app user
|
||||||
|
RUN mkdir -p /home/app && \
|
||||||
|
addgroup --system app && \
|
||||||
|
adduser --system --group app
|
||||||
|
|
||||||
|
# install packages from builder
|
||||||
|
COPY --from=BUILDER /usr/src/app/wheels /wheels
|
||||||
|
COPY --from=BUILDER /usr/src/app/requirements.txt requirements.txt
|
||||||
|
RUN pip install --no-cache /wheels/*
|
||||||
|
|
||||||
|
# copy in files
|
||||||
|
WORKDIR /home/app
|
||||||
|
COPY ./code .
|
||||||
|
|
||||||
|
# change ownership to app user
|
||||||
|
RUN chown -R app:app /home/app
|
||||||
|
|
||||||
|
# change to the app user
|
||||||
|
USER app
|
||||||
|
|
||||||
|
# start execution
|
||||||
|
ENTRYPOINT [ "python", "main.py" ]
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
# bandwidth_probing
|
# bandwidth_probing
|
||||||
|
|
||||||
Service that runs in a container and measures network bandwidth at a specified interval. The results are sent to a PostgreSQL database.
|
Service that runs in a container and measures network bandwidth at a specified interval. The results are sent to a MongoDB database. Logs are sent to discord channel.
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
from speedtest import Speedtest
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
def measure():
|
||||||
|
"""
|
||||||
|
Measure bandwidth usiing Ookla/speedtest.
|
||||||
|
"""
|
||||||
|
s = Speedtest()
|
||||||
|
s.get_servers(servers=[])
|
||||||
|
s.get_best_server()
|
||||||
|
s.download(threads=None)
|
||||||
|
s.upload(threads=None)
|
||||||
|
s.results.share()
|
||||||
|
return s.results.dict()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
load_dotenv()
|
||||||
|
res = measure()
|
||||||
|
print(res)
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
from pymongo import MongoClient
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
def connect(
|
||||||
|
ip_addr: str | None = None,
|
||||||
|
db_name: str | None = None,
|
||||||
|
collection_name: str | None = None
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Connect to MongoDB database and return collection.
|
||||||
|
"""
|
||||||
|
# ensure variables are set
|
||||||
|
if ip_addr is None:
|
||||||
|
ip_addr = os.getenv('DB_IP_ADDRESS')
|
||||||
|
if db_name is None:
|
||||||
|
db_name = os.getenv('DB_NAME')
|
||||||
|
if collection_name is None:
|
||||||
|
collection_name = os.getenv('DB_COLLECTION_NAME')
|
||||||
|
# connect to database
|
||||||
|
client = MongoClient(ip_addr)
|
||||||
|
db = client[db_name]
|
||||||
|
collection = db[collection_name]
|
||||||
|
return collection
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
load_dotenv()
|
||||||
|
collection = connect()
|
||||||
|
print(collection)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
from discord_logging.handler import DiscordHandler
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def initialise_app():
|
||||||
|
"""
|
||||||
|
Convienience function that ensures eveything is ready before running main loop.
|
||||||
|
"""
|
||||||
|
# load environment variables from file
|
||||||
|
load_dotenv()
|
||||||
|
# setup logging
|
||||||
|
fmt = '|%(asctime)s| %(levelname)s %(filename)s:%(funcName)s:%(message)s'
|
||||||
|
datefmt = '%Y-%m-%d %H:%M:%S'
|
||||||
|
logger_level = os.getenv('LOGGER_LEVEL', default=None)
|
||||||
|
if logger_level is None:
|
||||||
|
logger_level = 'info'
|
||||||
|
logging.info(f'environment variable LOGGER_LEVEL not set. Using default (info)')
|
||||||
|
level = getattr(logging, logger_level.upper())
|
||||||
|
logging.basicConfig(format=fmt, datefmt=datefmt, level=level)
|
||||||
|
# setup logging to discord
|
||||||
|
discord_url = os.getenv('DISCORD_URL', default=None)
|
||||||
|
assert discord_url is not None
|
||||||
|
logger = logging.getLogger()
|
||||||
|
discord_handler = DiscordHandler(
|
||||||
|
service_name = 'bandwidth_probing',
|
||||||
|
webhook_url = discord_url,
|
||||||
|
)
|
||||||
|
discord_handler.setFormatter(logging.Formatter('%(message)s'))
|
||||||
|
discord_handler.setLevel(logging.WARNING)
|
||||||
|
logger.addHandler(discord_handler)
|
||||||
|
# ensure environment variables are set
|
||||||
|
necessary_list = [
|
||||||
|
'DB_IP_ADDRESS',
|
||||||
|
'DB_NAME',
|
||||||
|
'DB_COLLECTION_NAME'
|
||||||
|
]
|
||||||
|
for var in necessary_list:
|
||||||
|
assert var in os.environ, f'environment variable {var} not set.'
|
||||||
|
# set defaults if not yet handled
|
||||||
|
default_dict = {
|
||||||
|
'USER_ID': 0,
|
||||||
|
'REPLICATES': 3,
|
||||||
|
'TRIGGER_INTERVAL_SECONDS': 60
|
||||||
|
}
|
||||||
|
for k, v in default_dict.items():
|
||||||
|
if not k in os.environ:
|
||||||
|
logging.info(f'environment variable {k} not set. Using default ({v}).')
|
||||||
|
os.environ[k] = str(v)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
initialise_app()
|
||||||
|
logging.warning('test message')
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
from initialise_app import initialise_app
|
||||||
|
from bandwidth import measure as measure_bandwidth
|
||||||
|
from database import connect
|
||||||
|
|
||||||
|
def event():
|
||||||
|
logging.info('started event')
|
||||||
|
# get env vars
|
||||||
|
replicates = int(os.getenv('REPLICATES'))
|
||||||
|
# setup database connection
|
||||||
|
db = connect()
|
||||||
|
# run event
|
||||||
|
for rep_num in range(replicates):
|
||||||
|
logging.info(f'running replicate {rep_num}')
|
||||||
|
# do measurement
|
||||||
|
try:
|
||||||
|
res = measure_bandwidth()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f'failed to measure bandwidth: {e}')
|
||||||
|
continue
|
||||||
|
# upload result to database
|
||||||
|
payload_dict = {
|
||||||
|
'user_id': os.getenv('USER_ID'),
|
||||||
|
'data': res
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
db_id = db.insert_one(payload_dict).inserted_id
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f'failed sending results to database: {e}')
|
||||||
|
continue
|
||||||
|
logging.debug(f'data sent to database received db_id: {db_id}')
|
||||||
|
time.sleep(1)
|
||||||
|
logging.info('finished event')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
initialise_app()
|
||||||
|
trigger_time = time.time()
|
||||||
|
while True:
|
||||||
|
if time.time() >= trigger_time:
|
||||||
|
# set new trigger time
|
||||||
|
trigger_time += int(os.getenv('TRIGGER_INTERVAL_SECONDS'))
|
||||||
|
# run event
|
||||||
|
try:
|
||||||
|
event()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
version: "3.9"
|
||||||
|
services:
|
||||||
|
bandwidth-probing:
|
||||||
|
build: .
|
||||||
|
container_name: bandwidth-probing
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
aiosignal==1.3.1
|
||||||
|
async-timeout==4.0.2
|
||||||
|
attrs==23.1.0
|
||||||
|
certifi==2023.5.7
|
||||||
|
charset-normalizer==3.2.0
|
||||||
|
discord-webhook==1.1.0
|
||||||
|
dnspython==2.3.0
|
||||||
|
frozenlist==1.3.3
|
||||||
|
idna==3.4
|
||||||
|
multidict==6.0.4
|
||||||
|
pymongo==4.4.0
|
||||||
|
python-dotenv==1.0.0
|
||||||
|
python-logging-discord-handler==0.1.4
|
||||||
|
requests==2.31.0
|
||||||
|
speedtest-cli==2.1.3
|
||||||
|
urllib3==2.0.3
|
||||||
|
yarl==1.9.2
|
||||||
Reference in New Issue
Block a user