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

Leave a comment

Your email address will not be published. Required fields are marked *