diff --git a/README.md b/README.md index 36463c2..bf667e1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # DRF API Logger -![version](https://img.shields.io/badge/version-1.1.12-blue.svg) +![version](https://img.shields.io/badge/version-1.1.13-blue.svg) [![Downloads](https://static.pepy.tech/personalized-badge/drf-api-logger?period=total&units=none&left_color=black&right_color=orange&left_text=Downloads%20Total)](http://pepy.tech/project/drf-api-logger) [![Downloads](https://static.pepy.tech/personalized-badge/drf-api-logger?period=month&units=none&left_color=black&right_color=orange&left_text=Downloads%20Last%20Month)](https://pepy.tech/project/drf-api-logger) [![Downloads](https://static.pepy.tech/personalized-badge/drf-api-logger?period=week&units=none&left_color=black&right_color=orange&left_text=Downloads%20Last%20Week)](https://pepy.tech/project/drf-api-logger) @@ -215,6 +215,28 @@ DRF_API_LOGGER_PATH_TYPE = 'ABSOLUTE' # Default to ABSOLUTE if not specified # Possible values are ABSOLUTE, FULL_PATH or RAW_URI ``` +### Tracing +You can enable tracing by specifying `DRF_API_LOGGER_ENABLE_TRACING` in settings.py. +This will add a tracing id (UUID.uuid4()) in the signals of DRF API Logger (if enabled). + +In views, you can use request.tracing_id to get the tracing id. +```python +DRF_API_LOGGER_ENABLE_TRACING = True # default to False +``` + +### Want to generate your own tracing uuid? +By default, DRF API Logger usage uuid.uuid4() to generate tracing id. +If you want to use your custom function to generate uuid, specify DRF_API_LOGGER_TRACING_FUNC in setting.py file. +```python +DRF_API_LOGGER_TRACING_FUNC = 'foo.bar.func_name' +``` + +### Tracing already present in headers? +If the tracing id is already coming as a part of request headers, you can specify the header name. +```python +DRF_API_LOGGER_TRACING_ID_HEADER_NAME: str = 'X_TRACING_ID' # Replace with actual header name. +``` + Considering we are accessing the following URL: http://127.0.0.1:8000/api/v1/?page=123 DRF_API_LOGGER_PATH_TYPE possible values are: 1. ABSOLUTE (Default) : diff --git a/drf_api_logger/middleware/api_logger_middleware.py b/drf_api_logger/middleware/api_logger_middleware.py index 9c00936..8ae9488 100644 --- a/drf_api_logger/middleware/api_logger_middleware.py +++ b/drf_api_logger/middleware/api_logger_middleware.py @@ -1,6 +1,8 @@ +import importlib import json import time -import re +import uuid + from django.conf import settings from django.urls import resolve from django.utils import timezone @@ -57,6 +59,19 @@ def __init__(self, get_response): settings.DRF_API_LOGGER_STATUS_CODES) is list: self.DRF_API_LOGGER_STATUS_CODES = settings.DRF_API_LOGGER_STATUS_CODES + self.DRF_API_LOGGER_ENABLE_TRACING = False + self.DRF_API_LOGGER_TRACING_ID_HEADER_NAME = None + if hasattr(settings, 'DRF_API_LOGGER_ENABLE_TRACING'): + self.DRF_API_LOGGER_ENABLE_TRACING = settings.DRF_API_LOGGER_ENABLE_TRACING + if self.DRF_API_LOGGER_ENABLE_TRACING and hasattr(settings, 'DRF_API_LOGGER_TRACING_ID_HEADER_NAME'): + self.DRF_API_LOGGER_TRACING_ID_HEADER_NAME = settings.DRF_API_LOGGER_TRACING_ID_HEADER_NAME + + self.tracing_func_name = None + if hasattr(settings, 'DRF_API_LOGGER_TRACING_FUNC'): + mod_name, func_name = settings.DRF_API_LOGGER_TRACING_FUNC.rsplit('.', 1) + mod = importlib.import_module(mod_name) + self.tracing_func_name = getattr(mod, func_name) + def __call__(self, request): # Run only if logger is enabled. @@ -77,13 +92,31 @@ def __call__(self, request): if namespace in self.DRF_API_LOGGER_SKIP_NAMESPACE: return self.get_response(request) + # Code to be executed for each request/response after + # the view is called. + start_time = time.time() + + headers = get_headers(request=request) + method = request.method + request_data = '' try: request_data = json.loads(request.body) if request.body else '' except: pass + tracing_id = None + if self.DRF_API_LOGGER_ENABLE_TRACING: + if self.DRF_API_LOGGER_TRACING_ID_HEADER_NAME: + tracing_id = headers.get(self.DRF_API_LOGGER_TRACING_ID_HEADER_NAME) + else: + if self.tracing_func_name: + tracing_id = self.tracing_func_name() + else: + tracing_id = str(uuid.uuid4()) + request.tracing_id = tracing_id + # Code to be executed for each request before # the view (and later middleware) are called. response = self.get_response(request) @@ -92,18 +125,13 @@ def __call__(self, request): if self.DRF_API_LOGGER_STATUS_CODES and response.status_code not in self.DRF_API_LOGGER_STATUS_CODES: return response - # Code to be executed for each request/response after - # the view is called. - - headers = get_headers(request=request) - method = request.method - # Log only registered methods if available. if len(self.DRF_API_LOGGER_METHODS) > 0 and method not in self.DRF_API_LOGGER_METHODS: return response - if response.get('content-type') in ('application/json', 'application/vnd.api+json', 'application/gzip', 'application/octet-stream'): - + if response.get('content-type') in ( + 'application/json', 'application/vnd.api+json', 'application/gzip', 'application/octet-stream'): + if response.get('content-type') == 'application/gzip': response_body = '** GZIP Archive **' elif response.get('content-type') == 'application/octet-stream': @@ -144,6 +172,10 @@ def __call__(self, request): d['response'] = json.dumps(d['response'], indent=4, ensure_ascii=False) LOGGER_THREAD.put_log_data(data=d) if self.DRF_API_LOGGER_SIGNAL: + if tracing_id: + data.update({ + 'tracing_id': tracing_id + }) API_LOGGER_SIGNAL.listen(**data) else: return response diff --git a/setup.py b/setup.py index a39f546..0874220 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def get_long_desc(): setuptools.setup( name="drf_api_logger", - version="1.1.12", + version="1.1.13", author="Vishal Anand", author_email="vishalanandl177@gmail.com", description="An API Logger for your Django Rest Framework project.",