Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-25 08:29:10

0001 """
0002 Database logging handler for Django.
0003 
0004 This handler writes log records directly to the AppLog database table,
0005 enabling monitor-internal logging to be captured alongside agent logs.
0006 """
0007 
0008 import logging
0009 import os
0010 import socket
0011 import threading
0012 
0013 
0014 class DbLogHandler(logging.Handler):
0015     """
0016     A logging handler that writes log records directly to the AppLog database.
0017 
0018     This is used for monitor-internal logging (MCP actions, SSE events, etc.)
0019     so they appear in the central logging database alongside agent logs.
0020 
0021     Unlike RestLogHandler which POSTs to the REST API, this handler writes
0022     directly via Django ORM since it runs inside the Django process.
0023     """
0024 
0025     def __init__(self, app_name: str = 'swf-monitor', instance_name: str = None):
0026         """
0027         Initialize the handler.
0028 
0029         Args:
0030             app_name: Application name for log records (default: 'swf-monitor')
0031             instance_name: Instance name for log records (default: hostname)
0032         """
0033         super().__init__()
0034         self.app_name = app_name
0035         self.instance_name = instance_name or socket.gethostname()
0036 
0037     def emit(self, record: logging.LogRecord) -> None:
0038         """
0039         Write a log record to the database.
0040 
0041         Args:
0042             record: The log record to write
0043         """
0044         # Import here to avoid circular imports and ensure Django is ready
0045         try:
0046             from django.utils import timezone
0047             from monitor_app.models import AppLog
0048         except Exception:
0049             # Django not ready or import failed - fall back to stderr
0050             import sys
0051             sys.stderr.write(f"DbLogHandler: Django not ready, cannot log: {record.getMessage()}\n")
0052             return
0053 
0054         try:
0055             # Format the message
0056             message = self.format(record)
0057 
0058             # Extract extra data if present (any attributes not in standard LogRecord)
0059             standard_attrs = {
0060                 'name', 'msg', 'args', 'created', 'filename', 'funcName',
0061                 'levelname', 'levelno', 'lineno', 'module', 'msecs',
0062                 'pathname', 'process', 'processName', 'relativeCreated',
0063                 'stack_info', 'exc_info', 'exc_text', 'thread', 'threadName',
0064                 'message', 'asctime'
0065             }
0066             extra_data = {
0067                 k: v for k, v in record.__dict__.items()
0068                 if k not in standard_attrs and not k.startswith('_')
0069             }
0070 
0071             AppLog.objects.create(
0072                 app_name=self.app_name,
0073                 instance_name=self.instance_name,
0074                 timestamp=timezone.now(),
0075                 level=record.levelno,
0076                 levelname=record.levelname,
0077                 message=message,
0078                 module=record.module or '',
0079                 funcname=record.funcName or '',
0080                 lineno=record.lineno or 0,
0081                 process=record.process or os.getpid(),
0082                 thread=record.thread or threading.current_thread().ident or 0,
0083                 extra_data=extra_data if extra_data else None,
0084             )
0085         except Exception as e:
0086             # Don't let logging failures crash the application
0087             import sys
0088             sys.stderr.write(f"DbLogHandler: Failed to write log to database: {e}\n")
0089             sys.stderr.write(f"DbLogHandler: Original message: {record.getMessage()}\n")