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
|
|
@ -6,26 +6,33 @@ Usage:
|
|||
"""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
from app.core.logging import configure_logging
|
||||
from app.db.session import SessionLocal
|
||||
from app.models.city import City
|
||||
from app.models.place import Place
|
||||
from app.models.place_content import PlaceContent
|
||||
|
||||
logger = logging.getLogger("guidecity.seed_loader")
|
||||
|
||||
|
||||
def load_cities(path: Path) -> None:
|
||||
logger.info("loading cities from %s", path)
|
||||
data = yaml.safe_load(path.read_text(encoding="utf-8"))
|
||||
db = SessionLocal()
|
||||
try:
|
||||
for c in data["cities"]:
|
||||
city = db.query(City).filter(City.slug == c["slug"]).one_or_none()
|
||||
if city is None:
|
||||
logger.debug("creating new city slug=%r", c["slug"])
|
||||
city = City(slug=c["slug"], name_ru=c["name_ru"], name_en=c["name_en"])
|
||||
db.add(city)
|
||||
else:
|
||||
logger.debug("updating existing city slug=%r", c["slug"])
|
||||
city.name_ru = c["name_ru"]
|
||||
city.name_en = c["name_en"]
|
||||
center = c.get("center")
|
||||
|
|
@ -33,7 +40,10 @@ def load_cities(path: Path) -> None:
|
|||
city.center_point = f"SRID=4326;POINT({center['lon']} {center['lat']})"
|
||||
db.flush()
|
||||
db.commit()
|
||||
print(f"Loaded {len(data['cities'])} cities from {path.name}")
|
||||
logger.info("loaded %d cities from %s", len(data["cities"]), path.name)
|
||||
except Exception:
|
||||
logger.exception("failed loading cities from %s", path)
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
|
@ -79,6 +89,7 @@ def _upsert_content(db, place_id: int, language: str, length: str, title: str, b
|
|||
|
||||
|
||||
def load_places(path: Path) -> None:
|
||||
logger.info("loading places from %s", path)
|
||||
data = yaml.safe_load(path.read_text(encoding="utf-8"))
|
||||
city_slug = data["city"]
|
||||
|
||||
|
|
@ -86,11 +97,13 @@ def load_places(path: Path) -> None:
|
|||
try:
|
||||
city = db.query(City).filter(City.slug == city_slug).one_or_none()
|
||||
if city is None:
|
||||
logger.error("city %r not found; run --cities seed/cities.yaml first", city_slug)
|
||||
raise SystemExit(
|
||||
f"City '{city_slug}' not found. Run `--cities seed/cities.yaml` first."
|
||||
)
|
||||
|
||||
for place_data in data["places"]:
|
||||
logger.debug("upserting place slug=%r", place_data["slug"])
|
||||
place = _upsert_place(db, city.id, place_data)
|
||||
titles = place_data.get("title", {})
|
||||
for language, lengths in place_data["content"].items():
|
||||
|
|
@ -99,12 +112,16 @@ def load_places(path: Path) -> None:
|
|||
_upsert_content(db, place.id, language, length, title, body.strip())
|
||||
|
||||
db.commit()
|
||||
print(f"Loaded {len(data['places'])} places from {path.name}")
|
||||
logger.info("loaded %d places from %s", len(data["places"]), path.name)
|
||||
except Exception:
|
||||
logger.exception("failed loading places from %s", path)
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
configure_logging()
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument("--cities", help="Path to a cities YAML file")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue