Skip to content
This repository has been archived by the owner on Dec 19, 2019. It is now read-only.

GraphQl-220: Implement exception logging #355

Merged
57 changes: 57 additions & 0 deletions app/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1768,4 +1768,61 @@
<preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface" type="Magento\Framework\MessageQueue\PoisonPill\PoisonPillPut"/>
<preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillReadInterface" type="Magento\Framework\MessageQueue\PoisonPill\PoisonPillRead"/>
<preference for="Magento\Framework\MessageQueue\CallbackInvokerInterface" type="Magento\Framework\MessageQueue\CallbackInvoker"/>
<preference for="\Magento\Framework\GraphQl\Query\ErrorHandlerInterface" type="\Magento\Framework\GraphQl\Query\ErrorHandler"/>
novikor marked this conversation as resolved.
Show resolved Hide resolved
<type name="\Magento\Framework\GraphQl\Query\ErrorHandler">
<arguments>
<argument name="clientLogger" xsi:type="object">GraphQLClientLogger</argument>
<argument name="serverLogger" xsi:type="object">GraphQLServerLogger</argument>
<argument name="generalLogger" xsi:type="object">GraphQLGeneralLogger</argument>
<argument name="clientErrorCategories" xsi:type="array">
<item name="graphql" xsi:type="const">\GraphQL\Error\Error::CATEGORY_GRAPHQL</item>
<item name="alreadyExists" xsi:type="const">\Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException::EXCEPTION_CATEGORY</item>
<item name="authentication" xsi:type="const">\Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException::EXCEPTION_CATEGORY</item>
<item name="authorization" xsi:type="const">\Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException::EXCEPTION_CATEGORY</item>
<item name="input" xsi:type="const">\Magento\Framework\GraphQl\Exception\GraphQlInputException::EXCEPTION_CATEGORY</item>
<item name="noSuchEntity" xsi:type="const">\Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException::EXCEPTION_CATEGORY</item>
<item name="request" xsi:type="string">request</item>
novikor marked this conversation as resolved.
Show resolved Hide resolved
<item name="user" xsi:type="string">user</item>
</argument>
<argument name="serverErrorCategories" xsi:type="array">
<item name="internal" xsi:type="const">\GraphQL\Error\Error::CATEGORY_INTERNAL</item>
</argument>
</arguments>
</type>
<virtualType name="GraphQLClientLogger" type="Magento\Framework\Logger\Monolog">
<arguments>
<argument name="handlers" xsi:type="array">
<item name="error" xsi:type="object">GraphQLClientErrorHandler</item>
</argument>
</arguments>
</virtualType>
<virtualType name="GraphQLClientErrorHandler" type="\Magento\Framework\Logger\Handler\Base">
<arguments>
<argument name="fileName" xsi:type="const">\Magento\Framework\GraphQl\Query\ErrorHandlerInterface::CLIENT_LOG_FILE</argument>
</arguments>
</virtualType>
<virtualType name="GraphQLServerLogger" type="Magento\Framework\Logger\Monolog">
<arguments>
<argument name="handlers" xsi:type="array">
<item name="error" xsi:type="object">GraphQLServerErrorHandler</item>
</argument>
</arguments>
</virtualType>
<virtualType name="GraphQLServerErrorHandler" type="\Magento\Framework\Logger\Handler\Base">
<arguments>
<argument name="fileName" xsi:type="const">\Magento\Framework\GraphQl\Query\ErrorHandlerInterface::SERVER_LOG_FILE</argument>
</arguments>
</virtualType>
<virtualType name="GraphQLGeneralLogger" type="Magento\Framework\Logger\Monolog">
<arguments>
<argument name="handlers" xsi:type="array">
<item name="error" xsi:type="object">GraphQLGeneralErrorHandler</item>
</argument>
</arguments>
</virtualType>
<virtualType name="GraphQLGeneralErrorHandler" type="\Magento\Framework\Logger\Handler\Base">
<arguments>
<argument name="fileName" xsi:type="const">\Magento\Framework\GraphQl\Query\ErrorHandlerInterface::GENERAL_LOG_FILE</argument>
</arguments>
</virtualType>
</config>
102 changes: 102 additions & 0 deletions lib/internal/Magento/Framework/GraphQl/Query/ErrorHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Framework\GraphQl\Query;

