feat: add comprehensive logging configuration, rotating file handlers, request middleware, and gunicorn log integration
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 29s
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 29s
This commit is contained in:
parent
97435c42ea
commit
926b6edabb
4 changed files with 102 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -13,6 +13,7 @@ ENV/
|
|||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
*.log
|
||||
logs/
|
||||
local_settings.py
|
||||
|
||||
# Environment variables & secrets
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ After=network.target
|
|||
User=ubuntu
|
||||
Group=ubuntu
|
||||
WorkingDirectory=/home/ubuntu/beta-documentverification
|
||||
ExecStart=/home/ubuntu/beta-documentverification/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8092 docverify.wsgi:application
|
||||
ExecStart=/home/ubuntu/beta-documentverification/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8092 --access-logfile /home/ubuntu/beta-documentverification/logs/gunicorn-access.log --error-logfile /home/ubuntu/beta-documentverification/logs/gunicorn-error.log --capture-output docverify.wsgi:application
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
|
||||
|
|
|
|||
30
docverify/middleware.py
Normal file
30
docverify/middleware.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import logging
|
||||
import time
|
||||
|
||||
logger = logging.getLogger("django.request")
|
||||
|
||||
|
||||
class RequestLoggingMiddleware:
|
||||
"""
|
||||
Captures incoming HTTP requests, client IPs, response status codes,
|
||||
and end-to-end processing durations to log to requests.log and console.
|
||||
"""
|
||||
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
start_time = time.time()
|
||||
response = self.get_response(request)
|
||||
duration_ms = (time.time() - start_time) * 1000
|
||||
|
||||
ip = (
|
||||
request.META.get("HTTP_X_FORWARDED_FOR", "").split(",")[0].strip()
|
||||
or request.META.get("REMOTE_ADDR", "unknown")
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"IP: {ip} | {request.method} {request.get_full_path()} | "
|
||||
f"Status: {response.status_code} | Duration: {duration_ms:.2f}ms"
|
||||
)
|
||||
return response
|
||||
|
|
@ -37,6 +37,7 @@ INSTALLED_APPS = [
|
|||
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"docverify.middleware.RequestLoggingMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
|
|
@ -120,4 +121,73 @@ CODEPLUS_BASE_URL = os.environ.get("CODEPLUS_BASE_URL", "https://apihub.services
|
|||
CODEPLUS_CLIENT_API_ID = os.environ.get("CODEPLUS_CLIENT_API_ID", "CAPI-YYR0YJIE0VMTDENY")
|
||||
CODEPLUS_CLIENT_API_SECRET = os.environ.get("CODEPLUS_CLIENT_API_SECRET", "s24Ts9wFsgl64mFzA61OqG0RDLRs2HFCpmOZBmqs")
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Comprehensive Logging Configuration & CloudWatch Shipments
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
LOGS_DIR = BASE_DIR / "logs"
|
||||
LOGS_DIR.mkdir(exist_ok=True)
|
||||
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"formatters": {
|
||||
"verbose": {
|
||||
"format": "{levelname} {asctime} [{name}] {process:d} {thread:d} {message}",
|
||||
"style": "{",
|
||||
},
|
||||
"simple": {
|
||||
"format": "{levelname} {asctime} {message}",
|
||||
"style": "{",
|
||||
},
|
||||
},
|
||||
"handlers": {
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "simple",
|
||||
},
|
||||
"app_file": {
|
||||
"level": "INFO",
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"filename": str(LOGS_DIR / "app.log"),
|
||||
"maxBytes": 10 * 1024 * 1024, # 10 MB
|
||||
"backupCount": 5,
|
||||
"formatter": "verbose",
|
||||
},
|
||||
"error_file": {
|
||||
"level": "ERROR",
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"filename": str(LOGS_DIR / "error.log"),
|
||||
"maxBytes": 10 * 1024 * 1024, # 10 MB
|
||||
"backupCount": 5,
|
||||
"formatter": "verbose",
|
||||
},
|
||||
"requests_file": {
|
||||
"level": "INFO",
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"filename": str(LOGS_DIR / "requests.log"),
|
||||
"maxBytes": 10 * 1024 * 1024, # 10 MB
|
||||
"backupCount": 5,
|
||||
"formatter": "simple",
|
||||
},
|
||||
},
|
||||
"loggers": {
|
||||
"django": {
|
||||
"handlers": ["console", "app_file", "error_file"],
|
||||
"level": "INFO",
|
||||
"propagate": True,
|
||||
},
|
||||
"django.request": {
|
||||
"handlers": ["console", "requests_file", "error_file"],
|
||||
"level": "INFO",
|
||||
"propagate": False,
|
||||
},
|
||||
"verifier": {
|
||||
"handlers": ["console", "app_file", "error_file"],
|
||||
"level": "INFO",
|
||||
"propagate": True,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue