Created
June 3, 2019 14:41
-
-
Save zeandrade/cbf13a17b391be9e0936f4b15bedabe7 to your computer and use it in GitHub Desktop.
Script to display squid's access log output in human-readable format.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
''' | |
Translate the squid access log output to an human friendly format. | |
- copy this script to some $PATH dir (ex. /usr/local/bin) | |
- set permission: chmod a+x tr_sal.py | |
usage: zcat /path/log/access.log.gz | tr_sal.py | |
cat /path/log/access.log | tr_sal.py -s > ~/myfile.txt | |
tail -F /path/log/access.log | tr_sal.py -s | less | |
''' | |
import random | |
import sys | |
import time | |
import argparse | |
from datetime import datetime, timedelta | |
parser = argparse.ArgumentParser() | |
parser.add_argument( | |
'-s', '--safe', help='safe output to redirect to a file', | |
action="store_true") | |
parser.add_argument('infile', nargs='?', | |
type=argparse.FileType('r'), | |
default=sys.stdin, help='read from stdin') | |
args = parser.parse_args() | |
def human_legible(num, iec=True): | |
""" | |
Human legible, IEC binary standard | |
""" | |
if not isinstance(num, int): | |
num = int(num) | |
ext_list = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] | |
divisor = 1000.0 | |
if iec: | |
ext_list = [item + 'i' for item in ext_list] | |
ext_list[0] = '' | |
divisor += 24.0 | |
for unit in ext_list: | |
if abs(num) < divisor: | |
break | |
num /= divisor | |
return "%.1f %sB" % (num, unit) | |
def colors(style=None): | |
# style = random.choice(range(8)) | |
if style == 0: | |
return 0, 36, 40 | |
elif style == 1: | |
return 6, 32, 40 | |
elif style == 'info': | |
return 1, 30, 40 | |
elif style == 'error': | |
return 0, 31, 40 | |
elif style == 'auth_error': | |
return 0, 35, 40 | |
elif style == 'ok': | |
return 2, 30, 42 | |
elif style == 'warn': | |
return 7, 30, 43 | |
else: | |
style = random.choice([0, 1, 5, 6]) | |
fg = random.choice(range(31, 38)) | |
bg = 40 # dark | |
return style, fg, bg | |
def color_format(texto='?', style=None): | |
style, fg, bg = colors(style) | |
formato = ';'.join([str(style), str(fg), str(bg)]) | |
return '\x1b[{}m{}\x1b[0m'.format(formato, texto) | |
try: | |
for line in args.infile: | |
date_t, time_spent, ip, status, size, method, url, user, *others = line.split() | |
obj_data = datetime.fromtimestamp(float(date_t)) | |
date_t = obj_data.strftime('%Y-%m-%d %H:%M:%S.%f') | |
time_spent = timedelta(milliseconds=int(time_spent)) | |
output = "{} [duration:{:>14}] {:^15} {:^12} {:^10} {} {} {} {} \n" | |
line_output = output.format( | |
date_t, str(time_spent), ip, status, human_legible(size), | |
method, url, user, "; ".join(others)) | |
if args.safe: | |
sys.stdout.write(line_output) | |
elif '_DENIED' in status and '407' in status: | |
sys.stdout.write(color_format(line_output, 'auth_error')) | |
elif '404' in status: | |
sys.stdout.write(color_format(line_output, 'info')) | |
elif any(num_status in status for num_status in ['500', '502']): | |
sys.stdout.write(color_format(line_output, 'warn')) | |
elif '_DENIED' in status: | |
sys.stdout.write(color_format(line_output, 'error')) | |
else: | |
sys.stdout.write(line_output) | |
sys.stdout.flush() | |
except ValueError: | |
quit("ERROR: this lines can't be formatted") | |
except KeyboardInterrupt: | |
quit() | |
except BrokenPipeError: | |
quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment