Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging fixes and enhancements #421

Merged
merged 6 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ RUN python -m pip install -U pip
# git and put .git (which setuptools_scm needs to determine the version) in the container
RUN SETUPTOOLS_SCM_PRETEND_VERSION=${VERSION} python -m pip install .
COPY ./velour_api /src/velour_api
CMD ["uvicorn", "velour_api.main:app", "--host", "0.0.0.0"]
CMD ["uvicorn", "velour_api.main:app", "--host", "0.0.0.0", "--log-level", "warning"]
15 changes: 15 additions & 0 deletions api/velour_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,23 @@
logging_level = 20


def status_endpoint_filter(
logger,
method_name,
event_dict,
ignore_paths=frozenset(["/health", "/ready"]),
):
if (
event_dict.get("path", "") in ignore_paths
and event_dict.get("status", 0) == 200
):
raise structlog.DropEvent
return event_dict


structlog.configure(
processors=[
status_endpoint_filter,
structlog.processors.add_log_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.dict_tracebacks,
Expand Down
44 changes: 38 additions & 6 deletions api/velour_api/logging.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,61 @@
from typing import Callable
from typing import Callable, Optional

import structlog
from fastapi import Request, Response
from fastapi import BackgroundTasks, HTTPException, Request, Response
from fastapi.routing import APIRoute
from starlette.background import BackgroundTask

logger = structlog.get_logger()


def log_request(request: Request):
def log_endpoint(
request: Request,
status_code: Optional[int],
):
logger.info(
"Velour API Call",
method=request.method,
path=request.url.path,
hostname=request.url.hostname,
status=status_code,
)


def add_task(response: Response, task: BackgroundTask) -> Response:
if not response.background:
response.background = BackgroundTasks([task])
elif isinstance(response.background, BackgroundTasks):
response.background.add_task(task)
else: # Empirically this doesn't happen but let's handle it anyway
if not isinstance(response.background, BackgroundTask):
logger.error(
"Unexpected response.background",
background_type=str(type(response.background)),
)
old_task = response.background
response.background = BackgroundTasks([old_task, task])

return response


class LoggingRoute(APIRoute):
def get_route_handler(self) -> Callable:
original_route_handler = super().get_route_handler()

async def custom_route_handler(request: Request) -> Response:
response = await original_route_handler(request)
BackgroundTask(log_request, request)
return response
try:
response = await original_route_handler(request)
except HTTPException as e:
log_endpoint(request, e.status_code)
raise
except Exception:
log_endpoint(request, None)
logger.exception("Uncaught exception")
raise
else:
task = BackgroundTask(
log_endpoint, request, response.status_code
)
return add_task(response, task)

return custom_route_handler
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ services:
VELOUR_SECRET_KEY: ${VELOUR_SECRET_KEY}
VELOUR_USERNAME: ${VELOUR_USERNAME}
VELOUR_PASSWORD: ${VELOUR_PASSWORD}
command: "uvicorn velour_api.main:app --reload --host 0.0.0.0"
command: "uvicorn velour_api.main:app --reload --host 0.0.0.0 --log-level warning"
depends_on:
- 'db'
- 'migrations'
Expand Down
Loading