|
| 1 | +import time |
| 2 | + |
| 3 | +# import subprocess |
| 4 | +# import select |
| 5 | +# |
| 6 | +# f = subprocess.Popen(['tail','-F',filename],\ |
| 7 | +# stdout=subprocess.PIPE,stderr=subprocess.PIPE) |
| 8 | +# p = select.poll() |
| 9 | +# p.register(f.stdout) |
| 10 | +# |
| 11 | +# while True: |
| 12 | +# if p.poll(1): |
| 13 | +# print f.stdout.readline() |
| 14 | +# time.sleep(1) |
| 15 | +# |
| 16 | +# |
| 17 | +import os, sys, time |
| 18 | +import re |
| 19 | +from dateutil.parser import parse |
| 20 | +import datetime |
| 21 | +import pdb |
| 22 | +from pytz import timezone |
| 23 | + |
| 24 | +cst = timezone("America/Chicago") |
| 25 | +timepat = re.compile( |
| 26 | + r".*/(dashboard|proxy|assignments|logger|assessment|books)/(\w+)(\s*|/.*?|\?.*?|\.html.*?) HTTP.*ResponseTime: (\d+\.\d+)" |
| 27 | +) |
| 28 | +datepat = re.compile( |
| 29 | + r".*\[(\d+/(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)/\d\d\d\d):(.*?)\].*" |
| 30 | +) |
| 31 | +statuspat = re.compile(r".*Status:\s+(\d+)\s+.*") |
| 32 | +hostpat = re.compile(r".*Host:\s+(\d+\.\d+\.\d+\.\d+:\d+)\s+.*") |
| 33 | + |
| 34 | +name = "/var/log/nginx/access.log" |
| 35 | + |
| 36 | + |
| 37 | +# Table mapping response codes to messages; entries have the |
| 38 | +# form {code: (shortmessage, longmessage)}. |
| 39 | +responses = { |
| 40 | + 100: ("Continue", "Request received, please continue"), |
| 41 | + 101: ("Switching Protocols", "Switching to new protocol; obey Upgrade header"), |
| 42 | + 200: ("OK", "Request fulfilled, document follows"), |
| 43 | + 201: ("Created", "Document created, URL follows"), |
| 44 | + 202: ("Accepted", "Request accepted, processing continues off-line"), |
| 45 | + 203: ("Non-Authoritative Information", "Request fulfilled from cache"), |
| 46 | + 204: ("No Content", "Request fulfilled, nothing follows"), |
| 47 | + 205: ("Reset Content", "Clear input form for further input."), |
| 48 | + 206: ("Partial Content", "Partial content follows."), |
| 49 | + 300: ("Multiple Choices", "Object has several resources -- see URI list"), |
| 50 | + 301: ("Moved Permanently", "Object moved permanently -- see URI list"), |
| 51 | + 302: ("Found", "Object moved temporarily -- see URI list"), |
| 52 | + 303: ("See Other", "Object moved -- see Method and URL list"), |
| 53 | + 304: ("Not Modified", "Document has not changed since given time"), |
| 54 | + 305: ( |
| 55 | + "Use Proxy", |
| 56 | + "You must use proxy specified in Location to access this " "resource.", |
| 57 | + ), |
| 58 | + 307: ("Temporary Redirect", "Object moved temporarily -- see URI list"), |
| 59 | + 400: ("Bad Request", "Bad request syntax or unsupported method"), |
| 60 | + 401: ("Unauthorized", "No permission -- see authorization schemes"), |
| 61 | + 402: ("Payment Required", "No payment -- see charging schemes"), |
| 62 | + 403: ("Forbidden", "Request forbidden -- authorization will not help"), |
| 63 | + 404: ("Not Found", "Nothing matches the given URI"), |
| 64 | + 405: ("Method Not Allowed", "Specified method is invalid for this server."), |
| 65 | + 406: ("Not Acceptable", "URI not available in preferred format."), |
| 66 | + 407: ( |
| 67 | + "Proxy Authentication Required", |
| 68 | + "You must authenticate with " "this proxy before proceeding.", |
| 69 | + ), |
| 70 | + 408: ("Request Timeout", "Request timed out; try again later."), |
| 71 | + 409: ("Conflict", "Request conflict."), |
| 72 | + 410: ("Gone", "URI no longer exists and has been permanently removed."), |
| 73 | + 411: ("Length Required", "Client must specify Content-Length."), |
| 74 | + 412: ("Precondition Failed", "Precondition in headers is false."), |
| 75 | + 413: ("Request Entity Too Large", "Entity is too large."), |
| 76 | + 414: ("Request-URI Too Long", "URI is too long."), |
| 77 | + 415: ("Unsupported Media Type", "Entity body in unsupported format."), |
| 78 | + 416: ("Requested Range Not Satisfiable", "Cannot satisfy request range."), |
| 79 | + 417: ("Expectation Failed", "Expect condition could not be satisfied."), |
| 80 | + 500: ("Internal Server Error", "Server got itself in trouble"), |
| 81 | + 501: ("Not Implemented", "Server does not support this operation"), |
| 82 | + 502: ("Bad Gateway", "Invalid responses from another server/proxy."), |
| 83 | + 503: ( |
| 84 | + "Service Unavailable", |
| 85 | + "The server cannot process the request due to a high load", |
| 86 | + ), |
| 87 | + 504: ("Gateway Timeout", "The gateway server did not receive a timely response"), |
| 88 | + 505: ("HTTP Version Not Supported", "Cannot fulfill request."), |
| 89 | +} |
| 90 | + |
| 91 | + |
| 92 | +def output_stats(the_bin, bin_num): |
| 93 | + with open("/home/bmiller/response_codes.txt", "w") as f: |
| 94 | + f.write(f"Time = {datetime.datetime.now(cst)}\n") |
| 95 | + f.write("-----\n") |
| 96 | + for k, v in sorted(the_bin.items()): |
| 97 | + f.write(f'{k} {v:>6} {responses.get(int(k), ("", ""))[0]}\n') |
| 98 | + |
| 99 | + |
| 100 | +current = open(name, "r") |
| 101 | +curino = os.fstat(current.fileno()).st_ino |
| 102 | +stats = {i: {} for i in range(12)} |
| 103 | +current_bin = 0 |
| 104 | + |
| 105 | +while True: |
| 106 | + while True: |
| 107 | + line = current.readline() |
| 108 | + if line == "": |
| 109 | + break |
| 110 | + if gd := datepat.match(line): |
| 111 | + current_time = parse(gd.group(1) + " " + gd.group(3)) |
| 112 | + bin = int(current_time.minute / 60 * 12) |
| 113 | + if bin != current_bin: |
| 114 | + # print(current_time, gd.group(1), gd.group(3)) |
| 115 | + output_stats(stats[current_bin], current_bin) |
| 116 | + stats[current_bin] = {} |
| 117 | + current_bin = bin |
| 118 | + if gd := statuspat.match(line): |
| 119 | + status = gd.group(1) |
| 120 | + stats[bin][status] = stats[bin].get(status, 0) + 1 |
| 121 | + # sys.stdout.write(str(currentday)) |
| 122 | + try: |
| 123 | + if os.stat(name).st_ino != curino: |
| 124 | + new = open(name, "r") |
| 125 | + current.close() |
| 126 | + current = new |
| 127 | + curino = os.fstat(current.fileno()).st_ino |
| 128 | + continue |
| 129 | + except IOError: |
| 130 | + pass |
| 131 | + time.sleep(1) |
0 commit comments