mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #8241 from creative-commoners/pulls/4.3/separate-logging
Separate core error logging from standard LoggerInterface
This commit is contained in:
commit
a9d57f5bfb
@ -1,21 +1,34 @@
|
|||||||
---
|
---
|
||||||
Name: logging
|
Name: logging
|
||||||
---
|
---
|
||||||
# Logging is built up of a chain containing:
|
# Core error logging is built up of a chain containing:
|
||||||
# - A top level \ErrorHandler which registers the error service
|
# - A top level \ErrorHandler which registers the error service
|
||||||
# - A \Logger which acts as the error service
|
# - A \Logger which acts as the error service
|
||||||
# - A \HandlerInterface which handles errors for the logger
|
# - A \HandlerInterface which handles errors for the logger
|
||||||
# - One or more \FormatterInterface which format errors for the handler
|
# - One or more \FormatterInterface which format errors for the handler
|
||||||
|
#
|
||||||
|
# Logging for use outside of core error handling also uses the same implementations,
|
||||||
|
# but is available without the HandlerInterfaces attached
|
||||||
SilverStripe\Core\Injector\Injector:
|
SilverStripe\Core\Injector\Injector:
|
||||||
SilverStripe\Logging\ErrorHandler:
|
SilverStripe\Logging\ErrorHandler:
|
||||||
class: SilverStripe\Logging\MonologErrorHandler
|
class: SilverStripe\Logging\MonologErrorHandler
|
||||||
properties:
|
calls:
|
||||||
Logger: '%$Psr\Log\LoggerInterface'
|
pushDefaultLogger: [ pushLogger, [ '%$Psr\Log\LoggerInterface' ] ]
|
||||||
|
pushErrorHandler: [ pushLogger, [ '%$Psr\Log\LoggerInterface.errorhandler' ] ]
|
||||||
|
|
||||||
|
# Default implementation for use as a standard logger. Up to developers to attach their own
|
||||||
|
# handlers
|
||||||
Psr\Log\LoggerInterface:
|
Psr\Log\LoggerInterface:
|
||||||
type: singleton
|
type: singleton
|
||||||
class: Monolog\Logger
|
class: Monolog\Logger
|
||||||
constructor:
|
constructor:
|
||||||
- "error-log"
|
- "error-log"
|
||||||
|
# Core error handling
|
||||||
|
Psr\Log\LoggerInterface.errorhandler:
|
||||||
|
type: singleton
|
||||||
|
class: Monolog\Logger
|
||||||
|
constructor:
|
||||||
|
- "error-handler"
|
||||||
calls:
|
calls:
|
||||||
pushDisplayErrorHandler: [ pushHandler, [ '%$Monolog\Handler\HandlerInterface' ] ]
|
pushDisplayErrorHandler: [ pushHandler, [ '%$Monolog\Handler\HandlerInterface' ] ]
|
||||||
---
|
---
|
||||||
|
@ -11,6 +11,7 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
fixtures: '%$SilverStripe\Dev\State\FixtureTestState'
|
fixtures: '%$SilverStripe\Dev\State\FixtureTestState'
|
||||||
requirements: '%$SilverStripe\View\Dev\RequirementsTestState'
|
requirements: '%$SilverStripe\View\Dev\RequirementsTestState'
|
||||||
ssviewer: '%$SilverStripe\View\Dev\SSViewerTestState'
|
ssviewer: '%$SilverStripe\View\Dev\SSViewerTestState'
|
||||||
|
logstate: '%$SilverStripe\Dev\State\LoggerState'
|
||||||
---
|
---
|
||||||
Name: kerneltest
|
Name: kerneltest
|
||||||
Before: '*'
|
Before: '*'
|
||||||
|
@ -4,13 +4,14 @@ summary: Trap, fire and report diagnostic logs, user exceptions, warnings and er
|
|||||||
# Logging and Error Handling
|
# Logging and Error Handling
|
||||||
|
|
||||||
SilverStripe uses Monolog for both error handling and logging. It comes with two default configurations: one for
|
SilverStripe uses Monolog for both error handling and logging. It comes with two default configurations: one for
|
||||||
development environments, and another for test or live environments. On development environments, SilverStripe will
|
logging, and another for core error handling. The core error handling implementation also comes with two default
|
||||||
deal harshly with any warnings or errors: a full call-stack is shown and execution stops for anything, giving you early
|
configurations: one for development environments, and another for test or live environments. On development
|
||||||
warning of a potential issue to handle.
|
environments, SilverStripe will deal harshly with any warnings or errors: a full call-stack is shown and execution
|
||||||
|
stops for anything, giving you early warning of a potential issue to handle.
|
||||||
|
|
||||||
## Raising errors and logging diagnostic information.
|
## Raising errors and logging diagnostic information.
|
||||||
|
|
||||||
For informational and debug logs, you can use the Logger directly. The Logger is a PSR-3 compatible LoggerInterface and
|
For general purpose logging, you can use the Logger directly. The Logger is a PSR-3 compatible LoggerInterface and
|
||||||
can be accessed via the `Injector`:
|
can be accessed via the `Injector`:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
@ -20,13 +21,15 @@ use SilverStripe\Security\Security;
|
|||||||
|
|
||||||
Injector::inst()->get(LoggerInterface::class)->info('User has logged in: ID #' . Security::getCurrentUser()->ID);
|
Injector::inst()->get(LoggerInterface::class)->info('User has logged in: ID #' . Security::getCurrentUser()->ID);
|
||||||
Injector::inst()->get(LoggerInterface::class)->debug('Query executed: ' . $sql);
|
Injector::inst()->get(LoggerInterface::class)->debug('Query executed: ' . $sql);
|
||||||
|
Injector::inst()->get(LoggerInterface::class)->error('Something went wrong, but let\'s continue on...');
|
||||||
```
|
```
|
||||||
|
|
||||||
Although you can raise more important levels of alerts in this way, we recommend using PHP's native error systems for
|
Although you can raise more important levels of alerts in this way, we recommend using PHP's native error systems for
|
||||||
these instead.
|
these instead.
|
||||||
|
|
||||||
For notice-level and warning-level issues, you should use [user_error](http://www.php.net/user_error) to throw errors
|
For notice-level and warning-level issues, you can also use [user_error](http://www.php.net/user_error) to throw errors
|
||||||
where appropriate. These will not halt execution but will send a message to the PHP error log.
|
where appropriate. As with the default Logger implementation these will not halt execution, but will send a message
|
||||||
|
to the PHP error log.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
public function delete()
|
public function delete()
|
||||||
@ -48,37 +51,52 @@ public function getRelatedObject()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For errors that should halt execution, you should use Exceptions. Normally, Exceptions will halt the flow of executuion,
|
For errors that should halt execution, you should use Exceptions. Normally, Exceptions will halt the flow of execution,
|
||||||
but they can be caught with a try/catch clause.
|
but they can be caught with a try/catch clause.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
throw new \LogicException("Query failed: " . $sql);
|
throw new \LogicException("Query failed: " . $sql);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Accessing the logger via dependency injection.
|
### Accessing the logger via dependency injection
|
||||||
|
|
||||||
It can be quite verbose to call `Injector::inst()->get(LoggerInterface::class)` all the time. More importantly,
|
It can be quite verbose to call `Injector::inst()->get(LoggerInterface::class)` all the time. More importantly,
|
||||||
it also means that you're coupling your code to global state, which is a bad design practise. A better
|
it also means that you're coupling your code to global state, which is a bad design practise. A better
|
||||||
approach is to use depedency injection to pass the logger in for you. The [Injector](../extending/Injector)
|
approach is to use dependency injection to pass the logger in for you. The [Injector](../extending/Injector)
|
||||||
can help with this. The most straightforward is to specify a `dependencies` config setting, like this:
|
can help with this. The most straightforward is to specify a `dependencies` config setting, like this:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
|
|
||||||
class MyController extends Controller
|
class MyController extends Controller
|
||||||
{
|
{
|
||||||
private static $dependencies = [
|
private static $dependencies = [
|
||||||
'logger' => '%$Psr\Log\LoggerInterface',
|
'Logger' => '%$' . LoggerInterface::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
// This will be set automatically, as long as MyController is instantiated via Injector
|
/**
|
||||||
public $logger;
|
* This will be set automatically, as long as MyController is instantiated via Injector
|
||||||
|
*
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
protected function init()
|
protected function init()
|
||||||
{
|
{
|
||||||
$this->logger->debug("MyController::init() called");
|
$this->logger->debug("MyController::init() called");
|
||||||
parent::init();
|
parent::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param LoggerInterface $logger
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setLogger(LoggerInterface $logger)
|
||||||
|
{
|
||||||
|
$this->logger = $logger;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -98,7 +116,7 @@ E_USER_ERROR if it's going to be **dangerous** or **impossible** to continue wit
|
|||||||
|
|
||||||
## Configuring error logging
|
## Configuring error logging
|
||||||
|
|
||||||
You can configure your logging using Monolog handlers. The handlers should be provided int the `Logger.handlers`
|
You can configure your logging using Monolog handlers. The handlers should be provided in the `Logger.handlers`
|
||||||
configuration setting. Below we have a couple of common examples, but Monolog comes with [many different handlers](https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md#handlers)
|
configuration setting. Below we have a couple of common examples, but Monolog comes with [many different handlers](https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md#handlers)
|
||||||
for you to try.
|
for you to try.
|
||||||
|
|
||||||
@ -145,24 +163,27 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
- "info"
|
- "info"
|
||||||
```
|
```
|
||||||
|
|
||||||
The log file will be relative to the framework/ path, so "../silverstripe.log" will create a file in your project root.
|
The log file will be relative to the main index.php file path (default: inside public/), so "../silverstripe.log" will
|
||||||
|
create a file in your project root.
|
||||||
|
|
||||||
|
The `info` argument provides the minimum level to start logging at.
|
||||||
|
|
||||||
### Disabling the default handler
|
### Disabling the default handler
|
||||||
|
|
||||||
You can disable a handler by removing its pushHandlers call from the calls option of the Logger service definition.
|
You can disable a handler by removing its pushHandlers call from the calls option of the Logger service definition.
|
||||||
The handler key of the default handler is `DisplayErrorHandler`, so you can disable it like this:
|
The handler key of the default handler is `pushDisplayErrorHandler`, so you can disable it like this:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
SilverStripe\Core\Injector\Injector:
|
SilverStripe\Core\Injector\Injector:
|
||||||
Psr\Log\LoggerInterface:
|
Psr\Log\LoggerInterface.errorhandler:
|
||||||
calls:
|
calls:
|
||||||
DisplayErrorHandler: %%remove%%
|
pushDisplayErrorHandler: %%remove%%
|
||||||
```
|
```
|
||||||
|
|
||||||
### Setting a different configuration for dev
|
### Setting a different configuration for dev
|
||||||
|
|
||||||
In order to set different logging configuration on different environment types, we rely on the environment-specific
|
In order to set different logging configuration on different environment types, we rely on the environment-specific
|
||||||
configuration features that the config system proviers. For example, here we have different configuration for dev and
|
configuration features that the config system providers. For example, here we have different configuration for dev and
|
||||||
non-dev.
|
non-dev.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@ -172,7 +193,7 @@ Only:
|
|||||||
environment: dev
|
environment: dev
|
||||||
---
|
---
|
||||||
SilverStripe\Core\Injector\Injector:
|
SilverStripe\Core\Injector\Injector:
|
||||||
Psr\Log\LoggerInterface:
|
Psr\Log\LoggerInterface.errorhandler:
|
||||||
calls:
|
calls:
|
||||||
pushDisplayErrorHandler: [ pushHandler, [ %$DisplayErrorHandler ]]
|
pushDisplayErrorHandler: [ pushHandler, [ %$DisplayErrorHandler ]]
|
||||||
DisplayErrorHandler:
|
DisplayErrorHandler:
|
||||||
@ -188,10 +209,21 @@ Except:
|
|||||||
environment: dev
|
environment: dev
|
||||||
---
|
---
|
||||||
SilverStripe\Core\Injector\Injector:
|
SilverStripe\Core\Injector\Injector:
|
||||||
|
# Default logger implementation for general purpose use
|
||||||
Psr\Log\LoggerInterface:
|
Psr\Log\LoggerInterface:
|
||||||
calls:
|
calls:
|
||||||
pushFileLogHandler: [ pushHandler, [ %$LogFileHandler ]]
|
# Save system logs to file
|
||||||
|
pushFileLogHandler: [ pushHandler, [ %$LogFileHandler ]]
|
||||||
|
|
||||||
|
# Core error handler for system use
|
||||||
|
Psr\Log\LoggerInterface.errorhandler:
|
||||||
|
calls:
|
||||||
|
# Save errors to file
|
||||||
|
pushFileLogHandler: [ pushHandler, [ %$LogFileHandler ]]
|
||||||
|
# Format and display errors in the browser/CLI
|
||||||
pushDisplayErrorHandler: [ pushHandler, [ %$DisplayErrorHandler ]]
|
pushDisplayErrorHandler: [ pushHandler, [ %$DisplayErrorHandler ]]
|
||||||
|
|
||||||
|
# Custom handler to log to a file
|
||||||
LogFileHandler:
|
LogFileHandler:
|
||||||
class: Monolog\Handler\StreamHandler
|
class: Monolog\Handler\StreamHandler
|
||||||
constructor:
|
constructor:
|
||||||
@ -200,12 +232,16 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
properties:
|
properties:
|
||||||
Formatter: %$Monolog\Formatter\HtmlFormatter
|
Formatter: %$Monolog\Formatter\HtmlFormatter
|
||||||
ContentType: text/html
|
ContentType: text/html
|
||||||
|
|
||||||
|
# Handler for displaying errors in the browser or CLI
|
||||||
DisplayErrorHandler:
|
DisplayErrorHandler:
|
||||||
class: SilverStripe\Logging\HTTPOutputHandler
|
class: SilverStripe\Logging\HTTPOutputHandler
|
||||||
constructor:
|
constructor:
|
||||||
- "error"
|
- "error"
|
||||||
properties:
|
properties:
|
||||||
Formatter: %$SilverStripe\Logging\DebugViewFriendlyErrorFormatter
|
Formatter: %$SilverStripe\Logging\DebugViewFriendlyErrorFormatter
|
||||||
|
|
||||||
|
# Configuration for the "friendly" error formatter
|
||||||
SilverStripe\Logging\DebugViewFriendlyErrorFormatter:
|
SilverStripe\Logging\DebugViewFriendlyErrorFormatter:
|
||||||
class: SilverStripe\Logging\DebugViewFriendlyErrorFormatter
|
class: SilverStripe\Logging\DebugViewFriendlyErrorFormatter
|
||||||
properties:
|
properties:
|
||||||
@ -214,7 +250,7 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
```
|
```
|
||||||
|
|
||||||
<div class="info" markdown="1">
|
<div class="info" markdown="1">
|
||||||
In addition to SilverStripe-integrated logging, it is advisable to fall back to PHPs native logging functionality. A
|
In addition to SilverStripe-integrated logging, it is advisable to fall back to PHP's native logging functionality. A
|
||||||
script might terminate before it reaches the SilverStripe error handling, for example in the case of a fatal error. Make
|
script might terminate before it reaches the SilverStripe error handling, for example in the case of a fatal error. Make
|
||||||
sure `log_errors` and `error_log` in your PHP ini file are configured.
|
sure `log_errors` and `error_log` in your PHP ini file are configured.
|
||||||
</div>
|
</div>
|
||||||
@ -228,11 +264,12 @@ others.
|
|||||||
### Replacing the logger
|
### Replacing the logger
|
||||||
|
|
||||||
Monolog comes by default with SilverStripe, but you may use another PSR-3 compliant logger, if you wish. To do this,
|
Monolog comes by default with SilverStripe, but you may use another PSR-3 compliant logger, if you wish. To do this,
|
||||||
set the `Injector.Logger` configuration parameter, providing a new injector definition. For example:
|
set the `SilverStripe\Core\Injector\Injector.Monolog\Logger` configuration parameter, providing a new injector
|
||||||
|
definition. For example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
SilverStripe\Core\Injector\Injector:
|
SilverStripe\Core\Injector\Injector:
|
||||||
ErrorHandler:
|
SilverStripe\Logging\ErrorHandler:
|
||||||
class: Logging\Logger
|
class: Logging\Logger
|
||||||
constructor:
|
constructor:
|
||||||
- 'alternative-logger'
|
- 'alternative-logger'
|
||||||
@ -243,7 +280,8 @@ be ignored.
|
|||||||
|
|
||||||
### Replacing the error handler
|
### Replacing the error handler
|
||||||
|
|
||||||
The Injector service `ErrorHandler` is responsible for initialising the error handler. By default it
|
The Injector service `SilverStripe\Logging\ErrorHandler` is responsible for initialising the error handler. By default
|
||||||
|
it:
|
||||||
|
|
||||||
* Create a `SilverStripe\Logging\MonologErrorHandler` object.
|
* Create a `SilverStripe\Logging\MonologErrorHandler` object.
|
||||||
* Attach the registered service `Psr\Log\LoggerInterface` to it, to start the error handler.
|
* Attach the registered service `Psr\Log\LoggerInterface` to it, to start the error handler.
|
||||||
@ -255,7 +293,7 @@ another. To replace this, you should registered a new service, `ErrorHandlerLoad
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
SilverStripe\Core\Injector\Injector:
|
SilverStripe\Core\Injector\Injector:
|
||||||
ErrorHandler:
|
SilverStripe\Logging\ErrorHandler:
|
||||||
class: MyApp\CustomErrorHandlerLoader
|
class: MyApp\CustomErrorHandlerLoader
|
||||||
```
|
```
|
||||||
|
|
||||||
|
42
src/Dev/State/LoggerState.php
Normal file
42
src/Dev/State/LoggerState.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\Dev\State;
|
||||||
|
|
||||||
|
use Monolog\Handler\NullHandler;
|
||||||
|
use Monolog\Logger;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables any user configured loggers by pushing a NullHandler during PHPUnit tests.
|
||||||
|
*
|
||||||
|
* This is designed specifically for Monolog. If using another PSR-3 compatible logging package, this will
|
||||||
|
* not do anything.
|
||||||
|
*/
|
||||||
|
class LoggerState implements TestState
|
||||||
|
{
|
||||||
|
public function setUp(SapphireTest $test)
|
||||||
|
{
|
||||||
|
/** @var Logger $userLogger */
|
||||||
|
$userLogger = Injector::inst()->get(LoggerInterface::class);
|
||||||
|
if ($userLogger && $userLogger instanceof Logger) {
|
||||||
|
$userLogger->setHandlers([new NullHandler()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown(SapphireTest $test)
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUpOnce($class)
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDownOnce($class)
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
@ -48,10 +48,12 @@ class DebugViewFriendlyErrorFormatter implements FormatterInterface
|
|||||||
* Set default status code
|
* Set default status code
|
||||||
*
|
*
|
||||||
* @param int $statusCode
|
* @param int $statusCode
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setStatusCode($statusCode)
|
public function setStatusCode($statusCode)
|
||||||
{
|
{
|
||||||
$this->statusCode = $statusCode;
|
$this->statusCode = $statusCode;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,10 +70,12 @@ class DebugViewFriendlyErrorFormatter implements FormatterInterface
|
|||||||
* Set friendly title
|
* Set friendly title
|
||||||
*
|
*
|
||||||
* @param string $title
|
* @param string $title
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setTitle($title)
|
public function setTitle($title)
|
||||||
{
|
{
|
||||||
$this->friendlyErrorMessage = $title;
|
$this->friendlyErrorMessage = $title;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,10 +92,12 @@ class DebugViewFriendlyErrorFormatter implements FormatterInterface
|
|||||||
* Set default error body
|
* Set default error body
|
||||||
*
|
*
|
||||||
* @param string $body
|
* @param string $body
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setBody($body)
|
public function setBody($body)
|
||||||
{
|
{
|
||||||
$this->friendlyErrorDetail = $body;
|
$this->friendlyErrorDetail = $body;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function format(array $record)
|
public function format(array $record)
|
||||||
|
@ -79,7 +79,7 @@ class DetailedErrorFormatter implements FormatterInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a developer facing error page, showing the stack trace and details
|
* Render a developer facing error page, showing the stack trace and details
|
||||||
* of the code where the error occured.
|
* of the code where the error occurred.
|
||||||
*
|
*
|
||||||
* @param int $errno
|
* @param int $errno
|
||||||
* @param string $errstr
|
* @param string $errstr
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Logging;
|
namespace SilverStripe\Logging;
|
||||||
|
|
||||||
|
use Monolog\Formatter\FormatterInterface;
|
||||||
|
use Monolog\Handler\AbstractProcessingHandler;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
use SilverStripe\Control\HTTPResponse;
|
use SilverStripe\Control\HTTPResponse;
|
||||||
use Monolog\Handler\AbstractProcessingHandler;
|
|
||||||
use Monolog\Formatter\FormatterInterface;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output the error to the browser, with the given HTTP status code.
|
* Output the error to the browser, with the given HTTP status code.
|
||||||
@ -79,7 +79,7 @@ class HTTPOutputHandler extends AbstractProcessingHandler
|
|||||||
/**
|
/**
|
||||||
* Set a formatter to use if Director::is_cli() is true
|
* Set a formatter to use if Director::is_cli() is true
|
||||||
*
|
*
|
||||||
* @param $cliFormatter
|
* @param FormatterInterface $cliFormatter
|
||||||
* @return HTTPOutputHandler Return $this to allow chainable calls
|
* @return HTTPOutputHandler Return $this to allow chainable calls
|
||||||
*/
|
*/
|
||||||
public function setCLIFormatter(FormatterInterface $cliFormatter)
|
public function setCLIFormatter(FormatterInterface $cliFormatter)
|
||||||
@ -153,12 +153,12 @@ class HTTPOutputHandler extends AbstractProcessingHandler
|
|||||||
$response = new HTTPResponse();
|
$response = new HTTPResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If headers have been sent then these won't be used, and may throw errors that we wont' want to see.
|
// If headers have been sent then these won't be used, and may throw errors that we won't want to see.
|
||||||
if (!headers_sent()) {
|
if (!headers_sent()) {
|
||||||
$response->setStatusCode($this->getStatusCode());
|
$response->setStatusCode($this->getStatusCode());
|
||||||
$response->addHeader('Content-Type', $this->getContentType());
|
$response->addHeader('Content-Type', $this->getContentType());
|
||||||
} else {
|
} else {
|
||||||
// To supress errors aboot errors
|
// To suppress errors about errors
|
||||||
$response->setStatusCode(200);
|
$response->setStatusCode(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,45 +2,97 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Logging;
|
namespace SilverStripe\Logging;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Monolog\ErrorHandler as MonologHandler;
|
use Monolog\ErrorHandler as MonologHandler;
|
||||||
|
use SilverStripe\Dev\Deprecation;
|
||||||
|
|
||||||
class MonologErrorHandler implements ErrorHandler
|
class MonologErrorHandler implements ErrorHandler
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var LoggerInterface
|
* @var LoggerInterface[]
|
||||||
*/
|
*/
|
||||||
private $logger;
|
private $loggers = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the PSR-3 logger to send errors & exceptions to
|
* Set the PSR-3 logger to send errors & exceptions to. Will overwrite any previously configured
|
||||||
|
* loggers
|
||||||
*
|
*
|
||||||
|
* @deprecated 4.4.0:5.0.0 Use pushHandler() instead
|
||||||
* @param LoggerInterface $logger
|
* @param LoggerInterface $logger
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setLogger(LoggerInterface $logger)
|
public function setLogger(LoggerInterface $logger)
|
||||||
{
|
{
|
||||||
$this->logger = $logger;
|
Deprecation::notice('4.4.0', 'Please use pushHandler() instead');
|
||||||
|
|
||||||
|
$this->loggers = [$logger];
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the PSR-3 logger to send errors & exceptions to
|
* Get the first registered PSR-3 logger to send errors & exceptions to
|
||||||
*
|
*
|
||||||
|
* @deprecated 4.4.0:5.0.0 Use getHandlers() instead
|
||||||
* @return LoggerInterface
|
* @return LoggerInterface
|
||||||
*/
|
*/
|
||||||
public function getLogger()
|
public function getLogger()
|
||||||
{
|
{
|
||||||
return $this->logger;
|
Deprecation::notice('4.4.0', 'Please use getHandlers() instead');
|
||||||
|
|
||||||
|
return reset($this->loggers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a PSR-3 logger to send messages to, to the end of the stack
|
||||||
|
*
|
||||||
|
* @param LoggerInterface $logger
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function pushLogger(LoggerInterface $logger)
|
||||||
|
{
|
||||||
|
$this->loggers[] = $logger;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stack of PSR-3 loggers
|
||||||
|
*
|
||||||
|
* @return LoggerInterface[]
|
||||||
|
*/
|
||||||
|
public function getLoggers()
|
||||||
|
{
|
||||||
|
return $this->loggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the PSR-3 loggers (overwrites any previously configured values)
|
||||||
|
*
|
||||||
|
* @param LoggerInterface[] $loggers
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setLoggers(array $loggers)
|
||||||
|
{
|
||||||
|
$this->loggers = $loggers;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
public function start()
|
public function start()
|
||||||
{
|
{
|
||||||
if (!$this->getLogger()) {
|
$loggers = $this->getLoggers();
|
||||||
throw new \InvalidArgumentException("No Logger property passed to MonologErrorHandler."
|
if (empty($loggers)) {
|
||||||
. "Is your Injector config correct?");
|
throw new InvalidArgumentException(
|
||||||
|
"No Logger properties passed to MonologErrorHandler. Is your Injector config correct?"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MonologHandler::register($this->getLogger());
|
foreach ($loggers as $logger) {
|
||||||
|
MonologHandler::register($logger);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Logging\Tests;
|
namespace SilverStripe\Logging\Tests;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use SilverStripe\Dev\SapphireTest;
|
use SilverStripe\Dev\SapphireTest;
|
||||||
use SilverStripe\Logging\MonologErrorHandler;
|
use SilverStripe\Logging\MonologErrorHandler;
|
||||||
|
|
||||||
@ -9,11 +10,27 @@ class MonologErrorHandlerTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @expectedException \InvalidArgumentException
|
* @expectedException \InvalidArgumentException
|
||||||
* @expectedExceptionMessageRegExp /No Logger property passed to MonologErrorHandler/
|
* @expectedExceptionMessageRegExp /No Logger properties passed to MonologErrorHandler/
|
||||||
*/
|
*/
|
||||||
public function testStartThrowsExceptionWithoutLoggerDefined()
|
public function testStartThrowsExceptionWithoutLoggerDefined()
|
||||||
{
|
{
|
||||||
$handler = new MonologErrorHandler();
|
$handler = new MonologErrorHandler();
|
||||||
$handler->start();
|
$handler->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetLoggerResetsStack()
|
||||||
|
{
|
||||||
|
/** @var LoggerInterface $logger */
|
||||||
|
$logger = $this->createMock(LoggerInterface::class);
|
||||||
|
|
||||||
|
$handler = new MonologErrorHandler();
|
||||||
|
$handler->pushLogger($logger)->pushLogger($logger);
|
||||||
|
$this->assertCount(2, $handler->getLoggers(), 'Loggers are pushed to the stack');
|
||||||
|
|
||||||
|
$handler->setLogger($logger);
|
||||||
|
$this->assertCount(1, $handler->getLoggers(), 'setLogger resets stack and pushes');
|
||||||
|
|
||||||
|
$handler->setLoggers([]);
|
||||||
|
$this->assertCount(0, $handler->getLoggers(), 'setLoggers overwrites all configured loggers');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user