Logging and Debugging
for Neos 5 and 7
#Logging
Be aware, that 'Logging' is programmatically a task of the underlying Flow framework ...
#System Log
A logger instance for the default System Log can be injected and used for logging quite easily:
use Psr\Log\LoggerInterface;
/**
* @var LoggerInterface
*/
protected $logger;
/**
* @param LoggerInterface $logger
* @return void
*/
public function injectLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
The various methods can then be used to log according to the level:
$message = 'Whatever you want to log';
$context = [
'anything' => 'you might need',
'but can be' => 'left empty as well'
];
$this->logger->debug(string $message, array $context);
$this->logger->info(string $message, array $context);
$this->logger->notice(string $message, array $context);
$this->logger->warning(string $message, array $context);
$this->logger->error(string $message, array $context);
$this->logger->critical(string $message, array $context);
$this->logger->alert(string $message, array $context);
In other to be able to distinguish log entries, it is wise to send the some metadata along with the log entry:
use Neos\Flow\Log\Utility\LogEnvironment;
$logger->debug(
'Some log message',
LogEnvironment::fromMethodName(__METHOD__)
);
#Other logs
While logging to the System Log is easily done, and probably the most common case, you might want to log to the Security Log.
For Neos 5.x (based on Flow 6.x) this can be done using the PsrSecurityLogerInterface
– but this is deprecated as of Flow 6.0 already:
/**
* @var \Neos\Flow\Log\PsrSecurityLoggerInterface
*/
protected $securityLogger;
/**
* @param \Neos\Flow\Log\PsrSecurityLoggerInterface $securityLogger
* @return void
*/
public function injectSecurityLogger(\Neos\Flow\Log\PsrSecurityLoggerInterface $securityLogger)
{
$this->securityLogger = $securityLogger;
}
The proper, non-deprecated method for this would be the use of the logger factory:
/**
* @var \Neos\Flow\Log\PsrLoggerFactoryInterface
*/
protected $loggerFactory;
/**
* @var \Neos\Flow\Log\PsrSecurityLoggerInterface
*/
protected $securityLogger;
/**
* @param \Neos\Flow\Log\PsrLoggerFactoryInterface $loggerFactory
* @return void
*/
public function injectLoggerFactory(\Neos\Flow\Log\PsrLoggerFactoryInterface $loggerFactory)
{
$this->securityLogger = $loggerFactory->get('securityLogger');
}
Flow comes with the following loggers defined by default:
systemLogger
securityLogger
sqlLogger
i18nLogger
With Neos 7.0 (based on Flow 7.0) the PsrSystemLoggerInterface
and PsrSecurityLoggerInterface
(that were deprecated with Flow 6.0) are removed, so either use the logger factory as explained above or use virtual objects to access loggers other than for the system log:
use Neos\Flow\Annotations as Flow;
use Psr\Log\LoggerInterface;
/**
* @Flow\Inject(name="Neos.Flow:SystemLogger")
* @var LoggerInterface
*/
protected $systemLogger;
Flow comes with the following virtual logger objects defined by default:
Neos.Flow:SystemLogger
Neos.Flow:SecurityLogger
Neos.Flow:SqlLogger
Neos.Flow:I18nLogger
#Defining a custom logger
A custom logger can in come handy when you want to log specific information to a separate log file to faster analyse e.g. api calls or service information.
First you have to register the a new logger which can get created by Flow:
Neos:
Flow:
log:
psr3:
'Neos\Flow\Log\PsrLoggerFactory':
myLogger:
default:
class: Neos\Flow\Log\Backend\FileBackend
options:
logFileURL: '%FLOW_PATH_DATA%Logs/My.log'
createParentDirectories: true
severityThreshold: '%LOG_INFO%'
maximumLogFileSize: 10485760
logFilesToKeep: 1
logIpAddress: true
Now the define an Object on how to create an instance of the logger, which class it is based on and some more information:
'Acme.Demo:Log.MyLogger':
className: Psr\Log\LoggerInterface
scope: singleton
factoryObjectName: Neos\Flow\Log\PsrLoggerFactoryInterface
factoryMethodName: get
arguments:
1:
value: 'myLogger'
To use your custom logger just inject it and specify the name of the custom logger, defined in your Objects.yaml. After that the logger can be used as any regular logger inside Flow
<?php
declare(strict_types=1);
namespace Acme\Demo\Service;
use Neos\Flow\Annotations as Flow;
use Psr\Log\LoggerInterface;
class ServiceWithCustomLogger
{
/**
* @Flow\Inject(name="Acme.Demo:Log.MyLogger")
* @var LoggerInterface
*/
protected $myLogger;
/**
* Create a log message with our custom logger to a separate log file
*
* @param $message
* @return void
*/
protected function createLogEntry($message)
{
$this->myLogger->info($message);
}
The log file can be found in Data/Logs/My.log