feat: improve stack trace rendering

This commit is contained in:
2025-11-25 04:13:25 +01:00
parent 57eabe30a5
commit dd7cfd97e6
4 changed files with 234 additions and 17 deletions

View File

@@ -12,6 +12,10 @@ namespace App\Framework\ExceptionHandling\ValueObjects;
*/
final readonly class StackItem
{
private const MAX_STRING_LENGTH = 80;
private const MAX_ARGS = 6;
private const MAX_PARAMS_LENGTH = 200;
public function __construct(
public string $file,
public int $line,
@@ -166,7 +170,7 @@ final readonly class StackItem
*/
public function getShortFile(): string
{
$projectRoot = dirname(__DIR__, 4); // Von src/Framework/ExceptionHandling/ValueObjects nach root
$projectRoot = self::projectRoot();
if (str_starts_with($this->file, $projectRoot)) {
return substr($this->file, strlen($projectRoot) + 1);
@@ -175,6 +179,17 @@ final readonly class StackItem
return $this->file;
}
/**
* True wenn Frame im vendor/ Verzeichnis liegt
*/
public function isVendorFrame(): bool
{
$projectRoot = self::projectRoot();
$vendorPath = $projectRoot . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR;
return str_starts_with($this->file, $vendorPath);
}
/**
* Gibt vollständigen Method/Function Call zurück (ohne Namespace)
*/
@@ -200,15 +215,28 @@ final readonly class StackItem
/**
* Formatiert Parameter für Display (kompakte Darstellung)
*/
public function formatParameters(): string
public function formatParameters(int $maxArgs = self::MAX_ARGS, int $maxTotalLength = self::MAX_PARAMS_LENGTH): string
{
if (empty($this->args)) {
return '';
}
$formatted = [];
foreach ($this->args as $arg) {
$formatted[] = $this->formatParameterForDisplay($arg);
$length = 0;
foreach ($this->args as $index => $arg) {
if ($index >= $maxArgs) {
$formatted[] = '…';
break;
}
$param = $this->formatParameterForDisplay($arg);
$length += strlen($param);
$formatted[] = $param;
if ($length > $maxTotalLength) {
$formatted[] = '…';
break;
}
}
return implode(', ', $formatted);
@@ -266,8 +294,8 @@ final readonly class StackItem
}
// Lange Strings kürzen
if (strlen($value) > 50) {
return sprintf("'%s...'", substr($value, 0, 50));
if (strlen($value) > self::MAX_STRING_LENGTH) {
return sprintf("'%s...'", substr($value, 0, self::MAX_STRING_LENGTH));
}
return sprintf("'%s'", $value);
@@ -349,6 +377,16 @@ final readonly class StackItem
return end($parts);
}
/**
* Kurzform für kompaktes Logging / JSON
*/
public function formatShort(): string
{
$call = $this->getCall() !== '' ? $this->getCall() : '{main}';
return sprintf('%s @ %s:%d', $call, $this->getShortFile(), $this->line);
}
/**
* Formatiert für Display (HTML/Console)
* Verwendet Standard PHP Stack Trace Format: ClassName->methodName($param1, $param2, ...) in file.php:line
@@ -437,5 +475,15 @@ final readonly class StackItem
default => $value,
};
}
}
private static function projectRoot(): string
{
static $projectRoot = null;
if ($projectRoot !== null) {
return $projectRoot;
}
$projectRoot = dirname(__DIR__, 4);
return $projectRoot;
}
}