mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-29 20:59:23 +02:00
API Apply default logger to all caches
API Rename ‘Logger’ service name to ‘Psr\Log\LoggerInterface’ API DefaultCacheFactory constructor now takes an array of default arguments
This commit is contained in:
parent
8f0f9fa119
commit
ce14060913
@ -5,7 +5,10 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
SilverStripe\Core\Cache\CacheFactory:
|
SilverStripe\Core\Cache\CacheFactory:
|
||||||
class: 'SilverStripe\Core\Cache\DefaultCacheFactory'
|
class: 'SilverStripe\Core\Cache\DefaultCacheFactory'
|
||||||
constructor:
|
constructor:
|
||||||
|
args:
|
||||||
directory: '`TEMP_FOLDER`'
|
directory: '`TEMP_FOLDER`'
|
||||||
|
version: null
|
||||||
|
logger: %$Psr\Log\LoggerInterface
|
||||||
Psr\SimpleCache\CacheInterface.GDBackend_Manipulations:
|
Psr\SimpleCache\CacheInterface.GDBackend_Manipulations:
|
||||||
factory: SilverStripe\Core\Cache\CacheFactory
|
factory: SilverStripe\Core\Cache\CacheFactory
|
||||||
constructor:
|
constructor:
|
||||||
|
@ -5,8 +5,8 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
ErrorHandler:
|
ErrorHandler:
|
||||||
class: SilverStripe\Logging\MonologErrorHandler
|
class: SilverStripe\Logging\MonologErrorHandler
|
||||||
properties:
|
properties:
|
||||||
Logger: %$Logger
|
Logger: %$Psr\Log\LoggerInterface
|
||||||
Logger:
|
Psr\Log\LoggerInterface:
|
||||||
type: singleton
|
type: singleton
|
||||||
class: Monolog\Logger
|
class: Monolog\Logger
|
||||||
constructor:
|
constructor:
|
||||||
|
@ -14,8 +14,8 @@ For informational and debug logs, you can use the Logger directly. The Logger is
|
|||||||
can be accessed via the `Injector`:
|
can be accessed via the `Injector`:
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
Injector::inst()->get('Logger')->info('User has logged in: ID #' . Member::currentUserID());
|
Injector::inst()->get(LoggerInterface::class)->info('User has logged in: ID #' . Member::currentUserID());
|
||||||
Injector::inst()->get('Logger')->debug('Query executed: ' . $sql);
|
Injector::inst()->get(LoggerInterface::class)->debug('Query executed: ' . $sql);
|
||||||
|
|
||||||
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.
|
||||||
@ -48,16 +48,16 @@ but they can be caught with a try/catch clause.
|
|||||||
|
|
||||||
### Accessing the logger via dependency injection.
|
### Accessing the logger via dependency injection.
|
||||||
|
|
||||||
It can quite verbose to call `Injector::inst()->get('Logger')` all the time. More importantly, it also means that you're
|
It can quite verbose to call `Injector::inst()->get(LoggerInterface::class)` all the time. More importantly,
|
||||||
coupling your code to global state, which is a bad design practise. A better approach is to use depedency injection to
|
it also means that you're coupling your code to global state, which is a bad design practise. A better
|
||||||
pass the logger in for you. The [Injector](../extending/Injector) can help with this. The most straightforward is to
|
approach is to use depedency injection to pass the logger in for you. The [Injector](../extending/Injector)
|
||||||
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
|
||||||
class MyController {
|
class MyController {
|
||||||
|
|
||||||
private static $dependencies = array(
|
private static $dependencies = array(
|
||||||
'logger' => '%$Logger',
|
'logger' => '%$Psr\Log\LoggerInterface',
|
||||||
);
|
);
|
||||||
|
|
||||||
// This will be set automatically, as long as MyController is instantiated via Injector
|
// This will be set automatically, as long as MyController is instantiated via Injector
|
||||||
|
@ -12,8 +12,8 @@ interface CacheFactory extends InjectorFactory
|
|||||||
* Note: While the returned object is used as a singleton (by the originating Injector->get() call),
|
* Note: While the returned object is used as a singleton (by the originating Injector->get() call),
|
||||||
* this cache object shouldn't be a singleton itself - it has varying constructor args for the same service name.
|
* this cache object shouldn't be a singleton itself - it has varying constructor args for the same service name.
|
||||||
*
|
*
|
||||||
* @param string $class
|
* @param string $service
|
||||||
* @param array $args
|
* @param array $params
|
||||||
* @return CacheInterface
|
* @return CacheInterface
|
||||||
*/
|
*/
|
||||||
public function create($service, array $params = array());
|
public function create($service, array $params = array());
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Core\Cache;
|
namespace SilverStripe\Core\Cache;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerAwareInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Psr\SimpleCache\CacheInterface;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use Symfony\Component\Cache\Simple\FilesystemCache;
|
use Symfony\Component\Cache\Simple\FilesystemCache;
|
||||||
use Symfony\Component\Cache\Simple\ApcuCache;
|
use Symfony\Component\Cache\Simple\ApcuCache;
|
||||||
@ -20,25 +23,24 @@ use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
|
|||||||
*/
|
*/
|
||||||
class DefaultCacheFactory implements CacheFactory
|
class DefaultCacheFactory implements CacheFactory
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Absolute directory path
|
* @var string Absolute directory path
|
||||||
*/
|
*/
|
||||||
protected $directory;
|
protected $args = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string APC version for apcu_add()
|
* @var LoggerInterface
|
||||||
*/
|
*/
|
||||||
protected $version;
|
protected $logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $directory
|
* @param array $args List of global options to merge with args during create()
|
||||||
* @param string $version
|
* @param LoggerInterface $logger Logger instance to assign
|
||||||
*/
|
*/
|
||||||
public function __construct($directory, $version = null)
|
public function __construct($args = [], LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
$this->directory = $directory;
|
$this->args = $args;
|
||||||
$this->version = $version;
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,33 +48,76 @@ class DefaultCacheFactory implements CacheFactory
|
|||||||
*/
|
*/
|
||||||
public function create($service, array $args = array())
|
public function create($service, array $args = array())
|
||||||
{
|
{
|
||||||
$namespace = (isset($args['namespace'])) ? $args['namespace'] : '';
|
// merge args with default
|
||||||
$defaultLifetime = (isset($args['defaultLifetime'])) ? $args['defaultLifetime'] : 0;
|
$args = array_merge($this->args, $args);
|
||||||
$version = $this->version;
|
$namespace = isset($args['namespace']) ? $args['namespace'] : '';
|
||||||
$directory = $this->directory;
|
$defaultLifetime = isset($args['defaultLifetime']) ? $args['defaultLifetime'] : 0;
|
||||||
|
$directory = isset($args['directory']) ? $args['directory'] : null;
|
||||||
|
$version = isset($args['version']) ? $args['version'] : null;
|
||||||
|
|
||||||
$apcuSupported = null;
|
// Check support
|
||||||
$phpFilesSupported = null;
|
$apcuSupported = $this->isAPCUSupported();
|
||||||
|
$phpFilesSupported = $this->isPHPFilesSupported();
|
||||||
|
|
||||||
if (null === $apcuSupported) {
|
// If apcu isn't supported, phpfiles is the next best preference
|
||||||
$apcuSupported = ApcuAdapter::isSupported();
|
if (!$apcuSupported && $phpFilesSupported) {
|
||||||
|
return $this->createCache(PhpFilesCache::class, [$namespace, $defaultLifetime, $directory]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$apcuSupported && null === $phpFilesSupported) {
|
// Create filessytem cache
|
||||||
$phpFilesSupported = PhpFilesAdapter::isSupported();
|
$fs = $this->createCache(FilesystemCache::class, [$namespace, $defaultLifetime, $directory]);
|
||||||
}
|
|
||||||
|
|
||||||
if ($phpFilesSupported) {
|
|
||||||
$opcache = Injector::inst()->create(PhpFilesCache::class, $namespace, $defaultLifetime, $directory);
|
|
||||||
return $opcache;
|
|
||||||
}
|
|
||||||
|
|
||||||
$fs = Injector::inst()->create(FilesystemCache::class, $namespace, $defaultLifetime, $directory);
|
|
||||||
if (!$apcuSupported) {
|
if (!$apcuSupported) {
|
||||||
return $fs;
|
return $fs;
|
||||||
}
|
}
|
||||||
$apcu = Injector::inst()->create(ApcuCache::class, $namespace, (int) $defaultLifetime / 5, $version);
|
|
||||||
|
|
||||||
return Injector::inst()->create(ChainCache::class, [$apcu, $fs]);
|
// Chain this cache with ApcuCache
|
||||||
|
$apcu = $this->createCache(ApcuCache::class, [$namespace, (int) $defaultLifetime / 5, $version]);
|
||||||
|
return $this->createCache(ChainCache::class, [[$apcu, $fs]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if apcu is supported
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isAPCUSupported()
|
||||||
|
{
|
||||||
|
static $apcuSupported = null;
|
||||||
|
if (null === $apcuSupported) {
|
||||||
|
$apcuSupported = ApcuAdapter::isSupported();
|
||||||
|
}
|
||||||
|
return $apcuSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if PHP files is supported
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isPHPFilesSupported()
|
||||||
|
{
|
||||||
|
static $phpFilesSupported = null;
|
||||||
|
if (null === $phpFilesSupported) {
|
||||||
|
$phpFilesSupported = PhpFilesAdapter::isSupported();
|
||||||
|
}
|
||||||
|
return $phpFilesSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @param array $args
|
||||||
|
* @return CacheInterface
|
||||||
|
*/
|
||||||
|
protected function createCache($class, $args)
|
||||||
|
{
|
||||||
|
/** @var CacheInterface $cache */
|
||||||
|
$cache = Injector::inst()->createWithArgs($class, $args);
|
||||||
|
|
||||||
|
// Assign cache logger
|
||||||
|
if ($this->logger && $cache instanceof LoggerAwareInterface) {
|
||||||
|
$cache->setLogger($this->logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,8 @@ class Log
|
|||||||
*/
|
*/
|
||||||
public static function get_logger()
|
public static function get_logger()
|
||||||
{
|
{
|
||||||
Deprecation::notice('5.0', 'Use Injector::inst()->get(\'Logger\') instead');
|
Deprecation::notice('5.0', 'Use Injector::inst()->get(LoggerInterface::class) instead');
|
||||||
return Injector::inst()->get('Logger');
|
return Injector::inst()->get(LoggerInterface::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,7 +55,7 @@ class Log
|
|||||||
*/
|
*/
|
||||||
public static function log($message, $priority)
|
public static function log($message, $priority)
|
||||||
{
|
{
|
||||||
Deprecation::notice('5.0', 'Use Injector::inst()->get(\'Logger\')->log($priority, $message) instead');
|
Deprecation::notice('5.0', 'Use Injector::inst()->get(LoggerInterface::class)->log($priority, $message) instead');
|
||||||
Injector::inst()->get('Logger')->log($priority, $message);
|
Injector::inst()->get(LoggerInterface::class)->log($priority, $message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,17 +10,22 @@ use Monolog\ErrorHandler;
|
|||||||
*/
|
*/
|
||||||
class MonologErrorHandler
|
class MonologErrorHandler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
private $logger;
|
private $logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the PSR-3 logger to send errors & exceptions to
|
* Set the PSR-3 logger to send errors & exceptions to
|
||||||
|
*
|
||||||
|
* @param LoggerInterface $logger
|
||||||
*/
|
*/
|
||||||
function setLogger(LoggerInterface $logger)
|
public function setLogger(LoggerInterface $logger)
|
||||||
{
|
{
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
function start()
|
public function start()
|
||||||
{
|
{
|
||||||
if (!$this->logger) {
|
if (!$this->logger) {
|
||||||
throw new \InvalidArgumentException("No Logger property passed to MonologErrorHandler."
|
throw new \InvalidArgumentException("No Logger property passed to MonologErrorHandler."
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
use Monolog\Logger;
|
use Monolog\Logger;
|
||||||
use Monolog\Handler\StreamHandler;
|
use Monolog\Handler\StreamHandler;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use SilverStripe\Control\Email\Email;
|
use SilverStripe\Control\Email\Email;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\Dev\Install\DatabaseAdapterRegistry;
|
use SilverStripe\Dev\Install\DatabaseAdapterRegistry;
|
||||||
@ -138,7 +139,7 @@ if ($useBasicAuth = getenv('SS_USE_BASIC_AUTH')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($errorLog = getenv('SS_ERROR_LOG')) {
|
if ($errorLog = getenv('SS_ERROR_LOG')) {
|
||||||
$logger = Injector::inst()->get('Logger');
|
$logger = Injector::inst()->get(LoggerInterface::class);
|
||||||
if ($logger instanceof Logger) {
|
if ($logger instanceof Logger) {
|
||||||
$logger->pushHandler(new StreamHandler(BASE_PATH . '/' . $errorLog, Logger::WARNING));
|
$logger->pushHandler(new StreamHandler(BASE_PATH . '/' . $errorLog, Logger::WARNING));
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user