compute static method
Computes a deterministic list of fingerprint tokens and SHA-256 hash.
Extracts top non-framework stack frames and combines them with the exceptionType.
Implementation
static List<String> compute({
required String exceptionType,
required String message,
String? stackTrace,
List<String>? customFingerprint,
}) {
if (customFingerprint != null && customFingerprint.isNotEmpty) {
return List<String>.from(customFingerprint);
}
final tokens = <String>[exceptionType];
if (stackTrace != null && stackTrace.isNotEmpty) {
final lines = stackTrace.split('\n');
for (final line in lines) {
final trimmed = line.trim();
if (trimmed.isEmpty) continue;
// Skip internal SDK / dart runtime frames to group by user code
if (trimmed.contains('package:flutter/') ||
trimmed.contains('dart:async') ||
trimmed.contains('dart:isolate') ||
trimmed.contains('dart:core') ||
trimmed.contains('dart_sdk.js') ||
trimmed.contains('package:bloom_framework/src/observability')) {
continue;
}
// Match frame symbol (e.g. #0 CartController.addItem or at CartController.addItem)
final vmMatch = _vmFramePattern.firstMatch(trimmed);
if (vmMatch != null) {
tokens.add(vmMatch.group(1)!);
} else {
final webMatch = _webFramePattern.firstMatch(trimmed);
if (webMatch != null) {
tokens.add(webMatch.group(1)!);
}
}
if (tokens.length >= 4) break; // Take up to top 3 user frames
}
}
if (tokens.length == 1 && message.isNotEmpty) {
// If no stack frames could be parsed, use sanitized message prefix
tokens.add(sanitizeMessage(message));
}
return tokens;
}