samsonasik / ErrorHeroModule

:gem: A Hero for your ZF2, ZF3, and ZF Expressive application to log ( DB and Mail ) and handle php errors & exceptions during Mvc process/between request and response


ErrorHeroModule

Latest Version Build Status Coverage Status PHPStan Downloads

Introduction

ErrorHeroModule is a module for Error Logging (DB and Mail) your ZF2, ZF3 Mvc Application, and ZF Expressive for Exceptions in 'dispatch.error' or 'render.error' or during request and response, and PHP E_* Error.

Features

  • [x] Save to DB with Db Writer Adapter.
  • [x] Log Exception (dispatch.error and render.error) and PHP Errors in all events process.
  • [x] Support excludes PHP E_* Error (eg: exclude E_USER_DEPRECATED) in config settings.
  • [x] Handle only once log error for same error per configured time range.
  • [x] Set default page (web access) or default message (console access) for error if configured 'display_errors' = 0.
  • [x] Set default content when request is XMLHttpRequest via 'ajax' configuration.
  • [x] Provide request information ( http method, raw data, query data, files data ).
  • [x] Send Mail
    • [x] many receivers to listed configured email
    • [x] with include $_FILES into attachments on upload error.

Installation

1. Import the following SQL for Mysql

DROP TABLE IF EXISTS `log`;

