diff --git a/.flake8 b/.flake8 index cedb762..9992ddd 100644 --- a/.flake8 +++ b/.flake8 @@ -3,3 +3,5 @@ extend-exclude = venv,dist,build max-line-length = 120 + +per-file-ignores = demo.py:F401 diff --git a/aiohttp_request_id_logging/__init__.py b/aiohttp_request_id_logging/__init__.py index ef2c3e1..03f1887 100644 --- a/aiohttp_request_id_logging/__init__.py +++ b/aiohttp_request_id_logging/__init__.py @@ -1,4 +1,5 @@ from asyncio import CancelledError +from os import getpid from aiohttp import web from aiohttp.web_exceptions import HTTPException from aiohttp.web_log import AccessLogger as _AccessLogger @@ -64,7 +65,7 @@ def log(self, request, response, time): request_id.reset(token) -def generate_request_id(): +def random_request_id_factory(): ''' Used in request_id_middleware to generate the request id ''' @@ -73,8 +74,55 @@ def generate_request_id(): return req_id +# old name for backward compatibility +generate_request_id = random_request_id_factory + + +class SequentialRequestIdFactory: + ''' + Can be used in request_id_middleware to generate the request id + ''' + + prefix_length = 4 + + def __init__(self): + self._pid = None + self._prefix = None + self._next_value = None + + def __call__(self): + pid = getpid() + if pid != self._pid: + self._prefix = self._generate_prefix() + self._next_value = 0 + self._pid = pid + value = self._next_value + self._next_value += 1 + return f'{self._prefix}{value:04}' + + @classmethod + def _generate_prefix(cls): + while True: + prefix = token_urlsafe(cls.prefix_length)[:cls.prefix_length] + if '_' in prefix or '-' in prefix: + continue + # Let's not have any numbers in the prefix so we keep more focus on the appended request number. + # This is just aesthetic thing. + if any(c.isdigit() for c in prefix): + continue + if 'l' in prefix or 'I' in prefix: + continue + return prefix + + +sequential_request_id_factory = SequentialRequestIdFactory() + + +default_request_id_factory = random_request_id_factory + + def request_id_middleware(request_id_factory=None, log_function_name=True): - request_id_factory = request_id_factory or generate_request_id + request_id_factory = request_id_factory or default_request_id_factory @web.middleware async def _request_id_middleware(request, handler): diff --git a/demo.py b/demo.py index 5b8d209..4235464 100644 --- a/demo.py +++ b/demo.py @@ -13,6 +13,7 @@ from aiohttp_request_id_logging import ( setup_logging_request_id_prefix, request_id_middleware, + sequential_request_id_factory, RequestIdContextAccessLogger) @@ -75,6 +76,8 @@ def main(): app = Application( middlewares=[ request_id_middleware(), + # Alternatively: + # request_id_middleware(request_id_factory=sequential_request_id_factory), ]) app.router.add_routes(routes)