From 01d3fe24891ede33892d4c3f4ac587fe0d453d6b Mon Sep 17 00:00:00 2001 From: MEHRSHAD MIRSHEKARY Date: Fri, 4 Oct 2024 20:24:26 +0330 Subject: [PATCH] :zap::books: docs(rst): Update RST docs to include new features and changes of django_logging --- docs/conf.py | 2 +- docs/contributing.rst | 2 +- docs/index.rst | 16 +- docs/quick_start.rst | 8 +- docs/settings.rst | 187 +++++++++++----- docs/usage.rst | 487 +++++++++++++++++++++++++++++++++++++++--- 6 files changed, 601 insertions(+), 101 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index d734c75..9c92746 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,7 +17,7 @@ author = 'ARYAN NIKNEZHAD, MEHRSHAD-MIRSHEKARY' # The full version, including alpha/beta/rc tags -release = '1.0.0' +release = '2.0.0' master_doc = 'index' diff --git a/docs/contributing.rst b/docs/contributing.rst index bd8b3e9..91041f5 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -82,7 +82,7 @@ Pre-commit hooks are used to automatically check and format code before you make .. code-block:: bash - poetry add --dev pre-commit + poetry add --group dev pre-commit 2. **Set Up the Hooks:** diff --git a/docs/index.rst b/docs/index.rst index a4cd4f1..f510038 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,7 +5,7 @@ Welcome to django_logging Documentation!
-.. image:: https://img.shields.io/github/license/ARYAN-NIKNEZHAD/django_logging +.. image:: https://img.shields.io/github/license/lazarus-org/django_logging :target: https://github.com/lazarus-org/django_logging/blob/main/LICENSE :alt: License @@ -33,19 +33,19 @@ Welcome to django_logging Documentation! :target: https://github.com/pre-commit/pre-commit :alt: pre-commit -.. image:: https://img.shields.io/github/issues/ARYAN-NIKNEZHAD/django_logging +.. image:: https://img.shields.io/github/issues/lazarus-org/django_logging :target: https://github.com/lazarus-org/django_logging/issues :alt: Open Issues -.. image:: https://img.shields.io/github/last-commit/ARYAN-NIKNEZHAD/django_logging +.. image:: https://img.shields.io/github/last-commit/lazarus-org/django_logging :target: https://github.com/lazarus-org/django_logging/commits/main :alt: Last Commit -.. image:: https://img.shields.io/github/languages/top/ARYAN-NIKNEZHAD/django_logging +.. image:: https://img.shields.io/github/languages/top/lazarus-org/django_logging :target: https://github.com/lazarus-org/django_logging :alt: Languages -.. image:: https://img.shields.io/codecov/c/github/ARYAN-NIKNEZHAD/django_logging/main +.. image:: https://img.shields.io/codecov/c/github/lazarus-org/django_logging/main :target: https://codecov.io/gh/lazarus-org/django_logging :alt: Coverage @@ -53,7 +53,11 @@ Welcome to django_logging Documentation! |br| -`django_logging` is a Django package designed to extend and enhance Python’s built-in logging capabilities. By providing customizable configurations and advanced features, it offers developers a comprehensive logging solution tailored specifically for Django applications. +`django_logging` is a powerful yet simple Django package that extends and enhances Python's built-in ``logging`` without relying on any **third-party** libraries. Our goal is to keep things straightforward while providing flexible and customizable logging solutions that are specifically designed for Django applications. + +One of the key advantages of ``django_logging`` is its seamless integration. Get started with django_logging in your existing projects without refactoring any code. Even if you're already using the **default logging setup**, you can instantly upgrade to advanced features with just a simple installation. No extra changes or complicated setup required! + +imagine you have a Django package that was developed a few years ago and already uses Python's built-in ``logging``. Refactoring the entire codebase to use another logging package would be a daunting task. But with ``django_logging``, you don't have to worry about that. Simply install django_logging and enjoy all its advanced features with logging each ``LEVEL`` in separate files with three extra formats (``json``, ``xml``, ``flat``) **without having to make any changes** to your existing code. Supported Versions ------------------ diff --git a/docs/quick_start.rst b/docs/quick_start.rst index 0587774..420818e 100644 --- a/docs/quick_start.rst +++ b/docs/quick_start.rst @@ -15,12 +15,12 @@ Getting Started with `django_logging` is simple. Follow these steps to get up an Add `django_logging` to your ``INSTALLED_APPS`` in your Django settings file: -.. code-block:: +.. code-block:: python INSTALLED_APPS = [ - ... - 'django_logging', - ... + # ... + "django_logging", + # ... ] 3. **Run Your Server** diff --git a/docs/settings.rst b/docs/settings.rst index 02ef085..4f1afb3 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -3,102 +3,168 @@ Settings By default, `django_logging` uses a built-in configuration that requires no additional setup. However, you can customize the logging settings by adding the ``DJANGO_LOGGING`` dictionary configuration to your Django ``settings`` file. -Example configuration +Default configuration --------------------- -here is an example of DJANGO_LOGGING in project settings: .. code-block:: python - DJANGO_LOGGING = { - "AUTO_INITIALIZATION_ENABLE": True, - "INITIALIZATION_MESSAGE_ENABLE": True, - "LOG_FILE_LEVELS": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], - "LOG_DIR": "logs", - "LOG_FILE_FORMATS": { - "DEBUG": 1, - "INFO": 1, - "WARNING": 1, - "ERROR": 1, - "CRITICAL": 1, - }, - "LOG_CONSOLE_LEVEL": "DEBUG", - "LOG_CONSOLE_FORMAT": 1, - "LOG_CONSOLE_COLORIZE": True, - "LOG_DATE_FORMAT": "%Y-%m-%d %H:%M:%S", - "LOG_EMAIL_NOTIFIER": { - "ENABLE": False, - "NOTIFY_ERROR": False, - "NOTIFY_CRITICAL": False, - "LOG_FORMAT": 1, - "USE_TEMPLATE": True, - }, - } - + DJANGO_LOGGING = { + "AUTO_INITIALIZATION_ENABLE": True, + "INITIALIZATION_MESSAGE_ENABLE": True, + "LOG_SQL_QUERIES_ENABLE": True, + "LOG_FILE_LEVELS": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], + "LOG_DIR": "logs", + "LOG_DIR_SIZE_LIMIT": 1024, # MB + "LOG_FILE_FORMATS": { + "DEBUG": 1, + "INFO": 1, + "WARNING": 1, + "ERROR": 1, + "CRITICAL": 1, + }, + "LOG_FILE_FORMAT_TYPES": { + "DEBUG": "normal", + "INFO": "normal", + "WARNING": "normal", + "ERROR": "normal", + "CRITICAL": "normal", + }, + "EXTRA_LOG_FILES": { # for extra formats (JSON, XML) + "DEBUG": False, + "INFO": False, + "WARNING": False, + "ERROR": False, + "CRITICAL": False, + }, + "LOG_CONSOLE_LEVEL": "DEBUG", + "LOG_CONSOLE_FORMAT": 1, + "LOG_CONSOLE_COLORIZE": True, + "LOG_DATE_FORMAT": "%Y-%m-%d %H:%M:%S", + "LOG_EMAIL_NOTIFIER": { + "ENABLE": False, + "NOTIFY_ERROR": False, + "NOTIFY_CRITICAL": False, + "LOG_FORMAT": 1, + "USE_TEMPLATE": True, + }, + } +Configuration Options +--------------------- Here's a breakdown of the available configuration options: ``AUTO_INITIALIZATION_ENABLE`` ------------------------------ -Accepts ``bool``. Enables automatic initialization of logging configurations. Defaults to ``True``. +- **Type**: ``bool`` +- **Description**: Enables automatic initialization of logging configurations. Defaults to ``True``. ``INITIALIZATION_MESSAGE_ENABLE`` --------------------------------- -Accepts ``bool``. Enables logging of the initialization message. Defaults to ``True``. +- **Type**: ``bool`` +- **Description**: Enables logging of the initialization message when logging starts. Defaults to ``True``. + +``LOG_SQL_QUERIES_ENABLE`` +-------------------------- + +- **Type**: ``bool`` +- **Description**: Enables logging of SQL queries within ``RequestLogMiddleware`` logs. Defaults to ``False``. When enabled, SQL queries executed in each request will be included in the log output. ``LOG_FILE_LEVELS`` ------------------- -Accepts a list of valid log levels (a list of ``str`` where each value must be one of the valid levels). Defines the log levels for file logging. Defaults to ``['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']``. +- **Type**: ``list[str]`` +- **Description**: Specifies which log levels should be captured in log files. Defaults to ``["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]``. ``LOG_DIR`` ----------- -Accepts ``str`` like ``"path/to/logs"`` or a path using functions like ``os.path.join()``. Specifies the directory where log files will be stored. Defaults to ``"logs"``. +- **Type**: ``str`` +- **Description**: Specifies the directory where log files will be stored. Defaults to ``"logs"``. + +``LOG_DIR_SIZE_LIMIT`` +---------------------- + +- **Type**: ``int`` +- **Description**: Specifies the maximum allowed size of the log directory in megabytes (MB). If the directory exceeds this limit and ``MonitorLogSizeMiddleware`` is enabled, a warning email will be sent to the admin weekly. Defaults to ``1024 MB`` (1 GB). ``LOG_FILE_FORMATS`` -------------------- -Accepts log levels as keys and format options as values. The format option can be an ``int`` chosen from predefined options or a user-defined format ``str``. Defines the format for log files. Defaults to ``1`` for all levels. +- **Type**: ``dict[str, int | str]`` +- **Description**: Maps each log level to its corresponding log format. The format can be an ``int`` representing predefined formats or a custom ``str`` format. +- **Default**: Format ``1`` for all levels. + +``LOG_FILE_FORMAT_TYPES`` +------------------------- + +- **Type**: ``dict[str, str]`` +- **Description**: Defines the format type (e.g., ``normal``, ``JSON``, ``XML``, ``FLAT``) for each log level. The keys are log levels, and the values are the format types. + + - **Format Types**: + + - ``normal``: Standard text log. + - ``JSON``: Structured logs in JSON format. + - ``XML``: Structured logs in XML format. + - ``FLAT``: logs with Flat format. + +``EXTRA_LOG_FILES`` +------------------- - - **Note**: - See the `Available Format Options`_ below for available formats. +- **Type**: ``dict[str, bool]`` +- **Description**: Determines whether separate log files for ``JSON`` or ``XML`` formats should be created for each log level. When set to ``True`` for a specific level, a dedicated directory (e.g., ``logs/json`` or ``logs/xml``) will be created with files like ``info.json`` or ``info.xml``. if ``False``, json and xml logs will be written to ``.log`` files. +- **Default**: ``False`` for all levels. ``LOG_CONSOLE_LEVEL`` --------------------- -Accepts ``str`` that is a valid log level. Specifies the log level for console output. Defaults to ``'DEBUG'``, +- **Type**: ``str`` +- **Description**: Specifies the log level for console output. Defaults to ``"DEBUG"``. ``LOG_CONSOLE_FORMAT`` ---------------------- -Accepts the same options as ``LOG_FILE_FORMATS``. Defines the format for console output. Defaults to ``1``. +- **Type**: ``int | str`` +- **Description**: Specifies the format for console logs, similar to ``LOG_FILE_FORMATS``. Defaults to format ``1``. ``LOG_CONSOLE_COLORIZE`` ------------------------ -Accepts ``bool``. Determines whether to colorize console output. Defaults to ``True``. +- **Type**: ``bool`` +- **Description**: Determines whether console output should be colorized. Defaults to ``True``. ``LOG_DATE_FORMAT`` ------------------- -Accepts ``str`` that is a valid datetime format. Specifies the date format for log messages. Defaults to ``'%Y-%m-%d %H:%M:%S'``. +- **Type**: ``str`` +- **Description**: Specifies the date format for log messages. Defaults to ``"%Y-%m-%d %H:%M:%S"``. ``LOG_EMAIL_NOTIFIER`` ---------------------- -Is a dictionary where: +- **Type**: ``dict`` +- **Description**: Configures the email notifier for sending log-related alerts. - - ``ENABLE``: Accepts ``bool``. Determines whether the email notifier is enabled. Defaults to ``False``. + - ``ENABLE``: + - **Type**: ``bool`` + - **Description**: Enables or disables the email notifier. Defaults to ``False``. - - ``NOTIFY_ERROR``: Accepts ``bool``. Determines whether to notify on error logs. Defaults to ``False``. + - ``NOTIFY_ERROR``: + - **Type**: ``bool`` + - **Description**: Sends an email notification for ``ERROR`` log level events. Defaults to ``False``. - - ``NOTIFY_CRITICAL``: Accepts ``bool``. Determines whether to notify on critical logs. Defaults to ``False``. + - ``NOTIFY_CRITICAL``: + - **Type**: ``bool`` + - **Description**: Sends an email notification for ``CRITICAL`` log level events. Defaults to ``False``. - - ``LOG_FORMAT``: Accepts the same options as other log formats (``int`` or ``str``). Defines the format for log messages sent via email. Defaults to ``1``. + - ``LOG_FORMAT``: + - **Type**: ``int | str`` + - **Description**: Specifies the log format for email notifications. Defaults to format ``1``. - - ``USE_TEMPLATE``: Accepts ``bool``. Determines whether the email includes an HTML template. Defaults to ``True``. + - ``USE_TEMPLATE``: + - **Type**: ``bool`` + - **Description**: Determines whether the email should include an HTML template. Defaults to ``True``. .. _available_format_options: @@ -111,19 +177,26 @@ The `django_logging` package provides predefined log format options that you can .. code-block:: python FORMAT_OPTIONS = { - 1: "%(levelname)s | %(asctime)s | %(module)s | %(message)s", - 2: "%(levelname)s | %(asctime)s | %(message)s", - 3: "%(levelname)s | %(message)s", - 4: "%(asctime)s - %(name)s - %(levelname)s - %(message)s", - 5: "%(levelname)s | %(message)s | [in %(pathname)s:%(lineno)d]", - 6: "%(asctime)s | %(levelname)s | %(message)s", - 7: "%(levelname)s | %(asctime)s | in %(module)s: %(message)s", - 8: "%(levelname)s | %(message)s | [%(filename)s:%(lineno)d]", - 9: "[%(asctime)s] | %(levelname)s | in %(module)s: %(message)s", - 10: "%(asctime)s | %(processName)s | %(name)s | %(levelname)s | %(message)s", - 11: "%(asctime)s | %(threadName)s | %(name)s | %(levelname)s | %(message)s", - 12: "%(levelname)s | [%(asctime)s] | (%(filename)s:%(lineno)d) | %(message)s", - 13: "%(levelname)s | [%(asctime)s] | {%(name)s} | (%(filename)s:%(lineno)d): %(message)s", + 1: "%(levelname)s | %(asctime)s | %(module)s | %(message)s | %(context)s", + 2: "%(levelname)s | %(asctime)s | %(context)s | %(message)s", + 3: "%(levelname)s | %(context)s | %(message)s", + 4: "%(context)s | %(asctime)s - %(name)s - %(levelname)s - %(message)s", + 5: "%(levelname)s | %(message)s | %(context)s | [in %(pathname)s:%(lineno)d]", + 6: "%(asctime)s | %(context)s | %(levelname)s | %(message)s", + 7: "%(levelname)s | %(asctime)s | %(context)s | in %(module)s: %(message)s", + 8: "%(levelname)s | %(context)s | %(message)s | [%(filename)s:%(lineno)d]", + 9: "[%(asctime)s] | %(levelname)s | %(context)s | in %(module)s: %(message)s", + 10: "%(asctime)s | %(processName)s | %(context)s | %(name)s | %(levelname)s | %(message)s", + 11: "%(asctime)s | %(context)s | %(threadName)s | %(name)s | %(levelname)s | %(message)s", + 12: "%(levelname)s | [%(asctime)s] | %(context)s | (%(filename)s:%(lineno)d) | %(message)s", + 13: "%(levelname)s | [%(asctime)s] | %(context)s | {%(name)s} | (%(filename)s:%(lineno)d): %(message)s", + 14: "[%(asctime)s] | %(levelname)s | %(context)s | %(name)s | %(module)s | %(message)s", + 15: "%(levelname)s | %(context)s | %(asctime)s | %(filename)s:%(lineno)d | %(message)s", + 16: "%(levelname)s | %(context)s | %(message)s | [%(asctime)s] | %(module)s", + 17: "%(levelname)s | %(context)s | [%(asctime)s] | %(process)d | %(message)s", + 18: "%(levelname)s | %(context)s | %(asctime)s | %(name)s | %(message)s", + 19: "%(levelname)s | %(asctime)s | %(context)s | %(module)s:%(lineno)d | %(message)s", + 20: "[%(asctime)s] | %(levelname)s | %(context)s | %(thread)d | %(message)s", } You can reference these formats by their corresponding **integer keys** in your logging configuration settings. diff --git a/docs/usage.rst b/docs/usage.rst index 6b7d82a..2b613fe 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -22,25 +22,6 @@ Basic Logging Usage These logs will be handled according to the configurations set up by `django_logging`, using either the default settings or any custom settings you've provided. -Request Logging Middleware --------------------------- - - To capture and log information of each request to the server, such as the ``request path``, ``user``, ``IP address`` and ``user agent``, add ``django_logging.middleware.RequestLogMiddleware`` to your ``MIDDLEWARE`` setting: - - .. code-block:: - - MIDDLEWARE = [ - ... - 'django_logging.middleware.RequestLogMiddleware', - ... - ] - - This middleware will log the request details at ``INFO`` level, here is an example with default format: - - .. code-block:: text - - INFO | 'datetime' | django_logging | Request Info: (request_path: /example-path, user: example_user, - IP: 192.168.1.1, user_agent: Mozilla/5.0) Context Manager --------------- @@ -109,20 +90,9 @@ Log and Notify Utility Additionally, ensure that all required email settings are configured in your Django settings file. - **Note**: For more detailed configuration options, refer to the :doc:`Settings `. -Send Logs Command +Execution Tracker ----------------- - To send the entire log directory to a specified email address, use the ``send_logs`` management command: - - .. code-block:: shell - - python manage.py send_logs example@domain.com - - This command will attach the log directory and send a zip file to the provided email address. - -Execution Tracker Decorator ---------------------------- - The ``execution_tracker`` decorator is used to log the performance metrics of any function. It tracks execution time and the number of database queries for decorated function (if enabled). Example Usage: @@ -159,7 +129,7 @@ Example Usage: INFO | 'datetime' | execution_tracking | Performance Metrics for Function: 'some_function' Module: some_module File: /path/to/file.py, Line: 123 - Execution Time: 0 minute(s) and 0.2132 second(s) + Execution Time: 0.21 second(s) Database Queries: 15 queries (exceeds threshold of 10) If `log_queries` is set to ``True`` but ``DEBUG`` is ``False``, a ``WARNING`` will be logged: @@ -169,4 +139,457 @@ If `log_queries` is set to ``True`` but ``DEBUG`` is ``False``, a ``WARNING`` wi WARNING | 'datetime' | execution_tracking | DEBUG mode is disabled, so database queries are not tracked. To include the number of queries, set ``DEBUG`` to ``True`` in your Django settings. +Request Logging Middleware +-------------------------- + +The ``django_logging.middleware.RequestLogMiddleware`` is a middleware that logs detailed information about each incoming request to the server. It is capable of handling both synchronous and asynchronous requests. + +To enable this middleware, add it to your Django project's ``MIDDLEWARE`` setting: + +.. code-block:: python + + MIDDLEWARE = [ + # ... + "django_logging.middleware.RequestLogMiddleware", + # ... + ] + +Key Features +^^^^^^^^^^^^ + +1. **Request Information Logging**: + - Logs the following details at the start of each request: + + - Request method + - Request path + - Query parameters + - Referrer (if available) + + - Example log at request start: + + .. code-block:: text + + INFO | 2024-10-03 16:29:47 | request_middleware | REQUEST STARTED: + method=GET + path=/admin/ + query_params=None + referrer=http://127.0.0.1:8000/admin/login/?next=/admin/ + | {'ip_address': '127.0.0.1', 'request_id': '09580021-6bff-4b82-99b5-c52406b2cc91', + 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'} + +2. **Response Information Logging**: + - Logs the following details after the request is processed: + + - User (or 'Anonymous' if not authenticated) + - HTTP Status code + - Content type + - Time taken to process the request + - Optionally logs SQL queries executed during the request (if enabled) + + - Example log at request completion: + + .. code-block:: text + + INFO | 2024-10-03 16:29:47 | request_middleware | REQUEST FINISHED: + user=[mehrshad (ID:1)] + status_code=200 + content_type=[text/html; charset=utf-8] + response_time=[0.08 second(s)] + 3 SQL QUERIES EXECUTED + Query1={'Time': 0.000(s), 'Query': + [SELECT "django_session"."session_key", "django_session"."session_data", "django_session"."expire_date" FROM "django_session" + WHERE ("django_session"."expire_date" > '2024-10-03 12:59:47.812918' AND "django_session"."session_key" = 'uq0nrbglazfm4cy656w3451xydfirh45') LIMIT 21]} + + Query2={'Time': 0.001(s), 'Query': + [SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user". + "username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user". + "is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 1 LIMIT 21]} + + | {'ip_address': '127.0.0.1', 'request_id': '09580021-6bff-4b82-99b5-c52406b2cc91', + 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'} + + +3. **Request ID**: + - A unique request ID is generated for each request (or taken from the ``X-Request-ID`` header if provided). This request ID is included in logs and can help with tracing specific requests. + +4. **SQL Query Logging**: + - If SQL query logging is enabled, all queries executed during the request will be logged along with their execution time. + + **Note**: to enable Query logging, you can set ``LOG_SQL_QUERIES_ENABLE`` to ``True`` in settings. for more details, refer to the :doc:`Settings `. + +5. **Streaming Response Support**: + - The middleware supports both synchronous and asynchronous streaming responses, logging the start and end of the streaming process, as well as any errors during streaming. + +6. **User Information**: + - Logs the authenticated user's username and ID if available, or 'Anonymous' if the user is not authenticated. + +7. **IP Address and User-Agent**: + - The middleware logs the client's IP address and user agent for each request. + + +Context Variables Usage +^^^^^^^^^^^^^^^^^^^^^^^^ + +We use context variables in ``RequestLogMiddleware`` to store the following information for each request: + +- **request_id**: A unique identifier for the request. +- **ip_address**: The client’s IP address. +- **user_agent**: The client's user agent string. + +These context variables can be accessed and used in other parts of the logging system or during the request processing lifecycle. + +MonitorLogSizeMiddleware +------------------------ + +This middleware monitors the size of the log directory and checks it weekly. +It triggers the ``logs_size_audit`` management command to assess the total size of the log files. +If the log directory size exceeds a certain limit (``LOG_DIR_SIZE_LIMIT``), the middleware sends a warning email to the ``ADMIN_EMAIL`` asynchronously. + +To enable this middleware, add it to your Django project's ``MIDDLEWARE`` setting: + +.. code-block:: python + + MIDDLEWARE = [ + # ... + "django_logging.middleware.MonitorLogSizeMiddleware", + # ... + ] + + + +Context Variable Management +--------------------------- + +``django_logging`` includes a powerful ``ContextVarManager`` class, allowing you to manage context variables dynamically within your logging system. These variables are bound to the current context and automatically included in your log entries via the ``%(context)s`` placeholder in the log format. + +Binding and Unbinding Context Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``ContextVarManager`` provides several methods to manage context variables efficiently: + +``bind(**kwargs)`` +~~~~~~~~~~~~~~~~~~ + +The ``bind`` method allows you to bind key-value pairs as context variables that will be available during the current context. These variables can be used to add contextual information to log entries. + +**Example**: + +.. code-block:: python + + from django_logging.contextvar import manager + import logging + + logger = logging.getLogger(__name__) + + # Binding context variables + manager.bind(user="test_user", request_id="abc123") + + logger.info("Logging with context") + +**Log Output**: + +.. code-block:: text + + INFO | 2024-10-03 12:00:00 | Logging with context | {'user': 'test_user', 'request_id': 'abc123'} + +``unbind(key: str)`` +~~~~~~~~~~~~~~~~~~~~ + +The ``unbind`` method removes a specific context variable by its key. It effectively clears the context variable from the log entry. + +**Example**: + +.. code-block:: python + + manager.unbind("user") + + logger.info("Logging without the 'user' context") + +**Log Output**: + +.. code-block:: text + + INFO | 2024-10-03 12:05:00 | Logging without the 'user' context | {'request_id': 'abc123'} + +Batch Binding and Resetting Context Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``batch_bind(**kwargs)`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``batch_bind`` method binds multiple context variables at once and returns tokens that can be used later to reset the variables to their previous state. This is useful when you need to bind a group of variables temporarily. + +**Example**: + +.. code-block:: python + + tokens = manager.batch_bind(user="admin_user", session_id="xyz789") + + logger.info("Logging with batch-bound context") + +**Log Output**: + +.. code-block:: text + + INFO | 2024-10-03 12:10:00 | Logging with batch-bound context | {'user': 'admin_user', 'session_id': 'xyz789'} + +``reset(tokens: Dict[str, contextvars.Token])`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``reset`` method allows you to reset context variables to their previous state using tokens returned by ``batch_bind``. + +**Example**: + +.. code-block:: python + + manager.reset(tokens) + + logger.info("Context variables have been reset") + +**Log Output**: + +.. code-block:: text + + INFO | 2024-10-03 12:15:00 | Context variables have been reset | + +``clear()`` +~~~~~~~~~~~ + +The ``clear`` method clears all bound context variables at once, effectively removing all contextual data from the log entry. + +**Example**: + +.. code-block:: python + + manager.clear() + + logger.info("All context variables cleared") + +**Log Output**: + +.. code-block:: text + + INFO | 2024-10-03 12:20:00 | All context variables cleared | + +Retrieving and Merging Context Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``get_contextvars()`` +~~~~~~~~~~~~~~~~~~~~~ + +The ``get_contextvars`` method retrieves the current context variables available in the context. This method is useful for inspecting or debugging the context. + +**Example**: + +.. code-block:: python + + current_context = manager.get_contextvars() + print(current_context) # Output: {'user': 'admin_user', 'session_id': 'xyz789'} + +``merge_contexts(bound_context: Dict[str, Any], local_context: Dict[str, Any])`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``merge_contexts`` method merges two dictionaries of context variables, giving priority to the ``bound_context``. This is useful when you want to combine different sources of context data. + +**Example**: + +.. code-block:: python + + bound_context = {"user": "admin_user"} + local_context = {"request_id": "12345"} + + merged_context = manager.merge_contexts(bound_context, local_context) + print(merged_context) # Output: {'user': 'admin_user', 'request_id': '12345'} + +``get_merged_context(bound_logger_context: Dict[str, Any])`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``get_merged_context`` method combines the bound logger context with the current context variables, allowing you to retrieve a single dictionary with all the context data. + +**Example**: + +.. code-block:: python + + bound_logger_context = {"app_name": "my_django_app"} + + merged_context = manager.get_merged_context(bound_logger_context) + print(merged_context) # Output: {'app_name': 'my_django_app', 'user': 'admin_user'} + +Scoped Context Management +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``scoped_context(**kwargs)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``scoped_context`` method provides a context manager to bind context variables temporarily for a specific block of code. After the block completes, the context variables are automatically unbound. + +**Example**: + +.. code-block:: python + + with manager.scoped_context(transaction_id="txn123"): + logger.info("Scoped context active") + + logger.info("Scoped context no longer active") + +**Log Output**: + +.. code-block:: text + + INFO | 2024-10-03 12:30:00 | Scoped context active | {'transaction_id': 'txn123'} + INFO | 2024-10-03 12:30:10 | Scoped context no longer active | + + +send_logs Command +----------------- + +This Django management command zips the log directory and emails it to a specified email address. The command is useful for retrieving logs remotely and securely, allowing administrators to receive log files via email. + +Key Features +^^^^^^^^^^^^ + +- **Zips Log Directory**: Automatically compresses the log directory into a single zip file. +- **Email Log Files**: Sends the zipped log file to a specified email address. + +How It Works +^^^^^^^^^^^^ + +1. **Setup Log Directory**: The command retrieves the log directory from Django settings (``DJANGO_LOGGING['LOG_DIR']``). +2. **Zip the Logs**: Compresses the entire log directory into a zip file stored in a temporary location. +3. **Email the Zip File**: Sends the zipped log file to the email address provided as an argument, attaching it to an email message. +4. **Cleanup**: After sending the email, the temporary zip file is deleted to free up disk space. + +Command Execution +^^^^^^^^^^^^^^^^^ + +To execute the command, use the following syntax: + +.. code-block:: shell + + python manage.py send_logs + +Example +^^^^^^^ + +If you want to send the logs to `admin@example.com`, the command would be: + +.. code-block:: shell + + python manage.py send_logs admin@example.com + +This will zip the log directory and send it to `admin@example.com` with the subject "Log Files". + + +generate_pretty_json Command +---------------------------- + +This Django management command allows you to locate and prettify JSON log files stored in a log directory that generated by ``django_logging``. It takes JSON files from the log directory, formats them into a clean, readable structure, and saves the result in the ``pretty`` directory. + +Key Features +^^^^^^^^^^^^ + +- **Locate JSON Logs**: Automatically finds ``.json`` files in the `json` log directory. +- **Pretty Formatting**: Reformats the JSON logs into a valid JSON array with proper indentation, improving readability. +- **Separate Output Directory**: Saves the reformatted JSON files in a ``pretty`` subdirectory, preserving the original files. + +How It Works +^^^^^^^^^^^^ + +1. **Setup Directories**: The command looks for a ``json`` subdirectory within your defined log directory. If it doesn't exist, an error is displayed. +2. **Process JSON Files**: Each `.json` file found in the directory is processed: + - Parses multiple JSON objects within the file. + - Reformats them as a pretty JSON array with proper indentation. + - Saves the new, formatted JSON in the ``pretty`` subdirectory with the prefix ``formatted_``. + +Command Execution +^^^^^^^^^^^^^^^^^ + +To execute the command, use the following syntax: + +.. code-block:: bash + + python manage.py generate_pretty_json + +Example +^^^^^^^ + +Running the command will process the following files: + +- ``logs/json/error.json`` ➡ ``logs/json/pretty/formatted_error.json`` +- ``logs/json/info.json`` ➡ ``logs/json/pretty/formatted_info.json`` + + +generate_pretty_xml Command +--------------------------- + +This Django management command allows you to locate and reformat XML log files stored in a log directory generated by ``django_logging``. It processes XML files by wrapping their content in a `` element and saves the reformatted files in a separate directory. + +Key Features +^^^^^^^^^^^^ + +- **Locate XML Logs**: Automatically finds ``.xml`` files in the ``xml`` log directory. +- **Reformatting**: Wraps XML content in a `` element, ensuring consistency in structure. +- **Separate Output Directory**: Saves the reformatted XML files in a ``pretty`` subdirectory with the prefix ``formatted_``, preserving the original files. + +How It Works +^^^^^^^^^^^^ + +1. **Setup Directories**: The command looks for an ``xml`` subdirectory within your defined log directory. If it doesn't exist, an error is displayed. +2. **Process XML Files**: Each `.xml` file found in the directory is processed: + - The content of each XML file is wrapped inside a `` element. + - The reformatted file is saved in the ``pretty`` subdirectory with the prefix ``formatted_``. + +Command Execution +^^^^^^^^^^^^^^^^^ + +To execute the command, use the following syntax: + +.. code-block:: bash + + python manage.py generate_pretty_xml + +Example +^^^^^^^ + +Running the command will process the following files: + +- ``logs/xml/error.xml`` ➡ ``logs/xml/pretty/formatted_error.xml`` +- ``logs/xml/info.xml`` ➡ ``logs/xml/pretty/formatted_info.xml`` + + +logs_size_audit Command +-------------------------- + +This Django management command monitors the size of your log directory. If the total size exceeds the configured limit, the command sends a warning email notification to the admin. The size check helps maintain log storage and prevent overflow by ensuring administrators are informed when logs grow too large. + +Key Features +^^^^^^^^^^^^ + +- **Log Directory Size Check**: Automatically calculates the total size of the log directory. +- **Configurable Size Limit**: Compares the total size of the log directory against a configured limit. +- **Email Notification**: Sends an email warning to the administrator when the log size exceeds the defined limit. + +How It Works +^^^^^^^^^^^^ + +1. **Setup Log Directory**: The command retrieves the log directory from Django settings, specifically `DJANGO_LOGGING['LOG_DIR']` or the Default. If the directory doesn't exist, an error is logged and displayed. +2. **Calculate Directory Size**: It calculates the total size of the files in the log directory. +3. **Compare with Size Limit**: The command compares the total directory size (in MB) with the configured size limit, which can be configured as ``LOG_DIR_SIZE_LIMIT`` in settings. +4. **Send Warning Email**: If the directory size exceeds the configured limit, the command sends a warning email to the admin, detailing the current log size. + +Command Execution +^^^^^^^^^^^^^^^^^ + +To execute the command, use the following syntax: + +.. code-block:: bash + + python manage.py logs_size_audit + +Example +^^^^^^^ + +Running the command when the log directory exceeds the size limit will trigger an email to the administrator: +- Example log size: ``1200 MB`` (limit: ``1024 MB``) +- An email will be sent to ``ADMIN_EMAIL`` configured in Django settings.