File: //usr/syno/sbin/syno_disk_testlog_convert
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os, errno, traceback
import sqlite3
import argparse
from datetime import datetime
def get_real_time(time, logtime):
if logtime < time:
return datetime.fromtimestamp(logtime).strftime('%Y/%m/%d %H:%M:%S')
else:
return datetime.fromtimestamp(time).strftime('%Y/%m/%d %H:%M:%S')
def get_logs(cursor, output=None, before=None, after=None, keywords=None, limit=None):
query = 'SELECT * FROM logs WHERE 1=1'
if before:
query += ' AND time <= {}'.format(int((datetime.strptime(before, '%Y/%m/%d %H:%M:%S') - datetime.fromtimestamp(0)).total_seconds()))
if after:
query += ' AND time >= {}'.format(int((datetime.strptime(after, '%Y/%m/%d %H:%M:%S') - datetime.fromtimestamp(0)).total_seconds()))
if keywords:
query += ' AND (1=2{})'.format(''.join(' OR msg GLOB "*{}*"'.format(k.strip().replace("'", "''")) for k in keywords.split(',')))
query += ' ORDER BY LOGTIME DESC, TIME DESC LIMIT {}'.format(limit if limit else 10000)
with open(output, 'w') if output else sys.stdout as out:
log_text = u'<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8;"></head><body><table border=1 width=95%>\n'
log_text += u'<tr><th>level</th><th>time</th><th>path</th><th>model</th><th>serial</th><th>msg</th><th>type</th><th>test_type</th><th>poh</th><th>temperature</th><th>cumsectorread</th><th>cumsectorwritten</th><th>test_code</th></tr>\n'
out.write(log_text.encode('utf8'))
for row in cursor.execute(query):
try:
log_text = u'<tr><td>{level}</td><td>{time}</td><td>{path}</td><td>{model}</td><td>{serial}</td><td>{msg}</td><td>{type}</td><td>{test_type}</td><td>{poh}</td><td>{temperature}</td><td>{cumsectorread}</td><td>{cumsectorwritten}</td><td>{test_code}</td></tr>\n'.format(
level = row[2],
time = get_real_time(int(row[1]), int(row[8])),
path = row[3],
model = row[4],
serial = row[5],
msg = row[6],
type = row[7],
test_type = row[9],
poh = row[10],
temperature = row[11],
cumsectorread = row[12],
cumsectorwritten = row[13],
test_code = row[14])
out.write(log_text.encode('utf8'))
except:
traceback.print_exc()
sys.stderr.write('row = {}\n'.format(row))
log_text = u'</table></body></html>\n'
out.write(log_text.encode('utf8'))
def main():
parser = argparse.ArgumentParser(description='Convert synolog to human readable format.')
parser.add_argument('database', help='Log database path')
parser.add_argument('-o', '--output', help='Save converted log to specified file.')
parser.add_argument('--after', help='Filter logs that after specified time only. Ex: YY/mm/dd HH:MM/SS')
parser.add_argument('--before', help='Filter logs that before specified time only. Ex: YY/mm/dd HH:MM/SS')
parser.add_argument('-k', '--keywords', help='Filter logs that included specified keywords only. '\
+ 'keywords can be splited by comma. Ex: "Log, FTP"')
parser.add_argument('--limit', help='Limit the number of logs. Default: 10000')
args = parser.parse_args()
if not os.path.exists(args.database):
raise OSError(errno.ENOENT, os.strerror(errno.ENOENT), args.database)
with sqlite3.connect(args.database) as conn:
get_logs(conn.cursor(), output=args.output, before=args.before, after=args.after, keywords=args.keywords, limit=args.limit)
if __name__ == '__main__':
main()