fix: adding request logger middleware
This commit is contained in:
parent
4c688b1d25
commit
df65b8c34a
6 changed files with 99 additions and 19 deletions
71
apiserver/plane/middleware/logger.py
Normal file
71
apiserver/plane/middleware/logger.py
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
# Python imports
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Django imports
|
||||||
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
# Third party imports
|
||||||
|
from rest_framework.request import Request
|
||||||
|
|
||||||
|
# Module imports
|
||||||
|
from plane.utils.ip_address import get_client_ip
|
||||||
|
|
||||||
|
api_logger = logging.getLogger("plane.api")
|
||||||
|
|
||||||
|
|
||||||
|
class RequestLoggerMiddleware:
|
||||||
|
def __init__(self, get_response):
|
||||||
|
self.get_response = get_response
|
||||||
|
|
||||||
|
def _should_log_route(self, request: Request | HttpRequest) -> bool:
|
||||||
|
"""
|
||||||
|
Determines whether a route should be logged based on the request and status code.
|
||||||
|
"""
|
||||||
|
# Don't log health checks
|
||||||
|
if request.path == "/" and request.method == "GET":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
|
# get the start time
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
# Get the response
|
||||||
|
response = self.get_response(request)
|
||||||
|
|
||||||
|
# calculate the duration
|
||||||
|
duration = time.time() - start_time
|
||||||
|
|
||||||
|
# Check if logging is required
|
||||||
|
log_true = self._should_log_route(request=request)
|
||||||
|
|
||||||
|
# If logging is not required, return the response
|
||||||
|
if not log_true:
|
||||||
|
return response
|
||||||
|
|
||||||
|
user_id = (
|
||||||
|
request.user.id
|
||||||
|
if getattr(request, "user")
|
||||||
|
and getattr(request.user, "is_authenticated", False)
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
|
user_agent = request.META.get("HTTP_USER_AGENT", "")
|
||||||
|
|
||||||
|
# Log the request information
|
||||||
|
api_logger.info(
|
||||||
|
f"{request.method} {request.get_full_path()} {response.status_code}",
|
||||||
|
extra={
|
||||||
|
"path": request.path,
|
||||||
|
"method": request.method,
|
||||||
|
"status_code": response.status_code,
|
||||||
|
"duration_ms": int(duration * 1000),
|
||||||
|
"remote_addr": get_client_ip(request),
|
||||||
|
"user_agent": user_agent,
|
||||||
|
"user_id": user_id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# return the response
|
||||||
|
return response
|
||||||
|
|
@ -59,6 +59,7 @@ MIDDLEWARE = [
|
||||||
"crum.CurrentRequestUserMiddleware",
|
"crum.CurrentRequestUserMiddleware",
|
||||||
"django.middleware.gzip.GZipMiddleware",
|
"django.middleware.gzip.GZipMiddleware",
|
||||||
"plane.middleware.api_log_middleware.APITokenLogMiddleware",
|
"plane.middleware.api_log_middleware.APITokenLogMiddleware",
|
||||||
|
"plane.middleware.logger.RequestLoggerMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Rest Framework settings
|
# Rest Framework settings
|
||||||
|
|
|
||||||
|
|
@ -37,26 +37,31 @@ if not os.path.exists(LOG_DIR):
|
||||||
|
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"disable_existing_loggers": False,
|
"disable_existing_loggers": True,
|
||||||
"formatters": {
|
"formatters": {
|
||||||
"verbose": {
|
"verbose": {
|
||||||
"format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
|
"format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
|
||||||
"style": "{",
|
"style": "{",
|
||||||
}
|
},
|
||||||
|
"json": {
|
||||||
|
"()": "pythonjsonlogger.jsonlogger.JsonFormatter",
|
||||||
|
"fmt": "%(levelname)s %(asctime)s %(module)s %(name)s %(message)s",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"handlers": {
|
"handlers": {
|
||||||
"console": {
|
"console": {
|
||||||
"level": "DEBUG",
|
"level": "DEBUG",
|
||||||
"class": "logging.StreamHandler",
|
"class": "logging.StreamHandler",
|
||||||
"formatter": "verbose",
|
"formatter": "json",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loggers": {
|
"loggers": {
|
||||||
"django.request": {
|
"plane.api": {"level": "INFO", "handlers": ["console"], "propagate": False},
|
||||||
|
"plane.worker": {"level": "INFO", "handlers": ["console"], "propagate": False},
|
||||||
|
"plane.exception": {
|
||||||
|
"level": "ERROR",
|
||||||
"handlers": ["console"],
|
"handlers": ["console"],
|
||||||
"level": "DEBUG",
|
|
||||||
"propagate": False,
|
"propagate": False,
|
||||||
},
|
},
|
||||||
"plane": {"handlers": ["console"], "level": "DEBUG", "propagate": False},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,10 @@ if not os.path.exists(LOG_DIR):
|
||||||
# Logging configuration
|
# Logging configuration
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"disable_existing_loggers": False,
|
"disable_existing_loggers": True,
|
||||||
"formatters": {
|
"formatters": {
|
||||||
"verbose": {
|
"verbose": {
|
||||||
"format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
|
"format": "%(asctime)s [%(process)d] %(levelname)s %(name)s: %(message)s"
|
||||||
"style": "{",
|
|
||||||
},
|
},
|
||||||
"json": {
|
"json": {
|
||||||
"()": "pythonjsonlogger.jsonlogger.JsonFormatter",
|
"()": "pythonjsonlogger.jsonlogger.JsonFormatter",
|
||||||
|
|
@ -40,7 +39,7 @@ LOGGING = {
|
||||||
"handlers": {
|
"handlers": {
|
||||||
"console": {
|
"console": {
|
||||||
"class": "logging.StreamHandler",
|
"class": "logging.StreamHandler",
|
||||||
"formatter": "verbose",
|
"formatter": "json",
|
||||||
"level": "INFO",
|
"level": "INFO",
|
||||||
},
|
},
|
||||||
"file": {
|
"file": {
|
||||||
|
|
@ -59,15 +58,19 @@ LOGGING = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"loggers": {
|
"loggers": {
|
||||||
"django": {"handlers": ["console", "file"], "level": "INFO", "propagate": True},
|
"plane.api": {
|
||||||
"django.request": {
|
"level": "DEBUG" if DEBUG else "INFO",
|
||||||
"handlers": ["console", "file"],
|
"handlers": ["console"],
|
||||||
"level": "INFO",
|
|
||||||
"propagate": False,
|
"propagate": False,
|
||||||
},
|
},
|
||||||
"plane": {
|
"plane.worker": {
|
||||||
|
"level": "DEBUG" if DEBUG else "INFO",
|
||||||
|
"handlers": ["console"],
|
||||||
|
"propagate": False,
|
||||||
|
},
|
||||||
|
"plane.exception": {
|
||||||
"level": "DEBUG" if DEBUG else "ERROR",
|
"level": "DEBUG" if DEBUG else "ERROR",
|
||||||
"handlers": ["console", "file"],
|
"handlers": ["console"],
|
||||||
"propagate": False,
|
"propagate": False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ from django.conf import settings
|
||||||
|
|
||||||
def log_exception(e):
|
def log_exception(e):
|
||||||
# Log the error
|
# Log the error
|
||||||
logger = logging.getLogger("plane")
|
logger = logging.getLogger("plane.exception")
|
||||||
logger.error(e)
|
logger.error(str(e))
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
# Print the traceback if in debug mode
|
# Print the traceback if in debug mode
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ scout-apm==3.1.0
|
||||||
# xlsx generation
|
# xlsx generation
|
||||||
openpyxl==3.1.2
|
openpyxl==3.1.2
|
||||||
# logging
|
# logging
|
||||||
python-json-logger==2.0.7
|
python-json-logger==3.3.0
|
||||||
# html parser
|
# html parser
|
||||||
beautifulsoup4==4.12.3
|
beautifulsoup4==4.12.3
|
||||||
# analytics
|
# analytics
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue