5.1 KiB
Logging in pydase
The pydase
library organizes its loggers per module, mirroring the Python package hierarchy. This structured approach allows for granular control over logging levels and behaviour across different parts of the library. Logs can also include details about client identification based on headers sent by the client or proxy, providing additional context for debugging or auditing.
Changing the pydase Log Level
You have two primary ways to adjust the log levels in pydase
:
-
Directly targeting
pydase
loggersYou can set the log level for any
pydase
logger directly in your code. This method is useful for fine-tuning logging levels for specific modules withinpydase
. For instance, if you want to change the log level of the mainpydase
logger or target a submodule likepydase.data_service
, you can do so as follows:# <your_script.py> import logging # Set the log level for the main pydase logger logging.getLogger("pydase").setLevel(logging.INFO) # Optionally, target a specific submodule logger # logging.getLogger("pydase.data_service").setLevel(logging.DEBUG) # Your logger for the current script from pydase.utils.logging import configure_logging_with_pydase_formatter configure_logging_with_pydase_formatter(level=logging.DEBUG) logger = logging.getLogger(__name__) logger.debug("My debug message.")
This approach allows for specific control over different parts of the
pydase
library, depending on your logging needs. -
Using the
ENVIRONMENT
environment variableFor a more global setting that affects the entire
pydase
library, you can utilize theENVIRONMENT
environment variable. Setting this variable to"production"
will configure allpydase
loggers to only log messages of level"INFO"
and above, filtering out more verbose logging. This is particularly useful for production environments where excessive logging can be overwhelming or unnecessary.ENVIRONMENT="production" python -m <module_using_pydase>
In the absence of this setting, the default behavior is to log everything of level
"DEBUG"
and above, suitable for development environments where more detailed logs are beneficial.
Client Identification in pydase Logs
The logging system in pydase
includes information about clients based on headers sent by the client or a proxy. The priority for identifying the client is fixed and as follows:
Remote-User
Header: This header is typically set by authentication servers like Authelia. While it can be set manually by users, its primary purpose is to provide client information authenticated through such servers.X-Client-ID
Header: This header is intended for use by Python clients to pass custom client identification information. It acts as a fallback when theRemote-User
header is not available.- Default Socket.IO Session ID: If neither of the above headers is present, the system falls back to the default Socket.IO session ID to identify the client.
For example, a log entries might include the following details based on the available headers:
2025-01-20 06:47:50.940 | INFO | pydase.server.web_server.api.v1.application:_get_value:36 - Client [id=This is me!] is getting the value of 'property_attr'
2025-01-20 06:48:13.710 | INFO | pydase.server.web_server.api.v1.application:_get_value:36 - Client [user=Max Muster] is getting the value of 'property_attr'
Configuring Logging in Services
To configure logging in services built with pydase
, use the helper function [configure_logging_with_pydase_formatter
][pydase.utils.logging.configure_logging_with_pydase_formatter]. This function sets up a logger with the same formatting used internally by pydase
, so your service logs match the style and structure of pydase
logs.
Example
If your service follows a typical layout like:
└── src
└── my_service
├── __init__.py
└── ...
you should call configure_logging_with_pydase_formatter
inside src/my_service/__init__.py
. This ensures the logger is configured as soon as your service is imported, and before any log messages are emitted.
import sys
from pydase.utils.logging import configure_logging_with_pydase_formatter
configure_logging_with_pydase_formatter(
name="my_service", # Use the package/module name or None for the root logger
level=logging.DEBUG, # Set the desired logging level (defaults to INFO)
stream=sys.stderr # Optional: set the output stream (stderr by default)
)
Notes
- If you pass
name=None
, the root logger will be configured. This affects all logs that propagate to the root logger. - Passing a specific
name
like"my_service"
allows you to scope the configuration to your service only, which is safer in multi-library environments. - You can use
sys.stdout
instead ofsys.stderr
if your logs are being captured or processed differently (e.g., in containers or logging systems).