feat(logging): improve local and docker log handling
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""日志文件轮转与敏感信息脱敏测试。"""
|
||||
|
||||
import gzip
|
||||
import logging
|
||||
import tempfile
|
||||
import unittest
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
from utils.logger import _SensitiveDataFilter, _SizeAndDayRotatingFileHandler, _parse_size
|
||||
|
||||
|
||||
class LoggerTests(unittest.TestCase):
|
||||
def test_size_parser_accepts_human_readable_values(self):
|
||||
self.assertEqual(_parse_size("2K"), 2 * 1024)
|
||||
self.assertEqual(_parse_size("3MiB"), 3 * 1024 * 1024)
|
||||
self.assertEqual(_parse_size("invalid", default=123), 123)
|
||||
|
||||
def test_file_log_redacts_credentials_and_compresses_rotation(self):
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
log_path = Path(tmpdir) / "app-2026-08-28.log"
|
||||
handler = _SizeAndDayRotatingFileHandler(log_path, max_bytes=1, retention_days=14)
|
||||
handler.setFormatter(logging.Formatter("%(message)s"))
|
||||
handler.addFilter(_SensitiveDataFilter())
|
||||
test_logger = logging.getLogger("tests.logger.redaction")
|
||||
test_logger.handlers = [handler]
|
||||
test_logger.setLevel(logging.INFO)
|
||||
test_logger.propagate = False
|
||||
try:
|
||||
test_logger.info("Cookie: access_token=super-secret; uid=1")
|
||||
test_logger.info("Authorization: Bearer top-secret-token")
|
||||
finally:
|
||||
handler.close()
|
||||
test_logger.handlers = []
|
||||
|
||||
archives = list(Path(tmpdir).glob("app-2026-08-28.log.*.gz"))
|
||||
self.assertEqual(len(archives), 1)
|
||||
archived_content = gzip.open(archives[0], "rt", encoding="utf-8").read()
|
||||
current_content = log_path.read_text(encoding="utf-8")
|
||||
combined = archived_content + current_content
|
||||
self.assertNotIn("super-secret", combined)
|
||||
self.assertNotIn("top-secret-token", combined)
|
||||
self.assertIn("Cookie: [REDACTED]", combined)
|
||||
self.assertIn("Authorization: [REDACTED]", combined)
|
||||
|
||||
def test_daily_log_switches_to_a_new_dated_file(self):
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
today = datetime.now().date()
|
||||
old_path = Path(tmpdir) / f"app-{(today - timedelta(days=1)).isoformat()}.log"
|
||||
handler = _SizeAndDayRotatingFileHandler(old_path, max_bytes=1024, retention_days=14)
|
||||
handler.setFormatter(logging.Formatter("%(message)s"))
|
||||
handler._active_day = today - timedelta(days=1)
|
||||
test_logger = logging.getLogger("tests.logger.daily")
|
||||
test_logger.handlers = [handler]
|
||||
test_logger.setLevel(logging.INFO)
|
||||
test_logger.propagate = False
|
||||
try:
|
||||
test_logger.info("today")
|
||||
finally:
|
||||
handler.close()
|
||||
test_logger.handlers = []
|
||||
|
||||
current_path = Path(tmpdir) / f"app-{today.isoformat()}.log"
|
||||
self.assertTrue(current_path.exists())
|
||||
self.assertEqual(current_path.read_text(encoding="utf-8").strip(), "today")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user