/**
* Class ErrorHandler
*
* @package Magento\Framework\GraphQl\Query
*/
class ErrorHandler implements ErrorHandlerInterface
{
/**
* @var \Magento\Framework\Logger\Monolog
*/
private $clientLogger;

/**
* @var \Magento\Framework\Logger\Monolog
*/
private $serverLogger;

/**
* @var array
*/
private $clientErrorCategories;

/**
* @var array
*/
private $serverErrorCategories;

/**
* @var \Magento\Framework\Logger\Monolog
*/
private $generalLogger;

/**
* ErrorHandler constructor.
*
* @param \Magento\Framework\Logger\Monolog $clientLogger
novikor marked this conversation as resolved.
Show resolved Hide resolved
* @param \Magento\Framework\Logger\Monolog $serverLogger
* @param \Magento\Framework\Logger\Monolog $generalLogger
* @param array $clientErrorCategories
* @param array $serverErrorCategories
*
* @SuppressWarnings(PHPMD.LongVariable)
*/
public function __construct(
\Magento\Framework\Logger\Monolog $clientLogger,
\Magento\Framework\Logger\Monolog $serverLogger,
\Magento\Framework\Logger\Monolog $generalLogger,
array $clientErrorCategories = [],
array $serverErrorCategories = []
) {
$this->clientLogger = $clientLogger;
$this->serverLogger = $serverLogger;
$this->generalLogger = $generalLogger;
$this->clientErrorCategories = $clientErrorCategories;
$this->serverErrorCategories = $serverErrorCategories;
}

/**
* Handle errors
*
* @param \GraphQL\Error\Error[] $errors
* @param callable $formatter
*
* @return array
*/
public function handle(array $errors, callable $formatter):array
novikor marked this conversation as resolved.
Show resolved Hide resolved
{
return array_map(
function (\GraphQL\Error\ClientAware $error) use ($formatter) {
$this->logError($error);

return $formatter($error);
},
$errors
);
}

/**
* @param \GraphQL\Error\ClientAware $error
*
* @return boolean
*/
private function logError(\GraphQL\Error\ClientAware $error):bool
vpodorozh marked this conversation as resolved.
Show resolved Hide resolved
{
if (in_array($error->getCategory(), $this->clientErrorCategories)) {
novikor marked this conversation as resolved.
Show resolved Hide resolved
return $this->clientLogger->error($error);
} elseif (in_array($error->getCategory(), $this->serverErrorCategories)) {
return $this->serverLogger->error($error);
}

return $this->generalLogger->error($error);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Framework\GraphQl\Query;

/**
* Interface ErrorHandlerInterface
*
* @package Magento\Framework\GraphQl\Query
*/
interface ErrorHandlerInterface
{
const SERVER_LOG_FILE = 'var/log/graphql/server/exception.log';
novikor marked this conversation as resolved.
Show resolved Hide resolved
const CLIENT_LOG_FILE = 'var/log/graphql/client/exception.log';
const GENERAL_LOG_FILE = 'var/log/graphql/exception.log';
/**
* Handle errors
*
* @param \GraphQL\Error\Error[] $errors
* @param callable $formatter
*
* @return array
*/
public function handle(array $errors, callable $formatter):array;
}
20 changes: 16 additions & 4 deletions lib/internal/Magento/Framework/GraphQl/Query/QueryProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
namespace Magento\Framework\GraphQl\Query;

use Magento\Framework\GraphQl\Exception\ExceptionFormatter;
use Magento\Framework\GraphQl\Schema;
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
use Magento\Framework\GraphQl\Schema;

/**
* Wrapper for GraphQl execution of a schema
Expand All @@ -27,15 +27,25 @@ class QueryProcessor
private $queryComplexityLimiter;

/**
* @param ExceptionFormatter $exceptionFormatter
* @param QueryComplexityLimiter $queryComplexityLimiter
* @var \Magento\Framework\GraphQl\Query\ErrorHandlerInterface
*/
private $errorHandler;

/**
* @param ExceptionFormatter $exceptionFormatter
* @param QueryComplexityLimiter $queryComplexityLimiter
*
* @param \Magento\Framework\GraphQl\Query\ErrorHandlerInterface $errorHandler
* @SuppressWarnings(PHPMD.LongVariable)
*/
public function __construct(
ExceptionFormatter $exceptionFormatter,
QueryComplexityLimiter $queryComplexityLimiter
QueryComplexityLimiter $queryComplexityLimiter,
ErrorHandlerInterface $errorHandler
) {
$this->exceptionFormatter = $exceptionFormatter;
$this->queryComplexityLimiter = $queryComplexityLimiter;
$this->errorHandler = $errorHandler;
}

/**
Expand Down Expand Up @@ -67,6 +77,8 @@ public function process(
$contextValue,
$variableValues,
$operationName
)->setErrorsHandler(
[$this->errorHandler, 'handle']
)->toArray(
$this->exceptionFormatter->shouldShowDetail() ?
\GraphQL\Error\Debug::INCLUDE_DEBUG_MESSAGE : false
Expand Down