aboutsummaryrefslogtreecommitdiff
path: root/kennel
diff options
context:
space:
mode:
Diffstat (limited to 'kennel')
-rw-r--r--kennel/__init__.py24
-rw-r--r--kennel/main.py45
2 files changed, 69 insertions, 0 deletions
diff --git a/kennel/__init__.py b/kennel/__init__.py
new file mode 100644
index 0000000..ac7ac5e
--- /dev/null
+++ b/kennel/__init__.py
@@ -0,0 +1,24 @@
+import logging
+import sys
+
+import structlog
+
+log = structlog.get_logger()
+
+# Disable uvicorn logging
+logging.getLogger("uvicorn.error").disabled = True
+logging.getLogger("uvicorn.access").disabled = True
+
+# Structlog configuration
+logging.basicConfig(format="%(message)s", stream=sys.stdout, level=logging.INFO)
+structlog.configure(
+ processors=[
+ structlog.contextvars.merge_contextvars,
+ structlog.processors.add_log_level,
+ structlog.processors.StackInfoRenderer(),
+ structlog.dev.set_exc_info,
+ structlog.processors.TimeStamper(fmt="iso", utc=True),
+ structlog.dev.ConsoleRenderer(),
+ ],
+ logger_factory=structlog.PrintLoggerFactory(),
+)
diff --git a/kennel/main.py b/kennel/main.py
new file mode 100644
index 0000000..f0eaaca
--- /dev/null
+++ b/kennel/main.py
@@ -0,0 +1,45 @@
+import uuid
+
+import structlog
+from fastapi import FastAPI, Request, Response
+
+app = FastAPI()
+logger = structlog.get_logger()
+
+
+@app.middleware("http")
+async def logger_middleware(request: Request, call_next):
+ structlog.contextvars.clear_contextvars()
+ structlog.contextvars.bind_contextvars(
+ path=request.url.path,
+ method=request.method,
+ client_host=request.client.host,
+ request_id=str(uuid.uuid4()),
+ )
+ response = await call_next(request)
+
+ structlog.contextvars.bind_contextvars(
+ status_code=response.status_code,
+ )
+
+ # Exclude /healthcheck endpoint from producing logs
+ if request.url.path != "/healthcheck":
+ if 400 <= response.status_code < 500:
+ logger.warn("Client error")
+ elif response.status_code >= 500:
+ logger.error("Server error")
+ else:
+ logger.info("OK")
+
+ return response
+
+
+@app.get("/healthcheck")
+async def healthcheck():
+ return Response()
+
+
+@app.get("/")
+async def read_main():
+ logger.info("In root path")
+ return {"msg": "Hello World"}