I configured loggng like this in the realestate/settings.py file.
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"standard": {
"format": "%(asctime)s [%(levelname)s] %(message)s %(context)s"
}
},
"handlers": {
"file": {
"level": "DEBUG",
"class": "logging.FileHandler",
"filename": "realestate.log",
"formatter": "standard"
},
"console": {
"class": "logging.StreamHandler",
"formatter": "standard"
}
},
"loggers": {
"":
{
"handlers": ["file", "console"],
"level": "DEBUG"
}
}
}
The logging format has additional format field, context.
"format": "%(asctime)s [%(levelname)s] %(message)s %(context)s"
I made a global logger in globals/logger.py that is used in views and services.
import logging
logger = logging.getLogger(__name__)
For example, register_post view function creates logs using this logger. The log messages are stored in globals/log_messages.py.
realestate\auth2\views.py:
from globals import log_messages
from globals.logger import logger
# ...
@ratelimit(key="ip", rate="10/m")
def register_post(request: HttpRequest, template: str):
form = RegisterForm(request.POST)
# 2 Input validation & sanitization
if not form.is_valid():
return render(request, template, {"form": form})
cleaned_data = form.cleaned_data
# 6 Error handling
if auth_serv.email_taken(cleaned_data["email"]):
messages.error(request, "Korisnik sa ovom imejl adresom već postoji.")
# 5 Security logging
logger.warning(log_messages.auth_view["register_email_taken"])
return redirect(reverse("register"))
if auth_serv.phone_taken(cleaned_data["phone"]):
messages.error(request, "Korisnik sa ovim brojem telefona već postoji.")
# 5 Security logging
logger.warning(log_messages.auth_view["register_phone_taken"])
return redirect(reverse("register"))
user = auth_serv.create(cleaned_data)
login2(request, user)
# 5 Security logging
logger.info(log_messages.auth_view["register_success"], extra={"context": {"user_id": user.pk}})
return redirect(reverse("listing-list"))
Some logs pass extra parameters:
logger.info(log_messages.auth_view["register_success"], extra={"context": {"user_id": user.pk}})
And some logs don’t.
logger.warning(log_messages.auth_view["register_email_taken"])
logger.warning(log_messages.auth_view["register_phone_taken"])
I keep getting key error for context. Perhaps it has to with context not being passed into some logs.
--- Logging error ---
Traceback (most recent call last):
File "C:\_dev\Python314\Lib\logging\__init__.py", line 472, in format
return self._format(record)
~~~~~~~~~~~~^^^^^^^^
File "C:\_dev\Python314\Lib\logging\__init__.py", line 468, in _format
return self._fmt % values
~~~~~~~~~~^~~~~~~~
KeyError: 'context'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\_dev\Python314\Lib\logging\__init__.py", line 1151, in emit
msg = self.format(record)
File "C:\_dev\Python314\Lib\logging\__init__.py", line 999, in format
return fmt.format(record)
~~~~~~~~~~^^^^^^^^
File "C:\_dev\Python314\Lib\logging\__init__.py", line 715, in format
s = self.formatMessage(record)
File "C:\_dev\Python314\Lib\logging\__init__.py", line 684, in formatMessage
return self._style.format(record)
~~~~~~~~~~~~~~~~~~^^^^^^^^
File "C:\_dev\Python314\Lib\logging\__init__.py", line 474, in format
raise ValueError('Formatting field not found in record: %s' % e)
ValueError: Formatting field not found in record: 'context'
Call stack:
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\realestate\manage.py", line 22, in <module>
main()
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\realestate\manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\venv\Lib\site-packages\django\core\management\__init__.py", line 443, in execute_from_command_line
utility.execute()
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\venv\Lib\site-packages\django\core\management\__init__.py", line 437, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\venv\Lib\site-packages\django\core\management\base.py", line 420, in run_from_argv
self.execute(*args, **cmd_options)
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\venv\Lib\site-packages\django\core\management\commands\runserver.py", line 69, in execute
super().execute(*args, **options)
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\venv\Lib\site-packages\django\core\management\base.py", line 464, in execute
output = self.handle(*args, **options)
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\venv\Lib\site-packages\django\core\management\commands\runserver.py", line 110, in handle
self.run(**options)
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\venv\Lib\site-packages\django\core\management\commands\runserver.py", line 117, in run
autoreload.run_with_reloader(self.inner_run, **options)
File "D:\Documents\_Dokumenti\Projekti\_Master\Real Estate App\Django\secure\venv\Lib\site-packages\django\utils\autoreload.py", line 681, in run_with_reloader
logger.info(
How do I make log format fields optional and not get such errors?