notebook vb
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
# trace_report.py – Excel report z Firebird audit trace logu
|
||||
# Ulozi do u:\Dropbox\!!!Days\Downloads Z230\, smaze predchozi verzi.
|
||||
|
||||
import re, sys, io, os, openpyxl
|
||||
from openpyxl.styles import Font, PatternFill, Alignment
|
||||
from openpyxl.utils import get_column_letter
|
||||
from datetime import datetime
|
||||
|
||||
LOG_PATH = r'C:\Program Files\Firebird\Firebird_2_5_CGM\default_trace.log'
|
||||
OUTPUT_DIR = r'u:\Dropbox\!!!Days\Downloads Z230'
|
||||
|
||||
TS_RE = re.compile(r'^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+)\s+\([\w:]+\)\s+(\w+)')
|
||||
ATT_RE = re.compile(r'\(ATT_\d+,\s*([\w]+):')
|
||||
SQL_S_RE = re.compile(r'^-{70,}$')
|
||||
SQL_E_RE = re.compile(r'^\^{70,}$')
|
||||
|
||||
HEADER_FILL = PatternFill('solid', fgColor='2F5496')
|
||||
HEADER_FONT = Font(bold=True, color='FFFFFF')
|
||||
ZEBRA_FILL = PatternFill('solid', fgColor='DCE6F1')
|
||||
WRAP_TOP = Alignment(wrap_text=True, vertical='top')
|
||||
|
||||
# ── Smazání předchozích verzí ───────────────────────────────────────────────
|
||||
for f in os.listdir(OUTPUT_DIR):
|
||||
if f.endswith('_trace.xlsx'):
|
||||
os.remove(os.path.join(OUTPUT_DIR, f))
|
||||
|
||||
# ── Výstupní soubor ─────────────────────────────────────────────────────────
|
||||
now = datetime.now()
|
||||
filename = now.strftime('%Y-%m-%d_%H-%M-%S') + '_trace.xlsx'
|
||||
out_path = os.path.join(OUTPUT_DIR, filename)
|
||||
|
||||
# ── Čtení logu ─────────────────────────────────────────────────────────────
|
||||
with open(LOG_PATH, 'r', encoding='cp1252', errors='replace') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
# ── Rozděl na bloky ─────────────────────────────────────────────────────────
|
||||
blocks = []
|
||||
i, n = 0, len(lines)
|
||||
|
||||
while i < n:
|
||||
m = TS_RE.match(lines[i].rstrip())
|
||||
if m:
|
||||
ts, event = m.group(1), m.group(2)
|
||||
i += 1
|
||||
block = []
|
||||
while i < n and not TS_RE.match(lines[i].rstrip()):
|
||||
block.append(lines[i].rstrip())
|
||||
i += 1
|
||||
blocks.append((ts, event, block))
|
||||
else:
|
||||
i += 1
|
||||
|
||||
# ── Extrahuj SQL z PREPARE_STATEMENT bloků ─────────────────────────────────
|
||||
results = []
|
||||
|
||||
for ts, event, block in blocks:
|
||||
if event != 'PREPARE_STATEMENT':
|
||||
continue
|
||||
|
||||
user = '?'
|
||||
for line in block:
|
||||
att = ATT_RE.search(line)
|
||||
if att:
|
||||
user = att.group(1)
|
||||
break
|
||||
|
||||
sql_lines, plan_lines = [], []
|
||||
in_sql, after_sql = False, False
|
||||
|
||||
for line in block:
|
||||
if SQL_S_RE.match(line):
|
||||
in_sql, after_sql = True, False
|
||||
continue
|
||||
if SQL_E_RE.match(line):
|
||||
in_sql, after_sql = False, True
|
||||
continue
|
||||
if in_sql:
|
||||
sql_lines.append(line)
|
||||
elif after_sql and line.startswith('PLAN'):
|
||||
plan_lines.append(line)
|
||||
|
||||
sql = '\n'.join(sql_lines).strip()
|
||||
plan = ' '.join(plan_lines).strip()
|
||||
|
||||
if sql:
|
||||
# Detekuj typ dotazu
|
||||
first = sql.lstrip().upper()
|
||||
if first.startswith('SELECT'):
|
||||
typ = 'SELECT'
|
||||
elif first.startswith('INSERT'):
|
||||
typ = 'INSERT'
|
||||
elif first.startswith('UPDATE'):
|
||||
typ = 'UPDATE'
|
||||
elif first.startswith('DELETE'):
|
||||
typ = 'DELETE'
|
||||
elif first.startswith('EXECUTE'):
|
||||
typ = 'EXECUTE'
|
||||
else:
|
||||
typ = 'OTHER'
|
||||
|
||||
results.append((ts, user, typ, sql, plan))
|
||||
|
||||
# Nejnovější nahoře
|
||||
results = list(reversed(results))
|
||||
|
||||
# ── Excel ───────────────────────────────────────────────────────────────────
|
||||
wb = openpyxl.Workbook()
|
||||
ws = wb.active
|
||||
ws.title = 'TRACE'
|
||||
|
||||
cols = ['CAS', 'UZIVATEL', 'TYP', 'SQL', 'PLAN']
|
||||
ws.append(cols)
|
||||
|
||||
for i, (ts, user, typ, sql, plan) in enumerate(results, start=2):
|
||||
ws.append([ts, user, typ, sql, plan])
|
||||
if i % 2 == 0:
|
||||
for cell in ws[i]:
|
||||
cell.fill = ZEBRA_FILL
|
||||
for cell in ws[i]:
|
||||
cell.alignment = WRAP_TOP
|
||||
|
||||
# Záhlaví
|
||||
for cell in ws[1]:
|
||||
cell.fill = HEADER_FILL
|
||||
cell.font = HEADER_FONT
|
||||
cell.alignment = Alignment(horizontal='center')
|
||||
|
||||
# Šířky sloupců
|
||||
for col, width in zip(['A','B','C','D','E'], [22, 12, 10, 80, 60]):
|
||||
ws.column_dimensions[col].width = width
|
||||
|
||||
# Výška řádků – SQL může být víceřádkový
|
||||
for row in ws.iter_rows(min_row=2):
|
||||
lines_count = max(row[3].value.count('\n') + 1 if row[3].value else 1, 1)
|
||||
ws.row_dimensions[row[0].row].height = min(lines_count * 15, 120)
|
||||
|
||||
ws.freeze_panes = 'A2'
|
||||
|
||||
# Autofiltr
|
||||
ws.auto_filter.ref = f'A1:E{len(results)+1}'
|
||||
|
||||
wb.save(out_path)
|
||||
sys.stdout.buffer.write(f'Ulozeno: {out_path}\n'.encode('utf-8'))
|
||||
sys.stdout.buffer.write(f'Dotazu: {len(results)}\n'.encode('utf-8'))
|
||||
Reference in New Issue
Block a user