This commit is contained in:
Stefanescu Mihai
2026-03-19 19:32:46 +02:00
parent 2673552733
commit 528a55cce7
9 changed files with 484 additions and 11 deletions
+85
View File
@@ -0,0 +1,85 @@
<?php
namespace App\Services;
class Fingerprinter
{
/**
* Compute a fingerprint hash for grouping events into issues.
*
* If the payload contains a custom `fingerprint` array (Sentry SDK standard),
* that takes precedence. Otherwise we derive one from exception type, a
* sanitized message, and the top stacktrace frames.
*/
public function compute(array $payload): string
{
if (! empty($payload['fingerprint']) && is_array($payload['fingerprint'])) {
return $this->hash($payload['fingerprint']);
}
$parts = [];
$exception = $this->extractPrimaryException($payload);
if ($exception) {
$parts[] = $exception['type'] ?? '';
$parts[] = $this->sanitizeMessage($exception['value'] ?? '');
$parts = array_merge($parts, $this->topFrames($exception, 5));
} else {
$parts[] = $payload['message'] ?? $payload['logentry']['message'] ?? 'unknown';
}
return $this->hash($parts);
}
public function extractPrimaryException(array $payload): ?array
{
$exceptions = $payload['exception']['values'] ?? [];
return end($exceptions) ?: null;
}
/**
* Strip variable parts (numbers, UUIDs, hex strings) so that
* "User 42 not found" and "User 99 not found" group together.
*/
private function sanitizeMessage(string $message): string
{
$message = preg_replace(
'/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i',
'{uuid}',
$message,
);
$message = preg_replace('/\b[0-9a-f]{24,}\b/i', '{hash}', $message);
$message = preg_replace('/\b\d+\b/', '{n}', $message);
return $message;
}
/**
* Return file+function strings from the top N stacktrace frames.
*/
private function topFrames(array $exception, int $limit): array
{
$frames = $exception['stacktrace']['frames'] ?? [];
$frames = array_reverse($frames);
$frames = array_slice($frames, 0, $limit);
$parts = [];
foreach ($frames as $frame) {
$file = $frame['filename'] ?? $frame['abs_path'] ?? '';
$function = $frame['function'] ?? '';
$parts[] = "{$file}:{$function}";
}
return $parts;
}
private function hash(array $parts): string
{
return md5(implode("\x00", $parts));
}
}