86 lines
2.5 KiB
Python
86 lines
2.5 KiB
Python
|
|
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 <type> <severity> <source> <service> <cid> [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}")
|