Загрузка данных
import sqlite3, http.server, time, threading, re, urllib.parse
PORT = 8080
LOG_FILES = [
(r"C:\app\Lenovo\product\21c\diag\rdbms\xe\xe\trace\alert_xe.log", "ПП-1 (Основной)"),
(r"C:\cym\alert_pp2.log", "ПП-2 (Склад)"),
]
con = sqlite3.connect("C:\\cym\\errors_new.db", check_same_thread=False)
con.execute("CREATE TABLE IF NOT EXISTS errors (code TEXT, tbl TEXT, pp TEXT, msg TEXT, ts TEXT, seen INTEGER DEFAULT 0)")
con.commit()
FIX = {
"ORA-00001": ("Нарушение уникальности", "Проверьте SEQUENCE, найдите дубликат."),
"ORA-00942": ("Таблица не существует", "Проверьте имя таблицы и права."),
"ORA-00313": ("Ошибка журнала", "Повреждён REDO log. Свяжитесь с DBA."),
"ORA-27041": ("Ошибка файла", "Oracle не может открыть файл. Проверьте права."),
}
def collect():
for log_path, pp_name in LOG_FILES:
try:
for line in open(log_path, "r", encoding="utf-8", errors="ignore"):
if "ORA-" not in line:
continue
line = line.strip()
ts = time.strftime("%Y-%m-%d %H:%M:%S")
code_match = re.search(r'ORA-\d{5}', line)
code = code_match.group(0) if code_match else "???"
tbl_match = re.search(r'\((\w+)\.(\w+)\)', line)
tbl = f"{tbl_match.group(1)}.{tbl_match.group(2)}" if tbl_match else "-"
# Не добавляем дубликаты
if not con.execute("SELECT 1 FROM errors WHERE msg=? AND ts=?", [line, ts]).fetchone():
con.execute("INSERT INTO errors (code,tbl,pp,msg,ts) VALUES (?,?,?,?,?)", [code, tbl, pp_name, line, ts])
con.commit()
print(f"+ {code} в {tbl} ({pp_name})")
except Exception as e:
print(f"[-] {pp_name}: {e}")
class H(http.server.BaseHTTPRequestHandler):
def do_GET(self):
query = urllib.parse.urlparse(self.path).query
params = urllib.parse.parse_qs(query)
pp_filter = params.get("pp", ["all"])[0]
# Если передан id — отметить как просмотренное
seen_id = params.get("seen", [None])[0]
if seen_id:
con.execute("UPDATE errors SET seen=1 WHERE rowid=?", [seen_id])
con.commit()
if pp_filter == "all":
errs = con.execute("SELECT rowid, * FROM errors ORDER BY ts DESC LIMIT 50").fetchall()
new_count = con.execute("SELECT COUNT(*) FROM errors WHERE seen=0").fetchone()[0]
else:
errs = con.execute("SELECT rowid, * FROM errors WHERE pp=? ORDER BY ts DESC LIMIT 50", [pp_filter]).fetchall()
new_count = con.execute("SELECT COUNT(*) FROM errors WHERE pp=? AND seen=0", [pp_filter]).fetchone()[0]
pps = ["ПП-1 (Основной)", "ПП-2 (Склад)"]
html = '<html><head><meta charset=utf-8><title>ЦУМ</title><style>body{font-family:Arial;margin:20px;background:#f5f5f5}.card{background:#fff;border-radius:8px;padding:15px;margin:10px 0;border-left:4px solid #ff9800}.card.seen{border-left-color:#ccc}.code{font-weight:bold;color:#d32f2f}.fix{background:#e8f5e9;padding:10px;border-radius:4px;margin-top:10px;white-space:pre-line}.pp{color:#1976d2;font-weight:bold}.btn{display:inline-block;padding:8px 16px;margin:4px;background:#1976d2;color:#fff;text-decoration:none;border-radius:4px}.btn.active{background:#0d47a1}.badge{background:#ff9800;color:#fff;padding:2px 8px;border-radius:10px;font-size:12px}</style></head><body><h2>ЦУМ — ошибки Oracle <span class=badge>{}</span></h2>'.format(f"{new_count} новых")
html += '<p>'
active = 'active' if pp_filter == 'all' else ''
html += f'<a href="/" class="btn {active}">Все</a>'
for pp in pps:
active = 'active' if pp_filter == pp else ''
html += f'<a href="/?pp={pp}" class="btn {active}">{pp}</a>'
html += '</p>'
for e in errs:
rowid, code, tbl, pp, msg, ts, seen = e[0], e[1], e[2], e[3], e[4], e[5], e[6]
name, fix = FIX.get(code, (code, "Пока нет описания"))
seen_class = 'seen' if seen else ''
html += f'<div class="card {seen_class}"><span class=code>{code}</span> — <b>{name}</b><br><span class=pp>{pp}</span><br><small>{ts} | {tbl}</small><div class=fix><b>Как исправить:</b><br>{fix}</div>'
if not seen:
html += f'<p><a href="/?pp={pp_filter}&seen={rowid}" style="color:green">✓ Отметить просмотренным</a></p>'
html += '</div>'
html += '</body></html>'
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(html.encode())
print("[*] Сбор...")
collect()
threading.Thread(target=lambda: [time.sleep(30), collect()], daemon=True).start()
print(f"[*] http://localhost:{PORT}")
http.server.HTTPServer(('0.0.0.0', PORT), H).serve_forever()