将日志写入 app_logs 表。 为避免递归写日志,emit 内部不再产生日志。
| 39 | |
| 40 | |
| 41 | class DatabaseLogHandler(logging.Handler): |
| 42 | """ |
| 43 | 将日志写入 app_logs 表。 |
| 44 | 为避免递归写日志,emit 内部不再产生日志。 |
| 45 | """ |
| 46 | |
| 47 | def __init__(self, min_level: int = logging.INFO): |
| 48 | super().__init__(level=min_level) |
| 49 | self._local = threading.local() |
| 50 | |
| 51 | def emit(self, record: logging.LogRecord) -> None: |
| 52 | if getattr(self._local, "busy", False): |
| 53 | return |
| 54 | if record.levelno < self.level: |
| 55 | return |
| 56 | if _should_skip_record(record): |
| 57 | return |
| 58 | |
| 59 | message = "" |
| 60 | exception_text = None |
| 61 | try: |
| 62 | self._local.busy = True |
| 63 | message = record.getMessage() |
| 64 | if record.exc_info: |
| 65 | exception_text = "".join(traceback.format_exception(*record.exc_info))[-4000:] |
| 66 | elif record.exc_text: |
| 67 | exception_text = str(record.exc_text)[-4000:] |
| 68 | |
| 69 | with get_db() as db: |
| 70 | db.add( |
| 71 | AppLog( |
| 72 | level=record.levelname, |
| 73 | logger=str(record.name or "root"), |
| 74 | module=str(record.module or ""), |
| 75 | pathname=str(record.pathname or ""), |
| 76 | lineno=int(record.lineno or 0), |
| 77 | message=str(message or ""), |
| 78 | exception=exception_text, |
| 79 | created_at=datetime.utcfromtimestamp(record.created), |
| 80 | ) |
| 81 | ) |
| 82 | db.commit() |
| 83 | except Exception: |
| 84 | self.handleError(record) |
| 85 | finally: |
| 86 | self._local.busy = False |
| 87 | |
| 88 | |
| 89 | def install_database_log_handler(min_level: int = logging.INFO) -> bool: |
no outgoing calls
no test coverage detected