Files
2025-08-02 16:30:27 +02:00

364 lines
13 KiB
PHP

<?php
namespace KupShop\KupShopBundle\Util\Logging;
use Composer\InstalledVersions;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Util\RequestUtil;
use Sentry\Event;
use Sentry\EventHint;
use Sentry\EventId;
use Sentry\Frame;
use Sentry\Integration\ErrorListenerIntegration;
use Sentry\Integration\ExceptionListenerIntegration;
use Sentry\Integration\FatalErrorListenerIntegration;
use Sentry\Integration\ModulesIntegration;
use Sentry\Stacktrace;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Contracts\Service\Attribute\Required;
if (InstalledVersions::getVersion('sentry/sentry') <= 2) {
#[AllowDynamicProperties]
class SentryLogger extends \Raven_Client
{
public const CHANNEL_ADMIN = 'admin';
public const CHANNEL_SYNC = 'sync';
public const CHANNEL_CRON = 'cron';
public const CHANNEL_FE = 'front-end';
public const CHANNEL_UPGRADE = 'upgrade';
protected ?string $channel = null;
public function __construct()
{
if (isDebug()) {
parent::__construct('http://156f2fdb588b4f23828c32ff878738cc:bc790801af7449b29c0ae807bb66d623@localhost/3', [
'install_default_breadcrumb_handlers' => false,
'install_shutdown_handler' => false,
]);
} else {
parent::__construct('http://156f2fdb588b4f23828c32ff878738cc:bc790801af7449b29c0ae807bb66d623@sentry.wpj.cz/3');
}
global $cfg;
$engine = getenv('KUPSHOP_ENGINE');
if (isAutoDeploy() && !empty($engine)) {
$this->setRelease($engine);
} else {
$this->setRelease($cfg['Program']['version']['folder']);
}
$branch = getShopName();
if (isAutoDeploy() && !empty($branch)) {
$web = $branch;
} else {
$web = substr($cfg['Connection']['database'], 8);
}
$env = 'production';
if (isDevelopment() && !isLocalDevelopment()) {
$env = 'review';
} elseif (isLocalDevelopment()) {
$env = 'local';
} elseif (!isLive()) {
$env = 'beta';
}
$this->setEnvironment($env);
$this->tags_context([
'templates' => $cfg['Path']['smarty_tpl']['theme'],
'web' => $web,
'channel' => $this->getChannel(),
]);
}
public function captureException($exception, $data = null, $logger = null, $vars = null)
{
$parentException = $exception;
while ($parentException) {
if ($parentException instanceof CustomDataExceptionInterface) {
$data['extra'] = array_merge($data['extra'] ?? [], $parentException->getData());
}
$parentException = $parentException->getPrevious();
}
return parent::captureException($exception, $data, $logger, $vars);
}
protected function getChannel()
{
if ($this->channel) {
return $this->channel;
}
if (php_sapi_name() == 'cli') {
return self::CHANNEL_SYNC;
}
if (isAdministration()) {
return self::CHANNEL_ADMIN;
} else {
return self::CHANNEL_FE;
}
}
public function setChannel(string $channel): self
{
$this->channel = $channel;
return $this;
}
}
} else {
#[AllowDynamicProperties]
class SentryLogger
{
public const CHANNEL_ADMIN = 'admin';
public const CHANNEL_SYNC = 'sync';
public const CHANNEL_CRON = 'cron';
public const CHANNEL_FE = 'front-end';
public const CHANNEL_UPGRADE = 'upgrade';
protected ?string $channel = null;
protected RequestUtil $requestUtil;
protected RequestStack $requestStack;
public function __construct(array $options = [])
{
$dsn = $this->getDsn();
$this->setChannel();
$tags = [
'templates' => Config::get()['Path']['smarty_tpl']['theme'],
'channel' => &$this->channel,
];
if (findModule(\Modules::COMPONENTS)) {
$env = substr($this->getWeb(), 5);
$tags['env'] = $this->getEnvironment();
} else {
$env = $this->getEnvironment();
$tags['web'] = $this->getWeb();
}
\Sentry\init(array_merge([
'dsn' => $dsn,
'error_types' => E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE & ~E_USER_DEPRECATED,
'tags' => $tags,
// Disable global handlers, use for now our custom handlers
'integrations' => function (array $defaultIntegrations) {
return array_filter($defaultIntegrations, function ($integration) {
return !($integration instanceof ExceptionListenerIntegration
or $integration instanceof ErrorListenerIntegration
or $integration instanceof FatalErrorListenerIntegration
or $integration instanceof ModulesIntegration);
});
},
'send_default_pii' => true,
'environment' => $env,
'release' => $this->getRelease(),
'ignore_exceptions' => [
BadRequestHttpException::class,
],
'before_send' => function (Event $event): Event {
try {
$transaction = $this->requestUtil->getTransactionInfoString($this->requestStack->getMainRequest());
$event->setTag('transaction', $transaction);
// Remove autogenerated hash from template filename
foreach ($event->getExceptions() as &$exception) {
$modifiedFrames = $exception->getStacktrace()->getFrames();
foreach ($exception->getStacktrace()->getFrames() as $key => $frame) {
if (!str_contains($frame->getFile(), '/templates/')) {
continue;
}
preg_match('/templates\/(.*?)\./', $frame->getFile(), $matches);
$hash = $matches[1] ?? '';
$modifiedFrames[$key] = new Frame(
functionName: 'block',
file: str_replace("{$hash}.", '', $frame->getFile()),
line: $frame->getLine(),
rawFunctionName: $frame->getRawFunctionName(),
absoluteFilePath: str_replace("{$hash}.", '', $frame->getAbsoluteFilePath()),
vars: $frame->getVars(),
inApp: $frame->isInApp()
);
$modifiedFrames[$key]->setContextLine($frame->getContextLine());
$modifiedFrames[$key]->setPreContext($frame->getPreContext());
$modifiedFrames[$key]->setPostContext($frame->getPostContext());
}
$exception->setStacktrace(new Stacktrace($modifiedFrames));
}
} catch (\Throwable $e) {
// pass
$event->setTag('error', $e->getMessage());
}
return $event;
},
], $options));
\Sentry\configureScope(function (\Sentry\State\Scope $scope) {
$scope->addEventProcessor(function (Event $event, EventHint $hint) {
if ($hint->exception instanceof CustomDataExceptionInterface) {
$event->setExtra(
array_merge($event->getExtra(), $hint->exception->getData())
);
}
return $event;
});
});
}
/**
* @deprecated Use \Sentry\captureMessage() instead
*/
public function captureMessage(string $message, $tmp = [], $data = []): ?EventId
{
\Sentry\withScope(function (\Sentry\State\Scope $scope) use ($message, $data, &$eventId): void {
if ($data) {
$scope->setExtras($data);
}
$eventId = \Sentry\captureMessage($message);
});
return $eventId;
}
/**
* @deprecated Use \Sentry\captureException() instead
*/
public function captureException($exception, $data = null, $logger = null, $vars = null): ?EventId
{
$parentException = $exception;
while ($parentException) {
if ($parentException instanceof CustomDataExceptionInterface) {
$data['extra'] = array_merge($data['extra'] ?? [], $parentException->getData());
}
$parentException = $parentException->getPrevious();
}
\Sentry\withScope(function (\Sentry\State\Scope $scope) use ($exception, $data, &$eventId): void {
if ($data) {
$scope->setExtras($data);
}
$eventId = \Sentry\captureException($exception);
});
return $eventId;
}
public function getIdent(?EventId $eventId): string
{
return (string) $eventId;
}
/**
* @param Exception $exception
*
* @return string|null
*
* @deprecated
*
* @codeCoverageIgnore
*/
public function exception($exception)
{
return $this->captureException($exception);
}
/**
* @deprecated
*/
public function message($message, $params = [], $level = null, $stack = false, $vars = null)
{
return $this->captureMessage($message, [], $params);
}
public function setChannel($channel = null): self
{
if ($channel) {
$this->channel = $channel;
} elseif (php_sapi_name() == 'cli') {
$this->channel = self::CHANNEL_SYNC;
} elseif (isAdministration()) {
$this->channel = self::CHANNEL_ADMIN;
} else {
$this->channel = self::CHANNEL_FE;
}
return $this;
}
private function getDsn(): string
{
if (isDebug()) {
return 'http://156f2fdb588b4f23828c32ff878738cc:bc790801af7449b29c0ae807bb66d623@localhost/3';
} elseif (findModule(\Modules::COMPONENTS)) {
return 'https://5fd110d7c17a2b186a776b82ca6df945@sentry.wpj.cz/15';
}
return 'http://156f2fdb588b4f23828c32ff878738cc:bc790801af7449b29c0ae807bb66d623@sentry.wpj.cz/3';
}
private function getWeb(): string
{
$branch = getShopName();
if (isAutoDeploy() && !empty($branch)) {
return $branch;
}
return substr(Config::get()['Connection']['database'], 8);
}
private function getRelease(): string
{
$engine = getenv('KUPSHOP_ENGINE');
if (isAutoDeploy() && !empty($engine)) {
return $engine;
}
return Config::get()['Program']['version']['folder'];
}
private function getEnvironment(): string
{
if (isDevelopment() && !isLocalDevelopment()) {
return 'review';
} elseif (isLocalDevelopment()) {
return 'local';
} elseif (!isLive()) {
return 'beta';
}
return 'production';
}
public function install()
{
// BC function
}
#[Required]
public function setRequestUtil(RequestUtil $requestUtil): void
{
$this->requestUtil = $requestUtil;
}
#[Required]
public function setRequestStack(RequestStack $requestStack): void
{
$this->requestStack = $requestStack;
}
}
}