Application Logging

Logs are important for monitoring the security of your application and to track events if problems occur, as well as for auditing the correct usage of the system. The PSR-Logger interface standard is supported.

Logging Config

Log

Configuring app file logger writer, data/log/app.log by default.

use WebinoAppLib\Application\CoreConfig;
use WebinoConfigLib\Feature\Log;

new CoreConfig([
    // Enabling default logging
    new Log,
    // Overriding default logging file
    new Log('my/folder/app.log'),
]);

Configuring file logger formatting.

use WebinoAppLib\Application\CoreConfig;
use WebinoConfigLib\Feature\Log;

new CoreConfig([
    // Simple format
    (new Log)->setSimpleFormat('%timestamp% %priorityName% (%priority%): %message% %extra%'),

    // XML format
    (new Log('my/folder/app.log.xml'))->setXmlFormat(),
]);

Forking Logger

Creating new logger writer instead of overriding the default.

use WebinoAppLib\Application\CoreConfig;
use WebinoConfigLib\Feature\Log;

new CoreConfig([
    (new Log('my/folder/my-app.log'))->setName('my'),
]);

Logger

Configuring custom logger.

use WebinoAppLib\Feature\Config;
use WebinoConfigLib\Feature\Log;
use WebinoConfigLib\Feature\Logger;
use WebinoConfigLib\Feature\FirePhpLog;

new Config([
    new Logger('myLogger', [
        new Log,
        // etc.
    ]),
]);

ChromePhpLog

Configuring app ChromePHP logger writer.

use WebinoAppLib\Application\CoreConfig;
use WebinoConfigLib\Feature\ChromePhpLog;

new CoreConfig([
    new ChromePhpLog,
]);

FirePhpLog

Configuring app FirePHP logger writer.

use WebinoAppLib\Application\CoreConfig;
use WebinoConfigLib\Feature\FirePhpLog;

new CoreConfig([
    new FirePhpLog,
]);

Logging Interface

$app->getLogger()

Obtaining logger service.

/** @var \WebinoLogLib\LoggerInterface $logger */
$logger = $app->getLogger();

Obtaining custom logger service.

/** @var \WebinoLogLib\LoggerInterface $logger */
$logger = $app->getLogger('myLogger');

$app->log()

Writing messages to a log.

// creating a debug message class
use WebinoLogLib\Message\AbstractDebugMessage;
use Zend\Stdlib\Parameters;

class MyDebugMessage extends AbstractDebugMessage
{
    public function getMessage(Parameters $args)
    {
        // do something...
        // $args[0]
        // $args[1]
        // $args->exception

        // return a log message
        return 'My log message text with arguments {0} {1}';
    }
}

// logging a message
$app->log(MyDebugMessage::class);

// logging a message with custom arguments
$app->log(MyDebugMessage::class, [$argOne, $argTwo]);

// possible but not the best practice
$app->log($app::DEBUG, 'My log message text with arguments {0} {1}', [$argOne, $argTwo]);

Obtaining PSR-3 logger.

/** @var \Psr\Log\LoggerInterface $logger */
$logger = $app->log();

PSR-3 Logger Interface

Calling the $app->log() method without arguments returns the standard PSR-3 logger object, on which we can call standard logging methods.

// just text
$app->log()->emergency('Something really bad happened.');

// text with argument placeholders
$app->log()->info('Message text example with arguments: {0} {1}', [$argOne, $argTwo]);

// text with context variables
$app->log()->debug('Some debug information...', ['exception' => $exc]);

Available methods:

$app->log()->emergency()

Emergency, the system is unusable.

$app->log()->alert()

Alert, immediate action is required.

$app->log()->critical()

Critical, critical conditions.

$app->log()->error()

Error, errors that do not require immediate attention but should be monitored.

$app->log()->warning()

Warning, unusual or undesirable occurrences that are not errors.

$app->log()->notice()

Notice, normal but significant events.

$app->log()->info()

Info, interesting events.

$app->log()->debug()

Debug, detailed information for debugging purposes.

Logging Filters

A filter blocks a message from being written to the log.

Priority filter

Configuring logger priority filter. Filters out all messages that are below required priority.

use WebinoAppLib\Application\CoreConfig;
use WebinoConfigLib\Feature\Log;
use WebinoConfigLib\Feature\FirePhpLog;

new CoreConfig([

    (new Log)->filterPriority(Log::EMERGENCY),

    (new FirePhpLog)->filterPriority(FirePhpLog::INFO),

    // etc.
]);

Regex filter

Configuring logger regex filter. Filters out all messages that do not match required pattern.

use WebinoAppLib\Application\CoreConfig;
use WebinoConfigLib\Feature\Log;
use WebinoConfigLib\Feature\FirePhpLog;

new CoreConfig([

    (new Log)->filterRegex('~^Attach~'),

    (new FirePhpLog)->filterRegex('~^Event~'),

    // etc.
]);

Log Message Classes

The best practice is to log messages via class.

use WebinoLogLib\Message\AbstractDebugMessage;

