Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
408
src/Framework/ErrorReporting/ErrorReport.php
Normal file
408
src/Framework/ErrorReporting/ErrorReport.php
Normal file
@@ -0,0 +1,408 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\ErrorReporting;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
use DateTimeImmutable;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Structured error report with comprehensive context
|
||||
*/
|
||||
final readonly class ErrorReport
|
||||
{
|
||||
public function __construct(
|
||||
public string $id,
|
||||
public DateTimeImmutable $timestamp,
|
||||
public string $level,
|
||||
public string $message,
|
||||
public string $exception,
|
||||
public string $file,
|
||||
public int $line,
|
||||
public string $trace,
|
||||
public array $context,
|
||||
public ?string $userId = null,
|
||||
public ?string $sessionId = null,
|
||||
public ?string $requestId = null,
|
||||
public ?string $userAgent = null,
|
||||
public ?string $ipAddress = null,
|
||||
public ?string $route = null,
|
||||
public ?string $method = null,
|
||||
public ?array $requestData = null,
|
||||
public ?Duration $executionTime = null,
|
||||
public ?int $memoryUsage = null,
|
||||
public array $tags = [],
|
||||
public array $breadcrumbs = [],
|
||||
public ?string $release = null,
|
||||
public ?string $environment = null,
|
||||
public array $serverInfo = [],
|
||||
public array $customData = []
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from Throwable
|
||||
*/
|
||||
public static function fromThrowable(
|
||||
Throwable $throwable,
|
||||
string $level = 'error',
|
||||
array $context = []
|
||||
): self {
|
||||
return new self(
|
||||
id: self::generateId(),
|
||||
timestamp: new DateTimeImmutable(),
|
||||
level: $level,
|
||||
message: $throwable->getMessage(),
|
||||
exception: $throwable::class,
|
||||
file: $throwable->getFile(),
|
||||
line: $throwable->getLine(),
|
||||
trace: $throwable->getTraceAsString(),
|
||||
context: $context,
|
||||
environment: $_ENV['APP_ENV'] ?? 'production',
|
||||
serverInfo: self::getServerInfo()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from manual report
|
||||
*/
|
||||
public static function create(
|
||||
string $level,
|
||||
string $message,
|
||||
array $context = [],
|
||||
?Throwable $exception = null
|
||||
): self {
|
||||
return new self(
|
||||
id: self::generateId(),
|
||||
timestamp: new DateTimeImmutable(),
|
||||
level: $level,
|
||||
message: $message,
|
||||
exception: $exception?->class ?? 'N/A',
|
||||
file: $exception?->getFile() ?? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'] ?? 'unknown',
|
||||
line: $exception?->getLine() ?? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['line'] ?? 0,
|
||||
trace: $exception?->getTraceAsString() ?? self::getCurrentTrace(),
|
||||
context: $context,
|
||||
environment: $_ENV['APP_ENV'] ?? 'production',
|
||||
serverInfo: self::getServerInfo()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user context
|
||||
*/
|
||||
public function withUser(string $userId, ?string $sessionId = null): self
|
||||
{
|
||||
return new self(
|
||||
id: $this->id,
|
||||
timestamp: $this->timestamp,
|
||||
level: $this->level,
|
||||
message: $this->message,
|
||||
exception: $this->exception,
|
||||
file: $this->file,
|
||||
line: $this->line,
|
||||
trace: $this->trace,
|
||||
context: $this->context,
|
||||
userId: $userId,
|
||||
sessionId: $sessionId ?? $this->sessionId,
|
||||
requestId: $this->requestId,
|
||||
userAgent: $this->userAgent,
|
||||
ipAddress: $this->ipAddress,
|
||||
route: $this->route,
|
||||
method: $this->method,
|
||||
requestData: $this->requestData,
|
||||
executionTime: $this->executionTime,
|
||||
memoryUsage: $this->memoryUsage,
|
||||
tags: $this->tags,
|
||||
breadcrumbs: $this->breadcrumbs,
|
||||
release: $this->release,
|
||||
environment: $this->environment,
|
||||
serverInfo: $this->serverInfo,
|
||||
customData: $this->customData
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add HTTP request context
|
||||
*/
|
||||
public function withRequest(
|
||||
string $method,
|
||||
string $route,
|
||||
?string $requestId = null,
|
||||
?string $userAgent = null,
|
||||
?string $ipAddress = null,
|
||||
?array $requestData = null
|
||||
): self {
|
||||
return new self(
|
||||
id: $this->id,
|
||||
timestamp: $this->timestamp,
|
||||
level: $this->level,
|
||||
message: $this->message,
|
||||
exception: $this->exception,
|
||||
file: $this->file,
|
||||
line: $this->line,
|
||||
trace: $this->trace,
|
||||
context: $this->context,
|
||||
userId: $this->userId,
|
||||
sessionId: $this->sessionId,
|
||||
requestId: $requestId,
|
||||
userAgent: $userAgent,
|
||||
ipAddress: $ipAddress,
|
||||
route: $route,
|
||||
method: $method,
|
||||
requestData: $requestData,
|
||||
executionTime: $this->executionTime,
|
||||
memoryUsage: $this->memoryUsage,
|
||||
tags: $this->tags,
|
||||
breadcrumbs: $this->breadcrumbs,
|
||||
release: $this->release,
|
||||
environment: $this->environment,
|
||||
serverInfo: $this->serverInfo,
|
||||
customData: $this->customData
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add performance context
|
||||
*/
|
||||
public function withPerformance(Duration $executionTime, int $memoryUsage): self
|
||||
{
|
||||
return new self(
|
||||
id: $this->id,
|
||||
timestamp: $this->timestamp,
|
||||
level: $this->level,
|
||||
message: $this->message,
|
||||
exception: $this->exception,
|
||||
file: $this->file,
|
||||
line: $this->line,
|
||||
trace: $this->trace,
|
||||
context: $this->context,
|
||||
userId: $this->userId,
|
||||
sessionId: $this->sessionId,
|
||||
requestId: $this->requestId,
|
||||
userAgent: $this->userAgent,
|
||||
ipAddress: $this->ipAddress,
|
||||
route: $this->route,
|
||||
method: $this->method,
|
||||
requestData: $this->requestData,
|
||||
executionTime: $executionTime,
|
||||
memoryUsage: $memoryUsage,
|
||||
tags: $this->tags,
|
||||
breadcrumbs: $this->breadcrumbs,
|
||||
release: $this->release,
|
||||
environment: $this->environment,
|
||||
serverInfo: $this->serverInfo,
|
||||
customData: $this->customData
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tags
|
||||
*/
|
||||
public function withTags(array $tags): self
|
||||
{
|
||||
return new self(
|
||||
id: $this->id,
|
||||
timestamp: $this->timestamp,
|
||||
level: $this->level,
|
||||
message: $this->message,
|
||||
exception: $this->exception,
|
||||
file: $this->file,
|
||||
line: $this->line,
|
||||
trace: $this->trace,
|
||||
context: $this->context,
|
||||
userId: $this->userId,
|
||||
sessionId: $this->sessionId,
|
||||
requestId: $this->requestId,
|
||||
userAgent: $this->userAgent,
|
||||
ipAddress: $this->ipAddress,
|
||||
route: $this->route,
|
||||
method: $this->method,
|
||||
requestData: $this->requestData,
|
||||
executionTime: $this->executionTime,
|
||||
memoryUsage: $this->memoryUsage,
|
||||
tags: array_unique(array_merge($this->tags, $tags)),
|
||||
breadcrumbs: $this->breadcrumbs,
|
||||
release: $this->release,
|
||||
environment: $this->environment,
|
||||
serverInfo: $this->serverInfo,
|
||||
customData: $this->customData
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add breadcrumbs
|
||||
*/
|
||||
public function withBreadcrumbs(array $breadcrumbs): self
|
||||
{
|
||||
return new self(
|
||||
id: $this->id,
|
||||
timestamp: $this->timestamp,
|
||||
level: $this->level,
|
||||
message: $this->message,
|
||||
exception: $this->exception,
|
||||
file: $this->file,
|
||||
line: $this->line,
|
||||
trace: $this->trace,
|
||||
context: $this->context,
|
||||
userId: $this->userId,
|
||||
sessionId: $this->sessionId,
|
||||
requestId: $this->requestId,
|
||||
userAgent: $this->userAgent,
|
||||
ipAddress: $this->ipAddress,
|
||||
route: $this->route,
|
||||
method: $this->method,
|
||||
requestData: $this->requestData,
|
||||
executionTime: $this->executionTime,
|
||||
memoryUsage: $this->memoryUsage,
|
||||
tags: $this->tags,
|
||||
breadcrumbs: array_merge($this->breadcrumbs, $breadcrumbs),
|
||||
release: $this->release,
|
||||
environment: $this->environment,
|
||||
serverInfo: $this->serverInfo,
|
||||
customData: $this->customData
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom data
|
||||
*/
|
||||
public function withCustomData(array $customData): self
|
||||
{
|
||||
return new self(
|
||||
id: $this->id,
|
||||
timestamp: $this->timestamp,
|
||||
level: $this->level,
|
||||
message: $this->message,
|
||||
exception: $this->exception,
|
||||
file: $this->file,
|
||||
line: $this->line,
|
||||
trace: $this->trace,
|
||||
context: $this->context,
|
||||
userId: $this->userId,
|
||||
sessionId: $this->sessionId,
|
||||
requestId: $this->requestId,
|
||||
userAgent: $this->userAgent,
|
||||
ipAddress: $this->ipAddress,
|
||||
route: $this->route,
|
||||
method: $this->method,
|
||||
requestData: $this->requestData,
|
||||
executionTime: $this->executionTime,
|
||||
memoryUsage: $this->memoryUsage,
|
||||
tags: $this->tags,
|
||||
breadcrumbs: $this->breadcrumbs,
|
||||
release: $this->release,
|
||||
environment: $this->environment,
|
||||
serverInfo: $this->serverInfo,
|
||||
customData: array_merge($this->customData, $customData)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get severity level as integer
|
||||
*/
|
||||
public function getSeverityLevel(): int
|
||||
{
|
||||
return match (strtolower($this->level)) {
|
||||
'emergency' => 0,
|
||||
'alert' => 1,
|
||||
'critical' => 2,
|
||||
'error' => 3,
|
||||
'warning' => 4,
|
||||
'notice' => 5,
|
||||
'info' => 6,
|
||||
'debug' => 7,
|
||||
default => 3,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if error is critical
|
||||
*/
|
||||
public function isCritical(): bool
|
||||
{
|
||||
return $this->getSeverityLevel() <= 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fingerprint for grouping similar errors
|
||||
*/
|
||||
public function getFingerprint(): string
|
||||
{
|
||||
$key = $this->exception . '|' . $this->file . '|' . $this->line;
|
||||
|
||||
return hash('xxh64', $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to array for storage/transmission
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'timestamp' => $this->timestamp->format('c'),
|
||||
'level' => $this->level,
|
||||
'message' => $this->message,
|
||||
'exception' => $this->exception,
|
||||
'file' => $this->file,
|
||||
'line' => $this->line,
|
||||
'trace' => $this->trace,
|
||||
'context' => $this->context,
|
||||
'user_id' => $this->userId,
|
||||
'session_id' => $this->sessionId,
|
||||
'request_id' => $this->requestId,
|
||||
'user_agent' => $this->userAgent,
|
||||
'ip_address' => $this->ipAddress,
|
||||
'route' => $this->route,
|
||||
'method' => $this->method,
|
||||
'request_data' => $this->requestData,
|
||||
'execution_time' => $this->executionTime?->toMilliseconds(),
|
||||
'memory_usage' => $this->memoryUsage,
|
||||
'tags' => $this->tags,
|
||||
'breadcrumbs' => $this->breadcrumbs,
|
||||
'release' => $this->release,
|
||||
'environment' => $this->environment,
|
||||
'server_info' => $this->serverInfo,
|
||||
'custom_data' => $this->customData,
|
||||
'fingerprint' => $this->getFingerprint(),
|
||||
'severity_level' => $this->getSeverityLevel(),
|
||||
];
|
||||
}
|
||||
|
||||
private static function generateId(): string
|
||||
{
|
||||
return bin2hex(random_bytes(16));
|
||||
}
|
||||
|
||||
private static function getCurrentTrace(): string
|
||||
{
|
||||
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
array_shift($trace); // Remove current method
|
||||
|
||||
$result = [];
|
||||
foreach ($trace as $frame) {
|
||||
$file = $frame['file'] ?? 'unknown';
|
||||
$line = $frame['line'] ?? 0;
|
||||
$function = $frame['function'] ?? 'unknown';
|
||||
$class = isset($frame['class']) ? $frame['class'] . '::' : '';
|
||||
|
||||
$result[] = "#{$file}({$line}): {$class}{$function}()";
|
||||
}
|
||||
|
||||
return implode("\n", $result);
|
||||
}
|
||||
|
||||
private static function getServerInfo(): array
|
||||
{
|
||||
return [
|
||||
'php_version' => PHP_VERSION,
|
||||
'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'unknown',
|
||||
'server_name' => $_SERVER['SERVER_NAME'] ?? 'unknown',
|
||||
'request_time' => $_SERVER['REQUEST_TIME'] ?? time(),
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'max_execution_time' => ini_get('max_execution_time'),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user