Added logger to classes that catch errors in order to log them

This commit is contained in:
Alejandro Celaya 2016-08-08 12:33:58 +02:00
parent fff058f44b
commit 34753ca7d3
8 changed files with 85 additions and 19 deletions

View File

@ -4,6 +4,8 @@ namespace Shlinkio\Shlink\Core\Action;
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
use Shlinkio\Shlink\Core\Service\VisitsTracker; use Shlinkio\Shlink\Core\Service\VisitsTracker;
@ -21,18 +23,27 @@ class RedirectAction implements MiddlewareInterface
* @var VisitsTrackerInterface * @var VisitsTrackerInterface
*/ */
private $visitTracker; private $visitTracker;
/**
* @var null|LoggerInterface
*/
private $logger;
/** /**
* RedirectMiddleware constructor. * RedirectMiddleware constructor.
* @param UrlShortenerInterface $urlShortener * @param UrlShortenerInterface $urlShortener
* @param VisitsTrackerInterface $visitTracker * @param VisitsTrackerInterface $visitTracker
* @param LoggerInterface|null $logger
* *
* @Inject({UrlShortener::class, VisitsTracker::class}) * @Inject({UrlShortener::class, VisitsTracker::class, "Logger_Shlink"})
*/ */
public function __construct(UrlShortenerInterface $urlShortener, VisitsTrackerInterface $visitTracker) public function __construct(
{ UrlShortenerInterface $urlShortener,
VisitsTrackerInterface $visitTracker,
LoggerInterface $logger = null
) {
$this->urlShortener = $urlShortener; $this->urlShortener = $urlShortener;
$this->visitTracker = $visitTracker; $this->visitTracker = $visitTracker;
$this->logger = $logger ?: new NullLogger();
} }
/** /**
@ -81,6 +92,7 @@ class RedirectAction implements MiddlewareInterface
return new RedirectResponse($longUrl); return new RedirectResponse($longUrl);
} catch (\Exception $e) { } catch (\Exception $e) {
// In case of error, dispatch 404 error // In case of error, dispatch 404 error
$this->logger->error('Error redirecting to long URL.' . PHP_EOL . $e);
return $this->notFoundResponse($request, $response, $out); return $this->notFoundResponse($request, $response, $out);
} }
} }

View File

@ -99,7 +99,7 @@ class UrlShortener implements UrlShortenerInterface
$this->em->close(); $this->em->close();
} }
throw new RuntimeException('An error occured while persisting the short URL', -1, $e); throw new RuntimeException('An error occurred while persisting the short URL', -1, $e);
} }
} }

View File

@ -3,10 +3,22 @@ namespace Shlinkio\Shlink\Rest\Action;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Zend\Stratigility\MiddlewareInterface; use Zend\Stratigility\MiddlewareInterface;
abstract class AbstractRestAction implements MiddlewareInterface abstract class AbstractRestAction implements MiddlewareInterface
{ {
/**
* @var LoggerInterface
*/
protected $logger;
public function __construct(LoggerInterface $logger = null)
{
$this->logger = $logger ?: new NullLogger();
}
/** /**
* Process an incoming request and/or response. * Process an incoming request and/or response.
* *

View File

@ -4,6 +4,7 @@ namespace Shlinkio\Shlink\Rest\Action;
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
@ -33,14 +34,17 @@ class CreateShortcodeAction extends AbstractRestAction
* @param UrlShortenerInterface|UrlShortener $urlShortener * @param UrlShortenerInterface|UrlShortener $urlShortener
* @param TranslatorInterface $translator * @param TranslatorInterface $translator
* @param array $domainConfig * @param array $domainConfig
* @param LoggerInterface|null $logger
* *
* @Inject({UrlShortener::class, "translator", "config.url_shortener.domain"}) * @Inject({UrlShortener::class, "translator", "config.url_shortener.domain", "Logger_Shlink"})
*/ */
public function __construct( public function __construct(
UrlShortenerInterface $urlShortener, UrlShortenerInterface $urlShortener,
TranslatorInterface $translator, TranslatorInterface $translator,
array $domainConfig array $domainConfig,
LoggerInterface $logger = null
) { ) {
parent::__construct($logger);
$this->urlShortener = $urlShortener; $this->urlShortener = $urlShortener;
$this->translator = $translator; $this->translator = $translator;
$this->domainConfig = $domainConfig; $this->domainConfig = $domainConfig;
@ -75,14 +79,16 @@ class CreateShortcodeAction extends AbstractRestAction
'shortCode' => $shortCode, 'shortCode' => $shortCode,
]); ]);
} catch (InvalidUrlException $e) { } catch (InvalidUrlException $e) {
$this->logger->warning('Provided Invalid URL.' . PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::getRestErrorCodeFromException($e), 'error' => RestUtils::getRestErrorCodeFromException($e),
'message' => sprintf( 'message' => sprintf(
$this->translator->translate('Provided URL "%s" is invalid. Try with a different one.'), $this->translator->translate('Provided URL %s is invalid. Try with a different one.'),
$longUrl $longUrl
), ),
], 400); ], 400);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Unexpected error creating shortcode.' . PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::UNKNOWN_ERROR, 'error' => RestUtils::UNKNOWN_ERROR,
'message' => $this->translator->translate('Unexpected error occurred'), 'message' => $this->translator->translate('Unexpected error occurred'),

