Add core service infrastructure

- NATS event bus (pub/sub, JetStream, KV storage)
- Service registry with health monitoring
- Base service class with lifecycle management
- Config system
- Logger with Vi formatting

Adapted from Lyra's patterns, namespace changed to vi.*

🦊💕
This commit is contained in:
Alex Kazaiev
2026-01-02 13:04:26 -06:00
parent c891740d7c
commit e2d24a66f1
8 changed files with 1321 additions and 0 deletions

73
core/logger.py Normal file
View File

@@ -0,0 +1,73 @@
import logging
import sys
import os
from datetime import datetime
from logging.handlers import TimedRotatingFileHandler
class ViFormatter(logging.Formatter):
"""Custom formatter for Vi services with symbolic level indicators"""
def format(self, record):
timestamp = datetime.now().strftime('%H:%M:%S')
level_map = {
'DEBUG': '·',
'INFO': '',
'WARNING': '',
'ERROR': '',
'CRITICAL': ''
}
level_symbol = level_map.get(record.levelname, '?')
return f"[{timestamp}] {level_symbol} {record.getMessage()}"
def _get_project_root():
"""Find the project root directory by looking for core/ directory"""
current_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.dirname(current_dir)
def setup_logger(name="vi", level=logging.INFO, service_name=None):
"""Set up a logger with console and optional file output"""
# Allow environment variable to override log level
env_level = os.getenv('LOG_LEVEL', '').upper()
if env_level in ['DEBUG', 'INFO', 'WARNING', 'ERROR']:
level = getattr(logging, env_level)
logger = logging.getLogger(name)
if logger.handlers:
return logger
logger.setLevel(level)
# Console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(ViFormatter())
logger.addHandler(console_handler)
# File handler with daily rotation if service_name is specified
if service_name:
project_root = _get_project_root()
logs_dir = os.path.join(project_root, 'logs')
if not os.path.exists(logs_dir):
os.makedirs(logs_dir, exist_ok=True)
log_file = os.path.join(logs_dir, f"{service_name}.log")
file_handler = TimedRotatingFileHandler(
log_file,
when='midnight',
interval=1,
backupCount=30,
encoding='utf-8'
)
file_handler.setFormatter(ViFormatter())
logger.addHandler(file_handler)
logger.propagate = False
return logger
logger = setup_logger()