class MyDebugMessage extends AbstractDebugMessage
{
    public function getMessage(array $args)
    {
        // do something...
        // $args[0]
        // $args[1]
        // $args['exception']

        // return a log message
        return 'My log message text with arguments {0} {1}';
    }
}

Use following log message classes in the WebinoLogLib\Message namespace to extend your custom message classes.

AbstractEmergencyMessage
Emergency, the system is unusable.
AbstractAlertMessage
Alert, immediate action is required.
AbstractCriticalMessage
Critical, critical conditions.
AbstractErrorMessage
Error, errors that do not require immediate attention but should be monitored.
AbstractWarningMessage
Warning, unusual or undesirable occurrences that are not errors.
AbstractNoticeMessage
Notice, normal but significant events.
AbstractInfoMessage
Info, interesting events.
AbstractDebugMessage
Debug, detailed information for debugging purposes.

Logging Cookbook

Creating Logger Messages

Choose one of the abstract log messages in the WebinoLogLib\Message namespace.

Create file in your package folder with the name of your log message. For example Log\MyLogMessage.php with the following contents:

namespace MyPackage\Log;

use WebinoLogLib\Message\AbstractDebugMessage;
use Zend\Stdlib\Parameters;

class MyLogMessage extends AbstractDebugMessage
{
    public function getMessage(Parameters $args)
    {
        // do something...
        // $args[0]
        // $args[1]
        // $args->exception

        // return a log message
        return 'My log message text with arguments {0} {1}';
    }
}

Then you can log the message via application logger:

use MyPackage\Log\MyLogMessage;

$app->log(MyLogMessage::class);

Or using custom logger, if you have configured one:

use MyPackage\Log\MyLogMessage;

$app->getLogger('myLogger')->log(MyLogMessage::class);

Creating Logger Aware Services

Create file in your package folder with the name of your service. For example Service\MyService.php with the following contents:

namespace MyPackage\Service;

use WebinoLogLib\LoggerAwareInterface;
use WebinoLogLib\LoggerAwareTrait;

class MyService implements LoggerAwareInterface
{
    use LoggerAwareTrait;

    public function doSomething()
    {
        $this->getLogger()->log(MyLogMessage::class);
    }
}

Create a factory for your service to inject the logger. For example Factory\MyServiceFactory.php with the following contents:

namespace MyPackage\Factory;

use MyPackage\Service\MyService;
use WebinoAppLib\Factory\AbstractFactory;

class MyServiceFactory extends AbstractFactory
{
    protected function create()
    {
        $myService = new MyService;

        /**
         * Injecting app logger
         * into custom service.
         */
        $myService->setLogger($this->getApp()->getLogger());

        return $myService;
    }
}

Add your service to the application via configuration.

use WebinoAppLib\Feature\Config;
use WebinoAppLib\Feature\Service;

new Config([
    new Service(MyService::class, MyServiceFactory::class),
]);

Then calling method on your service will write a message to the application log file.

use MyPackage\Service\MyService;

/** @var MyService $myService */
$myService = $app->get(MyService::class);
$myService->doSomething();

Creating Custom Loggers

Add new logger feature to application configuration:

use WebinoAppLib\Feature\Config;
use WebinoConfigLib\Feature\FirePhpLog;
use WebinoConfigLib\Feature\Log;
use WebinoConfigLib\Feature\Logger

new Config([
    new Logger('myLogger', [
        new Log('my.log'),
    ]),
]);

Then obtain your custom logger:

$myLogger = $app->getLogger('myLogger');

Creating Custom Logger Aware Services

Create file in your package folder with the name of your service. For example Service\MyService.php with the following contents:

namespace MyPackage\Service;

use WebinoLogLib\LoggerAwareInterface;
use WebinoLogLib\LoggerAwareTrait;

class MyService implements LoggerAwareInterface
{
    use LoggerAwareTrait;

    public function doSomething()
    {
        $this->getLogger()->log(MyLogMessage::class);
    }
}

Create a factory for your service to inject your custom logger. For example Factory\MyServiceFactory.php with the following contents:

namespace MyPackage\Factory;

use MyPackage\Service\MyService;
use WebinoAppLib\Factory\AbstractFactory;

class MyServiceFactory extends AbstractFactory
{
    protected function create()
    {
        $myService = new MyService;

        /**
         * Injecting custom logger
         * into custom service.
         */
        $myService->setLogger($this->getApp()->getLogger('myLogger'));

        return $myService;
    }
}

Add new logger feature to application configuration:

use WebinoAppLib\Feature\Config;
use WebinoConfigLib\Feature\FirePhpLog;
use WebinoConfigLib\Feature\Log;
use WebinoConfigLib\Feature\Logger

new Config([
    new Logger('myLogger', [
        new Log('my.log'),
    ]),
]);

Add your service to the application via configuration.

use WebinoAppLib\Feature\Config;
use WebinoAppLib\Feature\Service;

new Config([
    new Service(MyService::class, MyServiceFactory::class),
]);

Then calling method on your service will write a message to your custom log file.

use MyPackage\Service\MyService;

/** @var MyService $myService */
$myService = $app->get(MyService::class);
$myService->doSomething();