Hi. I am using Slim as API with tokens access and want to use psr-3 logger (monolog) to see the incoming requests. In particular, I want to see more detailed information about the user: id, email, role. The target log record should look like this:
[2021-05-11 15:32:48.011] uid [127.0.0.1.POST] NOTICE: 123/email@test.com/admin ... any other log info
To get this info first I add middleware, that search user by access token and add id, email & role as attributes to request:
class AddCurrentUserToRequestMiddleware implements MiddlewareInterface {
private $user;
public function __construct(Users $user) {
$this->user = $user;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
$token = $request->getHeaderLine('Authorization');
if ($token === NULL || ($user = $this->user->findByToken($token)) === NULL) {
throw new HttpUnauthorizedException($request);
}
return $handler->handle($request
->withAttribute('user.id', $user->getId())
->withAttribute('user.email', $user->getEmail())
->withAttribute('user.role', $user->getRole())
);
}
}
So, in logger I must get the request above. To do this, I wrote the custom processor which check the context
data of the record, and if instance of ServerRequestInterface
found, get user attributes from it:
class AddUserInfoProcessor implements ProcessorInterface {
public function __invoke(array $records): array {
foreach ($records['context'] as $context) {
if ($context instanceof ServerRequestInterface) {
$id = $context->getAttribute('user.id');
$login = $context->getAttribute('user.email');
$role = $context->getAttribute('user.role');
$message = empty($id) ? '-' : implode('/', [$id, $login, $role]);
$records['message'] = $message . ' | ' . $records['message'];
break;
}
}
return $records;
}
}
Finally, the logger must be call like this (using DI):
$app->get('/test', \App\Application\Actions\Controller1::class);
class Controller1 {
private $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
public function __invoke(ServerRequestInterface $request, ResponseInterface $response) {
$this->logger->notice('user want to do some action', [$request]);
$this->logger->notice('Any log info', [$request]);
if (...) {
$this->logger->error('Houston, we have a problem!', [$request]);
}
return $this->response->withStatus(...);
}
}
All work fine, but I’m not sure that adding [$this->request]
to every log command is a good thing.
Another trouble, if I want to log any other info (in business logic, for example), I must to forward $request
there. This look like piece of sh
Maybe there is another way with auto injecting the result request (after passing all middlewares) into the logger?