Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor excludeExceptionTypes handling #37

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 48 additions & 5 deletions Classes/Command/SentryCommandController.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

final class SentryCommandController extends CommandController
{
const TEST_MODE_MESSAGE = 'message';
const TEST_MODE_THROW = 'throw';
const TEST_MODE_ERROR = 'error';

/**
* @Flow\Inject
* @var SentryClient
Expand All @@ -39,13 +43,12 @@ final class SentryCommandController extends CommandController
*
* @throws SentryClientTestException
*/
public function testCommand(): void
public function testCommand(string $mode = self::TEST_MODE_THROW): void
{
$this->output->outputLine('<b>Testing Sentry setup …</b>');
$this->output->outputLine('Using the following configuration:');

$options = $this->sentryClient->getOptions();

$this->output->outputTable([
['DSN', $options->getDsn()],
['Environment', $options->getEnvironment()],
Expand All @@ -57,19 +60,59 @@ public function testCommand(): void
'Value'
]);

$eventId = $this->sentryClient->captureMessage(
switch ($mode) {
case self::TEST_MODE_MESSAGE:
$this->captureMessage();
break;
case self::TEST_MODE_THROW:
$this->throwException();
break;
case self::TEST_MODE_ERROR:
$this->triggerError();
break;
default:
$this->output->outputLine('<error>Unknown mode given</error>');
}
}

private function captureMessage(): void
{
$captureResult = $this->sentryClient->captureMessage(
'Flownative Sentry Plugin Test',
Severity::debug(),
[
'Flownative Sentry Client Version' => 'dev'
]
);

$this->outputLine('<success>An informational message was sent to Sentry</success> Event ID: #%s', [$eventId]);
$this->outputLine();
$this->outputLine('This command will now throw an exception for testing purposes.');
if ($captureResult->suceess) {
$this->outputLine('<success>An informational message was sent to Sentry</success> Event ID: #%s', [$captureResult->eventId]);
} else {
$this->outputLine('<error>Sending an informational message to Sentry failed</error>: %s', [$captureResult->message]);
}
$this->outputLine();
}

private function throwException(): void
{
$this->outputLine();
$this->outputLine('This command will now throw an exception for testing purposes.');
$this->outputLine();
(new ThrowingClass())->throwException(new StringableTestArgument((string)M_PI));
}

private function triggerError(): void
{
$this->outputLine();
$this->outputLine('This command will now cause a return type error for testing purposes.');
$this->outputLine();

$function = static function (): int {
/** @noinspection PhpStrictTypeCheckingInspection */
return 'wrong type';
};
/** @noinspection PhpExpressionResultUnusedInspection */
$function();
}
}
64 changes: 42 additions & 22 deletions Classes/Log/SentryFileBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@

use Flownative\Sentry\SentryClientTrait;
use Neos\Flow\Log\Backend\FileBackend;
use Sentry\Severity;
use Sentry\Breadcrumb;
use Sentry\SentrySdk;

class SentryFileBackend extends FileBackend
{
use SentryClientTrait;

private bool $capturingMessage = false;

/**
* Appends the given message along with the additional information into the log.
*
Expand All @@ -36,29 +35,50 @@ class SentryFileBackend extends FileBackend
*/
public function append(string $message, int $severity = LOG_INFO, $additionalData = null, ?string $packageKey = null, ?string $className = null, ?string $methodName = null): void
{
if ($this->capturingMessage) {
return;
try {
SentrySdk::getCurrentHub()->addBreadcrumb(
new Breadcrumb(
$this->getBreadcrumbLevel($severity),
$this->getBreadcrumbType($severity),
basename($this->logFileUrl),
$message,
($additionalData ?? []) + array_filter([
'packageKey' => $packageKey, 'className' => $className, 'methodName' => $methodName
]),
time()
)
);
} catch (\Throwable $throwable) {
parent::append(
sprintf('%s (%s)', $throwable->getMessage(), $throwable->getCode()),
LOG_WARNING,
null,
'Flownative.Sentry',
__CLASS__,
__METHOD__
);
}

try {
$this->capturingMessage = true;
parent::append($message, $severity, $additionalData, $packageKey, $className, $methodName);
}

$sentryClient = self::getSentryClient();
if ($severity <= LOG_NOTICE && $sentryClient) {
$sentrySeverity = match ($severity) {
LOG_WARNING => Severity::warning(),
LOG_ERR => Severity::error(),
LOG_CRIT, LOG_ALERT, LOG_EMERG => Severity::fatal(),
default => Severity::info(),
};
private function getBreadcrumbLevel(int $severity): string
{
return match ($severity) {
LOG_EMERG, LOG_ALERT, LOG_CRIT => Breadcrumb::LEVEL_FATAL,
LOG_ERR => Breadcrumb::LEVEL_ERROR,
LOG_WARNING => Breadcrumb::LEVEL_WARNING,
LOG_NOTICE, LOG_INFO => Breadcrumb::LEVEL_INFO,
default => Breadcrumb::LEVEL_DEBUG,
};
}

$sentryClient->captureMessage($message, $sentrySeverity, ['Additional Data' => $additionalData]);
}
parent::append($message, $severity, $additionalData, $packageKey, $className, $methodName);
} catch (\Throwable $throwable) {
echo sprintf('SentryFileBackend: %s (%s)', $throwable->getMessage(), $throwable->getCode());
} finally {
$this->capturingMessage = false;
private function getBreadcrumbType(int $severity): string
{
if ($severity >= LOG_ERR) {
return Breadcrumb::TYPE_ERROR;
}

return Breadcrumb::TYPE_DEFAULT;
}
}
24 changes: 24 additions & 0 deletions Classes/Package.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);

namespace Flownative\Sentry;

use Neos\Flow\Core\Booting\Sequence;
use Neos\Flow\Core\Bootstrap;
use Neos\Flow\Package\Package as BasePackage;

class Package extends BasePackage
{
public function boot(Bootstrap $bootstrap)
{
$dispatcher = $bootstrap->getSignalSlotDispatcher();

$dispatcher->connect(Sequence::class, 'afterInvokeStep', function ($step) {
if ($step->getIdentifier() === 'neos.flow:objectmanagement:runtime') {
// instantiate client to set up Sentry and register error handler early
/** @noinspection PhpExpressionResultUnusedInspection */
new SentryClient();
}
});
}
}
Loading