feat: improve stack trace rendering
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user