206 lines
6.6 KiB
Python
206 lines
6.6 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime, timedelta
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
from nexus_claude_api.logging_config import configure_logging, resolve_log_file
|
|
|
|
|
|
FIXED_NOW = datetime(2026, 6, 27, 10, 30, 0)
|
|
|
|
|
|
def fixed_date_provider(timestamp: float | None = None) -> datetime:
|
|
if timestamp is None:
|
|
return FIXED_NOW
|
|
return datetime.fromtimestamp(timestamp)
|
|
|
|
|
|
def test_configure_logging_writes_app_logs_to_file_without_console(
|
|
tmp_path,
|
|
capsys,
|
|
) -> None:
|
|
log_file = tmp_path / "nexus-claude-api.log"
|
|
dated_log_file = tmp_path / "nexus-claude-api-2026-06-27.log"
|
|
logger = logging.getLogger("nexus_claude_api.routes.messages")
|
|
app_logger = logging.getLogger("nexus_claude_api")
|
|
original_handlers = app_logger.handlers[:]
|
|
original_level = app_logger.level
|
|
original_propagate = app_logger.propagate
|
|
|
|
try:
|
|
returned_log_file = configure_logging(
|
|
verbose=False,
|
|
log_file=log_file,
|
|
date_provider=fixed_date_provider,
|
|
)
|
|
|
|
logger.info("detailed app request")
|
|
logger.debug("debug details hidden without verbose")
|
|
|
|
output = capsys.readouterr()
|
|
log_text = dated_log_file.read_text(encoding="utf-8")
|
|
assert returned_log_file == dated_log_file
|
|
assert output.err == ""
|
|
assert "detailed app request" in log_text
|
|
assert "debug details hidden without verbose" not in log_text
|
|
finally:
|
|
app_logger.handlers.clear()
|
|
app_logger.handlers.extend(original_handlers)
|
|
app_logger.setLevel(original_level)
|
|
app_logger.propagate = original_propagate
|
|
|
|
|
|
def test_configure_logging_verbose_writes_debug_app_logs_to_file(
|
|
tmp_path,
|
|
) -> None:
|
|
log_file = tmp_path / "nexus-claude-api.log"
|
|
dated_log_file = tmp_path / "nexus-claude-api-2026-06-27.log"
|
|
logger = logging.getLogger("nexus_claude_api.routes.messages")
|
|
app_logger = logging.getLogger("nexus_claude_api")
|
|
original_handlers = app_logger.handlers[:]
|
|
original_level = app_logger.level
|
|
original_propagate = app_logger.propagate
|
|
|
|
try:
|
|
configure_logging(
|
|
verbose=True,
|
|
log_file=log_file,
|
|
date_provider=fixed_date_provider,
|
|
)
|
|
|
|
logger.debug("debug details stay in file")
|
|
|
|
assert (
|
|
"debug details stay in file"
|
|
in dated_log_file.read_text(encoding="utf-8")
|
|
)
|
|
finally:
|
|
app_logger.handlers.clear()
|
|
app_logger.handlers.extend(original_handlers)
|
|
app_logger.setLevel(original_level)
|
|
app_logger.propagate = original_propagate
|
|
|
|
|
|
def test_resolve_log_file_uses_user_config_dir_by_default(
|
|
tmp_path,
|
|
monkeypatch,
|
|
) -> None:
|
|
user_config_dir = tmp_path / ".config" / "nexus-claude-api"
|
|
monkeypatch.setattr("nexus_claude_api.config.USER_CONFIG_DIR", user_config_dir)
|
|
monkeypatch.setattr(
|
|
"nexus_claude_api.logging_config._local_datetime",
|
|
lambda timestamp=None: FIXED_NOW,
|
|
)
|
|
|
|
assert (
|
|
resolve_log_file()
|
|
== user_config_dir / "logs" / "nexus-claude-api-2026-06-27.log"
|
|
)
|
|
|
|
|
|
def test_resolve_log_file_uses_local_logs_in_dev_mode(monkeypatch) -> None:
|
|
monkeypatch.setattr(
|
|
"nexus_claude_api.logging_config._local_datetime",
|
|
lambda timestamp=None: FIXED_NOW,
|
|
)
|
|
|
|
assert resolve_log_file(dev=True) == Path("logs") / "nexus-claude-api-2026-06-27.log"
|
|
|
|
|
|
def test_configure_logging_prunes_logs_older_than_recent_seven_days(tmp_path) -> None:
|
|
for days_ago in range(10):
|
|
log_date = FIXED_NOW - timedelta(days=days_ago)
|
|
(tmp_path / f"nexus-claude-api-{log_date:%Y-%m-%d}.log").write_text(
|
|
f"log {days_ago}",
|
|
encoding="utf-8",
|
|
)
|
|
ignored_log = tmp_path / "nexus-claude-api-debug.log"
|
|
ignored_log.write_text("keep me", encoding="utf-8")
|
|
|
|
app_logger = logging.getLogger("nexus_claude_api")
|
|
original_handlers = app_logger.handlers[:]
|
|
original_level = app_logger.level
|
|
original_propagate = app_logger.propagate
|
|
|
|
try:
|
|
configure_logging(
|
|
verbose=False,
|
|
log_file=tmp_path / "nexus-claude-api.log",
|
|
date_provider=fixed_date_provider,
|
|
)
|
|
|
|
remaining_logs = sorted(
|
|
path.name for path in tmp_path.glob("nexus-claude-api-*.log")
|
|
)
|
|
assert remaining_logs == [
|
|
"nexus-claude-api-2026-06-21.log",
|
|
"nexus-claude-api-2026-06-22.log",
|
|
"nexus-claude-api-2026-06-23.log",
|
|
"nexus-claude-api-2026-06-24.log",
|
|
"nexus-claude-api-2026-06-25.log",
|
|
"nexus-claude-api-2026-06-26.log",
|
|
"nexus-claude-api-2026-06-27.log",
|
|
"nexus-claude-api-debug.log",
|
|
]
|
|
finally:
|
|
app_logger.handlers.clear()
|
|
app_logger.handlers.extend(original_handlers)
|
|
app_logger.setLevel(original_level)
|
|
app_logger.propagate = original_propagate
|
|
|
|
|
|
def test_configure_logging_switches_files_when_record_date_changes(tmp_path) -> None:
|
|
log_file = tmp_path / "nexus-claude-api.log"
|
|
logger = logging.getLogger("nexus_claude_api.routes.messages")
|
|
app_logger = logging.getLogger("nexus_claude_api")
|
|
original_handlers = app_logger.handlers[:]
|
|
original_level = app_logger.level
|
|
original_propagate = app_logger.propagate
|
|
|
|
try:
|
|
configure_logging(
|
|
verbose=False,
|
|
log_file=log_file,
|
|
date_provider=lambda timestamp=None: datetime.fromtimestamp(timestamp)
|
|
if timestamp is not None
|
|
else datetime(2026, 6, 27, 10, 30, 0),
|
|
)
|
|
|
|
before_record = logger.makeRecord(
|
|
logger.name,
|
|
logging.INFO,
|
|
__file__,
|
|
1,
|
|
"before midnight",
|
|
(),
|
|
None,
|
|
)
|
|
before_record.created = datetime(2026, 6, 27, 23, 59, 0).timestamp()
|
|
after_record = logger.makeRecord(
|
|
logger.name,
|
|
logging.INFO,
|
|
__file__,
|
|
1,
|
|
"after midnight",
|
|
(),
|
|
None,
|
|
)
|
|
after_record.created = datetime(2026, 6, 28, 0, 1, 0).timestamp()
|
|
|
|
for handler in app_logger.handlers:
|
|
handler.handle(before_record)
|
|
handler.handle(after_record)
|
|
|
|
assert "before midnight" in (
|
|
tmp_path / "nexus-claude-api-2026-06-27.log"
|
|
).read_text(encoding="utf-8")
|
|
assert "after midnight" in (
|
|
tmp_path / "nexus-claude-api-2026-06-28.log"
|
|
).read_text(encoding="utf-8")
|
|
finally:
|
|
app_logger.handlers.clear()
|
|
app_logger.handlers.extend(original_handlers)
|
|
app_logger.setLevel(original_level)
|
|
app_logger.propagate = original_propagate
|