litewave-logger 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- litewave_logger/__init__.py +20 -5
- litewave_logger/middleware.py +36 -8
- {litewave_logger-0.1.0.dist-info → litewave_logger-0.2.0.dist-info}/METADATA +1 -1
- litewave_logger-0.2.0.dist-info/RECORD +8 -0
- litewave_logger-0.1.0.dist-info/RECORD +0 -8
- {litewave_logger-0.1.0.dist-info → litewave_logger-0.2.0.dist-info}/WHEEL +0 -0
- {litewave_logger-0.1.0.dist-info → litewave_logger-0.2.0.dist-info}/top_level.txt +0 -0
litewave_logger/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
import
|
|
2
|
+
import json
|
|
3
3
|
from contextvars import ContextVar
|
|
4
4
|
|
|
5
5
|
# Context variable to hold the request ID
|
|
@@ -17,11 +17,28 @@ class RequestIdFilter(logging.Filter):
|
|
|
17
17
|
record.request_id = request_id_var.get()
|
|
18
18
|
return True
|
|
19
19
|
|
|
20
|
+
class JsonLogFormatter(logging.Formatter):
|
|
21
|
+
"""
|
|
22
|
+
Formatter that outputs logs as JSON with required fields.
|
|
23
|
+
"""
|
|
24
|
+
def format(self, record):
|
|
25
|
+
# Collect fields with fallback to None for path, method, and status_code
|
|
26
|
+
log_object = {
|
|
27
|
+
"timestamp": self.formatTime(record, self.datefmt),
|
|
28
|
+
"level": record.levelname,
|
|
29
|
+
"request_id": getattr(record, "request_id", None),
|
|
30
|
+
"path": getattr(record, "path", None),
|
|
31
|
+
"method": getattr(record, "method", None),
|
|
32
|
+
"message": record.getMessage(),
|
|
33
|
+
"status_code": getattr(record, "status_code", None),
|
|
34
|
+
"error": getattr(record, "error", None),
|
|
35
|
+
}
|
|
36
|
+
return json.dumps(log_object)
|
|
20
37
|
|
|
21
38
|
def setup_logging():
|
|
22
39
|
"""
|
|
23
40
|
Configures the logging for the application.
|
|
24
|
-
|
|
41
|
+
Uses a JSON formatter and adds the RequestIdFilter.
|
|
25
42
|
"""
|
|
26
43
|
logger = logging.getLogger()
|
|
27
44
|
logger.setLevel(logging.INFO)
|
|
@@ -29,9 +46,7 @@ def setup_logging():
|
|
|
29
46
|
# Prevent adding duplicate handlers
|
|
30
47
|
if not logger.handlers:
|
|
31
48
|
handler = logging.StreamHandler()
|
|
32
|
-
formatter =
|
|
33
|
-
"%(asctime)s - %(name)s - %(levelname)s - [%(request_id)s] - %(message)s"
|
|
34
|
-
)
|
|
49
|
+
formatter = JsonLogFormatter()
|
|
35
50
|
handler.setFormatter(formatter)
|
|
36
51
|
logger.addHandler(handler)
|
|
37
52
|
|
litewave_logger/middleware.py
CHANGED
|
@@ -1,31 +1,59 @@
|
|
|
1
1
|
import uuid
|
|
2
|
+
import time
|
|
3
|
+
import logging
|
|
4
|
+
from datetime import datetime
|
|
2
5
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
3
6
|
from starlette.requests import Request
|
|
4
7
|
|
|
5
8
|
from . import request_id_var
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
RequestIdHeader = "X-Request-ID"
|
|
12
|
+
# This middleware is used to handle the request ID and provide comprehensive debugging.
|
|
8
13
|
# It checks for a 'X-Request-ID' header in the incoming request.
|
|
9
14
|
# If the header is present, its value is used as the request ID.
|
|
10
15
|
# If not, a new UUID is generated.
|
|
11
16
|
# The request ID is then stored in a context variable.
|
|
12
17
|
class RequestIdMiddleware(BaseHTTPMiddleware):
|
|
13
18
|
"""
|
|
14
|
-
FastAPI middleware to handle the request ID.
|
|
19
|
+
FastAPI middleware to handle the request ID and provide comprehensive debugging.
|
|
15
20
|
It checks for a 'X-Request-ID' header in the incoming request.
|
|
16
21
|
If the header is present, its value is used as the request ID.
|
|
17
22
|
If not, a new UUID is generated.
|
|
18
23
|
The request ID is then stored in a context variable.
|
|
24
|
+
Provides detailed logging for incoming requests and outgoing responses.
|
|
19
25
|
"""
|
|
20
26
|
async def dispatch(self, request: Request, call_next):
|
|
21
|
-
|
|
27
|
+
# Extract request information
|
|
28
|
+
method = request.method
|
|
29
|
+
path = request.url.path
|
|
30
|
+
# Get or generate request ID
|
|
31
|
+
request_id = request.headers.get(RequestIdHeader)
|
|
22
32
|
if not request_id:
|
|
23
33
|
request_id = str(uuid.uuid4())
|
|
24
|
-
|
|
34
|
+
|
|
35
|
+
# Set request ID in context
|
|
25
36
|
request_id_var.set(request_id)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
|
|
38
|
+
logger.info("request received", extra={"method": method, "path": path})
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
# Process the request
|
|
42
|
+
response = await call_next(request)
|
|
43
|
+
|
|
44
|
+
# Add request ID to response headers
|
|
45
|
+
response.headers[RequestIdHeader] = request_id
|
|
46
|
+
|
|
47
|
+
# Log response details
|
|
48
|
+
logger.info("response sent", extra={"status_code": response.status_code})
|
|
49
|
+
|
|
50
|
+
return response
|
|
51
|
+
|
|
52
|
+
except Exception as e:
|
|
53
|
+
# Log error details
|
|
54
|
+
logger.error("request failed", extra={"method": method, "path": path, "error": str(e)})
|
|
55
|
+
|
|
56
|
+
# Re-raise the exception
|
|
57
|
+
raise
|
|
30
58
|
|
|
31
59
|
__all__ = ["RequestIdMiddleware"]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
litewave_logger/__init__.py,sha256=kWrhjCNg8Zr15n0XE1ph6TXHQAUiyK0zZeFnRmieabU,2071
|
|
2
|
+
litewave_logger/celery.py,sha256=KkeuXNTQm7P_TFj_POdt7WTHL-mcP_Jv60g06Fkw_M4,3358
|
|
3
|
+
litewave_logger/middleware.py,sha256=3edT_iHYCDJXEm9w2DIOKYV664Xn4umLwXpZyDtqIts,2120
|
|
4
|
+
litewave_logger/requests.py,sha256=tagJVwWWSVnrYHYRJ24HXu7YNBs9WxIHql0E1fRkbGA,1236
|
|
5
|
+
litewave_logger-0.2.0.dist-info/METADATA,sha256=wPqhwIIgLaDLDVZe9WDh_QR3dSYlp76ReUqJHYLUVkg,3211
|
|
6
|
+
litewave_logger-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
+
litewave_logger-0.2.0.dist-info/top_level.txt,sha256=omvs1vFc7ccmip7_gMDjF_3F8omnR-Gdfm2UudrqWuo,16
|
|
8
|
+
litewave_logger-0.2.0.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
litewave_logger/__init__.py,sha256=NgRQIlAbGXrlVoL5hcWHs3jbeNZPJ3j9zLuPfpf6vPc,1443
|
|
2
|
-
litewave_logger/celery.py,sha256=KkeuXNTQm7P_TFj_POdt7WTHL-mcP_Jv60g06Fkw_M4,3358
|
|
3
|
-
litewave_logger/middleware.py,sha256=oiWsRO9i8W7hlQrg0wJvOmAxqTkjkvASKa2psaA9Tbk,1161
|
|
4
|
-
litewave_logger/requests.py,sha256=tagJVwWWSVnrYHYRJ24HXu7YNBs9WxIHql0E1fRkbGA,1236
|
|
5
|
-
litewave_logger-0.1.0.dist-info/METADATA,sha256=0TSMGW8hGWb42X7Ls7Hfe7LN7gIqv3eyPBDD0C7StwA,3211
|
|
6
|
-
litewave_logger-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
-
litewave_logger-0.1.0.dist-info/top_level.txt,sha256=omvs1vFc7ccmip7_gMDjF_3F8omnR-Gdfm2UudrqWuo,16
|
|
8
|
-
litewave_logger-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|