Membuat Aplikasi Monitoring Server Sederhana dengan Flask dan Socket.IO

Profile
Ridwan Fajar

2 Februari 2016

Pendahuluan

Memantau performa sebuah server terkadang dilakukan oleh beberapa sysadmin dengan memeriksanya melalui command line. Asumsikan seorang sysadmin ingin melihat performa CPU dan RAM, akan menggunakan perintah free dan cat /proc/stat. Ada juga yang memasang aplikasi server monitoring yang sudah menyediakan berbagai alat untuk memantau kinerja server. Selain melihat performa hardware terkadang ingin juga melihat beberapa file log penting seperti log milik Apache untuk melihat akses yang masuk atau error yang terjadi pada sebuah aplikasi web yang dijalankan di atas Apache. Kali ini kita akan mencoba membangun sebuah aplikasi sederhana yang akan memantau kinerja CPU dan RAM server berbasis Linux dan melihat log Apache yang dipasang di server tersebut. Untuk mendapatkan informasi tersebut kita akan menggunakan bantuan SocketIO, sebuah library Javascript yang membantu developer untuk mengembangkan aplikasi web berbasis Websocket. Untuk mencoba pengalaman yang lebih berbeda, aplikasi ini akan dibuat menggunakan Python dan Flask.

Persiapan Alat

Untuk tutorial ini, Anda membutuhkan beberapa perlengkapan yang cukup banyak. Diantaranya adalah sebagai berikut:
  • Sistem operasi Linux yang dipasang secara lokal. Anda dapat memasangnya di VirtualBox atau VMWare, Laptop Anda sendiri, atau PC yang dijadikan server di ruangan laboratorium komputer milik instansi Anda. Saya sarankan untuk memasang Ubuntu di mesin tersebut bagi yang baru mencoba Linux, dan untuk yang sudah berpengalaman silahkan gunakan Linux favoritnya :D
  • Apache Web Server, Anda dapat memasangnya di Linux melalui package manager atau pun memasangnya dari installer
  • Text Editor, untuk menulis kode Python dan HTML
  • Web Browser, untuk menampilkan aplikasi yang akan dicoba di tutorial ini
  • Python, untuk menjalankan kode Python yang akan ditulis biasanya sudah terpasang di beberapa distro Linux (contoh cara install: apt-get install python)
  • PIP, merupakan package manager untuk memasang library Python (contoh cara install: apt-get install python-pip)
  • Flask, sebuah web framework Python yang mungil dan powerful (contoh cara install: pip install flask)
  • Flask-SocketIO, sebuah ekstensi Flask yang dipergunakan untuk membantu Anda membangun aplikasi web berbasis Websocket dan SocketIO (contoh cara install: pip install flask-socketio)
  • PSUtil, sebuah library Python yang mempermudah Anda untuk mengakses informasi hardware seperti penggunaan CPU dan RAM (contoh cara install: pip install psutil)
  • SocketIO-Client, sebuah library Javascript yang mempermudah pembangunan aplikasi berbasis Websocket. Anda dapat mengunduhnya di website resmi Socket.IO
  • jQuery, sebuah library Javascript yang mempermudah Anda memanipulasi halaman HTML. Anda dapat mengunduhnya di website resmi jQuery
Struktur Folder dan File Aplikasi Monitoring Server berbasis Flask dan Socketio

Membuat kode server.py

Di dalam file server.py akan ada beberapa bagian kode yang harus dipahami. Pada bagian pertama ini kita akan melakukan proses penyertaan library yang terdapat di Python. Kita akakn menggunakan library Flask, Thread, PSUtil, dan Flask-SocketIO. Kita juga akan menggunakan library seperti datetime, time, random, dan subprocess. Berikut adalah bagian kode server.py yang melakukan proses penyertaan library:
from flask import Flask, render_template
from flask.ext.socketio import SocketIO, emit
from threading import Thread, Event
import datetime, time, random, subprocess, psutil

# akan ada kode lain sesudah kode ini

Berikutnya kita akan membuat sebuah aplikasi Flask dengan nama variabel app kemudian kita sertakan SECRET_KEY untuk menjamin security yang dijalankan oleh proses internal Flask, Anda dapat mengisinya dengan key milik Anda. Tidak lupa kita jalankan juga mode debug agar dapat mempermudah kita menepis error yang terdapat di aplikasi kita bilamana error datang. Untuk membuat socketio kita membutuhkan SocketIO() dengan melewatkan app ke dalam constructor. Untuk threading sendiri, kita buat sebuah variabel bernama thread dan membuat variabel thread_stop_event untuk mendeteksi event yang terjadi pada thread. Berikut adalah bagian kode server.py yang melakukan proses penciptaan objek global di aplikasi server monitoring kita.:

