Attach a unique identifier to every WSGI request.
Project description
request-id
Attach a unique identifier to every request in your WSGI application.
request-id is implemented as a WSGI middleware.
The package will do 3 things:
Generate a unique request_id identifier which will be stored in the WSGI environ and set as the X-Request-ID response header.
Rename the processing thread with the request_id such that any log messages output by the logger have the request_id attached.
Log the request to the Python stdlib logging library, which can be used to generate a simple access log.
Installation
You may install the request-id package using pip:
$ pip install request-id
Configure with PasteDeploy
Update your application INI to run in a pipeline with the request-id filter:
[app:myapp] use = egg:myapp [filter:request-id] use = egg:request-id format = {status} {REQUEST_METHOD:<6} {REQUEST_PATH:<60} {REQUEST_ID} [pipeline:main] pipeline = request-id myapp [loggers] keys = translogger [handlers] keys = translogger [formatters] keys = minimal [logger_translogger] level = INFO handlers = translogger qualname = request_id propagate = 0 [handler_translogger] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = minimal [formatter_minimal] format = %(message)s
Configure in code
Create a RequestIdMiddleware object and compose it with your WSGI application:
from request_id import RequestIdMiddleware
from wsgiref.simple_server import make_server
def app(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
yield 'Hello World\n'
app = RequestIdMiddleware(
app,
format='{status} {REQUEST_METHOD:<6} {REQUEST_PATH:<60} {REQUEST_ID}',
)
if __name__ == '__main__':
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
Access the request_id
The request_id is stored in the request environ dictionary and may be accessed from anywhere this is available using request_id.get_request_id(request) where request is an instance of webob.request.Request.
Settings
- logger_name
The name of the Python stdlib logger to which the log output will be delivered. Default: request_id
- logging_level
The name of the Python stdlib logging level on which request information will be output. Default: INFO
- format
A formatting string using PEP-3101 string format syntax. Possible options are:
REQUEST_ID
REMOTE_ADDR
REMOTE_USER
REQUEST_METHOD
REQUEST_URI
REQUEST_PATH
HTTP_HOST
HTTP_VERSION
HTTP_REFERER
HTTP_USER_AGENT
time
duration
bytes
status
Default: '{REMOTE_ADDR} {HTTP_HOST} {REMOTE_USER} [{time}] "{REQUEST_METHOD} {REQUEST_URI} {HTTP_VERSION}" {status} {bytes} {duration} "{HTTP_REFERER}" "{HTTP_USER_AGENT}" - {REQUEST_ID}
- source_header
If not None then the request_id will be pulled from this header in the request. This is useful if another system upstream is setting a request identifier which you want to use in the WSGI application. Default: None
- exclude_prefixes
A (space or line separated) list of URL paths to be ignored based on request.path_info. Paths should have a leading / in order to match properly. Default: None
Acknowledgements
This code is heavily based on the translogger middleware from Paste.
1.0.1 (2020-10-06)
Fix a bug in which exclude_prefixes was not matching in cases where the PATH_INFO in the WSGI environ was mutated while processing the request.
1.0 (2018-11-26)
Fix a bug in exclude_prefixes where it only matches the first request on Python 3.
0.3.1 (2017-11-26)
Fix changelog.
0.3 (2017-11-26)
Do not crash when the source header is missing. Instead set the request id to “-“.
Properly format the UTC offset in the {time} timestamp.
Add 100% test coverage.
0.2.1 (2016-11-03)
Fix logging_level option on Python 3. See https://github.com/mmerickel/request-id/pull/2
0.2 (2016-08-09)
Catch exceptions and return webob.exc.HTTPInternalServerError so that a request_id may be attached to the response.
0.1.2 (2016-07-26)
Fix a couple bugs with exclude_prefixes and add some docs for it.
0.1.1 (2016-07-26)
Add a new setting exclude_prefixes which can be used to avoid logging certain requests.
0.1.0 (2016-07-26)
Initial release.