Spaces:
Running
Running
ming
Claude
commited on
Commit
·
75fe59b
1
Parent(s):
7ab470d
Apply ruff formatting to Loguru migration files
Browse filesAutomatic code formatting applied by ruff during pre-commit hook.
These are cosmetic changes only (code style, no functional changes).
Files formatted:
- app/core/logging.py
- tests/test_logging.py
- tests/test_loguru_context.py
- tests/test_loguru_integration.py
- tests/test_loguru_setup.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- app/core/logging.py +9 -14
- tests/test_logging.py +0 -1
- tests/test_loguru_context.py +2 -7
- tests/test_loguru_integration.py +4 -5
- tests/test_loguru_setup.py +3 -2
app/core/logging.py
CHANGED
|
@@ -53,7 +53,9 @@ def _serialize_record(record: dict) -> str:
|
|
| 53 |
# Add exception info if present
|
| 54 |
if record["exception"]:
|
| 55 |
log_entry["exception"] = {
|
| 56 |
-
"type": record["exception"].type.__name__
|
|
|
|
|
|
|
| 57 |
"value": str(record["exception"].value),
|
| 58 |
}
|
| 59 |
|
|
@@ -122,9 +124,7 @@ def setup_logging() -> None:
|
|
| 122 |
)
|
| 123 |
|
| 124 |
# Log startup configuration
|
| 125 |
-
logger.info(
|
| 126 |
-
f"Logging initialized with format={log_format_type}, level={log_level}"
|
| 127 |
-
)
|
| 128 |
|
| 129 |
|
| 130 |
def get_logger(name: str) -> Any:
|
|
@@ -176,10 +176,7 @@ class RequestLogger:
|
|
| 176 |
context_request_id = request_id_var.get() or request_id
|
| 177 |
|
| 178 |
self.logger.bind(
|
| 179 |
-
request_id=context_request_id,
|
| 180 |
-
method=method,
|
| 181 |
-
path=path,
|
| 182 |
-
**kwargs
|
| 183 |
).info(f"Request {context_request_id}: {method} {path}")
|
| 184 |
|
| 185 |
def log_response(
|
|
@@ -201,7 +198,7 @@ class RequestLogger:
|
|
| 201 |
request_id=context_request_id,
|
| 202 |
status_code=status_code,
|
| 203 |
duration_ms=duration_ms,
|
| 204 |
-
**kwargs
|
| 205 |
).info(f"Response {context_request_id}: {status_code} ({duration_ms:.2f}ms)")
|
| 206 |
|
| 207 |
def log_error(self, request_id: str, error: str, **kwargs: Any) -> None:
|
|
@@ -216,8 +213,6 @@ class RequestLogger:
|
|
| 216 |
# Get request ID from context var (fallback to parameter)
|
| 217 |
context_request_id = request_id_var.get() or request_id
|
| 218 |
|
| 219 |
-
self.logger.bind(
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
**kwargs
|
| 223 |
-
).error(f"Error {context_request_id}: {error}")
|
|
|
|
| 53 |
# Add exception info if present
|
| 54 |
if record["exception"]:
|
| 55 |
log_entry["exception"] = {
|
| 56 |
+
"type": record["exception"].type.__name__
|
| 57 |
+
if record["exception"].type
|
| 58 |
+
else None,
|
| 59 |
"value": str(record["exception"].value),
|
| 60 |
}
|
| 61 |
|
|
|
|
| 124 |
)
|
| 125 |
|
| 126 |
# Log startup configuration
|
| 127 |
+
logger.info(f"Logging initialized with format={log_format_type}, level={log_level}")
|
|
|
|
|
|
|
| 128 |
|
| 129 |
|
| 130 |
def get_logger(name: str) -> Any:
|
|
|
|
| 176 |
context_request_id = request_id_var.get() or request_id
|
| 177 |
|
| 178 |
self.logger.bind(
|
| 179 |
+
request_id=context_request_id, method=method, path=path, **kwargs
|
|
|
|
|
|
|
|
|
|
| 180 |
).info(f"Request {context_request_id}: {method} {path}")
|
| 181 |
|
| 182 |
def log_response(
|
|
|
|
| 198 |
request_id=context_request_id,
|
| 199 |
status_code=status_code,
|
| 200 |
duration_ms=duration_ms,
|
| 201 |
+
**kwargs,
|
| 202 |
).info(f"Response {context_request_id}: {status_code} ({duration_ms:.2f}ms)")
|
| 203 |
|
| 204 |
def log_error(self, request_id: str, error: str, **kwargs: Any) -> None:
|
|
|
|
| 213 |
# Get request ID from context var (fallback to parameter)
|
| 214 |
context_request_id = request_id_var.get() or request_id
|
| 215 |
|
| 216 |
+
self.logger.bind(request_id=context_request_id, error=error, **kwargs).error(
|
| 217 |
+
f"Error {context_request_id}: {error}"
|
| 218 |
+
)
|
|
|
|
|
|
tests/test_logging.py
CHANGED
|
@@ -7,7 +7,6 @@ without using mocks - testing real behavior with Loguru.
|
|
| 7 |
|
| 8 |
from pathlib import Path
|
| 9 |
|
| 10 |
-
import pytest
|
| 11 |
from loguru import logger
|
| 12 |
|
| 13 |
|
|
|
|
| 7 |
|
| 8 |
from pathlib import Path
|
| 9 |
|
|
|
|
| 10 |
from loguru import logger
|
| 11 |
|
| 12 |
|
tests/test_loguru_context.py
CHANGED
|
@@ -8,7 +8,6 @@ These tests verify:
|
|
| 8 |
"""
|
| 9 |
|
| 10 |
import asyncio
|
| 11 |
-
import io
|
| 12 |
from pathlib import Path
|
| 13 |
|
| 14 |
import pytest
|
|
@@ -68,9 +67,7 @@ class TestLoguruContext:
|
|
| 68 |
|
| 69 |
log_file = tmp_path / "isolation.log"
|
| 70 |
logger.remove()
|
| 71 |
-
logger.add(
|
| 72 |
-
log_file, format="{extra[request_id]} | {message}", level="INFO"
|
| 73 |
-
)
|
| 74 |
|
| 75 |
# Simulate first request
|
| 76 |
request_id_var.set("request-1")
|
|
@@ -91,9 +88,7 @@ class TestLoguruContext:
|
|
| 91 |
|
| 92 |
log_file = tmp_path / "preservation.log"
|
| 93 |
logger.remove()
|
| 94 |
-
logger.add(
|
| 95 |
-
log_file, format="{extra[request_id]} | {message}", level="INFO"
|
| 96 |
-
)
|
| 97 |
|
| 98 |
async def process_with_delay(request_id: str):
|
| 99 |
request_id_var.set(request_id)
|
|
|
|
| 8 |
"""
|
| 9 |
|
| 10 |
import asyncio
|
|
|
|
| 11 |
from pathlib import Path
|
| 12 |
|
| 13 |
import pytest
|
|
|
|
| 67 |
|
| 68 |
log_file = tmp_path / "isolation.log"
|
| 69 |
logger.remove()
|
| 70 |
+
logger.add(log_file, format="{extra[request_id]} | {message}", level="INFO")
|
|
|
|
|
|
|
| 71 |
|
| 72 |
# Simulate first request
|
| 73 |
request_id_var.set("request-1")
|
|
|
|
| 88 |
|
| 89 |
log_file = tmp_path / "preservation.log"
|
| 90 |
logger.remove()
|
| 91 |
+
logger.add(log_file, format="{extra[request_id]} | {message}", level="INFO")
|
|
|
|
|
|
|
| 92 |
|
| 93 |
async def process_with_delay(request_id: str):
|
| 94 |
request_id_var.set(request_id)
|
tests/test_loguru_integration.py
CHANGED
|
@@ -5,7 +5,6 @@ These tests verify observable behavior through the API rather than log output,
|
|
| 5 |
since log output testing is covered by unit tests.
|
| 6 |
"""
|
| 7 |
|
| 8 |
-
import pytest
|
| 9 |
from fastapi.testclient import TestClient
|
| 10 |
|
| 11 |
|
|
@@ -16,9 +15,7 @@ class TestLoguruIntegration:
|
|
| 16 |
"""Verify request ID is preserved in response headers."""
|
| 17 |
custom_request_id = "header-preservation-test-456"
|
| 18 |
|
| 19 |
-
response = client.get(
|
| 20 |
-
"/health", headers={"X-Request-ID": custom_request_id}
|
| 21 |
-
)
|
| 22 |
|
| 23 |
assert response.status_code == 200
|
| 24 |
assert response.headers["X-Request-ID"] == custom_request_id
|
|
@@ -72,7 +69,9 @@ class TestLoguruIntegration:
|
|
| 72 |
# Request ID should still be in headers
|
| 73 |
assert response.headers["X-Request-ID"] == custom_request_id
|
| 74 |
|
| 75 |
-
def test_logging_context_does_not_interfere_with_responses(
|
|
|
|
|
|
|
| 76 |
"""Verify logging context doesn't affect normal request/response cycle."""
|
| 77 |
# Make several requests to ensure logging doesn't cause issues
|
| 78 |
for i in range(5):
|
|
|
|
| 5 |
since log output testing is covered by unit tests.
|
| 6 |
"""
|
| 7 |
|
|
|
|
| 8 |
from fastapi.testclient import TestClient
|
| 9 |
|
| 10 |
|
|
|
|
| 15 |
"""Verify request ID is preserved in response headers."""
|
| 16 |
custom_request_id = "header-preservation-test-456"
|
| 17 |
|
| 18 |
+
response = client.get("/health", headers={"X-Request-ID": custom_request_id})
|
|
|
|
|
|
|
| 19 |
|
| 20 |
assert response.status_code == 200
|
| 21 |
assert response.headers["X-Request-ID"] == custom_request_id
|
|
|
|
| 69 |
# Request ID should still be in headers
|
| 70 |
assert response.headers["X-Request-ID"] == custom_request_id
|
| 71 |
|
| 72 |
+
def test_logging_context_does_not_interfere_with_responses(
|
| 73 |
+
self, client: TestClient
|
| 74 |
+
):
|
| 75 |
"""Verify logging context doesn't affect normal request/response cycle."""
|
| 76 |
# Make several requests to ensure logging doesn't cause issues
|
| 77 |
for i in range(5):
|
tests/test_loguru_setup.py
CHANGED
|
@@ -10,7 +10,6 @@ These tests verify:
|
|
| 10 |
import json
|
| 11 |
from pathlib import Path
|
| 12 |
|
| 13 |
-
import pytest
|
| 14 |
from loguru import logger
|
| 15 |
|
| 16 |
|
|
@@ -55,7 +54,9 @@ class TestLoguruSetup:
|
|
| 55 |
logger.remove()
|
| 56 |
logger.add(log_file, serialize=True, level="INFO")
|
| 57 |
|
| 58 |
-
logger.bind(field1="value1", field2="value2", field3=123).info(
|
|
|
|
|
|
|
| 59 |
|
| 60 |
with open(log_file) as f:
|
| 61 |
log_entry = json.loads(f.readline())
|
|
|
|
| 10 |
import json
|
| 11 |
from pathlib import Path
|
| 12 |
|
|
|
|
| 13 |
from loguru import logger
|
| 14 |
|
| 15 |
|
|
|
|
| 54 |
logger.remove()
|
| 55 |
logger.add(log_file, serialize=True, level="INFO")
|
| 56 |
|
| 57 |
+
logger.bind(field1="value1", field2="value2", field3=123).info(
|
| 58 |
+
"Multi-bind test"
|
| 59 |
+
)
|
| 60 |
|
| 61 |
with open(log_file) as f:
|
| 62 |
log_entry = json.loads(f.readline())
|