CREATE TABLE `log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `type` int(11) NOT NULL,
  `event` text NOT NULL,
  `url` varchar(2000) NOT NULL,
  `file` varchar(2000) NOT NULL,
  `line` int(11) NOT NULL,
  `error_type` varchar(255) NOT NULL,
  `trace` text NULL,
  `request_data` text NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

If you use other RDBMS, you may follow the log table structure above.

2. Setup your Zend\Db\Adapter\Adapter service or your Doctrine\ORM\EntityManager service config

You can use 'db' (with Zend\Db) config or 'doctrine' (with DoctrineORMModule) config that will be converted to be usable with Zend\Log\Writer\Db.

<?php
// config/autoload/local.php
return [
    'db' => [
        'username' => 'mysqluser',
        'password' => 'mysqlpassword',
        'driver'   => 'pdo_mysql',
        'database' => 'mysqldbname',
        'host'     => 'mysqlhost',
        'driver_options' => [
            PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
        ],
    ],      
];

OR

<?php
// config/autoload/local.php
return [
    'doctrine' => [
        'connection' => [
            'orm_default' => [
                'driverClass' =>'Doctrine\DBAL\Driver\PDOMySql\Driver',
                'params' => [
                    'user'     => 'mysqluser',
                    'password' => 'mysqlpassword',
                    'dbname'   => 'mysqldbname',
                    'host'     => 'mysqlhost',
                    'port'     => '3306',
                    'driverOptions' => [
                        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
                    ],
                ],
            ],
        ],
    ]
];

If you use other RDBMS, you may configure your own db or doctrine config.

3. Require this module uses composer.

composer require samsonasik/error-hero-module

4. Copy config

a. For ZF2/ZF3 Mvc application, copy error-hero-module.local.php.dist config to your local's autoload and configure it

source destination
vendor/samsonasik/error-hero-module/config/error-hero-module.local.php.dist config/autoload/error-hero-module.local.php

Or run copy command:

cp vendor/samsonasik/error-hero-module/config/error-hero-module.local.php.dist config/autoload/error-hero-module.local.php

b. For ZF Expressive application, copy expressive-error-hero-module.local.php.dist config to your local's autoload and configure it

source destination
vendor/samsonasik/error-hero-module/config/expressive-error-hero-module.local.php.dist config/autoload/expressive-error-hero-module.local.php

Or run copy command:

cp vendor/samsonasik/error-hero-module/config/expressive-error-hero-module.local.php.dist config/autoload/expressive-error-hero-module.local.php

When done, you can modify logger service named ErrorHeroModuleLogger and error-hero-module config in your's local config:

<?php
// config/autoload/error-hero-module.local.php or config/autoload/expressive-error-hero-module.local.php
return [

    'log' => [
        'ErrorHeroModuleLogger' => [
            'writers' => [

                [
                    'name' => 'db',
                    'options' => [
                        'db'     => 'Zend\Db\Adapter\Adapter',
                        'table'  => 'log',
                        'column' => [
                            'timestamp' => 'date',
                            'priority'  => 'type',
                            'message'   => 'event',
                            'extra'     => [
                                'url'  => 'url',
                                'file' => 'file',
                                'line' => 'line',
                                'error_type' => 'error_type',
                            ],
                        ],
                    ],
                ],

            ],
        ],
    ],

    'error-hero-module' => [
    // it's for the enable/disable the logger functionality
        'enable' => true,

        // default to true, if set to true, then you can see sample:
        // 1. /error-preview page ( ErrorHeroModule\Controller\ErrorPreviewController )
        // 2. error-preview command (ErrorHeroModule\Controller\ErrorPreviewConsoleController) via
        //       php public/index.php error-preview
        //
        // for zf-expressive ^1.0, the disable error-preview page is by unregister 'error-preview' from this config under "routes",
        // for zf-expressive ^2.0, the disable error-preview page is by unregister 'error-preview' from config/routes
        //
        //
        // otherwise(false), you can't see them, eg: on production env.
        'enable-error-preview-page' => true,

        'display-settings' => [

            // excluded php errors ( http://www.php.net/manual/en/errorfunc.constants.php )
            'exclude-php-errors' => [
                E_USER_DEPRECATED,
            ],

            // show or not error
            'display_errors'  => 0,

            // if enable and display_errors = 0, the page will bring layout and view
            'template' => [
                'layout' => 'layout/layout',               
                'view'   => 'error-hero-module/error-default'
            ],

            // if enable and display_errors = 0, the console will bring message
            'console' => [
                'message' => 'We have encountered a problem and we can not fulfill your request. An error report has been generated and send to the support team and someone will attend to this problem urgently. Please try again later. Thank you for your patience.',
            ],
            // if enable, display_errors = 0, and request XMLHttpRequest
            // on this case, the "template" key will be ignored.
            'ajax' => [
                'message' => <<<json
{
    "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "We have encountered a problem and we can not fulfill your request. An error report has been generated and send to the support team and someone will attend to this problem urgently. Please try again later. Thank you for your patience."
}
json
            ],
        ],

        'logging-settings' => [
            // time range for same error, file, line, url, message to be re-logged
            // in seconds range, 86400 means 1 day
            'same-error-log-time-range' => 86400,
        ],

        'email-notification-settings' => [
            // set to true to activate email notification on log error event
            'enable' => false,

            // Zend\Mail\Message instance registered at service manager
            'mail-message'   => 'YourMailMessageService',

            // Zend\Mail\Transport\TransportInterface instance registered at service manager
            'mail-transport' => 'YourMailTransportService',

            // email sender
            'email-from'    => 'Sender Name <sender@host.com>',

            'email-to-send' => [
                'developer1@foo.com',
                'developer2@foo.com',
            ],
        ],
    ],
    // ...
];

5. Lastly, enable it

a. For ZF Mvc application

// config/modules.config.php or config/application.config.php
return [
    'Application',
    'ErrorHeroModule', // <-- register here
],

b. For ZF Expressive application

You need to use Zend\ServiceManager for service container and Zend\View for template engine.

For zend-expressive-skeleton ^1.0, It's should already just works!

For zend-expressive-skeleton ^2.0, you need to open config/pipeline.php and add the ErrorHeroModule\Middleware\Expressive::class middleware after default ErrorHandler::class registration:

$app->pipe(ErrorHandler::class);
$app->pipe(ErrorHeroModule\Middleware\Expressive::class); // here

and also add error-preview routes in config/routes.php (optional) :

$app->get('/error-preview[/:action]', ErrorHeroModule\Middleware\Routed\Preview\ErrorPreviewAction::class, 'error-preview');

to enable error preview page. To disable error preview page, just remove it from routes.

Give it a try!

Web Access

URl Preview For
http://yourzfapp/error-preview Exception
http://yourzfapp/error-preview/error Error

You will get the following page if display_errors config is 0:

error preview in web

For production env, you can disable error-preview sample page with set ['error-hero-module']['enable-error-preview-page'] to false.

Console Access

If you use zend-mvc v3, you need to have zendframework/zend-mvc-console in your vendor, if you don't have, you can install it via command:

composer require zendframework/zend-mvc-console --sort-packages
Command Preview For
php public/index.php error-preview Exception
php public/index.php error-preview error Error

You will get the following page if display_errors config is 0:

error preview in console

For production env, you can disable error-preview sample page with set ['error-hero-module']['enable-error-preview-page'] to false.

For ZF Expressive, there is no default console implementation, so, if you want to apply it in your console in ZF Expressive, you may need to custom implementation error handler that utilize ErrorHeroModule\Handler\Logging service (see detailed usage at ErrorHeroModule\Middleware\Expressive class)

Contributing

Contributions are very welcome. Please read CONTRIBUTING.md

Copyright (c) 2016 Abdul Malik Ikhsan

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
php composer.phar require "samsonasik/error-hero-module"

Require

  • php: ^5.6|^7.0
  • seld/jsonlint: ^1.5
  • zendframework/zend-console: ^2.5
  • zendframework/zend-db: ^2.5
  • zendframework/zend-log: ^2.5
  • zendframework/zend-mail: ^2.5
  • zendframework/zend-servicemanager: ^2.5|^3.0
  • zendframework/zend-text: ^2.5

Require Dev

  • doctrine/doctrine-orm-module: ^1.1
  • kahlan/kahlan: ^3.0.0
  • satooshi/php-coveralls: ^1.0
  • zendframework/zend-config-aggregator: ^0.2.0
  • zendframework/zend-expressive: ^1.1|^2.0
  • zendframework/zend-expressive-helpers: ^3.0.1
  • zendframework/zend-expressive-zendrouter: ^2.0.1
  • zendframework/zend-expressive-zendviewrenderer: ^1.3
  • zendframework/zend-mvc: ^2.5|^3.0
  • zendframework/zend-mvc-console: ^1.1