ok
Direktori : /home2/selectio/www/3-idiots/vendor/laravel/framework/src/Illuminate/Log/ |
Current File : //home2/selectio/www/3-idiots/vendor/laravel/framework/src/Illuminate/Log/LogManager.php |
<?php namespace Illuminate\Log; use Closure; use Illuminate\Support\Str; use InvalidArgumentException; use Monolog\Formatter\LineFormatter; use Monolog\Handler\ErrorLogHandler; use Monolog\Handler\FingersCrossedHandler; use Monolog\Handler\FormattableHandlerInterface; use Monolog\Handler\HandlerInterface; use Monolog\Handler\RotatingFileHandler; use Monolog\Handler\SlackWebhookHandler; use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogHandler; use Monolog\Handler\WhatFailureGroupHandler; use Monolog\Logger as Monolog; use Psr\Log\LoggerInterface; use Throwable; class LogManager implements LoggerInterface { use ParsesLogConfiguration; /** * The application instance. * * @var \Illuminate\Contracts\Foundation\Application */ protected $app; /** * The array of resolved channels. * * @var array */ protected $channels = []; /** * The registered custom driver creators. * * @var array */ protected $customCreators = []; /** * The standard date format to use when writing logs. * * @var string */ protected $dateFormat = 'Y-m-d H:i:s'; /** * Create a new Log manager instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public function __construct($app) { $this->app = $app; } /** * Build an on-demand log channel. * * @param array $config * @return \Psr\Log\LoggerInterface */ public function build(array $config) { unset($this->channels['ondemand']); return $this->get('ondemand', $config); } /** * Create a new, on-demand aggregate logger instance. * * @param array $channels * @param string|null $channel * @return \Psr\Log\LoggerInterface */ public function stack(array $channels, $channel = null) { return new Logger( $this->createStackDriver(compact('channels', 'channel')), $this->app['events'] ); } /** * Get a log channel instance. * * @param string|null $channel * @return \Psr\Log\LoggerInterface */ public function channel($channel = null) { return $this->driver($channel); } /** * Get a log driver instance. * * @param string|null $driver * @return \Psr\Log\LoggerInterface */ public function driver($driver = null) { return $this->get($this->parseDriver($driver)); } /** * Attempt to get the log from the local cache. * * @param string $name * @param array|null $config * @return \Psr\Log\LoggerInterface */ protected function get($name, ?array $config = null) { try { return $this->channels[$name] ?? with($this->resolve($name, $config), function ($logger) use ($name) { return $this->channels[$name] = $this->tap($name, new Logger($logger, $this->app['events'])); }); } catch (Throwable $e) { return tap($this->createEmergencyLogger(), function ($logger) use ($e) { $logger->emergency('Unable to create configured logger. Using emergency logger.', [ 'exception' => $e, ]); }); } } /** * Apply the configured taps for the logger. * * @param string $name * @param \Illuminate\Log\Logger $logger * @return \Illuminate\Log\Logger */ protected function tap($name, Logger $logger) { foreach ($this->configurationFor($name)['tap'] ?? [] as $tap) { [$class, $arguments] = $this->parseTap($tap); $this->app->make($class)->__invoke($logger, ...explode(',', $arguments)); } return $logger; } /** * Parse the given tap class string into a class name and arguments string. * * @param string $tap * @return array */ protected function parseTap($tap) { return Str::contains($tap, ':') ? explode(':', $tap, 2) : [$tap, '']; } /** * Create an emergency log handler to avoid white screens of death. * * @return \Psr\Log\LoggerInterface */ protected function createEmergencyLogger() { $config = $this->configurationFor('emergency'); $handler = new StreamHandler( $config['path'] ?? $this->app->storagePath().'/logs/laravel.log', $this->level(['level' => 'debug']) ); return new Logger( new Monolog('laravel', $this->prepareHandlers([$handler])), $this->app['events'] ); } /** * Resolve the given log instance by name. * * @param string $name * @param array|null $config * @return \Psr\Log\LoggerInterface * * @throws \InvalidArgumentException */ protected function resolve($name, ?array $config = null) { $config = $config ?? $this->configurationFor($name); if (is_null($config)) { throw new InvalidArgumentException("Log [{$name}] is not defined."); } if (isset($this->customCreators[$config['driver']])) { return $this->callCustomCreator($config); } $driverMethod = 'create'.ucfirst($config['driver']).'Driver'; if (method_exists($this, $driverMethod)) { return $this->{$driverMethod}($config); } throw new InvalidArgumentException("Driver [{$config['driver']}] is not supported."); } /** * Call a custom driver creator. * * @param array $config * @return mixed */ protected function callCustomCreator(array $config) { return $this->customCreators[$config['driver']]($this->app, $config); } /** * Create a custom log driver instance. * * @param array $config * @return \Psr\Log\LoggerInterface */ protected function createCustomDriver(array $config) { $factory = is_callable($via = $config['via']) ? $via : $this->app->make($via); return $factory($config); } /** * Create an aggregate log driver instance. * * @param array $config * @return \Psr\Log\LoggerInterface */ protected function createStackDriver(array $config) { if (is_string($config['channels'])) { $config['channels'] = explode(',', $config['channels']); } $handlers = collect($config['channels'])->flatMap(function ($channel) { return $channel instanceof LoggerInterface ? $channel->getHandlers() : $this->channel($channel)->getHandlers(); })->all(); $processors = collect($config['channels'])->flatMap(function ($channel) { return $channel instanceof LoggerInterface ? $channel->getProcessors() : $this->channel($channel)->getProcessors(); })->all(); if ($config['ignore_exceptions'] ?? false) { $handlers = [new WhatFailureGroupHandler($handlers)]; } return new Monolog($this->parseChannel($config), $handlers, $processors); } /** * Create an instance of the single file log driver. * * @param array $config * @return \Psr\Log\LoggerInterface */ protected function createSingleDriver(array $config) { return new Monolog($this->parseChannel($config), [ $this->prepareHandler( new StreamHandler( $config['path'], $this->level($config), $config['bubble'] ?? true, $config['permission'] ?? null, $config['locking'] ?? false ), $config ), ]); } /** * Create an instance of the daily file log driver. * * @param array $config * @return \Psr\Log\LoggerInterface */ protected function createDailyDriver(array $config) { return new Monolog($this->parseChannel($config), [ $this->prepareHandler(new RotatingFileHandler( $config['path'], $config['days'] ?? 7, $this->level($config), $config['bubble'] ?? true, $config['permission'] ?? null, $config['locking'] ?? false ), $config), ]); } /** * Create an instance of the Slack log driver. * * @param array $config * @return \Psr\Log\LoggerInterface */ protected function createSlackDriver(array $config) { return new Monolog($this->parseChannel($config), [ $this->prepareHandler(new SlackWebhookHandler( $config['url'], $config['channel'] ?? null, $config['username'] ?? 'Laravel', $config['attachment'] ?? true, $config['emoji'] ?? ':boom:', $config['short'] ?? false, $config['context'] ?? true, $this->level($config), $config['bubble'] ?? true, $config['exclude_fields'] ?? [] ), $config), ]); } /** * Create an instance of the syslog log driver. * * @param array $config * @return \Psr\Log\LoggerInterface */ protected function createSyslogDriver(array $config) { return new Monolog($this->parseChannel($config), [ $this->prepareHandler(new SyslogHandler( Str::snake($this->app['config']['app.name'], '-'), $config['facility'] ?? LOG_USER, $this->level($config) ), $config), ]); } /** * Create an instance of the "error log" log driver. * * @param array $config * @return \Psr\Log\LoggerInterface */ protected function createErrorlogDriver(array $config) { return new Monolog($this->parseChannel($config), [ $this->prepareHandler(new ErrorLogHandler( $config['type'] ?? ErrorLogHandler::OPERATING_SYSTEM, $this->level($config) )), ]); } /** * Create an instance of any handler available in Monolog. * * @param array $config * @return \Psr\Log\LoggerInterface * * @throws \InvalidArgumentException * @throws \Illuminate\Contracts\Container\BindingResolutionException */ protected function createMonologDriver(array $config) { if (! is_a($config['handler'], HandlerInterface::class, true)) { throw new InvalidArgumentException( $config['handler'].' must be an instance of '.HandlerInterface::class ); } $with = array_merge( ['level' => $this->level($config)], $config['with'] ?? [], $config['handler_with'] ?? [] ); return new Monolog($this->parseChannel($config), [$this->prepareHandler( $this->app->make($config['handler'], $with), $config )]); } /** * Prepare the handlers for usage by Monolog. * * @param array $handlers * @return array */ protected function prepareHandlers(array $handlers) { foreach ($handlers as $key => $handler) { $handlers[$key] = $this->prepareHandler($handler); } return $handlers; } /** * Prepare the handler for usage by Monolog. * * @param \Monolog\Handler\HandlerInterface $handler * @param array $config * @return \Monolog\Handler\HandlerInterface */ protected function prepareHandler(HandlerInterface $handler, array $config = []) { if (isset($config['action_level'])) { $handler = new FingersCrossedHandler($handler, $this->actionLevel($config)); } if (Monolog::API !== 1 && (Monolog::API !== 2 || ! $handler instanceof FormattableHandlerInterface)) { return $handler; } if (! isset($config['formatter'])) { $handler->setFormatter($this->formatter()); } elseif ($config['formatter'] !== 'default') { $handler->setFormatter($this->app->make($config['formatter'], $config['formatter_with'] ?? [])); } return $handler; } /** * Get a Monolog formatter instance. * * @return \Monolog\Formatter\FormatterInterface */ protected function formatter() { return tap(new LineFormatter(null, $this->dateFormat, true, true), function ($formatter) { $formatter->includeStacktraces(); }); } /** * Get fallback log channel name. * * @return string */ protected function getFallbackChannelName() { return $this->app->bound('env') ? $this->app->environment() : 'production'; } /** * Get the log connection configuration. * * @param string $name * @return array */ protected function configurationFor($name) { return $this->app['config']["logging.channels.{$name}"]; } /** * Get the default log driver name. * * @return string|null */ public function getDefaultDriver() { return $this->app['config']['logging.default']; } /** * Set the default log driver name. * * @param string $name * @return void */ public function setDefaultDriver($name) { $this->app['config']['logging.default'] = $name; } /** * Register a custom driver creator Closure. * * @param string $driver * @param \Closure $callback * @return $this */ public function extend($driver, Closure $callback) { $this->customCreators[$driver] = $callback->bindTo($this, $this); return $this; } /** * Unset the given channel instance. * * @param string|null $driver * @return $this */ public function forgetChannel($driver = null) { $driver = $this->parseDriver($driver); if (isset($this->channels[$driver])) { unset($this->channels[$driver]); } } /** * Parse the driver name. * * @param string|null $driver * @return string|null */ protected function parseDriver($driver) { $driver = $driver ?? $this->getDefaultDriver(); if ($this->app->runningUnitTests()) { $driver = $driver ?? 'null'; } return $driver; } /** * Get all of the resolved log channels. * * @return array */ public function getChannels() { return $this->channels; } /** * System is unusable. * * @param string $message * @param array $context * @return void */ public function emergency($message, array $context = []) { $this->driver()->emergency($message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * @return void */ public function alert($message, array $context = []) { $this->driver()->alert($message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * @return void */ public function critical($message, array $context = []) { $this->driver()->critical($message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * @return void */ public function error($message, array $context = []) { $this->driver()->error($message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * @return void */ public function warning($message, array $context = []) { $this->driver()->warning($message, $context); } /** * Normal but significant events. * * @param string $message * @param array $context * @return void */ public function notice($message, array $context = []) { $this->driver()->notice($message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * @return void */ public function info($message, array $context = []) { $this->driver()->info($message, $context); } /** * Detailed debug information. * * @param string $message * @param array $context * @return void */ public function debug($message, array $context = []) { $this->driver()->debug($message, $context); } /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * @return void */ public function log($level, $message, array $context = []) { $this->driver()->log($level, $message, $context); } /** * Dynamically call the default driver instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->driver()->$method(...$parameters); } }