View File

@ -4,6 +4,7 @@ namespace Shlinkio\Shlink\Rest\Action;
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException; use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
use Shlinkio\Shlink\Common\Util\DateRange; use Shlinkio\Shlink\Common\Util\DateRange;
use Shlinkio\Shlink\Core\Service\VisitsTracker; use Shlinkio\Shlink\Core\Service\VisitsTracker;
@ -27,11 +28,16 @@ class GetVisitsAction extends AbstractRestAction
* GetVisitsAction constructor. * GetVisitsAction constructor.
* @param VisitsTrackerInterface $visitsTracker * @param VisitsTrackerInterface $visitsTracker
* @param TranslatorInterface $translator * @param TranslatorInterface $translator
* @param LoggerInterface $logger
* *
* @Inject({VisitsTracker::class, "translator"}) * @Inject({VisitsTracker::class, "translator", "Logger_Shlink"})
*/ */
public function __construct(VisitsTrackerInterface $visitsTracker, TranslatorInterface $translator) public function __construct(
{ VisitsTrackerInterface $visitsTracker,
TranslatorInterface $translator,
LoggerInterface $logger = null
) {
parent::__construct($logger);
$this->visitsTracker = $visitsTracker; $this->visitsTracker = $visitsTracker;
$this->translator = $translator; $this->translator = $translator;
} }
@ -57,14 +63,16 @@ class GetVisitsAction extends AbstractRestAction
] ]
]); ]);
} catch (InvalidArgumentException $e) { } catch (InvalidArgumentException $e) {
$this->logger->warning('Provided nonexistent shortcode'. PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::getRestErrorCodeFromException($e), 'error' => RestUtils::getRestErrorCodeFromException($e),
'message' => sprintf( 'message' => sprintf(
$this->translator->translate('Provided short code "%s" does not exist'), $this->translator->translate('Provided short code %s does not exist'),
$shortCode $shortCode
), ),
], 404); ], 404);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Unexpected error while parsing short code'. PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::UNKNOWN_ERROR, 'error' => RestUtils::UNKNOWN_ERROR,
'message' => $this->translator->translate('Unexpected error occurred'), 'message' => $this->translator->translate('Unexpected error occurred'),

View File

@ -4,6 +4,8 @@ namespace Shlinkio\Shlink\Rest\Action;
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Shlinkio\Shlink\Common\Paginator\Util\PaginatorUtilsTrait; use Shlinkio\Shlink\Common\Paginator\Util\PaginatorUtilsTrait;
use Shlinkio\Shlink\Core\Service\ShortUrlService; use Shlinkio\Shlink\Core\Service\ShortUrlService;
use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface; use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
@ -28,11 +30,16 @@ class ListShortcodesAction extends AbstractRestAction
* ListShortcodesAction constructor. * ListShortcodesAction constructor.
* @param ShortUrlServiceInterface|ShortUrlService $shortUrlService * @param ShortUrlServiceInterface|ShortUrlService $shortUrlService
* @param TranslatorInterface $translator * @param TranslatorInterface $translator
* @param LoggerInterface $logger
* *
* @Inject({ShortUrlService::class, "translator"}) * @Inject({ShortUrlService::class, "translator", "Logger_Shlink"})
*/ */
public function __construct(ShortUrlServiceInterface $shortUrlService, TranslatorInterface $translator) public function __construct(
{ ShortUrlServiceInterface $shortUrlService,
TranslatorInterface $translator,
LoggerInterface $logger = null
) {
parent::__construct($logger);
$this->shortUrlService = $shortUrlService; $this->shortUrlService = $shortUrlService;
$this->translator = $translator; $this->translator = $translator;
} }
@ -50,6 +57,7 @@ class ListShortcodesAction extends AbstractRestAction
$shortUrls = $this->shortUrlService->listShortUrls(isset($query['page']) ? $query['page'] : 1); $shortUrls = $this->shortUrlService->listShortUrls(isset($query['page']) ? $query['page'] : 1);
return new JsonResponse(['shortUrls' => $this->serializePaginator($shortUrls)]); return new JsonResponse(['shortUrls' => $this->serializePaginator($shortUrls)]);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Unexpected error while listing short URLs.' . PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::UNKNOWN_ERROR, 'error' => RestUtils::UNKNOWN_ERROR,
'message' => $this->translator->translate('Unexpected error occurred'), 'message' => $this->translator->translate('Unexpected error occurred'),