# ada kode lain sebelum kode ini

app = Flask (__name__)
app.config['SECRET_KEY'] = 'rahasia'
app.debug = True
socketio = SocketIO(app)
thread = Thread()
thread_stop_event = Event()

# akan ada kode lain sesudah kode ini

Kemudian kita akan mendefinisikan sebuah class thread yang akan melakukan beberapa fitur monitoring. Di dalam class SystemInfoThread() dibawah ini, akan terdapat 7 method yang mempunyai perannya masing - masing. Berikut adalah method - method yang terdapat di class SystemInfoThread():

  • method init merupakan constructor yang akan dieksekusi saat class pertama kali diciptakan. method ini menerima sebuah parameter yaitu socketio. Parameter tersebut akan menerima objek socketio yang dilewatkan ke class ini
  • method get_cpu_info() merupakan method yang akan mengambil informasi penggunaan CPU dalam bentuk persen. Kemudian kita kirimkan data tersebut ke client yang terkoneksi ke server Websocket kita menggunakan self.socketio.emit() yang akan diterima oleh event receiveMessage
  • method get_mem_info() merupakan method yang akan mengambil informasi penggunaan RAM
  • method get_swap_info() merupakan method yang akan mengambil informasi penggunaan SWAP
  • method get_apache_access_log() merupakan method yang akan mengambil informasi terbaru dari file access.log milik Apache
  • method get_apache_error_log() merupakan method yang akan mengambil informasi terbaru dari file error.log milik Apache
  • method run() merupakan method yang akan menjalankan semua proses utama dari thread ketika method start() dari suatu thread dipanggil. Di dalam method ini terdapat pemeriksaan apakah thread masih berjalan atau tidak. Kemudian terdapat delay selama 1 detik untuk setiap kali pengambilan informasi.
