Skip to content

Commit 0b4b961

Browse files
committed
feat: [logging] Enhance logging for production and staging environments
Add comprehensive logging configuration with per-app loggers and environment-aware formatting. - Add loggers for api, authentication, django.request, django.security, and django.db.backends - Add verbose formatter used automatically in DEBUG mode - Add DJANGO_DB_LOG_LEVEL env var for database query logging - Add logging to API views (login, user CRUD) and auth views (signup, login) - All app loggers respect DJANGO_LOG_LEVEL env var Fixes #44
1 parent c83b178 commit 0b4b961

File tree

3 files changed

+52
-5
lines changed

3 files changed

+52
-5
lines changed

api/views.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
from testing.models import TlsScanHistory
2323
from testing_platform import tools
2424

25+
import logging
26+
2527
from .serializers import (
2628
DomainNameAndServiceSerializer,
2729
DomainNameSerializer,
@@ -32,6 +34,8 @@
3234
UserSerializer,
3335
)
3436

37+
logger = logging.getLogger(__name__)
38+
3539

3640
class LoginApiView(APIView):
3741
authentication_classes = [JWTAuthentication]
@@ -43,6 +47,7 @@ def post(self, request):
4347
user = authenticate(username=username, password=password)
4448

4549
if user is not None:
50+
logger.info("API login successful for user '%s'", username)
4651
refresh = RefreshToken.for_user(user)
4752
access_token = str(refresh.access_token)
4853
refresh_token = str(refresh)
@@ -67,6 +72,7 @@ def post(self, request):
6772

6873
return response
6974

75+
logger.warning("API login failed for user '%s'", username)
7076
return Response(status=status.HTTP_401_UNAUTHORIZED)
7177

7278

@@ -199,6 +205,7 @@ def post(self, request, *args, **kwargs):
199205
)
200206
new_user.set_password(password)
201207
new_user.save()
208+
logger.info("API user created: '%s'", new_user.username)
202209
return Response(UserSerializer(new_user).data, status=status.HTTP_201_CREATED)
203210

204211

@@ -231,6 +238,7 @@ def delete(self, request, id=None):
231238
"""
232239
user = User.objects.filter(id=id)
233240
user.delete()
241+
logger.info("API user deleted: id=%s", id)
234242
return Response(status=status.HTTP_204_NO_CONTENT)
235243

236244

authentication/views.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import socket
23

34
from django.contrib import messages
@@ -17,6 +18,8 @@
1718
UserUpdateForm,
1819
)
1920

21+
logger = logging.getLogger(__name__)
22+
2023

2124
def signup(request):
2225
if request.method == "POST":
@@ -28,6 +31,7 @@ def signup(request):
2831
raw_password = clean_form.get("password1")
2932
user = authenticate(username=username, password=raw_password)
3033
login(request, user)
34+
logger.info("New user registered: '%s'", username)
3135
messages.success(request, "Your signed up successfully!")
3236
return redirect("/")
3337
else:
@@ -63,9 +67,10 @@ def login_user(request):
6367
user = authenticate(request=request, username=username, password=password)
6468
if user is not None:
6569
login(request, user)
66-
# messages.success(request, "Logged in successfully")
70+
logger.info("User logged in: '%s'", username)
6771
return HttpResponseRedirect("/")
6872
else:
73+
logger.warning("Failed login attempt for user '%s'", username)
6974
return render(request, "login.html", {"form": form})
7075
else:
7176
form = LoginForm()

testing_platform/settings.py

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
For the full list of settings and their values, see
1010
https://docs.djangoproject.com/en/3.2/ref/settings/
1111
"""
12+
1213
import os
1314
import sys
1415
from datetime import timedelta
@@ -136,7 +137,9 @@
136137
"django.contrib.messages.middleware.MessageMiddleware",
137138
"django.middleware.clickjacking.XFrameOptionsMiddleware",
138139
]
139-
_cors_origins = os.environ.get("CORS_ALLOWED_ORIGINS", "http://localhost:3000,http://127.0.0.1:3000")
140+
_cors_origins = os.environ.get(
141+
"CORS_ALLOWED_ORIGINS", "http://localhost:3000,http://127.0.0.1:3000"
142+
)
140143
CORS_ALLOWED_ORIGINS = [o.strip() for o in _cors_origins.split(",") if o.strip()]
141144

142145

@@ -237,12 +240,18 @@
237240

238241
DMARC_API_KEY = os.environ.get("DMARC_API_KEY", "")
239242

243+
LOG_LEVEL = os.getenv("DJANGO_LOG_LEVEL", "INFO")
244+
240245
LOGGING = {
241246
"version": 1,
242247
"disable_existing_loggers": False,
243248
"formatters": {
244249
"simple": {
245-
"format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
250+
"format": "{levelname} {asctime} {module} {message}",
251+
"style": "{",
252+
},
253+
"verbose": {
254+
"format": "{levelname} {asctime} {name} {module} {process:d} {thread:d} {message}",
246255
"style": "{",
247256
},
248257
},
@@ -251,7 +260,7 @@
251260
"class": "logging.StreamHandler",
252261
"level": "DEBUG",
253262
"stream": sys.stdout,
254-
"formatter": "simple",
263+
"formatter": "verbose" if DEBUG else "simple",
255264
},
256265
},
257266
"root": {
@@ -261,7 +270,32 @@
261270
"loggers": {
262271
"testing": {
263272
"handlers": ["console"],
264-
"level": os.getenv("DJANGO_LOG_LEVEL", "INFO"),
273+
"level": LOG_LEVEL,
274+
"propagate": False,
275+
},
276+
"api": {
277+
"handlers": ["console"],
278+
"level": LOG_LEVEL,
279+
"propagate": False,
280+
},
281+
"authentication": {
282+
"handlers": ["console"],
283+
"level": LOG_LEVEL,
284+
"propagate": False,
285+
},
286+
"django.request": {
287+
"handlers": ["console"],
288+
"level": "WARNING",
289+
"propagate": False,
290+
},
291+
"django.security": {
292+
"handlers": ["console"],
293+
"level": "WARNING",
294+
"propagate": False,
295+
},
296+
"django.db.backends": {
297+
"handlers": ["console"],
298+
"level": os.getenv("DJANGO_DB_LOG_LEVEL", "WARNING"),
265299
"propagate": False,
266300
},
267301
},

0 commit comments

Comments
 (0)