Testowanie czasów odpowiedzi aplikacji webowej przy pomocy narzędzi skryptowych

Jeśli czasem będziecie mieli potrzebę zmierzenia czasu odpowiedzi aplikacji webowej, to nic prostszego niż sięgnąć po język skryptowy, na przykład Pythona, podobnie jak ja to tym razem uczyniłem, i w kilkanaście minut napisać własne narzędzia służące do tego celu.

keep-calm-and-code-python_BWZaprezentowanym w tym poście punktem wyjścia są dwa skrypty – jeden do uruchamiania jako narzędzie CLI (z poziomu linii poleceń powłoki systemu operacyjnego), a drugi z graficznym interfejsem użytkownika – do wyboru przez użytkownika.

Piszę celowo o punkcie wyjścia, bo nic nie stoi na przeszkodzie, by poprzestać jedynie na tabelarycznej prezentacji danych. Można bowiem zapisywać je na przykład do pliku o uporządkowanej strukturze CSV (pola separowane przecinkiem), albo do bazy danych, a potem w jakiś inteligentny sposób wizualizować. To wszystko jest możliwe do relatywnie prostego wykonania przy użyciu bibliotek CSV i PANDAS. Pierwsza z nich doskonale ułatwia przetwarzanie danych zapisanych w plikach CSV (na przykład wyeksportowanych z arkusza kalkulacyjnego lub z bazy danych), druga natomiast to potężne narzędzie do wizualizacji danych.

O analizie danych i ich wizualizacji przy pomocy narzędzi skryptowych napiszę jednak oddzielny artykuł ze względu na obszerny charakter zagadnienia.

Tymczasem, jak zwykle, zachęcam do eksperymentów z kodem źródłowym skryptów. Pamiętajcie proszę o rygorach struktury kodów Pythona (chodzi o wcięcia), a będzie dobrze. Powodzenia!

Interfejs CLI skryptu:

Usage: python web_performance.py -d URL -t cycle_in_seconds -c number_of_samples
where -d URL (--destination URL) points out to URL to ping
      -t seconds (--time seconds) is the cycle of the ping
      -c sumber_of_samples (--count number_of_samples)
       python web_performance.py -h (or --help) displays this banner

Interfejs skryptu w wersji graficznej:

web_server_performance

Kod wersji konsolowej (CLI) skryptu:

# ------------------------------------------------------------------------------
# Web server response time measurement
# Author: Janusz Nawrat - 2015
# 
# Usage: python net_performance.py -d URL -t sample_period_in_s -c sample_count
# ------------------------------------------------------------------------------
import socket, time, urllib, urlparse
import sys, getopt, os, signal

def ping(URL, cycle=60, count=100):
    urlinfo = urlparse.urlparse(URL)
    print "URL: {0} timing: ".format(URL)
    print "{0}".format(47 * '-')
    print "|{0:>15s}{1:>15s}{2:>15s}|".format("DNS (s)|", "Load (s)|", "w/o DNS (s)")
    print "{0}".format(47 * '-')
    prb = 0
    while prb < count:         
        start = time.time()         
        ip = socket.gethostbyname(urlinfo.netloc)         
        dns_tm = time.time()-start         
        start = time.time()         
        _data = urllib.urlopen(URL).read()         
        load_tm = time.time()-start         
        print "|{0:>14.4f}|{1:>14.4f}|{2:>15.4f}|".format(dns_tm, load_tm, load_tm-dns_tm)
        time.sleep(cycle)
        prb += 1
    print "{0}".format(47 * '-')    
# End of function ping()

def usage():
    print """
\nUsage: {0} -d URL -t cycle_in_seconds -c number_of_samples
where -d URL (--destination URL) points out to URL to ping
      -t seconds (--time seconds) is the cycle of the ping
      -c sumber_of_samples (--count number_of_samples)
       {1} -h (or --help) displays this banner
    """.format(os.path.basename(sys.argv[0]), os.path.basename(sys.argv[0]))
# End of function usage()

def handler(signal, frame):
    print "Interrupted by user... Signal: %s: %s\n" % (signal, frame)
    sys.exit(2)
# End of function handler()

signal.signal(signal.SIGINT, handler)

if len(sys.argv) < 2:
    usage()
    sys.exit(2)

destination = 'google.com'
cycle = float(30)
count = 100    
    
try:
    opts, args = getopt.getopt(sys.argv[1:], 'd:t:c:h', ['destination=', 'time=', "count=", 'help'])
except getopt.GetoptError:
    usage()
    sys.exit(2)

for opt, arg in opts:
    if opt in ('-h', '--help'):
        usage()
        sys.exit(2)
    elif opt in ('-d', '--destination'):
        destination = arg
        URL = r'http://' + destination
    elif opt in ('-t', '--time'):
        cycle = float(arg)
    elif opt in ('-c', '--count'):
        count = int(arg)
    else:
        usage()
        sys.exit(2)

try:
    ping(URL, cycle, count)
except:
    print "Something went wrong..."
    sys.exit(2)

Wersja skryptu z graficznym interfejsem użytkownika:

# ------------------------------------------------------------------------------
# Web server response time measurement with GUI
# Author: Janusz Nawrat - 2015
# ------------------------------------------------------------------------------
import socket, time, urllib, urlparse
import sys, os, signal
import tkMessageBox

from Tkinter import *

def ping():
    global URL, cycle, count, output_text, ok_button
    ok_button.config(text="Wait...", state=DISABLED)
    url = URL.get()
    urlinfo = urlparse.urlparse(url)
    output_text.insert(END, "URL: {0} timing: \n".format(url))
    output_text.insert(END, "{0}\n".format(47 * '-'))
    output_text.insert(END, "|{0:>15s}{1:>15s}{2:>15s}|\n".format("DNS (s)|", "Load (s)|", "w/o DNS (s)"))
    output_text.insert(END, "{0}\n".format(47 * '-'))
    prb = 0
    sleeping = cycle.get(); counting = count.get()
    try:
        while prb < counting:             
            start = time.time()             
            ip = socket.gethostbyname(urlinfo.netloc)             
            dns_tm = time.time()-start             
            start = time.time()             
            _data = urllib.urlopen(url).read()             
            load_tm = time.time()-start             
            result = "|{0:>14.4f}|{1:>14.4f}|{2:>15.4f}|\n".format(dns_tm, load_tm, load_tm-dns_tm)
            output_text.insert(END, result)
            output_text.update()
            time.sleep(sleeping)
            prb += 1
        output_text.insert(END, "{0}\n".format(47 * '-'))
        output_text.update()
    except:
        tkMessageBox.showinfo("ATTENTION", "Error ocurred...")
        ok_button.config(text="OK", state=NORMAL)
        return
    ok_button.config(text="OK", state=NORMAL)    
# End of function ping()

def clear_output():
    global output_text
    output_text.delete(1.0, END)
# End of function clear_output() 

def handler(signal, frame):
    tkMessageBox.showinfo("ATTENTION", "Interrupted by user... Signal: %s: %s\n" % (signal, frame))
    sys.exit(1)
# End of function handler()

signal.signal(signal.SIGINT, handler)

master = Tk()
master.wm_title("Web server response time measurement - Janusz Nawrat (2015)")

URL = StringVar()
URL.set(r"http://google.com")
count = IntVar(); count.set(10)
cycle = IntVar(); cycle.set(60)

url_label = Label(master, text="URL ").grid(row=0, column=0, sticky=E, pady=5, padx=5)
url_entry = Entry(master, bd=2, textvariable=URL).grid(row=0, column=1, columnspan=3, sticky=W+E+N+S, pady=5, padx=5)
time_label = Label(master, text="Sampling cycle in sec.: ").grid(row=1, column=0, sticky=E, pady=2, padx=5)
time_spinbox = Spinbox(master, from_=10, to=3600, textvariable=cycle).grid(row=1, column=1, sticky=W+E, pady=2, padx=5)
count_label = Label(master, text="Sampling count: ").grid(row=1, column=2, sticky=E, pady=2, padx=5)
count_spinbox = Spinbox(master, from_=1, to=1000, textvariable=count).grid(row=1, column=3, sticky=W+E, pady=2, padx=5)
output_frame = LabelFrame(master, text=" Results ")
output_frame.grid(row=2, column=0, columnspan=4, pady=2, padx=5)
output_text = Text(output_frame, width=65)
scr = Scrollbar(output_frame)
scr.config(command=output_text.yview)
output_text.config(yscrollcommand=scr.set)
scr.grid(row=3, column=4, sticky=N+S)
output_text.grid(row=3, column=0, columnspan=4, pady=2, padx=5)

Grid.columnconfigure(master, 0, weight=1)
Grid.columnconfigure(master, 1, weight=2)
Grid.columnconfigure(master, 2, weight=1)
Grid.columnconfigure(master, 3, weight=2)

button_frame = Frame(master)
button_frame.grid(row=4, column=0, columnspan=4, padx=5)
ok_button = Button(button_frame, text="OK", width=15, command=ping)
ok_button.grid(row=4, column=1, sticky=E+W, pady=5, padx=2)
clear_button = Button(button_frame, text="Output clear", width=15, command=clear_output).grid(row=4, column=2, sticky=E+W, pady=5, padx=2)
exit_button = Button(button_frame, text="Exit", width=15, command=exit).grid(row=4, column=3, sticky=E+W, pady=5, padx=2)

Grid.columnconfigure(button_frame, 0, weight=1)
Grid.columnconfigure(button_frame, 1, weight=1)
Grid.columnconfigure(button_frame, 2, weight=1)
Grid.columnconfigure(button_frame, 3, weight=1)

mainloop()

Informacje Janusz Nawrat
Just ordinary man who likes thinking...

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

TOMASZ WEŁNA

artysta grafik | wykładowca

PRACOWNIA OKO

Szkoła Rysunku Malarstwa i Grafiki DR TOMASZA WEŁNY | KRAKÓW | Plac Matejki 10 | tel 691 81 75 74

Piękno neurobiologii

Blog Jerzego Vetulaniego

Teoria muzyki, zasady muzyki, podstawy muzyki

Teoria muzyki, zasady muzyki, podstawy muzyki - czyli to co każdy amator muzyki wiedzieć powinien :)

Personal Development & Inspirations

Przemyślenia i refleksje, którymi warto się podzielić (blog by Janusz Nawrat)

Business IT Cooperation Platform

Biznes i IT - dwa światy, które muszą współdziałać

%d bloggers like this: