Я хочу добавить текущий аутентифицированный идентификатор пользователя в строки журнала (я использую драйвер системного журнала) в качестве настраиваемого форматирования журнала.
В рамках своего исследования я обнаружил, что есть хорошие пакеты и учебные пособия для регистрации активности пользователя в базе данных. Но, по крайней мере, на данный момент я намерен двигаться вперед без дополнительных пакетов и регистрации в системный журнал, как я сейчас делаю.
Типичный вызов журнала в моем приложении будет выглядеть так:
logger()->info("Listing all items");
Еще я мог бы сделать что-нибудь вроде:
$uid = Auth::id();
logger()->info("Listing all items for {$uid}");
Это было бы похоже на то, что предлагает пример документации:
В настоящее время я делаю это для определенных строк, но поскольку я хотел бы, чтобы это было во всех вызовах журнала, это стало бы похоже на повторение себя каждый раз, когда я что-то регистрирую.
Текущий:
Dec 10 23:54:05 trinsic Laravel[13606]: local.INFO: Hello world []
Желанный:
Dec 10 23:54:05 trinsic Laravel[13606]: local.INFO [AUTH_USER_ID=2452]: Hello world []
Я попытался кран регистратора с успехом при изменении формата, как предложено в документах.
Но моя текущая проблема заключается в том, что в момент исключения класса CustomizeFormatter идентификатор Auth, похоже, еще не решен (не уверен в этом, но dd() возвращает null, так что это мое предположение):
<?php
namespace App\Logging;
use Illuminate\Support\Facades\Auth;
use Monolog\Formatter\LineFormatter;
class CustomizeFormatter
{
/**
* Customize the given logger instance.
*
* @param \Illuminate\Log\Logger $logger
* @return void
*/
public function __invoke($logger)
{
$authUser = Auth::id(); // null
foreach ($logger->getHandlers() as $handler) {
$formatter = new LineFormatter("%channel%.%level_name% [AUTH = {$authUser}]: %message% %extra%");
$handler->setFormatter($formatter);
}
}
}
Laravel 5.7
Драйвер журнала: syslog
// config/logging.php
'syslog' => [
'driver' => 'syslog',
'tap' => [ App\Logging\CustomizeFormatter::class ],
'level' => 'debug',
],






Попробуйте передать объект запроса в качестве аргумента конструктора в свой собственный класс средства форматирования, а затем получить доступ к пользователю оттуда:
<?php
namespace App\Logging;
use Illuminate\Support\Facades\Auth;
use Monolog\Formatter\LineFormatter;
class CustomizeFormatter
{
public $request;
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Customize the given logger instance.
*
* @param \Illuminate\Log\Logger $logger
* @return void
*/
public function __invoke($logger)
{
$authUser = $this->request->user();
foreach ($logger->getHandlers() as $handler) {
$formatter = new LineFormatter("%channel%.%level_name% [AUTH = {$authUser->id}]: %message% %extra%");
$handler->setFormatter($formatter);
}
}
}
dd($this->request) прямо в __invoke($logger). Я подозреваю, что это потому, что \Illuminate\Session\Middleware\AuthenticateSession::class, запускается много раз после настройки журналирования? Но на самом деле не уверен в этом.
Если вы используете dd($this->request->user()); сразу после присваивания в конструкторе, что будет на выходе?
Сразу после присваивания в конструкторе или сразу после получения __invoke в обоих случаях он возвращает null.
Другой возможный вариант - расширить или обернуть Illuminate \ Log \ Logger и разрешить и добавить идентификатор пользователя аутентификации в этой точке.
На основании ответа DigitalDrifter и части это сообщение Эмира Каршиякалы мне удалось получить достаточно справедливое решение.
Мне не удалось получить идентификатор пользователя, поскольку (насколько я понимаю на данный момент) он еще не может быть решен. Но я был удовлетворен получением более или менее точного идентификатора клиента и идентификатора сеанса, поэтому я могу отслеживать поток взаимодействия с пользователем в журналах:
<?php
namespace App\Loggers;
use Monolog\Formatter\LineFormatter;
class LocalLogger
{
private $request;
public function __construct(\Illuminate\Http\Request $request)
{
$this->request = $request;
}
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter($this->getLogFormatter());
}
}
protected function getLogFormatter()
{
$uniqueClientId = $this->getUniqueClientId();
$format = str_replace(
'[%datetime%] ',
sprintf('[%%datetime%%] %s ', $uniqueClientId),
LineFormatter::SIMPLE_FORMAT
);
return new LineFormatter($format, null, true, true);
}
protected function getUniqueClientId()
{
$clientId = md5($this->request->server('HTTP_USER_AGENT').'/'.$this->request->ip());
$sessionId = \Session::getId();
return "[{$clientId}:{$sessionId}]";
}
}
Конфиг:
// config/logger.php
'syslog' => [
'driver' => 'syslog',
'level' => 'debug',
'tap' => [App\Loggers\LocalLogger::class],
],
Теперь я могу получить что-то вроде:
Dec 11 13:54:13 trinsic Fimedi[13390]: [2018-12-11 16:54:13] c6c6cb03fafd4b31493478e76b490650 local.INFO: Hello world
или
Dec 11 13:55:44 trinsic Fimedi[13390]: [2018-12-11 16:55:44] [c6c6cb03fafd4b31493478e76b490650:xUs2WxIb3TvKcpCpFNPFyvBChE88Nk0YbwZI3KrY] local.INFO: Hello world
В зависимости от того, как я рассчитываю идентификаторы пользователя / сеанса.
Спасибо за подсказку, @DigitalDrifter. Имеет большой смысл заставить Laravel разрешить объект запроса и получить оттуда доступ к пользователю auth, и мы, кажется, приближаемся к проблеме. Однако, несмотря на то, что объект запроса доступен, пользователь (
$this->request->user()) возвращает значение null. (Я проверяю, что я вошел в систему, поэтому я не бегаю с консоли или чего-то подобного).