litewave-logger 0.4.0__py3-none-any.whl → 0.6.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 +1 -1
- litewave_logger/flask_middleware.py +116 -0
- litewave_logger/middleware.py +2 -0
- {litewave_logger-0.4.0.dist-info → litewave_logger-0.6.0.dist-info}/METADATA +60 -2
- litewave_logger-0.6.0.dist-info/RECORD +9 -0
- {litewave_logger-0.4.0.dist-info → litewave_logger-0.6.0.dist-info}/WHEEL +1 -1
- litewave_logger-0.4.0.dist-info/RECORD +0 -8
- {litewave_logger-0.4.0.dist-info → litewave_logger-0.6.0.dist-info}/top_level.txt +0 -0
litewave_logger/__init__.py
CHANGED
|
@@ -78,4 +78,4 @@ def get_excluded_endpoints():
|
|
|
78
78
|
"""
|
|
79
79
|
return _excluded_endpoints
|
|
80
80
|
|
|
81
|
-
__all__ = ["setup_logging", "request_id_var", "RequestIdFilter", "get_excluded_endpoints"]
|
|
81
|
+
__all__ = ["setup_logging", "request_id_var", "RequestIdFilter", "get_excluded_endpoints", "JsonLogFormatter"]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
import logging
|
|
3
|
+
from flask import Flask, request, g
|
|
4
|
+
|
|
5
|
+
from . import request_id_var, get_excluded_endpoints
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
RequestIdHeader = "X-Request-ID"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class FlaskRequestIdMiddleware:
|
|
12
|
+
"""
|
|
13
|
+
Flask middleware to handle the request ID and provide comprehensive debugging.
|
|
14
|
+
It checks for a 'X-Request-ID' header in the incoming request.
|
|
15
|
+
If the header is present, its value is used as the request ID.
|
|
16
|
+
If not, a new UUID is generated.
|
|
17
|
+
The request ID is then stored in a context variable.
|
|
18
|
+
Provides detailed logging for incoming requests and outgoing responses.
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
from flask import Flask
|
|
22
|
+
from litewave_logger import setup_logging
|
|
23
|
+
from litewave_logger.flask_middleware import FlaskRequestIdMiddleware
|
|
24
|
+
|
|
25
|
+
app = Flask(__name__)
|
|
26
|
+
setup_logging(excluded_endpoints=['/health'])
|
|
27
|
+
FlaskRequestIdMiddleware(app)
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, app: Flask = None):
|
|
31
|
+
"""
|
|
32
|
+
Initialize the middleware.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
app: Flask application instance. If provided, init_app() is called automatically.
|
|
36
|
+
"""
|
|
37
|
+
self.app = app
|
|
38
|
+
if app is not None:
|
|
39
|
+
self.init_app(app)
|
|
40
|
+
|
|
41
|
+
def init_app(self, app: Flask):
|
|
42
|
+
"""
|
|
43
|
+
Initialize the middleware with a Flask application.
|
|
44
|
+
Supports Flask's application factory pattern.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
app: Flask application instance.
|
|
48
|
+
"""
|
|
49
|
+
app.before_request(self._before_request)
|
|
50
|
+
app.after_request(self._after_request)
|
|
51
|
+
|
|
52
|
+
def _before_request(self):
|
|
53
|
+
"""
|
|
54
|
+
Handler called before each request.
|
|
55
|
+
Sets up request ID and logs incoming request.
|
|
56
|
+
"""
|
|
57
|
+
# Get or generate request ID
|
|
58
|
+
request_id = request.headers.get(RequestIdHeader)
|
|
59
|
+
if not request_id:
|
|
60
|
+
request_id = str(uuid.uuid4())
|
|
61
|
+
|
|
62
|
+
# Store request ID in Flask's g object for easy access in views
|
|
63
|
+
g.request_id = request_id
|
|
64
|
+
|
|
65
|
+
# Set request ID in context variable (for logging filter)
|
|
66
|
+
request_id_var.set(request_id)
|
|
67
|
+
|
|
68
|
+
# Check if this endpoint should be excluded from logging
|
|
69
|
+
excluded_endpoints = get_excluded_endpoints()
|
|
70
|
+
path = request.path
|
|
71
|
+
g.should_log = path not in excluded_endpoints
|
|
72
|
+
|
|
73
|
+
if g.should_log:
|
|
74
|
+
logger.info("request received", extra={
|
|
75
|
+
"method": request.method,
|
|
76
|
+
"path": path
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
def _after_request(self, response):
|
|
80
|
+
"""
|
|
81
|
+
Handler called after each request.
|
|
82
|
+
Adds request ID to response headers and logs response.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
response: Flask response object.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Modified response with request ID header.
|
|
89
|
+
"""
|
|
90
|
+
# Add request ID to response headers
|
|
91
|
+
request_id = getattr(g, 'request_id', None)
|
|
92
|
+
if request_id:
|
|
93
|
+
response.headers[RequestIdHeader] = request_id
|
|
94
|
+
|
|
95
|
+
# Log response details only if endpoint is not excluded
|
|
96
|
+
should_log = getattr(g, 'should_log', True)
|
|
97
|
+
if should_log:
|
|
98
|
+
logger.info("response sent", extra={
|
|
99
|
+
"status_code": response.status_code
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
return response
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def get_request_id():
|
|
106
|
+
"""
|
|
107
|
+
Utility function to get the current request ID from Flask's g object.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
The current request ID or None if not available.
|
|
111
|
+
"""
|
|
112
|
+
return getattr(g, 'request_id', None)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
__all__ = ["FlaskRequestIdMiddleware", "get_request_id"]
|
|
116
|
+
|
litewave_logger/middleware.py
CHANGED
|
@@ -31,6 +31,8 @@ class RequestIdMiddleware(BaseHTTPMiddleware):
|
|
|
31
31
|
request_id = request.headers.get(RequestIdHeader)
|
|
32
32
|
if not request_id:
|
|
33
33
|
request_id = str(uuid.uuid4())
|
|
34
|
+
# Set the request ID in the request headers if not present
|
|
35
|
+
request.scope["headers"].append((RequestIdHeader.lower().encode(), request_id.encode()))
|
|
34
36
|
|
|
35
37
|
# Set request ID in context
|
|
36
38
|
request_id_var.set(request_id)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: litewave_logger
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: A lightweight logging library with context carry forward
|
|
5
5
|
Author: Litewave
|
|
6
6
|
Author-email: Sonu Sudhakaran <sonu@litewave.ai>
|
|
@@ -21,6 +21,7 @@ This module provides a centralized and consistent logging solution for Litewave
|
|
|
21
21
|
- **JSON Logging**: All logs are formatted as JSON for easy parsing and integration with log aggregation systems.
|
|
22
22
|
- **Request ID Propagation**: Automatically injects a `request-id` into all log messages.
|
|
23
23
|
- **FastAPI Integration**: Middleware for FastAPI to handle `request-id` for incoming HTTP requests and adds it to response headers.
|
|
24
|
+
- **Flask Integration**: Middleware for Flask to handle `request-id` for incoming HTTP requests and adds it to response headers.
|
|
24
25
|
- **Celery Integration**: Signal handlers to propagate the `request-id` to Celery tasks automatically.
|
|
25
26
|
- **Requests Library Patching**: Automatically injects the `request-id` into outgoing HTTP requests made with the `requests` library.
|
|
26
27
|
- **Endpoint Exclusion**: Configure endpoints that should not be logged (e.g., health checks, metrics).
|
|
@@ -53,6 +54,16 @@ To use the `litewave_logger` in your service, follow these steps:
|
|
|
53
54
|
app.add_middleware(RequestIdMiddleware)
|
|
54
55
|
```
|
|
55
56
|
|
|
57
|
+
**Or for Flask applications**: If your service is a Flask application, use the `FlaskRequestIdMiddleware`.
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from flask import Flask
|
|
61
|
+
from litewave_logger.flask_middleware import FlaskRequestIdMiddleware
|
|
62
|
+
|
|
63
|
+
app = Flask(__name__)
|
|
64
|
+
FlaskRequestIdMiddleware(app)
|
|
65
|
+
```
|
|
66
|
+
|
|
56
67
|
3. **Patch the `requests` library**: To ensure the `request-id` is propagated to other services, patch the `requests` library.
|
|
57
68
|
|
|
58
69
|
```python
|
|
@@ -68,7 +79,7 @@ To use the `litewave_logger` in your service, follow these steps:
|
|
|
68
79
|
import litewave_logger.celery
|
|
69
80
|
```
|
|
70
81
|
|
|
71
|
-
### Example
|
|
82
|
+
### FastAPI Example
|
|
72
83
|
|
|
73
84
|
Here's a complete example of how to integrate the `litewave_logger` into a FastAPI application:
|
|
74
85
|
|
|
@@ -95,6 +106,53 @@ app.add_middleware(RequestIdMiddleware)
|
|
|
95
106
|
# Your application code here...
|
|
96
107
|
```
|
|
97
108
|
|
|
109
|
+
### Flask Example
|
|
110
|
+
|
|
111
|
+
Here's a complete example of how to integrate the `litewave_logger` into a Flask application:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from flask import Flask
|
|
115
|
+
from litewave_logger import setup_logging
|
|
116
|
+
from litewave_logger.flask_middleware import FlaskRequestIdMiddleware
|
|
117
|
+
from litewave_logger.requests import patch_requests
|
|
118
|
+
|
|
119
|
+
# Import Celery module to register signal handlers (if using Celery)
|
|
120
|
+
import litewave_logger.celery
|
|
121
|
+
|
|
122
|
+
# 1. Initialize logging (optionally exclude endpoints)
|
|
123
|
+
setup_logging(excluded_endpoints=['/health', '/metrics'])
|
|
124
|
+
|
|
125
|
+
# 2. Patch requests library
|
|
126
|
+
patch_requests()
|
|
127
|
+
|
|
128
|
+
app = Flask(__name__)
|
|
129
|
+
|
|
130
|
+
# 3. Add FlaskRequestIdMiddleware
|
|
131
|
+
FlaskRequestIdMiddleware(app)
|
|
132
|
+
|
|
133
|
+
@app.route('/')
|
|
134
|
+
def hello():
|
|
135
|
+
return 'Hello, World!'
|
|
136
|
+
|
|
137
|
+
# Your application code here...
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The Flask middleware also supports the application factory pattern:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from flask import Flask
|
|
144
|
+
from litewave_logger import setup_logging
|
|
145
|
+
from litewave_logger.flask_middleware import FlaskRequestIdMiddleware
|
|
146
|
+
|
|
147
|
+
middleware = FlaskRequestIdMiddleware()
|
|
148
|
+
|
|
149
|
+
def create_app():
|
|
150
|
+
setup_logging(excluded_endpoints=['/health'])
|
|
151
|
+
app = Flask(__name__)
|
|
152
|
+
middleware.init_app(app)
|
|
153
|
+
return app
|
|
154
|
+
```
|
|
155
|
+
|
|
98
156
|
## How It Works
|
|
99
157
|
|
|
100
158
|
### Request ID Flow
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
litewave_logger/__init__.py,sha256=m6ErCBPgjLOctD6sPTqkfQh-lcfclAj7WccRlfVPZdY,2838
|
|
2
|
+
litewave_logger/celery.py,sha256=KkeuXNTQm7P_TFj_POdt7WTHL-mcP_Jv60g06Fkw_M4,3358
|
|
3
|
+
litewave_logger/flask_middleware.py,sha256=oNkbq2ZWAeoI2-Ivv0DxiG5D2Tk-HiZdY2NFBtt1kD0,3609
|
|
4
|
+
litewave_logger/middleware.py,sha256=UJiBy2fIS4c5iw1EvgTpWmjGu2Ukkdv6ZChL7r2_6hc,2547
|
|
5
|
+
litewave_logger/requests.py,sha256=tagJVwWWSVnrYHYRJ24HXu7YNBs9WxIHql0E1fRkbGA,1236
|
|
6
|
+
litewave_logger-0.6.0.dist-info/METADATA,sha256=D1hmVvjdLz9sh6F-t38pGTKCpYcbXwwDbUi-V5wfvno,6429
|
|
7
|
+
litewave_logger-0.6.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
8
|
+
litewave_logger-0.6.0.dist-info/top_level.txt,sha256=omvs1vFc7ccmip7_gMDjF_3F8omnR-Gdfm2UudrqWuo,16
|
|
9
|
+
litewave_logger-0.6.0.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
litewave_logger/__init__.py,sha256=zYrepQkWHlyKDwxIKEaMCMSnv7oiTeWx9jjdzZASL98,2818
|
|
2
|
-
litewave_logger/celery.py,sha256=KkeuXNTQm7P_TFj_POdt7WTHL-mcP_Jv60g06Fkw_M4,3358
|
|
3
|
-
litewave_logger/middleware.py,sha256=P3Mjv0RZ7Bh7cxmJ4pH537wsORSXP-Dgn1PE9EKUcgQ,2375
|
|
4
|
-
litewave_logger/requests.py,sha256=tagJVwWWSVnrYHYRJ24HXu7YNBs9WxIHql0E1fRkbGA,1236
|
|
5
|
-
litewave_logger-0.4.0.dist-info/METADATA,sha256=sst7qtaxV4ZJyegWwYwXLPDyb6dowOWVnXCGokTWr1g,4839
|
|
6
|
-
litewave_logger-0.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
-
litewave_logger-0.4.0.dist-info/top_level.txt,sha256=omvs1vFc7ccmip7_gMDjF_3F8omnR-Gdfm2UudrqWuo,16
|
|
8
|
-
litewave_logger-0.4.0.dist-info/RECORD,,
|
|
File without changes
|