pig.py/serp/logging.py
Russell Ballestrini 7fff500f2f CSS-only side quests: no JS, pure delight
Interactions via CSS animations and SVG:
- Hover logo: 🐷 appears, click: oink!
- Hover body: 'grow food not lawn' rises from below
- Print stylesheet: Sign Maker approves
- Spider descends from nav on hover
- About page: spider-pig SVG descends on hero hover
- Sign Maker's mark ☉ at page end - spins on hover
- ::selection styled in brand colors

Side quest comments scattered: 1/21, 2/21, 3/21...

No JavaScript easter eggs. CSS only. The way it should be.
2026-01-05 20:31:29 -05:00

42 lines
1.3 KiB
Python

"""Job logging utilities for SERP.
# Side quest 3/21: Look out! Here comes the spider-pig.
"""
import logging
from pathlib import Path
from typing import Dict
LOGS_PATH = Path("data/logs")
JOB_LOG_HANDLERS: Dict[int, logging.FileHandler] = {}
def start_job_logging(job_id: int) -> None:
"""Start capturing logs for a crawl job."""
LOGS_PATH.mkdir(parents=True, exist_ok=True)
log_file = LOGS_PATH / f"{job_id}.log"
handler = logging.FileHandler(log_file, mode='w', encoding='utf-8')
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s', datefmt='%H:%M:%S'))
logging.getLogger().addHandler(handler)
JOB_LOG_HANDLERS[job_id] = handler
def stop_job_logging(job_id: int) -> None:
"""Stop capturing logs for a crawl job."""
handler = JOB_LOG_HANDLERS.pop(job_id, None)
if handler:
handler.close()
logging.getLogger().removeHandler(handler)
def get_job_logs(job_id: int, tail: int = 0) -> str:
"""Get logs for a crawl job."""
log_file = LOGS_PATH / f"{job_id}.log"
if not log_file.exists():
return ""
content = log_file.read_text(encoding='utf-8')
if tail > 0:
lines = content.splitlines()
return '\n'.join(lines[-tail:])
return content