Skip to content

Commit 4e77044

Browse files
authored
Merge pull request #1 from basit26374/overlap_request_ids
Centralized logging
2 parents 0398766 + 51306de commit 4e77044

File tree

11 files changed

+107
-0
lines changed

11 files changed

+107
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
venv/*

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
11
# FastAPI_centralized_logging
22
Learn how to do centralized logging in FastAPI framework
3+
4+
# How to run
5+
- `uvicorn main:app --workers 4`
6+
7+
## Problem with this code
8+
Once we called four /wait api at the same time with few seconds of difference, we observe request_id in log message are overlap in those messages which are logged after waited_longer function
9+
10+
![Alt text](Snap.png)

Snap.png

528 KB
Loading

__pycache__/common.cpython-311.pyc

929 Bytes
Binary file not shown.
1.43 KB
Binary file not shown.

__pycache__/main.cpython-311.pyc

4.42 KB
Binary file not shown.

common.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import logging
2+
import asyncio
3+
4+
5+
logger = logging.getLogger('test-app')
6+
7+
async def wait_longer():
8+
logger.info('[INFO] Starting long process...')
9+
await asyncio.sleep(10)
10+
return None
11+
12+
def quick():
13+
logger.info('[INFO] Starting quick process¡...')
14+
return None

image.png

142 KB
Loading

logger_singleton.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class SingletonLogger:
2+
3+
def __init__(self, cls):
4+
self._cls = cls
5+
6+
def Instance(self):
7+
try:
8+
return self._instance
9+
except AttributeError:
10+
self._instance = self._cls()
11+
return self._instance
12+
13+
def __call__(self):
14+
raise TypeError('Singletons must be accessed through `Instance()`.')
15+
16+
def __instancecheck__(self, inst):
17+
return isinstance(inst, self._cls)

main.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import logging
2+
import uuid
3+
4+
from logging import LogRecord
5+
from fastapi import FastAPI
6+
7+
import common
8+
9+
10+
app = FastAPI()
11+
12+
# Setup Logger
13+
class ContextInfo(logging.Filter):
14+
def __init__(self, request_id: str=None):
15+
self._request_id = request_id
16+
17+
def filter(self, record: LogRecord) -> bool:
18+
record.request_id = self._request_id
19+
return True
20+
21+
logger = logging.getLogger('test-app')
22+
logger.setLevel(logging.DEBUG)
23+
24+
formatter = logging.Formatter('%(name)-12s: %(asctime)s - %(levelname)-8s - request_id: %(request_id)-15s - %(funcName)s - %(message)s')
25+
26+
stream_handler = logging.StreamHandler()
27+
stream_handler.setFormatter(formatter)
28+
29+
logger.addHandler(stream_handler)
30+
31+
# On default behaviour, we don't set any message_id
32+
# because we dont't have at the very begining
33+
context_info = ContextInfo()
34+
logger.addFilter(context_info)
35+
36+
logger.propagate = False
37+
38+
39+
@app.get("/wait")
40+
async def wait():
41+
# Generate random unique id for each and every request
42+
ranGenReqId = str(uuid.uuid4())
43+
context_info = ContextInfo(request_id=ranGenReqId)
44+
logger.addFilter(context_info)
45+
46+
logger.info("[INFO] Request comes from client to get long-waited resource access")
47+
await common.wait_longer()
48+
49+
logger.info("[INFO] Long-waited request process is completed now")
50+
return {"message": "I am come afer long wait"}
51+
52+
53+
@app.get("/quick")
54+
async def quick():
55+
# Generate random unique id for each and every request
56+
ranGenReqId = str(uuid.uuid4())
57+
context_info = ContextInfo(request_id=ranGenReqId)
58+
logger.addFilter(context_info)
59+
60+
logger.info("[INFO] Request comes from client to get quick resource access")
61+
common.quick()
62+
63+
logger.info("[INFO] Quick request process is completed now")
64+
return {"message": "I come quickly"}

0 commit comments

Comments
 (0)