In part 3 of this article series we looked at how to debug possible errors in your development environment. Now let’s talk about logging in production. The most famous WordPress log file is of course the debug.log which can be turned off and on with a setting in the wp-config.php but in a common WordPress & WooCommerce setup, you might be doing some excessive logging in places and of data you will never need.

Here’s a list of common logs:

  • Nginx (or Apache) Access log
  • Nginx (or Apache) Error log
  • WordPress debug.log
  • WooCommerce Error log
  • Payment Gateways Transaction and API logs to log files or the database
  • other Plugins log files or database logs
  • Website crawlers and system agents used for SEO and performance monitoring (APM)

These are the main areas and types of logs one can usually find in a WordPress & WooCommerce store. There could be more logging going on when you add third party providers such as APM tools like New Relic or Nginx Amplify, Logging Providers like Loggly or DataDog.
Even external tools that consume your servers resources for SEO Analysis and other Crawling Tools could and should be considered to being log tools, since they visualize certain aspects and data sets of your store over time. Even Security and CSP monitoring tools like Rapidsec are using your servers resources and establish TCP connections.

In general, all of these logs either write to physical files or to database tables or even establish TCP connections to communicate with external servers. Ans all of these are relatively slow compared to an in-memory storage such as a Redis Database or OPCache for example.

So in production we want to stick to a bare minimum of these slow writes. Eliminate everything you don’t need but keep in mind that you might need something in the future you’re not thinking of today.

Some rules of thumb:

  • Either disable access logs completely or at least disable access logs for static assets such as images, css, js files
  • Disable error logs for Deprecations, Warnings and Notices in production. If you’re doing things right and work on the same nginx and PHP versions locally as on your production servers, you can eliminate those notices and warnings locally just by testing your code thoroughly on dev or staging. There’s no need to fill up production logs with stuff you can fix before deploying code.
  • In Ecommerce everything related to payments, orders, and warehouse updated should be logged to a database because that makes data searchable, visualisable, in short: usable.
  • Move logs to a single location to avoid clutter and wasting time searching appropriate files.

Disabling access.log

/etc/nginx/sites-available/website.confserver {    listen          80;    ...    # Logging    access_log      off;                            # turn access log off completely    log_not_found   off;                            # log requests to non existing URIs?    error_log       /var/log/nginx/error.log error;  # turn on error logs}

Alternatively, you can use the access_log directive inside a http, server or location block, too either turn it on/off. So if you only want to disable access logs for some specific file types, you can do so in the location block:

/etc/nginx/sites-available/website.confserver {    listen          80;    ...    # Logging    access_log              /var/log/nginx/access.log combined;    error_log               /var/log/nginx/error.log error;     # robots.txt    location = /robots.txt {        log_not_found off;        access_log    off;    }    # static CSS/JS    location ~ \.(css|htc|less|js|js2|js3|js4)$ {        log_not_found off;        access_log off;    }    # static text    location ~ \.(html|htm|rtf|rtx|svg|txt|xsd|xsl|xml)$ {        log_not_found off;        access_log off;    }    # assets, media    location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {        log_not_found off;        access_log off;    }    # svg, fonts    location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {        log_not_found off;        access_log off;    }}

Log less in the error.log

As you can see in the example above, you can raise the error severity of Nginx errors from warn to error.

/etc/nginx/sites-available/website.confserver {    ...    error_log       /var/log/nginx/error.log error;  # default severity is warn, we use error!}

For PHP we want to do something similar. We want to log errors and errors only, so let’s go further than the default value and also exclude warnings and notices.

/etc/php/8.0/fpm/php.inierror_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE & ~E_WARNING

If you cannot edit your php.ini you set and override the php setting at runtime:

wordpress/wp-config.php@ini_set('display_errors', '0');@ini_set('display_startup_errors', '0');error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE & ~E_WARNING); // log errors only

The debug.log

wordpress/wp-config.phpif (WORDPRESS_ENV === 'development' || WORDPRESS_ENV === 'staging') {    define('WP_DEBUG', true);    define('WP_DEBUG_LOG', '/var/log/nginx/debug.log');    define('WP_DEBUG_DISPLAY', true);    define('WC_LOG_PATH', realpath('/../log') . '/'); // WooCommerce logs outside document root    define('SAVEQUERIES', true);    define('SCRIPT_DEBUG', true);    define('DIEONDBERROR', true);    define('WP_DISABLE_FATAL_ERROR_HANDLER', true);}if (WORDPRESS_ENV === 'production') {    define('WP_DEBUG', false); // this turns off debug.log and WooCommerce logs    define('WP_DEBUG_DISPLAY', false);    define('SAVEQUERIES', false);    define('SCRIPT_DEBUG', false);    define('DIEONDBERROR', false);}

Both WordPress and WooCommerce use application-wide constants to determine the path where log files ought to be stored. As you can see, for development and staging we define a specific path for our debug.log and it’s the same folder Nginx logs to. So we have one unique path – outside of the document root for increased security.