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
0045 try:
0046 from django.utils import timezone
0047 from monitor_app.models import AppLog
0048 except Exception:
0049
0050 import sys
0051 sys.stderr.write(f"DbLogHandler: Django not ready, cannot log: {record.getMessage()}\n")
0052 return
0053
0054 try:
0055
0056 message = self.format(record)
0057
0058
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
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")