Logging
Learn how to control and customize logging behavior in ZenML pipelines.
By default, ZenML uses a logging handler to capture two types of logs:
Pipeline run logs: Logs collected from your ZenML client while triggering and waiting for a pipeline to run. These logs cover everything that happens client-side: building and pushing container images, triggering the pipeline, waiting for it to start, and waiting for it to finish. These logs are now stored in the artifact store, making them accessible even after the client session ends.
Step logs: Logs collected from the execution of individual steps. These logs only cover what happens during the execution of a single step and originate mostly from the user-provided step code and the libraries it calls.
For step logs, users are free to use the default python logging module or print statements, and ZenML's logging handler will catch these logs and store them.
import logging
from zenml import step
@step
def my_step() -> None:
logging.warning("`Hello`") # You can use the regular `logging` module.
print("World.") # You can utilize `print` statements as well. All these logs are stored within the respective artifact store of your stack. You can visualize the pipeline run logs and step logs in the dashboard as follows:
Local ZenML server (
zenml login --local): Both local and remote artifact stores may be accessibleDeployed ZenML server: Local artifact store logs won't be accessible; remote artifact store logs require service connector configuration (see remote storage guide)
In order for logs to be visible in the dashboard with a deployed ZenML server, you must configure both a remote artifact store and the appropriate service connector to access it. Without this configuration, your logs won't be accessible through the dashboard.


Logging Configuration
Environment Variables and Remote Execution
For all logging configurations below, note:
Setting environment variables on your local machine only affects local pipeline runs
For remote pipeline runs, you must set these variables in the pipeline's execution environment using Docker settings:
Enabling or Disabling Logs Storage
You can control log storage for both pipeline runs and steps:
Step Logs
To disable storing step logs in your artifact store:
Using the
enable_step_logsparameter with step decorator:Setting the
ZENML_DISABLE_STEP_LOGS_STORAGE=trueenvironment variable in the execution environment:This environment variable takes precedence over the parameter mentioned above.
Pipeline Run Logs
To disable storing client-side pipeline run logs in your artifact store:
Using the
enable_pipeline_logsparameter with pipeline decorator:Using the runtime configuration:
Setting the
ZENML_DISABLE_PIPELINE_LOGS_STORAGE=trueenvironment variable:The environment variable takes precedence over parameters set in the decorator or runtime configuration.
Setting Logging Verbosity
Change the default logging level (INFO) with:
Options: INFO, WARN, ERROR, CRITICAL, DEBUG
For remote pipeline runs:
Setting Console Logging Format
Change the console/stdout logging format with:
Options:
console(default): Human-readable console output. Client-sideINFOlogs use a compact layout, whileDEBUGlogs and server logs use a full structured text layout.json: JSON formatted console/stdout logs.Any other valid Python
%-style logging format string, such as%(asctime)s - %(message)s, for custom console output.
The format must use %-string formatting style. See the available LogRecord attributes. This only changes terminal output; stored logs keep their raw message and structured metadata.
The older ZENML_LOGGING_FORMAT environment variable is deprecated and will be removed in a future version. Use ZENML_CONSOLE_LOGGING_FORMAT instead. Existing configurations such as ZENML_LOGGING_FORMAT='%(asctime)s %(message)s' continue to work during the deprecation period.
The compact client console layout is:
The full structured console layout for DEBUG logs is:
The JSON format emits the same information as fields:
When an exception is logged, the JSON output includes an exception object with the exception type, message, and stack trace.
Adding Structured Fields
ZenML uses Python's standard logging module. If you want to attach structured fields to a log record, use the standard extra argument:
Avoid using Python LogRecord attribute names such as name, message, levelname, filename, or lineno as keys in extra because they are reserved for Python's internal use.
When a custom console format string is configured, ZenML uses that format as-is for console output. It does not append structured extra fields or apply ZenML's default console coloring and highlighting to that custom layout.
Disabling Rich Traceback Output
ZenML uses rich for enhanced traceback display. Disable it with:
Disabling Colorful Logging
Console logs use colors by default. Disable colorful logging with:
Showing Step Names in Logs
ZenML hides step name prefixes in console logs by default. You can show them with:
When enabled, console logs include the step name as a prefix:
These prefixes only appear in console output, not in stored logs. You can disable the step name prefixes in console with:
Limitations
on Steps and pipelines
When running steps and pipelines, ZenML only captures logs emitted from the thread that executes the corresponding function. If your step code spawns additional threads or runs async code, logs from those execution contexts may not be captured.
For instance, only the log emitted directly in the step function is captured:
As a workaround, you can run it under the copied contextvars context so ZenML can associate the log records with the running step:
on the Dashboard
When viewing logs in the dashboard, ZenML currently loads logs in bulk and pagination/filtering happens on the client side. To keep the response size and server memory usage bounded (especially when logs are stored in remote artifact stores), the dashboard is limited to 500 pages (100 log entries per page, i.e. 50,000 entries total) by default.
You can adjust this limit by setting ZENML_LOGS_MAX_ENTRIES_PER_REQUEST in the environment when you are deploying your ZenML workspace.
Downloading logs from the dashboard will also only include up to this limit.
We’re actively working on improving log loading to remove the need for this cap. We'll update the documentation as this evolves with future releases.
Best Practices for Logging
Use appropriate log levels:
DEBUG: Detailed diagnostic informationINFO: Confirmation that things work as expectedWARNING: Something unexpected happenedERROR: A more serious problem occurredCRITICAL: A serious error that may prevent continued execution
Include contextual information in logs
Log at decision points to track execution flow
Avoid logging sensitive information
Use structured logging when appropriate
Configure appropriate verbosity for different environments
See Also
Last updated
Was this helpful?