Add structured logging throughout the backend
Request-level logging middleware (method/path/status/duration), per-module loggers in routes/services (nearby search radius expansion, 404s, name search), LOG_LEVEL setting wired through docker-compose, and seed_loader converted from print() to logging. Verified: pytest passes, and manually confirmed log lines appear for both successful and 404 requests via `docker compose logs api`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
188bf01d6e
commit
be67902b45
11 changed files with 114 additions and 4 deletions
|
|
@ -1,3 +1,5 @@
|
|||
import logging
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from geoalchemy2 import Geometry
|
||||
from sqlalchemy import cast, func, select
|
||||
|
|
@ -8,6 +10,8 @@ from app.models.city import City
|
|||
from app.schemas.city import CityOut
|
||||
from app.schemas.common import LatLon, LocalizedName
|
||||
|
||||
logger = logging.getLogger("guidecity.cities")
|
||||
|
||||
router = APIRouter(tags=["cities"])
|
||||
|
||||
|
||||
|
|
@ -31,4 +35,5 @@ def list_cities(db: Session = Depends(get_db)) -> list[CityOut]:
|
|||
center=center,
|
||||
)
|
||||
)
|
||||
logger.debug("listed %d cities", len(out))
|
||||
return out
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import logging
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
|
|
@ -8,6 +10,8 @@ from app.schemas.nearby import NearbyPlace, NearbyResponse
|
|||
from app.schemas.place import ContentOut
|
||||
from app.services.nearby_search import find_nearby
|
||||
|
||||
logger = logging.getLogger("guidecity.nearby")
|
||||
|
||||
router = APIRouter(tags=["nearby"])
|
||||
|
||||
|
||||
|
|
@ -32,6 +36,9 @@ def nearby(
|
|||
),
|
||||
db: Session = Depends(get_db),
|
||||
) -> NearbyResponse:
|
||||
if speed is not None or heading is not None:
|
||||
logger.debug("nearby called with reserved v2 params speed=%s heading=%s (ignored)", speed, heading)
|
||||
|
||||
result = find_nearby(
|
||||
db,
|
||||
lat=lat,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import logging
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from geoalchemy2 import Geometry
|
||||
from sqlalchemy import and_, cast, func, select
|
||||
|
|
@ -13,6 +15,8 @@ from app.schemas.common import LatLon
|
|||
from app.schemas.place import ContentOut, PlaceDetail, PlaceListItem
|
||||
from app.services.geocoding import search_places
|
||||
|
||||
logger = logging.getLogger("guidecity.places")
|
||||
|
||||
router = APIRouter(tags=["places"])
|
||||
|
||||
|
||||
|
|
@ -56,6 +60,7 @@ def get_place(
|
|||
)
|
||||
row = db.execute(stmt).first()
|
||||
if row is None:
|
||||
logger.warning("place_id=%d not found for lang=%s length=%s", place_id, lang, length)
|
||||
raise HTTPException(status_code=404, detail="Place not found")
|
||||
|
||||
place, content, lon, lat = row
|
||||
|
|
@ -84,6 +89,7 @@ def list_city_places(
|
|||
) -> list[PlaceListItem]:
|
||||
city = db.scalar(select(City).where(City.slug == city_slug))
|
||||
if city is None:
|
||||
logger.warning("city_slug=%r not found", city_slug)
|
||||
raise HTTPException(status_code=404, detail="City not found")
|
||||
|
||||
stmt = (
|
||||
|
|
@ -111,6 +117,7 @@ def list_city_places(
|
|||
stmt = stmt.where(PlaceContent.title.ilike(f"%{q}%"))
|
||||
|
||||
rows = db.execute(stmt).all()
|
||||
logger.debug("city_slug=%r listing -> %d place(s)", city_slug, len(rows))
|
||||
return [
|
||||
PlaceListItem(id=p.id, slug=p.slug, category=p.category, name=pc.title, location=LatLon(lat=lat, lon=lon))
|
||||
for p, pc, lon, lat in rows
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue