Загрузка данных


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()