Files
medicus/MedicusWithClaudeSelects/trace_report.py
T
2026-03-28 11:56:55 +01:00

145 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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'))