### Setup and Run Tests Source: https://jrobichaud.github.io/django-structlog/running_tests.html Ensure Redis is running via Docker Compose, install dependencies, and then execute tests for the main app and the demo app using pytest. Remember to stop Redis when finished. ```bash docker compose up -d redis ``` ```bash pip install -r requirements.txt ``` ```bash env CELERY_BROKER_URL=redis://0.0.0.0:6379 DJANGO_SETTINGS_MODULE=config.settings.test pytest test_app ``` ```bash env CELERY_BROKER_URL=redis://0.0.0.0:6379 DJANGO_SETTINGS_MODULE=config.settings.test_demo_app pytest django_structlog_demo_project ``` ```bash docker compose stop redis ``` -------------------------------- ### Start Demo App with Docker Compose Source: https://jrobichaud.github.io/django-structlog/_sources/development.rst.txt Build and start the demo application using Docker Compose. This command launches the default configuration. ```bash $ docker compose up --build ``` -------------------------------- ### Clone and Install Project Dependencies Source: https://jrobichaud.github.io/django-structlog/_sources/development.rst.txt Clone the repository, navigate into the directory, install project dependencies, and set up pre-commit hooks. ```bash $ git clone https://github.com/jrobichaud/django-structlog.git $ cd django-structlog $ pip install -r requirements.txt $ pre-commit install ``` -------------------------------- ### Install django-structlog Source: https://jrobichaud.github.io/django-structlog/getting_started.html Use pip to install the library. ```bash pip install django-structlog ``` -------------------------------- ### Example Log Output for Basic Command Source: https://jrobichaud.github.io/django-structlog/_sources/commands.rst.txt This output shows the logs generated when running a basic command with django-structlog's command support enabled. It includes command start and finish events, along with the custom log message. ```bash $ python manage.py example_command bar 2023-09-13T21:10:50.084368Z [info ] command_started [django_structlog.commands] command_name=django_structlog_demo_project.users.example_command command_id=be723d34-59f5-468e-9258-24232aa4cedd 2023-09-13T21:10:50.085325Z [info ] my log [django_structlog_demo_project.users.management.commands.example_command] command_id=be723d34-59f5-468e-9258-24232aa4cedd foo=bar 2023-09-13T21:10:50.085877Z [info ] command_finished [django_structlog.commands] command_id=be723d34-59f5-468e-9258-24232aa4cedd ``` -------------------------------- ### Start Demo App with RabbitMQ Broker Source: https://jrobichaud.github.io/django-structlog/_sources/development.rst.txt Build and start the demo application using Docker Compose, specifically configuring it to use RabbitMQ as the message broker instead of Redis. ```bash $ docker compose -f ./docker-compose.yml -f ./docker-compose.amqp.yml up --build ``` -------------------------------- ### Install django-structlog with Commands Source: https://jrobichaud.github.io/django-structlog/commands.html Install the django-structlog package with the 'commands' extra to include django-extensions. ```bash pip install django-structlog[commands] ``` -------------------------------- ### Get a structlog logger instance Source: https://jrobichaud.github.io/django-structlog/getting_started.html Obtain a logger instance using structlog.get_logger(__name__) to start logging. ```python import structlog logger = structlog.get_logger(__name__) ``` -------------------------------- ### Standard Logging Example Source: https://jrobichaud.github.io/django-structlog/index.html Demonstrates basic logging using Python's standard logging library. ```python >>> import logging >>> logger = logging.get_logger(__name__) >>> logger.info("An error occurred") ``` ```text An error occurred ``` -------------------------------- ### Install django-extensions Directly Source: https://jrobichaud.github.io/django-structlog/commands.html Alternatively, install django-extensions separately if not using the 'commands' extra for django-structlog. ```bash pip install django-extensions ``` -------------------------------- ### Build and Run Demo App Source: https://jrobichaud.github.io/django-structlog/demo.html Use this command to build the Docker image and start the demo application. Access the app at http://127.0.0.1:8000/ and observe log output. ```bash docker compose up --build ``` -------------------------------- ### Bind Extra Request Metadata with Signals Source: https://jrobichaud.github.io/django-structlog/api_documentation.html The bind_extra_request_metadata signal allows you to add custom context to logs when a request starts. This example binds the domain of the current site. ```python from django.contrib.sites.shortcuts import get_current_site from django.dispatch import receiver from django_structlog import signals import structlog @receiver(signals.bind_extra_request_metadata) def bind_domain(request, logger, log_kwargs, **kwargs): current_site = get_current_site(request) structlog.contextvars.bind_contextvars(domain=current_site.domain) ``` -------------------------------- ### Install Django-Structlog with Celery Extra Source: https://jrobichaud.github.io/django-structlog/upgrade_guide.html For django-structlog 4.0+, you can explicitly install it with the 'celery' extra to validate compatibility with your Celery version. ```bash django-structlog[celery]==4.0.0 ``` -------------------------------- ### Basic Command Log Output Source: https://jrobichaud.github.io/django-structlog/commands.html Example log output when running a command with django-structlog enabled, showing added command_name and command_id fields. ```text $ python manage.py example_command bar 2023-09-13T21:10:50.084368Z [info ] command_started [django_structlog.commands] command_name=django_structlog_demo_project.users.example_command command_id=be723d34-59f5-468e-9258-24232aa4cedd 2023-09-13T21:10:50.085325Z [info ] my log [django_structlog_demo_project.users.management.commands.example_command] command_id=be723d34-59f5-468e-9258-24232aa4cedd foo=bar 2023-09-13T21:10:50.085877Z [info ] command_finished [django_structlog.commands] command_id=be723d34-59f5-468e-9258-24232aa4cedd ``` -------------------------------- ### Nested Command Log Output with Parent ID Source: https://jrobichaud.github.io/django-structlog/commands.html Example log output for nested commands, demonstrating the use of parent_command_id to track command hierarchy. ```text $ python manage.py example_command bar 2023-09-15T00:10:10.466616Z [info ] command_started [django_structlog.commands] command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed command_name=django_structlog_demo_project.users.example_command 2023-09-15T00:10:10.467250Z [info ] my log [django_structlog_demo_project.users.management.commands.example_command] command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed foo=bar 2023-09-15T00:10:10.468176Z [info ] command_started [django_structlog.commands] baz=2 command_id=57524ccb-a8eb-4d30-a989-4e83ffdca9c0 command_name=django_structlog_demo_project.users.example_nested_command parent_command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed 2023-09-15T00:10:10.468871Z [info ] my nested log [django_structlog_demo_project.users.management.commands.example_nested_command] command_id=57524ccb-a8eb-4d30-a989-4e83ffdca9c0 parent_command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed 2023-09-15T00:10:10.469418Z [info ] command_finished [django_structlog.commands] command_id=57524ccb-a8eb-4d30-a989-4e83ffdca9c0 parent_command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed 2023-09-15T00:10:10.469964Z [info ] my log 2 [django_structlog_demo_project.users.management.commands.example_command] command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed 2023-09-15T00:10:10.470585Z [info ] command_finished [django_structlog.commands] command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed ``` -------------------------------- ### Example Log Output for Nested Commands Source: https://jrobichaud.github.io/django-structlog/_sources/commands.rst.txt This output demonstrates logging for nested commands, showing how parent_command_id is used to track command hierarchy. It includes logs for the parent command, a nested command, and subsequent logs from the parent. ```bash $ python manage.py example_command bar 2023-09-15T00:10:10.466616Z [info ] command_started [django_structlog.commands] command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed command_name=django_structlog_demo_project.users.example_command 2023-09-15T00:10:10.467250Z [info ] my log [django_structlog_demo_project.users.management.commands.example_command] command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed foo=bar 2023-09-15T00:10:10.468176Z [info ] command_started [django_structlog.commands] baz=2 command_id=57524ccb-a8eb-4d30-a989-4e83ffdca9c0 command_name=django_structlog_demo_project.users.example_nested_command parent_command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed 2023-09-15T00:10:10.468871Z [info ] my nested log [django_structlog_demo_project.users.management.commands.example_nested_command] command_id=57524ccb-a8eb-4d30-a989-4e83ffdca9c0 parent_command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed 2023-09-15T00:10:10.469418Z [info ] command_finished [django_structlog.commands] command_id=57524ccb-a8eb-4d30-a989-4e83ffdca9c0 parent_command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed 2023-09-15T00:10:10.469964Z [info ] my log 2 [django_structlog_demo_project.users.management.commands.example_command] command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed 2023-09-15T00:10:10.470585Z [info ] command_finished [django_structlog.commands] command_id=f2a8c9a8-5aa3-4e22-b11c-f387449a34ed ``` -------------------------------- ### Filter logs from being recorded Source: https://jrobichaud.github.io/django-structlog/_sources/how_tos.rst.txt Implement a custom logging filter to exclude specific log events from being recorded. This example shows how to filter out 'request_started' events. ```python # your_project/logging/filters.py import logging class ExcludeEventsFilter(logging.Filter): def __init__(self, excluded_event_type=None): super().__init__() self.excluded_event_type = excluded_event_type def filter(self, record): if not isinstance(record.msg, dict) or self.excluded_event_type is None: return True # Include the log message if msg is not a dictionary or excluded_event_type is not provided if record.msg.get('event') in self.excluded_event_type: return False # Exclude the log message return True # Include the log message # in your settings.py LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'filters': ['exclude_request_started'] }, }, 'filters': { 'exclude_request_started': { '()': 'your_project.logging.filters.ExcludeEventsFilter', 'excluded_event_type': ['request_started'] # Example excluding request_started event }, }, 'loggers': { 'django': { 'handlers': ['console'], 'level': 'DEBUG', }, }, } ``` -------------------------------- ### Bind Extra Request Finished Metadata with Signals Source: https://jrobichaud.github.io/django-structlog/api_documentation.html Utilize the bind_extra_request_finished_metadata signal to enrich logs for finished requests. This example adds the current site's domain to the log context. ```python from django.contrib.sites.shortcuts import get_current_site from django.dispatch import receiver from django_structlog import signals import structlog @receiver(signals.bind_extra_request_finished_metadata) def bind_domain(request, logger, response, log_kwargs, **kwargs): current_site = get_current_site(request) structlog.contextvars.bind_contextvars(domain=current_site.domain) ``` -------------------------------- ### Initialize Celery Worker with DjangoStructLogInitStep Source: https://jrobichaud.github.io/django-structlog/_sources/celery.rst.txt Add DjangoStructLogInitStep to your Celery AppConfig to initialize django-structlog when the worker starts. This ensures proper logging context for tasks. ```python import logging import structlog from celery import Celery from celery.signals import setup_logging from django_structlog.celery.steps import DjangoStructLogInitStep app = Celery("your_celery_project") # A step to initialize django-structlog app.steps['worker'].add(DjangoStructLogInitStep) ``` -------------------------------- ### Bind Extra Request Failed Metadata with Signals Source: https://jrobichaud.github.io/django-structlog/api_documentation.html Use the bind_extra_request_failed_metadata signal to add custom context to logs when a request fails. This example binds the domain of the current site. ```python from django.contrib.sites.shortcuts import get_current_site from django.dispatch import receiver from django_structlog import signals import structlog @receiver(signals.bind_extra_request_failed_metadata) def bind_domain(request, logger, exception, log_kwargs, **kwargs): current_site = get_current_site(request) structlog.contextvars.bind_contextvars(domain=current_site.domain) ``` -------------------------------- ### Modify Task Context Before Publish - Python Source: https://jrobichaud.github.io/django-structlog/_sources/celery.rst.txt Connect to the `modify_context_before_task_publish` signal to alter task metadata before it's stored. This example demonstrates stripping down the context to keep only specific keys. ```python from django_structlog import celery as signals from django.dispatch import receiver @receiver(signals.modify_context_before_task_publish) def receiver_modify_context_before_task_publish(sender, signal, context, task_routing_key=None, task_properties=None, **kwargs): keys_to_keep = {"request_id", "parent_task_id"} new_dict = {key_to_keep: context[key_to_keep] for key_to_keep in keys_to_keep if key_to_keep in context} context.clear() context.update(new_dict) ``` -------------------------------- ### Add Structlog Bindings for Successful Celery Tasks Source: https://jrobichaud.github.io/django-structlog/api_documentation.html Utilize the pre_task_succeeded signal to add structlog bindings from a Celery task's result. This example binds the string representation of the result. ```python from django.dispatch import receiver from django_structlog.celery import signals import structlog @receiver(signals.pre_task_succeeded) def receiver_pre_task_succeeded(sender, signal, logger=None, result=None, **kwargs): structlog.contextvars.bind_contextvars(result=str(result)) ``` -------------------------------- ### Build and Serve Documentation Locally Source: https://jrobichaud.github.io/django-structlog/_sources/development.rst.txt Build and serve the project's documentation locally using Docker Compose. The documentation will be available at http://127.0.0.1:8080. ```bash $ docker compose -p django-structlog-docs -f docker-compose.docs.yml up --build Serving on http://127.0.0.1:8080 ``` -------------------------------- ### Configure structlog logging in settings.py Source: https://jrobichaud.github.io/django-structlog/getting_started.html Set up structlog processors and formatters for JSON, console, and key-value output. Ensure handlers are adapted for your project and consider environment-specific configurations. ```python import structlog LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { "json_formatter": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.JSONRenderer(), }, "plain_console": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(), }, "key_value": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.KeyValueRenderer(key_order=['timestamp', 'level', 'event', 'logger']), }, }, "handlers": { # Important notes regarding handlers. # # 1. Make sure you use handlers adapted for your project. # These handlers configurations are only examples for this library. # See python's logging.handlers: https://docs.python.org/3/library/logging.handlers.html # # 2. You might also want to use different logging configurations depending of the environment. # Different files (local.py, tests.py, production.py, ci.py, etc.) or only conditions. # See https://docs.djangoproject.com/en/dev/topics/settings/#designating-the-settings "console": { "class": "logging.StreamHandler", "formatter": "plain_console", }, "json_file": { "class": "logging.handlers.WatchedFileHandler", "filename": "logs/json.log", "formatter": "json_formatter", }, "flat_line_file": { "class": "logging.handlers.WatchedFileHandler", "filename": "logs/flat_line.log", "formatter": "key_value", }, }, "loggers": { "django_structlog": { "handlers": ["console", "flat_line_file", "json_file"], "level": "INFO", }, # Make sure to replace the following logger's name for yours "django_structlog_demo_project": { "handlers": ["console", "flat_line_file", "json_file"], "level": "INFO", }, } } structlog.configure( processors=[ structlog.contextvars.merge_contextvars, 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, ], logger_factory=structlog.stdlib.LoggerFactory(), cache_logger_on_first_use=True, ) ``` -------------------------------- ### Set 4XX Log Level in Django-Structlog Source: https://jrobichaud.github.io/django-structlog/_sources/configuration.rst.txt Customize the logging level for 4XX status codes by setting DJANGO_STRUCTLOG_STATUS_4XX_LOG_LEVEL in your settings.py. This example sets it to logging.INFO. ```python import logging DJANGO_STRUCTLOG_STATUS_4XX_LOG_LEVEL = logging.INFO ``` -------------------------------- ### DjangoStructLogInitStep Source: https://jrobichaud.github.io/django-structlog/api_documentation.html Celery worker boot step to initialize django-structlog. This ensures that logging is properly configured for Celery workers. ```APIDOC ## DjangoStructLogInitStep ### Description Celery worker boot step to initialize `django_structlog`. ### Usage ```python >>> from celery import Celery >>> from django_structlog.celery.steps import DjangoStructLogInitStep >>> >>> app = Celery("django_structlog_demo_project") >>> app.steps['worker'].add(DjangoStructLogInitStep) ``` ### Class Definition `class django_structlog.celery.steps.DjangoStructLogInitStep(_parent : Any_, _** kwargs: Any_) Bases: `Step` ``` -------------------------------- ### Configure Celery Logger and Structlog Processors Source: https://jrobichaud.github.io/django-structlog/celery.html Set up logging configuration using dictConfig for different handlers and formatters, and configure structlog processors for Celery workers. ```python @setup_logging.connect def receiver_setup_logging(loglevel, logfile, format, colorize, **kwargs): # pragma: no cover logging.config.dictConfig( { "version": 1, "disable_existing_loggers": False, "formatters": { "json_formatter": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.JSONRenderer(), }, "plain_console": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(), }, "key_value": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.KeyValueRenderer(key_order=['timestamp', 'level', 'event', 'logger']), }, }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "plain_console", }, "json_file": { "class": "logging.handlers.WatchedFileHandler", "filename": "logs/json.log", "formatter": "json_formatter", }, "flat_line_file": { "class": "logging.handlers.WatchedFileHandler", "filename": "logs/flat_line.log", "formatter": "key_value", }, }, "loggers": { "django_structlog": { "handlers": ["console", "flat_line_file", "json_file"], "level": "INFO", }, "django_structlog_demo_project": { "handlers": ["console", "flat_line_file", "json_file"], "level": "INFO", }, } } ) structlog.configure( processors=[ structlog.contextvars.merge_contextvars, 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, ], logger_factory=structlog.stdlib.LoggerFactory(), cache_logger_on_first_use=True, ) ``` -------------------------------- ### Modify Context Before Task Publish with Celery Signal Source: https://jrobichaud.github.io/django-structlog/api_documentation.html Customize the context passed to Celery tasks before they are published. This example filters the context to keep only specific keys. ```python from django.dispatch import receiver from django_structlog.celery import signals @receiver(signals.modify_context_before_task_publish) def receiver_modify_context_before_task_publish(sender, signal, context, task_routing_key=None, task_properties=None, **kwargs): keys_to_keep = {"request_id", "parent_task_id"} new_dict = { key_to_keep: context[key_to_keep] for key_to_keep in keys_to_keep if key_to_keep in context } context.clear() context.update(new_dict) ``` -------------------------------- ### Configure RequestMiddleware Source: https://jrobichaud.github.io/django-structlog/upgrade_guide.html When upgrading to 6.0+, ensure you are using `django_structlog.middlewares.RequestMiddleware`. Remove any previous experimental or deprecated middleware entries. ```python 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 with JSON Logging Source: https://jrobichaud.github.io/django-structlog/index.html Demonstrates django-structlog configured with JSON output, suitable for machine parsing and integration with log aggregation systems. This format allows for more complex querying using tools like jq. ```python >>> import structlog >>> logger = structlog.get_logger(__name__) >>> logger.info("an_error_occurred", bar="Buz") ``` ```json {"request_id": "3a8f801c-072b-4805-8f38-e1337f363ed4", "user_id": 1, "ip": "0.0.0.0", "event": "an_error_occurred", "timestamp": "2019-04-13T19:39:31.089925Z", "logger": "my_awesome_project.my_awesome_module", "level": "info", "bar": "Buz"} ``` ```bash $ cat logs/json.log | jq '.[] | select(.request_id="3a8f801c-072b-4805-8f38-e1337f363ed4")' -s ``` -------------------------------- ### Enable Command Logging Configuration Source: https://jrobichaud.github.io/django-structlog/commands.html Set this Django setting to True to enable command logging within django-structlog. ```python DJANGO_STRUCTLOG_COMMAND_LOGGING_ENABLED = True ``` -------------------------------- ### Configure Celery Logger with Multiple Formatters Source: https://jrobichaud.github.io/django-structlog/_sources/celery.rst.txt Set up Celery's logging configuration using dictConfig to define multiple formatters (JSON, console, key-value) and handlers for different log outputs. ```python @setup_logging.connect def receiver_setup_logging(loglevel, logfile, format, colorize, **kwargs): # pragma: no cover logging.config.dictConfig( { "version": 1, "disable_existing_loggers": False, "formatters": { "json_formatter": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.JSONRenderer(), }, "plain_console": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(), }, "key_value": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.KeyValueRenderer(key_order=['timestamp', 'level', 'event', 'logger']), }, }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "plain_console", }, "json_file": { "class": "logging.handlers.WatchedFileHandler", "filename": "logs/json.log", "formatter": "json_formatter", }, "flat_line_file": { "class": "logging.handlers.WatchedFileHandler", "filename": "logs/flat_line.log", "formatter": "key_value", }, }, "loggers": { "django_structlog": { "handlers": ["console", "flat_line_file", "json_file"], "level": "INFO", }, "django_structlog_demo_project": { "handlers": ["console", "flat_line_file", "json_file"], "level": "INFO", }, } } ) structlog.configure( processors=[ structlog.contextvars.merge_contextvars, 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, ], logger_factory=structlog.stdlib.LoggerFactory(), cache_logger_on_first_use=True, ) ``` -------------------------------- ### Bind Extra Task Metadata with Celery Signal Source: https://jrobichaud.github.io/django-structlog/api_documentation.html Use the bind_extra_task_metadata signal to add custom metadata to Celery tasks. This example binds the task's correlation ID to the structlog context. ```python from django.dispatch import receiver from django_structlog.celery import signals import structlog @receiver(signals.bind_extra_task_metadata) def receiver_bind_extra_task_metadata(sender, signal, task=None, logger=None, **kwargs): structlog.contextvars.bind_contextvars(correlation_id=task.request.correlation_id) ``` -------------------------------- ### django-structlog with flat_line Logging Source: https://jrobichaud.github.io/django-structlog/index.html Shows how to use django-structlog with the flat_line formatter for structured logging. This format is useful for direct log file reading and simple grep operations. ```python >>> import structlog >>> logger = structlog.get_logger(__name__) >>> logger.info("an_error_occurred", bar="Buz") ``` ```text timestamp='2019-04-13T19:39:31.089925Z' level='info' event='an_error_occurred' logger='my_awesome_project.my_awesome_module' request_id='3a8f801c-072b-4805-8f38-e1337f363ed4' user_id=1 ip='0.0.0.0' bar='Buz' ``` ```bash $ cat logs/flat_line.log | grep request_id='3a8f801c-072b-4805-8f38-e1337f363ed4' ``` -------------------------------- ### RequestMiddleware Source: https://jrobichaud.github.io/django-structlog/api_documentation.html The RequestMiddleware class provides functionality to bind request-specific information to the logging context. ```APIDOC ## `RequestMiddleware` ### Description Provides functionality to bind request-specific information to the logging context. ### Methods - `async_capable` (property) - `bind_ip()` - `bind_user_id()` - `format_request()` - `handle_response()` - `prepare()` - `process_got_request_exception()` - `sync_capable` (property) ``` -------------------------------- ### Add django_structlog to INSTALLED_APPS Source: https://jrobichaud.github.io/django-structlog/getting_started.html Include 'django_structlog' in your Django project's INSTALLED_APPS setting. ```python INSTALLED_APP = [ # ... "django_structlog", # ... ] ``` -------------------------------- ### Utility Functions Source: https://jrobichaud.github.io/django-structlog/api_documentation.html Utility functions for binding extra metadata to the logging context. ```APIDOC ## Utility Functions ### Description Functions to bind extra metadata to the logging context or update response information. ### Functions - `bind_extra_request_failed_metadata` - `bind_extra_request_finished_metadata` - `bind_extra_request_metadata` - `update_failure_response` ``` -------------------------------- ### Replace logger.bind with structlog.contextvars.bind_contextvars Source: https://jrobichaud.github.io/django-structlog/upgrade_guide.html In django-structlog 3.0+, replace all instances of `logger.bind` with `structlog.contextvars.bind_contextvars` to leverage context variables. ```python @receiver(bind_extra_request_metadata) def bind_domain(request, logger, **kwargs): current_site = get_current_site(request) # logger.bind(domain=current_site.domain) structlog.contextvars.bind_contextvars(domain=current_site.domain) ``` -------------------------------- ### RequestMiddleware Source: https://jrobichaud.github.io/django-structlog/_sources/api_documentation.rst.txt A Django middleware to bind request-related metadata to the structlog context. ```APIDOC ## RequestMiddleware ### Description Binds request-related metadata to the structlog context for logging. ### Class `django_structlog.middlewares.RequestMiddleware` ``` -------------------------------- ### Signal Bindings Source: https://jrobichaud.github.io/django-structlog/_sources/api_documentation.rst.txt Functions to bind extra metadata to structlog context for requests and tasks. ```APIDOC ## Signal Bindings ### Description Functions to bind extra request or task metadata to the structlog context. ### Functions - `bind_extra_request_metadata` - `bind_extra_request_finished_metadata` - `bind_extra_request_failed_metadata` - `update_failure_response` - `bind_extra_task_metadata` - `modify_context_before_task_publish` - `pre_task_succeeded` ``` -------------------------------- ### Initialize Celery Worker with DjangoStructLogInitStep Source: https://jrobichaud.github.io/django-structlog/celery.html Add DjangoStructLogInitStep to your Celery app's worker steps for automatic django-structlog initialization. ```python import logging import structlog from celery import Celery from celery.signals import setup_logging from django_structlog.celery.steps import DjangoStructLogInitStep app = Celery("your_celery_project") # A step to initialize django-structlog app.steps['worker'].add(DjangoStructLogInitStep) ``` -------------------------------- ### Add Celery Extra to Requirements Source: https://jrobichaud.github.io/django-structlog/_sources/celery.rst.txt Update your requirements.txt to include the celery extra for django-structlog to ensure compatibility. ```python django-structlog[celery]==X.Y.Z ``` -------------------------------- ### Celery Integration Source: https://jrobichaud.github.io/django-structlog/api_documentation.html Components for integrating django-structlog with Celery for structured logging of background tasks. ```APIDOC ## Celery Integration (`django_structlog.celery`) ### Description Components for integrating django-structlog with Celery for structured logging of background tasks. ### Classes - `DjangoStructLogInitStep` - `name` (property) ### Functions - `bind_extra_task_metadata` - `modify_context_before_task_publish` - `pre_task_succeeded` ``` -------------------------------- ### Enable Celery Integration in Django Settings Source: https://jrobichaud.github.io/django-structlog/celery.html Add 'django_structlog.middlewares.RequestMiddleware' to your MIDDLEWARE and set DJANGO_STRUCTLOG_CELERY_ENABLED to True in settings.py. ```python MIDDLEWARE = [ # ... 'django_structlog.middlewares.RequestMiddleware', ] DJANGO_STRUCTLOG_CELERY_ENABLED = True ``` -------------------------------- ### Configure foreign_pre_chain for standard loggers Source: https://jrobichaud.github.io/django-structlog/getting_started.html When using standard Python loggers with structlog, add 'foreign_pre_chain' to your formatters and include structlog.contextvars.merge_contextvars to ensure context variables are merged. ```python LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { "json_formatter": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.JSONRenderer(), # Add this section: "foreign_pre_chain": [ structlog.contextvars.merge_contextvars, # <---- add this # customize the rest as you need structlog.processors.TimeStamper(fmt="iso"), structlog.stdlib.add_logger_name, structlog.stdlib.add_log_level, structlog.stdlib.PositionalArgumentsFormatter(), ], }, }, ... } ``` -------------------------------- ### Flat Lines Log Output Source: https://jrobichaud.github.io/django-structlog/example_outputs.html This log format is suitable for simple text-based log analysis. Each log entry is a single line with key-value pairs. ```log timestamp='2019-04-13T19:39:29.321453Z' level='info' event='request_started' logger='django_structlog.middlewares.request' request_id='c53dff1d-3fc5-4257-a78a-9a567c937561' user_id=1 ip='0.0.0.0' request=GET / user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36' timestamp='2019-04-13T19:39:29.345207Z' level='info' event='request_finished' logger='django_structlog.middlewares.request' request_id='c53dff1d-3fc5-4257-a78a-9a567c937561' user_id=1 ip='0.0.0.0' code=200 timestamp='2019-04-13T19:39:31.086155Z' level='info' event='request_started' logger='django_structlog.middlewares.request' request_id='3a8f801c-072b-4805-8f38-e1337f363ed4' user_id=1 ip='0.0.0.0' request=POST /success_task user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36' timestamp='2019-04-13T19:39:31.089925Z' level='info' event='Enqueuing successful task' logger='django_structlog_demo_project.home.views' request_id='3a8f801c-072b-4805-8f38-e1337f363ed4' user_id=1 ip='0.0.0.0' timestamp='2019-04-13T19:39:31.147590Z' level='info' event='task_enqueued' logger='django_structlog.middlewares.celery' request_id='3a8f801c-072b-4805-8f38-e1337f363ed4' user_id=1 ip='0.0.0.0' child_task_id='6b11fd80-3cdf-4de5-acc2-3fd4633aa654' timestamp='2019-04-13T19:39:31.153081Z' level='info' event='This is a successful task' logger='django_structlog_demo_project.taskapp.celery' task_id='6b11fd80-3cdf-4de5-acc2-3fd4633aa654' request_id='3a8f801c-072b-4805-8f38-e1337f363ed4' user_id=1 ip='0.0.0.0' timestamp='2019-04-13T19:39:31.160043Z' level='info' event='request_finished' logger='django_structlog.middlewares.request' request_id='3a8f801c-072b-4805-8f38-e1337f363ed4' user_id=1 ip='0.0.0.0' code=201 timestamp='2019-04-13T19:39:31.162372Z' level='info' event='task_succeed' logger='django_structlog.middlewares.celery' task_id='6b11fd80-3cdf-4de5-acc2-3fd4633aa654' request_id='3a8f801c-072b-4805-8f38-e1337f363ed4' user_id=1 ip='0.0.0.0' result='None' ``` -------------------------------- ### Celery Integration Source: https://jrobichaud.github.io/django-structlog/_sources/api_documentation.rst.txt Components for integrating django-structlog with Celery tasks. ```APIDOC ## Celery Integration ### Description Provides components for structured logging within Celery tasks. ### Classes - `django_structlog.celery.steps.DjangoStructLogInitStep` ``` -------------------------------- ### Enable Celery Integration in Django Settings Source: https://jrobichaud.github.io/django-structlog/_sources/celery.rst.txt Configure your Django settings.py to enable Celery integration by adding the RequestMiddleware and setting DJANGO_STRUCTLOG_CELERY_ENABLED to True. ```python MIDDLEWARE = [ # ... 'django_structlog.middlewares.RequestMiddleware', ] DJANGO_STRUCTLOG_CELERY_ENABLED = True ``` -------------------------------- ### Bind AWS X-Amzn-Trace-Id Source: https://jrobichaud.github.io/django-structlog/how_tos.html Bind the AWS `X-Amzn-Trace-Id` header to the request context for tracing requests through Application Load Balancers. It uses a helper function to retrieve the header. ```python from django.dispatch import receiver from django_structlog import signals from django_structlog.middlewares.request import get_request_header import structlog @receiver(signals.bind_extra_request_metadata) def bind_trace_id(request, logger, **kwargs): trace_id = get_request_header( request, "x-amzn-trace-id", "HTTP_X_AMZN_TRACE_ID" ) if trace_id: structlog.contextvars.bind_contextvars(trace_id=trace_id) ``` -------------------------------- ### Add RequestMiddleware to MIDDLEWARE Source: https://jrobichaud.github.io/django-structlog/getting_started.html Incorporate the RequestMiddleware into your Django project's MIDDLEWARE setting. ```python MIDDLEWARE = [ # ... "django_structlog.middlewares.RequestMiddleware", ] ``` -------------------------------- ### Celery Task Protocol v1 Warning Source: https://jrobichaud.github.io/django-structlog/_sources/celery.rst.txt Note that if you use Celery's task_protocol v1, django-structlog may not be able to transfer metadata to child tasks. ```python app = Celery("your_celery_project", task_protocol=1) ``` -------------------------------- ### Bind AWS X-Amzn-Trace-Id Source: https://jrobichaud.github.io/django-structlog/_sources/how_tos.rst.txt Binds the AWS X-Amzn-Trace-Id header to the request context for tracing requests originating from an Application Load Balancer. ```python from django.dispatch import receiver from django_structlog import signals from django_structlog.middlewares.request import get_request_header import structlog @receiver(signals.bind_extra_request_metadata) def bind_trace_id(request, logger, **kwargs): trace_id = get_request_header( request, "x-amzn-trace-id", "HTTP_X_AMZN_TRACE_ID" ) if trace_id: structlog.contextvars.bind_contextvars(trace_id=trace_id) ```