Berikut adalah bagian kode server.py yang mendefinisikan class thread yaitu SystemInfoThread(): ``` # ada kode lain sebelum kode ini

class SystemInfoThread(Thread): def init(self, socketio): self.delay = 1 self.socketio = socketio super(SystemInfoThread, self).init()

def get_cpu_info(self):
    output = psutil.cpu_percent(interval=0, percpu=True)
    server_time = "%s" % datetime.datetime.now()
    self.socketio.emit('receiveMessage', {'type':'cpu', 'msg': output, 'time':server_time}, broadcast=True)

def get_mem_info(self):
    mem = psutil.virtual_memory()
    output = mem.percent
    server_time = "%s" % datetime.datetime.now()
    self.socketio.emit('receiveMessage', {'type':'mem', 'msg': output, 'time':server_time}, broadcast=True)

def get_swap_info(self):
    swap = psutil.swap_memory()
    output = swap.percent
    server_time = "%s" % datetime.datetime.now()
    self.socketio.emit('receiveMessage', {'type':'swap', 'msg': output, 'time':server_time}, broadcast=True)

def get_apache_access_log(self):
    output = subprocess.check_output('tail /var/log/apache2/access.log', shell=True)
    server_time = "%s" % datetime.datetime.now()
    self.socketio.emit('receiveMessage', {'type':'apache_access_log', 'msg': output, 'time':server_time}, broadcast=True)

def get_apache_error_log(self):
    output = subprocess.check_output('tail /var/log/apache2/error.log', shell=True)
    server_time = "%s" % datetime.datetime.now()
    self.socketio.emit('receiveMessage', {'type':'apache_error_log', 'msg': output, 'time':server_time}, broadcast=True)

def run(self):
    while not thread_stop_event.isSet():
        self.get_cpu_info()
        self.get_mem_info()
        self.get_swap_info()
        self.get_apache_access_log()
        self.get_apache_error_log()

        time.sleep(self.delay)

ada kode lain sesudah kode ini


Setelah membuat <em>class</em> <strong>SysInfoThread()</strong> sekarang kita akan menentukan fungsi yang akan melayani <em>request</em> via HTTP dan Websocket. Untuk menampilkan halaman <em>index</em> kita akan memberikan <em>route</em> "/" pada <em>function</em> <strong>index()</strong> yang akan melakukan proses <em>template rendering</em> terhadap <em>file</em> <strong>index.html</strong>. Lalu kita akan mendefinisikan dua <em>event</em> pada socketio yaitu ketika <strong>connect</strong> dan <strong>disconnect</strong>. Pada saat <em>event</em> <strong>connect</strong> dipanggil, <em>thread</em> SystemInfoThread() akan dibentuk kemudian dijalankan. Sebelum dijalankan akan diperiksa terlebih dahulu apakah <em>thread</em> tersebut sudah pernah dijalankan atau belum. Kemudian untuk <em>event</em> <strong>disconnect</strong> hanya terdapat informasi saja untuk <em>server</em> bilamana ada yang memutuskan koneksi. Setelah itu baris <strong>socketio.run(app, '0.0.0.0', 5000)</strong> akan menjalankan aplikasi pada <em>port</em> 5000. Berikut adalah bagian kode <strong>server.py</strong> yang mendefinisikan <em>routing</em> dan <em>event</em> dari aplikasi <em>server monitoring</em>:

ada kode lain sebelum kode ini

@app.route('/') def index(): return render_template('index.html')

@socketio.on('connect', namespace='/') def on_connect(): print 'Ada yang terhubung dengan server...'

global thread
if not thread.isAlive():
    print "Starting Thread"
    thread = SystemInfoThread(socketio)
    thread.start()

@socketio.on('disconnect', namespace='/') def on_disconnect(): print 'Ada yang memutus hubungan dengan server...'

if name == 'main': socketio.run(app, '0.0.0.0', 5000)


<h2>Membuat kode index.html</h2>
Untuk <em>file</em> <strong>index.html</strong> kita akan membuat sebuah judul dengan <strong>h1</strong> kemudian ada <strong>div</strong> dengan id <strong>dashboard</strong> di dalamnya terdapat sebuah <strong>table</strong> dan <strong>div</strong> untuk menampilkan informasi RAM, CPU, dan <em>file</em> <em>log</em> Apache. Kemudian di dalam <em>script</em> terdapat inisialisasi untuk konek ke Websocket. Variabel <strong>socket</strong> tersebut akan menerima sebuah <em>event</em> yaitu <strong>receiveMessage</strong>. Di dalam <em>event</em> tersebut akan ada penentuan dalam menampilkan pesan apakah pesan yang diterima adalah <em>cpu</em>, <em>ram</em>, <em>swap</em>, <em>access_log</em>, atau <em>error_log</em>. Berikut adalah kode <strong>index.html</strong> yang akan menampilkan informasi RAM, CPU, Swap, dan <em>file log</em> Apache:

Simple Server Monitoring using Python .apache-log { width: 1150px; height: 200px; background: #F5F5F5 none repeat scroll 0% 0%; overflow-y: scroll; font-size:11px; margin: 10px; }

Basic Server Monitor

```

Cara Menjalankan Aplikasi

Untuk menjalakan aplikasi, Anda tinggal masuk ke dalam folder tempat dimana server.py berada kemudian jalankan perintah python server.py dan akhirnya program akan berjalan seperti pada gambar berikut ini:

Jika diakses melalui web browser akan muncul tampilan seperti pada gambar berikut:

Aplikasi Monitoring Server di tutorial ini dijalankan di sebuah browser

Jika terjadi proses request terhadap server maka perubahan akan terjadi segera pada halaman monitoring. Jika Anda mempunyai Apache Benchmark, Anda dapat melakukan benchmark terhadap website yang tersimpan di Apache Anda dan Anda akan melihat log akan berganti karena terjadi proses request secara konkuren.

Penutup

Anda dapat menambahkan grafik garis agar informasi yang ditampilkan lebih menarik, dan salah satu kekurangan yang terdapat di tutorial ini adalah log yang ditampilkan akan ditimpa oleh log baru yang diambil. Sehingga ketika ingin melihat log sebelumnya tidak bisa dilakukan. Dan tidak hanya itu, log Apache yang diambil hampir semuanya ditampilkan sehingga bila dipasang di server yang sudah dalam fase produksi dapat menciptakan peluang ketidakamanan bila informasinya jatuh ke tangan yang tidak berhak.

Dengan menyelesaikan tutorial ini, Anda sudah dapat mengenal bagaimana cara kerja Websocket yang dibangun diatas Python dan Flask. Sehingga Anda dapat mengenal bahwa aplikasi Websocket tidak hanya dapat dibangun menggunakan Node.js, menggunakan Python pun dapat dilakukan.

Referensi

  • Miguel Grinberg Blog
  • Flask Official Documentation
  • Flask-SocketIO Documentation
  • jQuery Documentation
  • PSUtil Documentation
  • Python Documentation
  • W3Schools
(rfs)

Tags:

What do you think?

Reactions