Upgrade Guide

Upgrading to 5.0+

Minimum requirements

  • requires asgiref 3.6+

Change you may need to do

Make sure you use django_structlog.middlewares.RequestMiddleware

If you used any of the experimental async or sync middlewares, you do not need to anymore. Make sure you use django_structlog.middlewares.RequestMiddleware instead of any of the other request middlewares commented below:

MIDDLEWARE += [
    # "django_structlog.middlewares.request_middleware_router", # <- remove
    # "django_structlog.middlewares.requests.SyncRequestMiddleware", # <- remove
    # "django_structlog.middlewares.requests.AsyncRequestMiddleware", # <- remove
    "django_structlog.middlewares.RequestMiddleware", # <- make sure you use this one
    "django_structlog.middlewares.CeleryMiddleware",
]

They will be removed in another major version.

Upgrading to 4.0+

django-structlog drops support of django below 3.2.

Minimum requirements

  • requires django 3.2+
  • requires python 3.7+
  • requires structlog 21.4.0+
  • (optionally) requires celery 5.1+

Changes if you use celery

You can now install django-structlog explicitly with celery extra in order to validate the compatibility with your version of celery.

django-structlog[celery]==4.0.0

See Installing “Extras” for more information about this pip feature.

Upgrading to 3.0+

django-structlog now use structlog.contextvars.bind_contextvars instead of threadlocal.

Minimum requirements

  • requires python 3.7+
  • requires structlog 21.4.0+

Changes you need to do

1. Update structlog settings

  • add structlog.contextvars.merge_contextvars as first processors
  • remove context_class=structlog.threadlocal.wrap_dict(dict),
  • (if you use standard loggers) add structlog.contextvars.merge_contextvars in foreign_pre_chain
  • (if you use standard loggers) remove django_structlog.processors.inject_context_dict,
structlog.configure(
    processors=[
        structlog.contextvars.merge_contextvars, # <---- add this
        structlog.stdlib.filter_by_level,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        structlog.stdlib.PositionalArgumentsFormatter(),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.processors.UnicodeDecoder(),
        structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
    ],
    # context_class=structlog.threadlocal.wrap_dict(dict), # <---- remove this
    logger_factory=structlog.stdlib.LoggerFactory(),
    cache_logger_on_first_use=True,
)

# If you use standard logging
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "json_formatter": {
            "()": structlog.stdlib.ProcessorFormatter,
            "processor": structlog.processors.JSONRenderer(),
            "foreign_pre_chain": [
                structlog.contextvars.merge_contextvars, # <---- add this
                # django_structlog.processors.inject_context_dict, # <---- remove this
                structlog.processors.TimeStamper(fmt="iso"),
                structlog.stdlib.add_logger_name,
                structlog.stdlib.add_log_level,
                structlog.stdlib.PositionalArgumentsFormatter(),
            ],
        },
    },
    ...
 }

2. Replace all logger.bind with structlog.contextvars.bind_contextvars

@receiver(bind_extra_request_metadata)
def bind_user_email(request, logger, **kwargs):
   # logger.bind(user_email=getattr(request.user, 'email', ''))
   structlog.contextvars.bind_contextvars(user_email=getattr(request.user, 'email', ''))

Upgrading to 2.0+

django-structlog was originally developed using the debug configuration ExceptionPrettyPrinter which led to incorrect handling of exception.

  • remove structlog.processors.ExceptionPrettyPrinter(), of your processors.
  • make sure you have structlog.processors.format_exc_info, in your processors if you want appropriate exception logging.