Robust log capture on SIGINT/SIGTERM and cleaner Discord reporting
This commit is contained in:
@@ -4,13 +4,14 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import atexit
|
import atexit
|
||||||
|
import sys
|
||||||
|
import signal
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
logger = logging.getLogger(__name__ + ".network_logging")
|
logger = logging.getLogger(__name__ + ".network_logging")
|
||||||
|
|
||||||
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/1468696228647932280/L9XSHS6TPEeK0wwJTFdK9RUyZvztSGQBd4xEfVvb4Y1AXGQAOc4YTsuxeFuWC9HxymJn"
|
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/1468696228647932280/L9XSHS6TPEeK0wwJTFdK9RUyZvztSGQBd4xEfVvb4Y1AXGQAOc4YTsuxeFuWC9HxymJn"
|
||||||
|
|
||||||
LOG_QUEUE = []
|
|
||||||
FULL_LOG = []
|
FULL_LOG = []
|
||||||
QUEUE_LOCK = threading.Lock()
|
QUEUE_LOCK = threading.Lock()
|
||||||
ENABLED = True
|
ENABLED = True
|
||||||
@@ -22,6 +23,11 @@ def init_network_logging(enabled: bool = True):
|
|||||||
ENABLED = enabled
|
ENABLED = enabled
|
||||||
if ENABLED:
|
if ENABLED:
|
||||||
atexit.register(send_full_log)
|
atexit.register(send_full_log)
|
||||||
|
# Handle signals to ensure atexit runs
|
||||||
|
def signal_handler(sig, frame):
|
||||||
|
sys.exit(0)
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
|
||||||
|
|
||||||
def log_to_discord(level: str, message: str, module: str = "general"):
|
def log_to_discord(level: str, message: str, module: str = "general"):
|
||||||
@@ -39,16 +45,14 @@ def log_to_discord(level: str, message: str, module: str = "general"):
|
|||||||
with QUEUE_LOCK:
|
with QUEUE_LOCK:
|
||||||
FULL_LOG.append(log_entry)
|
FULL_LOG.append(log_entry)
|
||||||
|
|
||||||
# If it's an error, try to send it immediately as a message too
|
# Send immediate notification for critical errors
|
||||||
if level.upper() in ["ERROR", "CRITICAL"]:
|
if level.upper() in ["ERROR", "CRITICAL"]:
|
||||||
formatted_msg = f"**[{level.upper()}] [{module}]**\n```\n{message[:1800]}\n```"
|
formatted_msg = f"🚨 **CRITICAL ERROR** in `{module}`\n```\n{message[:1800]}\n```"
|
||||||
# Use a non-daemon thread to ensure it finishes even if main thread exits
|
threading.Thread(
|
||||||
t = threading.Thread(
|
|
||||||
target=send_discord_message,
|
target=send_discord_message,
|
||||||
args=(formatted_msg,),
|
args=(formatted_msg,),
|
||||||
daemon=False
|
daemon=False
|
||||||
)
|
).start()
|
||||||
t.start()
|
|
||||||
|
|
||||||
|
|
||||||
def flush_logs():
|
def flush_logs():
|
||||||
@@ -63,8 +67,8 @@ def send_full_log():
|
|||||||
|
|
||||||
LOG_SENT = True
|
LOG_SENT = True
|
||||||
|
|
||||||
# Give a tiny bit of time for final async logs to land
|
# Final sync wait
|
||||||
time.sleep(0.5)
|
time.sleep(1)
|
||||||
|
|
||||||
with QUEUE_LOCK:
|
with QUEUE_LOCK:
|
||||||
logs_to_send = FULL_LOG.copy()
|
logs_to_send = FULL_LOG.copy()
|
||||||
@@ -72,18 +76,23 @@ def send_full_log():
|
|||||||
if not logs_to_send:
|
if not logs_to_send:
|
||||||
return
|
return
|
||||||
|
|
||||||
def send_sync():
|
|
||||||
temp_file = f"/tmp/iridium_install_log_{int(time.time())}.txt"
|
temp_file = f"/tmp/iridium_install_log_{int(time.time())}.txt"
|
||||||
try:
|
try:
|
||||||
|
error_count = 0
|
||||||
with open(temp_file, "w") as f:
|
with open(temp_file, "w") as f:
|
||||||
for log in logs_to_send:
|
for log in logs_to_send:
|
||||||
|
if log["level"] in ["ERROR", "CRITICAL"]:
|
||||||
|
error_count += 1
|
||||||
ts = log["timestamp"][:19].replace("T", " ")
|
ts = log["timestamp"][:19].replace("T", " ")
|
||||||
line = f"[{ts}] [{log['level']}] [{log['module']}] {log['message']}\n"
|
line = f"[{ts}] [{log['level']}] [{log['module']}] {log['message']}\n"
|
||||||
f.write(line)
|
f.write(line)
|
||||||
|
|
||||||
with open(temp_file, "rb") as f:
|
with open(temp_file, "rb") as f:
|
||||||
files = {"file": ("iridium_install_log.txt", f)}
|
files = {"file": ("iridium_install_log.txt", f)}
|
||||||
requests.post(DISCORD_WEBHOOK_URL, files=files, timeout=30)
|
payload = {
|
||||||
|
"content": f"📝 **Session Log Attached**\nTotal entries: {len(logs_to_send)}\nErrors: {error_count}"
|
||||||
|
}
|
||||||
|
requests.post(DISCORD_WEBHOOK_URL, data=payload, files=files, timeout=30)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to send full log file to Discord: {e}")
|
print(f"Failed to send full log file to Discord: {e}")
|
||||||
@@ -93,9 +102,6 @@ def send_full_log():
|
|||||||
os.remove(temp_file)
|
os.remove(temp_file)
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
# Run sync if we are in atexit, otherwise thread is fine
|
|
||||||
send_sync()
|
|
||||||
|
|
||||||
|
|
||||||
def send_discord_message(content: str):
|
def send_discord_message(content: str):
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user