# Daily Email Summary of New PHP Errors

> Reads new lines in debug.log once a day and emails a short summary of fatal errors, warnings and notices with how often each occurred, so problems do not go unnoticed.

- Type: PHP
- Runs: Run everywhere
- Category: [Email](https://wpide.com/library/category/email/)
- Tags: email, debugging, errors
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/email-daily-php-error-summary/

## Code

```php
$wpide_errors_to = ''; // Recipient; empty = admin email.

add_action( 'init', function () {
    if ( ! wp_next_scheduled( 'wpide_php_error_summary' ) ) {
        wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'wpide_php_error_summary' );
    }
} );

add_action( 'wpide_php_error_summary', function () use ( $wpide_errors_to ) {
    $file = ( defined( 'WP_DEBUG_LOG' ) && is_string( WP_DEBUG_LOG ) && '' !== WP_DEBUG_LOG ) ? WP_DEBUG_LOG : WP_CONTENT_DIR . '/debug.log';

    if ( ! is_readable( $file ) ) {
        return;
    }

    $size   = filesize( $file );
    $offset = (int) get_option( 'wpide_php_error_offset', 0 );
    if ( $offset > $size ) {
        $offset = 0; // The log was rotated or cleared.
    }

    $handle = fopen( $file, 'rb' );
    if ( ! $handle ) {
        return;
    }
    fseek( $handle, $offset );
    $chunk = (string) fread( $handle, MB_IN_BYTES );
    update_option( 'wpide_php_error_offset', ftell( $handle ), false );
    fclose( $handle );

    $counts = array();
    foreach ( preg_split( '/\R/', $chunk ) as $line ) {
        if ( preg_match( '/PHP (Fatal error|Parse error|Warning|Notice|Deprecated):\s*(.+?)( in \/.+? on line \d+)?$/', $line, $m ) ) {
            $key            = $m[1] . ': ' . wp_html_excerpt( $m[2] . ( isset( $m[3] ) ? $m[3] : '' ), 300, '…' );
            $counts[ $key ] = isset( $counts[ $key ] ) ? $counts[ $key ] + 1 : 1;
        }
    }

    if ( ! $counts ) {
        return;
    }

    arsort( $counts );
    $lines = array();
    foreach ( array_slice( $counts, 0, 30, true ) as $message => $count ) {
        $lines[] = sprintf( '%4dx  %s', $count, $message );
    }

    $to = is_email( $wpide_errors_to ) ? $wpide_errors_to : get_option( 'admin_email' );
    wp_mail( $to, sprintf( '[%s] %d distinct PHP error(s) in the last day', wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), count( $counts ) ), implode( "\n", $lines ) );
} );
```

## Notes

Needs WP_DEBUG_LOG enabled, reads at most 1 MB of new log per day and lists the 30 most frequent messages; set the recipient at the top.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Daily Email Summary of New PHP Errors" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
