import os import json import datetime import uuid import socket EVENTS_BASE_DIR = os.getenv("RUNTIME_PATH", "/opt/homelab") + "/events" def emit_event(event_type, severity, source, service, correlation_id, payload=None): """ Emits a normalized JSON event to the filesystem. """ if payload is None: payload = {} node = socket.gethostname() now = datetime.datetime.now(datetime.timezone.utc) timestamp = now.strftime("%Y-%m-%dT%H:%M:%SZ") date_dir = now.strftime("%Y-%m-%d") event_dir = os.path.join(EVENTS_BASE_DIR, date_dir, node) os.makedirs(event_dir, exist_ok=True) event_id = str(uuid.uuid4()) filename = f"{timestamp}_{event_type}_{event_id}.json" event_path = os.path.join(event_dir, filename) event_data = { "timestamp": timestamp, "node": node, "type": event_type, "severity": severity, "source": source, "service": service, "correlation_id": correlation_id, "payload": payload } with open(event_path, "w") as f: json.dump(event_data, f, indent=2) return event_path def list_events(date_str=None, node=None): """ Lists paths to event files for a specific date and/or node. """ if date_str is None: date_str = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d") search_path = os.path.join(EVENTS_BASE_DIR, date_str) if node: search_path = os.path.join(search_path, node) if not os.path.exists(search_path): return [] event_files = [] for root, dirs, files in os.walk(search_path): for file in files: if file.endswith(".json"): event_files.append(os.path.join(root, file)) return sorted(event_files) def get_event(event_path): """ Reads and parses an event file. """ with open(event_path, "r") as f: return json.load(f) if __name__ == "__main__": # Simple CLI for emitting events from Python import sys if len(sys.argv) > 1 and sys.argv[1] == "emit": # emit [payload_json] etype = sys.argv[2] sev = sys.argv[3] src = sys.argv[4] svc = sys.argv[5] cid = sys.argv[6] payload = json.loads(sys.argv[7]) if len(sys.argv) > 7 else {} path = emit_event(etype, sev, src, svc, cid, payload) print(f"Event emitted: {path}")