setModules([]); $event->setOsContext(null); /** @var \Sentry\ExceptionDataBag[] */ $exceptionBag = []; foreach ($event->getExceptions() as $exceptionDataBag) { $exceptionBag[] = self::getAnonymizedSentryException($exceptionDataBag); } $event->setExceptions($exceptionBag); return $event; } /** * Anonimize Sentry Exception bag * * @param \Sentry\ExceptionDataBag $exceptionDataBag * @return \Sentry\ExceptionDataBag */ private static function getAnonymizedSentryException( \Sentry\ExceptionDataBag $exceptionDataBag ): \Sentry\ExceptionDataBag { $exceptionDataBag->setValue(self::getAnonymizedMessage($exceptionDataBag->getValue())); if ($stackTrace = $exceptionDataBag->getStacktrace()) { $exceptionDataBag->setStacktrace(self::getAnonymizedSentryStackTrace($stackTrace)); } return $exceptionDataBag; } /** * Anonymise sentry stacktrace * * @param \Sentry\Stacktrace $stackTrace * @return \Sentry\Stacktrace */ private static function getAnonymizedSentryStackTrace(\Sentry\Stacktrace $stackTrace): \Sentry\Stacktrace { /** @var \Sentry\Frame[] */ $frames = \array_reverse($stackTrace->getFrames(), true); $i = \count($frames) - 1; // * Remove all but keep first (index.php). while ($i-- > 0) { $stackTrace->removeFrame(count($stackTrace->getFrames()) - 1); } foreach ($frames as $index => $frame) { $frame->setPostContext([]); $frame->setPreContext([]); $frame->setContextLine(''); $frame->setVars(self::getAnonymizedSentryParams($frame->getVars())); $stackTrace->addFrame($frame); if ($index === 0) { $stackTrace->removeFrame(count($stackTrace->getFrames()) - 1); } } return $stackTrace; } /** * Get anonymized sentry params * * @param mixed[] $params * @return string[] */ private static function getAnonymizedSentryParams(array $params): array { foreach ($params as &$param) { $type = \strtolower(\gettype($param)); if (\is_string($param)) { $type = \explode(' ', \trim(strtolower($param)))[0] ?? null; } switch (true) { case $type === 'lambda': case $type === 'object': continue 2; case $type === 'array' and \is_array($param): $param = sprintf('Array(%d)', \count($param)); continue 2; default: if (\is_numeric($param)) { $param = \ucfirst($type); continue 2; } if (\is_string($param)) { $param = sprintf('String(%d)', \strlen($param)); continue 2; } } //end switch } //end foreach return $params; } /** * Anonymize at least Sql queries * * @param string $message * @return string */ public static function getAnonymizedMessage(string $message): string { $message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message; if ($sqlPos = \strpos($message, 'to use near')) { $message = \mb_strcut($message, 0, $sqlPos); } return $message; } /** * Anonymize stack trace * * @param \Throwable $e * @return string */ public static function getAnonymizedStackTrace(\Throwable $e): string { $projectPath = \realpath(\sprintf('%s/../', \app_path())); $traceStack = $e->getTrace(); $traceStr = ''; $maxStackStage = 0; foreach ($traceStack as $stackStage => $stack) { $maxStackStage = $stackStage; $traceStr .= \sprintf( '#%s %s(%d): ', $stackStage, str_replace($projectPath, '', $stack['file'] ?? ''), $stack['line'] ?? '' ); if (isset($stack['class'])) { $traceStr .= "{$stack['class']}->{$stack['function']}("; if (isset($stack['args'])) { $traceStr .= self::handleArgs($stack); } $traceStr .= ")\n"; } else { $traceStr .= "{$stack['function']}("; if (isset($stack['args'])) { $traceStr .= self::handleArgs($stack); } $traceStr .= ")\n"; } } //end foreach $maxStackStage++; $traceStr .= "#$maxStackStage {main}"; return $traceStr; } /** * Handle Args * * @param array $stack * @return string */ public static function handleArgs(array $stack): string { $traceArgs = ''; $argsCount = count($stack['args']); for ($i = 0; $i < $argsCount; $i++) { $type = \gettype($stack['args'][$i]); switch ($type) { case 'object': $traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i])); break; case 'array': $traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i])); break; case 'string': $traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i])); break; default: $traceArgs .= \gettype($stack['args'][$i]); } $traceArgs .= ($i !== ($argsCount - 1) ? ',' : ''); } return $traceArgs; } }