Kali ini kita akan membuat script untuk monitoring HTTP dengan Python. Ada banyak script monitoring diluar sana yang bisa digunakan, tetapi ada baiknya kita belajar untuk membuatnya sehingga kita mengerti cara logiknya.
Sebelum bisa menjalankan script ini, install terlebih modul request dengan pip
pip install requests
Script Python
Copy script dibawah ini, lalu simpan sebagai monitoring.py
#!/usr/bin/env python import requests default_timeout = 10; url = "https://google.com/" r = requests.get(url, timeout=default_timeout) print(r.status_code)
jalankan script tersebut dari terminal
python monitoring.py # output 200
format tersebut masih sangat sederhana, karena belum ada handling error, ganti url dengan https://google.lalalalala
, maka script akan langsung menampilkan error. Dibawah akan kita kembangkan script ini lebih jauh, seperti menangkap error yang muncul. Script akan tetap berjalan sampai semua domain berhasil dicek, lalu menampilkan hasilnya pada bagian akhir.
Error Handler dan File Domain
Karena sekarang zamannya cloud, mari sekalian kita buat konfigurasi filenya menggunakan yaml
, agar lebih di deploy di Kubernetes ataupun di on premises (VM)
#!/usr/bin/env python # monitoring.py import requests import json import yaml import os domain_file = os.environ['DOMAIN_FILE'] def check_url(url): status_code = "" error_messages= "" try: r = requests.get(url, timeout=10) if(r.ok): status_code = r.status_code else: status_code = r.status_code except requests.exceptions.HTTPError as err: error_messages = err except requests.exceptions.ConnectionError as err: error_messages = err except requests.exceptions.Timeout as err: error_messages = err except requests.exceptions.RequestException as err: error_messages = err finally: if status_code is not None: http_status_code = status_code else: http_status_code = "" if error_messages is not None: err_msg = error_messages else: err_msg = "" response = dict(); response['status_code'] = http_status_code response['err_msg'] = str(err_msg).replace("'",'') return response with open(domain_file, 'r') as file: urls = yaml.safe_load(file).items() for key,values in urls: for value in values: getData = check_url(value['url']) logs = { "project": key, "name": value['name'], "url": value['url'], "status_code": getData['status_code'], "messages": getData['err_msg'] } print(logs)
Daftar domain yang di monitoring diambil dari file domains.yaml
, buat file domains.yaml
yang berisi
client: - name: bing.com url: https://bing.com project: - name: example.com url: https://example.com - name: example.com-error url: httpx://example.com - name: example.con url: https://example.con - name: google.com url: https://google.com - name: google.com-error url: https://google.com/900000000000x - name: yahoo.com url: https://yahoo.com - name: yahoo.com-error url: https://yahoo.com/900000000000x open-source: - name: debian.org url: https://www.debian.org - name: ubuntu.com url: https://ubuntu.com/
Untuk modul Python yang perlu di install buat file requirements.txt
requests
install module tersebut
pip install -r requirements.txt
Sebelum menjalankan script tersebut set environment variable DOMAIN_FILE
ke lokasi domains.yaml
, contoh export DOMAIN_FILE=/app/domains.yaml
lalu jalankan script monitoring.py
export DOMAIN_FILE=domains.yaml python monitoring.py
output
{'project': 'client', 'name': 'bing.com', 'url': 'https://bing.com', 'status_code': 200, 'messages': ''} {'project': 'project', 'name': 'example.com', 'url': 'https://example.com', 'status_code': 200, 'messages': ''} {'project': 'project', 'name': 'example.com-error', 'url': 'httpx://example.com', 'status_code': '', 'messages': 'No connection adapters were found for httpx://example.com/'} {'project': 'project', 'name': 'example.con', 'url': 'https://example.con', 'status_code': '', 'messages': 'HTTPSConnectionPool(host=example.con, port=443): Max retries exceeded with url: / (Caused by NewConnectionError(<urllib3.connection.HTTPSConnection object at 0x7faea9ea5f70>: Failed to establish a new connection: [Errno -2] Name or service not known))'} {'project': 'project', 'name': 'google.com', 'url': 'https://google.com', 'status_code': 200, 'messages': ''} {'project': 'project', 'name': 'google.com-error', 'url': 'https://google.com/900000000000x', 'status_code': 404, 'messages': ''} {'project': 'project', 'name': 'yahoo.com', 'url': 'https://yahoo.com', 'status_code': 200, 'messages': ''} {'project': 'project', 'name': 'yahoo.com-error', 'url': 'https://yahoo.com/900000000000x', 'status_code': 404, 'messages': ''} {'project': 'open-source', 'name': 'debian.org', 'url': 'https://www.debian.org', 'status_code': 200, 'messages': ''} {'project': 'open-source', 'name': 'ubuntu.com', 'url': 'https://ubuntu.com/', 'status_code': 200, 'messages': ''}
Build Docker Image/Containerization
Sekarang mari kita buat Dockerfile
, untuk membuat docker image.
FROM python:3.12-bookworm ENV DOMAIN_FILE=/app/domains.yaml USER root RUN groupadd -g 10000 python && useradd -u 10000 -g python -m -d /app python USER python WORKDIR /app COPY --chown=python:python domains.yaml monitoring.py requirements.txt /app/ RUN pip install -r requirements.txt --no-cache-dir --user CMD [ "python", "monitoring.py" ]
lalu build docker image
docker build . -t jaranguda/python-monitoring # output [+] Building 0.2s (10/10) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 380B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/python:3.12-bookworm 0.0s => [1/5] FROM docker.io/library/python:3.12-bookworm 0.0s => [internal] load build context 0.0s => => transferring context: 102B 0.0s => CACHED [2/5] RUN groupadd -g 10000 python && useradd -u 10000 -g python -m -d /app python 0.0s => CACHED [3/5] WORKDIR /app 0.0s => CACHED [4/5] COPY --chown=python:python domains.yaml monitoring.py requirements.txt /app/ 0.0s => CACHED [5/5] RUN pip install -r requirements.txt --no-cache-dir --user 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:6be6dac77ed9cda16f4d372edcf6d82d4403f070f3fa53e27af36a9212b838f1 0.0s => => naming to docker.io/jaranguda/python-monitoring
jalankan docker image tersebut
$ jaranguda/python-monitoring {'project': 'client', 'name': 'bing.com', 'url': 'https://bing.com', 'status_code': 200, 'messages': ''} {'project': 'project', 'name': 'example.com', 'url': 'https://example.com', 'status_code': 200, 'messages': ''} {'project': 'project', 'name': 'example.com-error', 'url': 'httpx://example.com', 'status_code': '', 'messages': 'No connection adapters were found for httpx://example.com/'} {'project': 'project', 'name': 'example.con', 'url': 'https://example.con', 'status_code': '', 'messages': 'HTTPSConnectionPool(host=example.con, port=443): Max retries exceeded with url: / (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x7f64f035a300>: Failed to resolve example.con ([Errno -2] Name or service not known)"))'} {'project': 'project', 'name': 'google.com', 'url': 'https://google.com', 'status_code': 200, 'messages': ''} {'project': 'project', 'name': 'google.com-error', 'url': 'https://google.com/xxxx', 'status_code': 404, 'messages': ''} {'project': 'project', 'name': 'yahoo.com', 'url': 'https://yahoo.com', 'status_code': 200, 'messages': ''} {'project': 'project', 'name': 'yahoo.com-error', 'url': 'https://yahoo.com/xxxx', 'status_code': 404, 'messages': ''} {'project': 'open-source', 'name': 'debian.org', 'url': 'https://www.debian.org', 'status_code': 200, 'messages': ''} {'project': 'open-source', 'name': 'ubuntu.com', 'url': 'https://ubuntu.com/', 'status_code': 200, 'messages': ''}
hasilnya sama persis dengan script yang kita jalankan di lokal.
Semua code diatas ada di repository https://github.com/jaranguda/python-monitoring