View File

@ -4,6 +4,7 @@ namespace Shlinkio\Shlink\Rest\Action;
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
@ -26,11 +27,16 @@ class ResolveUrlAction extends AbstractRestAction
* ResolveUrlAction constructor. * ResolveUrlAction constructor.
* @param UrlShortenerInterface|UrlShortener $urlShortener * @param UrlShortenerInterface|UrlShortener $urlShortener
* @param TranslatorInterface $translator * @param TranslatorInterface $translator
* @param LoggerInterface $logger
* *
* @Inject({UrlShortener::class, "translator"}) * @Inject({UrlShortener::class, "translator"})
*/ */
public function __construct(UrlShortenerInterface $urlShortener, TranslatorInterface $translator) public function __construct(
{ UrlShortenerInterface $urlShortener,
TranslatorInterface $translator,
LoggerInterface $logger = null
) {
parent::__construct($logger);
$this->urlShortener = $urlShortener; $this->urlShortener = $urlShortener;
$this->translator = $translator; $this->translator = $translator;
} }
@ -58,6 +64,7 @@ class ResolveUrlAction extends AbstractRestAction
'longUrl' => $longUrl, 'longUrl' => $longUrl,
]); ]);
} catch (InvalidShortCodeException $e) { } catch (InvalidShortCodeException $e) {
$this->logger->warning('Provided short code with invalid format.' . PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::getRestErrorCodeFromException($e), 'error' => RestUtils::getRestErrorCodeFromException($e),
'message' => sprintf( 'message' => sprintf(
@ -66,6 +73,7 @@ class ResolveUrlAction extends AbstractRestAction
), ),
], 400); ], 400);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Unexpected error while resolving the URL behind a short code.' . PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::UNKNOWN_ERROR, 'error' => RestUtils::UNKNOWN_ERROR,
'message' => $this->translator->translate('Unexpected error occurred'), 'message' => $this->translator->translate('Unexpected error occurred'),

View File

@ -4,6 +4,8 @@ namespace Shlinkio\Shlink\Rest\Middleware;
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Shlinkio\Shlink\Rest\Authentication\JWTService; use Shlinkio\Shlink\Rest\Authentication\JWTService;
use Shlinkio\Shlink\Rest\Authentication\JWTServiceInterface; use Shlinkio\Shlink\Rest\Authentication\JWTServiceInterface;
use Shlinkio\Shlink\Rest\Exception\AuthenticationException; use Shlinkio\Shlink\Rest\Exception\AuthenticationException;
@ -25,18 +27,27 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
* @var JWTServiceInterface * @var JWTServiceInterface
*/ */
private $jwtService; private $jwtService;
/**
* @var LoggerInterface
*/
private $logger;
/** /**
* CheckAuthenticationMiddleware constructor. * CheckAuthenticationMiddleware constructor.
* @param JWTServiceInterface|JWTService $jwtService * @param JWTServiceInterface|JWTService $jwtService
* @param TranslatorInterface $translator * @param TranslatorInterface $translator
* @param LoggerInterface $logger
* *
* @Inject({JWTService::class, "translator"}) * @Inject({JWTService::class, "translator", "Logger_Shlink"})
*/ */
public function __construct(JWTServiceInterface $jwtService, TranslatorInterface $translator) public function __construct(
{ JWTServiceInterface $jwtService,
TranslatorInterface $translator,
LoggerInterface $logger = null
) {
$this->translator = $translator; $this->translator = $translator;
$this->jwtService = $jwtService; $this->jwtService = $jwtService;
$this->logger = $logger ?: new NullLogger();
} }
/** /**
@ -118,6 +129,7 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
// Return the response with the updated token on it // Return the response with the updated token on it
return $response->withHeader(self::AUTHORIZATION_HEADER, 'Bearer ' . $jwt); return $response->withHeader(self::AUTHORIZATION_HEADER, 'Bearer ' . $jwt);
} catch (AuthenticationException $e) { } catch (AuthenticationException $e) {
$this->logger->warning('Tried to access API with an invalid JWT.' . PHP_EOL . $e);
return $this->createTokenErrorResponse(); return $this->createTokenErrorResponse();
} }
} }