docs/best-practices/data-management/logging.md
WooCommerce has its own robust system for logging, which can be used for debugging during development, catching errors on production, or even sending notifications when specific events occur. By default, WooCommerce uses this logger to record errors, warnings, and other notices that may be useful for troubleshooting problems with a store. Many extensions for WooCommerce also make use of the logger for similar purposes.
You can view the entries created by the logger by going to WooCommerce > Status > Logs. The log viewing interface depends on which log storage method is configured (see the "Configuring the logger" section below).
With the default file system storage method, the first thing you will see is the list of existing log files:
The name of a log file is based on the source of the entries it contains (meaning the extension or the part of the WooCommerce codebase), as well as the date the entries were generated. In this file browsing view, you can sort the files in different ways as well as filtering them to show only those from a specific source. Clicking on a file will take you to a single file view, where you can see the actual log entries:
Click on a line number in the file to highlight it. This can also be used to link to a specific line in a file from elsewhere.
From the file browser view, you can sort and filter a list of log files, and then search for a string within the contents of those files:
Clicking on a search result line number will take you to that line in the single file view.
With the database storage method, you will see a list of log entries, starting with the most recent:
These entries can be sorted by timestamp, level, and source, as well as filtered to only show a particular source or a minimum level. You can also search for a string within the log entry message fields.
From the Logs screen at WooCommerce > Status > Logs, click the "Settings" link to make configuration changes:
Uncheck the box here to turn off all logging. This is not recommended in most circumstances, as logging can provide valuable information about what is happening on your site!
Out-of-the-box, WooCommerce has two different log storage methods available:
source value for the log entry (see the "Adding logs" section below), and by the current date. The files are stored in the wc-logs subdirectory of the site's uploads directory. A custom directory can be defined using the woocommerce_log_directory filter hook. Log files can be up to 5 MB in size, after which the log file will rotate.{$wpdb->prefix}woocommerce_log table.If you change this setting, and you already have some log entries, those entries will not be migrated to the other storage method, but neither will they be deleted.
The logger will periodically go through and delete logs that are older than this time period, as a space-saving measure. If log entries are stored in the file system, the entire log file that is beyond the retention period will be deleted, while with database storage, individual log entries will be deleted.
Each log entry has a severity level (see the "Adding logs" section below). This sets a minimum severity level, and any log entries that are generated that are not at or above the minimum level will not be recorded. Use this setting with caution!
If this setting is set to "None", it means that all log entries will be recorded, regardless of severity level.
Logs are added via methods in the WC_Logger class. The class instance is accessed by using the wc_get_logger() function. The basic method for adding a log entry is WC_Logger::log( $level, $message, $context ). There are also shortcut methods for each log severity level, for example WC_Logger::warning( $message, $context ). It is preferable to use the shortcut methods rather than the generic log method.
Logs have eight different severity levels:
emergencyalertcriticalerrorwarningnoticeinfodebugAside from giving a site owner context as to how important a log entry is, these levels also allow logs to be filtered. If you only want log entries to be recorded for error severity and higher, you can set the threshold on the Logs Settings screen (see the "Configuring the logger" above).
Note that this threshold will apply to all logs, regardless of which log handler is in use. The WC_Log_Handler_Email class, for example, has its own threshold setting, but it is secondary to the global threshold.
The message is the main content of a log entry. Make sure it's understandable by anyone who might be viewing the logs!
The context parameter is intended to be used to store additional structured data related to the log entry. For example, in a log entry about an order, you may want to include contents of the related order object. When the logger is generating an entry, the data in the context parameter is converted to JSON before it is stored. So, if you want to add multiple pieces of context data, each should be added as a separate key within the context array.
There are two specific keys that can be added to the context array that will cause special behavior:
sourceIt is recommended that every log entry include a source value in the context parameter. source is intended to provide context about where in the application or codebase the log was generated, and can be used to filter log entries.
If a source is not specified, the logger will generate a source value based on the plugin or file where the log entry was generated.
backtraceSetting the backtrace key in your context parameter to true will cause the logger to generate a backtrace (i.e. stack trace) in array format, which will be included in the context in place of the true value. This is useful particularly for error-related logs, so you can see what code was executed that led to the log entry being generated.
wc_get_logger()->info(
'It is time for lunch.',
array(
'source' => 'your_stomach',
'backtrace' => true,
'previous_meal' => $elapsed_time_since_breakfast,
'lunch_options' => array( 'fridge leftovers', 'bahn mi', 'tacos', 'pupusas' ),
)
);
wc_doing_it_wrong()).WC_Logger's log() method directly, it's better to use one of the wrapper methods that's specific to the log level. E.g. info() or error().The WC_Logger class can be substituted for another class via the woocommerce_logging_class filter hook. The alternative class must implement WC_Logger_Interface, or it will not be used. Generally it is better to create a custom log handler (see below) rather than overriding the logger class itself.
In WooCommerce, a log handler is a PHP class that takes the raw log data and transforms it into a log entry that can be stored or dispatched. WooCommerce ships with four different log handler classes:
Automattic\\WooCommerce\\Internal\\Admin\\Logging\\LogHandlerFileV2: This is the default handler, representing the "file system" log storage method. It records log entries to files.WC_Log_Handler_File: This is the old default handler that also records log entries to files. It may be deprecated in the future, and it is not recommended to use this class or extend it.WC_Log_Handler_DB: This handler represents the "database" log storage method. It records log entries to the database.WC_Log_Handler_Email: This handler does not store log entries, but instead sends them as email messages. Emails are sent to the site admin email address. This handler has some limitations.To switch from the file handler to the database handler, you can simply update the option on the Logs Settings screen. However, in some cases, you may want to have more than one log handler, and/or you might want to modify the settings of a handler. For example, you may want to have most logs saved to files, but log entries that are classified as emergency or critical errors also sent to an email address. For this, you can use the woocommerce_register_log_handlers filter hook to create an array of log handler class instances that you want to use. Some handler class constructors have optional parameters that you can use when instantiating the class to change their default behavior.
Here's an example of adding the email handler:
function my_wc_log_handlers( $handlers ) {
$recipients = array( '[email protected]', '[email protected]' ); // Send logs to multiple recipients.
$threshold = 'critical'; // Only send emails for logs of this level and higher.
$handlers[] = new WC_Log_Handler_Email( $recipients, $threshold );
return $handlers;
}
add_filter( 'woocommerce_register_log_handlers', 'my_wc_log_handlers' );
You may want to create your own log handler class in order to send logs somewhere else, such as a Slack channel or perhaps an InfluxDB instance. Your class must extend the WC_Log_Handler abstract class and implement the WC_Log_Handler_Interface interface. The WC_Log_Handler_Email handler class provides a good example of how to set this up.
When using the "file system" log handler, by default the log files are stored in the wc-logs subdirectory of the WordPress uploads directory, which means they might be publicly accessible. WooCommerce adds an .htaccess file to prevent access to wc-logs, but not all web servers recognize that file. If you have the option, you may want to consider storing your log files in a directory outside of the web root. Make sure the directory has the same user/group permissions as the uploads directory so that WordPress can access it. Then use the woocommerce_log_directory filter hook to set the path to your custom directory.
If there is a particular log that is recurring frequently and clogging up your log files, you should probably figure out why it keeps getting triggered and resolve the issue. However, if that's not possible, you can add a callback to the woocommerce_logger_log_message filter hook to ignore that particular log while still allowing other logs to get through:
function my_ignored_logs( $message, $level, $context, $handler ) {
if ( false !== strpos( $message, 'Look, a squirrel!' ) ) {
return null;
}
return $message;
}
add_filter( 'woocommerce_logger_log_message', 'my_ignored_logs', 10, 4 );
If you create a custom log handler and you want to build a separate interface for it on the Logs screen, there are a couple of filter hooks that you can work with:
woocommerce_logger_handler_options: This filter hook allows you to add your custom log handler to the list of "Log storage" options on the Settings screen. Your handler must be selected for this setting, making it the "default" log handler, before you can render an alternative interface for it.wc_logs_render_page: This is the action to hook into for rendering your own Logs interface. It only fires if the default log handler is set to something that is not one of the built-in handlers.wc_logs_load_tab: This action fires when the Logs tab first starts loading, before any content is output. It's useful for handling form submissions.