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:
@@ -1,43 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Application\Admin;
|
||||
|
||||
use App\Framework\Attributes\Route;
|
||||
use App\Framework\Auth\Auth;
|
||||
use App\Framework\Config\Environment;
|
||||
use App\Framework\Config\TypedConfiguration;
|
||||
use App\Framework\Core\VersionInfo;
|
||||
use App\Framework\DateTime\Clock;
|
||||
use App\Framework\DI\DefaultContainer;
|
||||
use App\Framework\Http\HttpResponse;
|
||||
use App\Framework\Http\Method;
|
||||
use App\Framework\Http\Response;
|
||||
use App\Framework\Meta\MetaData;
|
||||
use App\Framework\Meta\OpenGraphTypeWebsite;
|
||||
use App\Framework\Performance\MemoryUsageTracker;
|
||||
use App\Framework\Router\Result\ViewResult;
|
||||
use App\Framework\Http\Session\SessionManager;
|
||||
use App\Framework\Http\Status;
|
||||
use Dom\HTMLDocument;
|
||||
use App\Framework\Meta\MetaData;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
use App\Framework\Redis\RedisConnectionPool;
|
||||
use App\Framework\Router\Result\ViewResult;
|
||||
|
||||
final readonly class Dashboard
|
||||
{
|
||||
public function __construct(
|
||||
private DefaultContainer $container,
|
||||
private VersionInfo $versionInfo,
|
||||
private MemoryUsageTracker $memoryTracker,
|
||||
private TypedConfiguration $config,
|
||||
) {}
|
||||
private MemoryMonitor $memoryMonitor,
|
||||
private Clock $clock,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Auth]
|
||||
#[Route(path: '/admin', method: Method::GET)]
|
||||
public function show(): ViewResult
|
||||
{
|
||||
/** @var array<string, mixed> $stats */
|
||||
$stats = [
|
||||
'frameworkVersion' => $this->versionInfo->getVersion(),
|
||||
'phpVersion' => PHP_VERSION,
|
||||
'memoryUsage' => $this->formatBytes(memory_get_usage(true)),
|
||||
'peakMemoryUsage' => $this->formatBytes(memory_get_peak_usage(true)),
|
||||
'memoryUsage' => $this->memoryMonitor->getCurrentMemory()->toHumanReadable(),
|
||||
'peakMemoryUsage' => $this->memoryMonitor->getPeakMemory()->toHumanReadable(),
|
||||
'serverInfo' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
|
||||
'serverTime' => date('Y-m-d H:i:s'),
|
||||
'serverTime' => $this->clock->now()->format('Y-m-d H:i:s'),
|
||||
'timezone' => date_default_timezone_get(),
|
||||
'operatingSystem' => PHP_OS,
|
||||
'loadedExtensions' => $this->getLoadedExtensions(),
|
||||
@@ -51,9 +57,10 @@ final readonly class Dashboard
|
||||
return new ViewResult(
|
||||
template: 'dashboard',
|
||||
metaData: new MetaData('Admin Dashboard'),
|
||||
/** @var array<string, mixed> */
|
||||
data: [
|
||||
'title' => 'Admin Dashboard',
|
||||
'stats' => $stats
|
||||
'stats' => $stats,
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -66,7 +73,7 @@ final readonly class Dashboard
|
||||
$routes = $routeRegistry->getRoutes();
|
||||
|
||||
// Sort routes by path for better readability
|
||||
usort($routes, function($a, $b) {
|
||||
usort($routes, function ($a, $b) {
|
||||
return strcmp($a->path, $b->path);
|
||||
});
|
||||
|
||||
@@ -75,7 +82,7 @@ final readonly class Dashboard
|
||||
metaData: new MetaData('', ''),
|
||||
data: [
|
||||
'title' => 'Routen-Übersicht',
|
||||
'routes' => $routes
|
||||
'routes' => $routes,
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -84,14 +91,44 @@ final readonly class Dashboard
|
||||
#[Route(path: '/admin/services', method: Method::GET)]
|
||||
public function services(): ViewResult
|
||||
{
|
||||
$services = $this->container->getServiceIds();
|
||||
sort($services);
|
||||
$registeredServices = $this->container->getRegisteredServices();
|
||||
|
||||
// The registered services are returned as a numeric array with class names as values
|
||||
$serviceNames = array_filter($registeredServices, 'is_string');
|
||||
$serviceNames = array_unique($serviceNames); // Remove duplicates
|
||||
sort($serviceNames);
|
||||
|
||||
// Prepare service data with categorization
|
||||
$serviceData = [];
|
||||
foreach ($serviceNames as $serviceName) {
|
||||
// Ensure $serviceName is a string before exploding
|
||||
if (is_string($serviceName) && strpos($serviceName, '\\') !== false) {
|
||||
$parts = explode('\\', $serviceName);
|
||||
$category = $parts[1] ?? 'Unknown';
|
||||
$subCategory = $parts[2] ?? '';
|
||||
|
||||
$serviceData[] = [
|
||||
'name' => $serviceName,
|
||||
'category' => $category,
|
||||
'subCategory' => $subCategory,
|
||||
];
|
||||
} else {
|
||||
// Handle non-namespaced services
|
||||
$serviceData[] = [
|
||||
'name' => (string)$serviceName,
|
||||
'category' => 'Other',
|
||||
'subCategory' => '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return new ViewResult(
|
||||
template: 'admin/services',
|
||||
template: 'services',
|
||||
metaData: new MetaData('', ''),
|
||||
data: [
|
||||
'title' => 'Registrierte Dienste',
|
||||
'services' => $services
|
||||
'services' => $serviceData,
|
||||
'servicesCount' => count($serviceData),
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -100,27 +137,32 @@ final readonly class Dashboard
|
||||
#[Route(path: '/admin/environment', method: Method::GET)]
|
||||
public function environment(): ViewResult
|
||||
{
|
||||
$environment = $this->container->get(Environment::class);
|
||||
/** @var array<int, array<string, string>> $env */
|
||||
$env = [];
|
||||
foreach ($_ENV as $key => $value) {
|
||||
foreach ($environment->all() as $key => $value) {
|
||||
// Maskiere sensible Daten
|
||||
if (str_contains(strtolower($key), 'password') ||
|
||||
str_contains(strtolower($key), 'secret') ||
|
||||
str_contains(strtolower($key), 'key')) {
|
||||
$value = '********';
|
||||
}
|
||||
$env[$key] = $value;
|
||||
$env[] = [
|
||||
'key' => $key,
|
||||
'value' => is_array($value) ? json_encode($value) : (string)$value,
|
||||
];
|
||||
}
|
||||
|
||||
ksort($env);
|
||||
|
||||
dd($env);
|
||||
// Sort by key
|
||||
usort($env, fn ($a, $b) => strcmp($a['key'], $b['key']));
|
||||
|
||||
return new ViewResult(
|
||||
template: 'admin/environment',
|
||||
template: 'environment',
|
||||
metaData: new MetaData('', ''),
|
||||
data: [
|
||||
'title' => 'Umgebungsvariablen',
|
||||
'env' => $env
|
||||
'env' => $env,
|
||||
'current_year' => $this->clock->now()->format('Y'),
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -128,10 +170,10 @@ final readonly class Dashboard
|
||||
#[Auth]
|
||||
#[Route('/admin/phpinfo')]
|
||||
#[Route(path: '/admin/phpinfo/{mode}', method: Method::GET)]
|
||||
public function phpInfo(int $mode = 1): Response
|
||||
public function phpInfo(string $mode = '1'): Response
|
||||
{
|
||||
ob_start();
|
||||
phpinfo($mode);
|
||||
phpinfo((int)$mode);
|
||||
$phpinfo = ob_get_clean();
|
||||
|
||||
// Extraktion des <body> Inhalts, um nur den relevanten Teil anzuzeigen
|
||||
@@ -182,15 +224,17 @@ final readonly class Dashboard
|
||||
#[Route(path: '/admin/performance', method: Method::GET)]
|
||||
public function performance(): ViewResult
|
||||
{
|
||||
/** @var array<string, mixed> $performanceData */
|
||||
$performanceData = [
|
||||
'currentMemoryUsage' => $this->formatBytes(memory_get_usage(true)),
|
||||
'peakMemoryUsage' => $this->formatBytes(memory_get_peak_usage(true)),
|
||||
'memoryLimit' => $this->formatBytes($this->getMemoryLimitInBytes()),
|
||||
'memoryUsagePercentage' => round((memory_get_usage(true) / $this->getMemoryLimitInBytes()) * 100, 2),
|
||||
'currentMemoryUsage' => $this->memoryMonitor->getCurrentMemory()->toHumanReadable(),
|
||||
'peakMemoryUsage' => $this->memoryMonitor->getPeakMemory()->toHumanReadable(),
|
||||
'memoryLimit' => $this->memoryMonitor->getMemoryLimit()->toHumanReadable(),
|
||||
'memoryUsagePercentage' => $this->memoryMonitor->getMemoryUsagePercentage()->format(2),
|
||||
'loadAverage' => function_exists('sys_getloadavg') ? sys_getloadavg() : ['N/A', 'N/A', 'N/A'],
|
||||
'opcacheEnabled' => function_exists('opcache_get_status') ? 'Ja' : 'Nein',
|
||||
'executionTime' => number_format(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], 4) . ' Sekunden',
|
||||
'includedFiles' => count(get_included_files()),
|
||||
'files' => get_included_files(),
|
||||
];
|
||||
|
||||
if (function_exists('opcache_get_status')) {
|
||||
@@ -210,9 +254,11 @@ final readonly class Dashboard
|
||||
|
||||
return new ViewResult(
|
||||
template: 'performance',
|
||||
metaData: new MetaData('Performance-Daten', 'Performance-Daten'),
|
||||
data: [
|
||||
'title' => 'Performance-Daten',
|
||||
'performance' => $performanceData
|
||||
'performance' => $performanceData,
|
||||
'current_year' => $this->clock->now()->format('Y'),
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -221,10 +267,11 @@ final readonly class Dashboard
|
||||
#[Route(path: '/admin/redis', method: Method::GET)]
|
||||
public function redisInfo(): ViewResult
|
||||
{
|
||||
/** @var array<string, mixed> $redisInfo */
|
||||
$redisInfo = [];
|
||||
|
||||
try {
|
||||
$redis = $this->container->get('Predis\Client');
|
||||
$redis = $this->container->get(RedisConnectionPool::class)->getConnection()->getClient();
|
||||
$info = $redis->info();
|
||||
$redisInfo['status'] = 'Verbunden';
|
||||
$redisInfo['version'] = $info['redis_version'];
|
||||
@@ -236,16 +283,20 @@ final readonly class Dashboard
|
||||
|
||||
// Einige Schlüssel auflisten (begrenzt auf 50)
|
||||
$keys = $redis->keys('*');
|
||||
$redisInfo['key_sample'] = array_slice($keys, 0, 50);
|
||||
/** @var array<int, string> $keySample */
|
||||
$keySample = array_slice($keys, 0, 50);
|
||||
$redisInfo['key_sample'] = $keySample;
|
||||
} catch (\Throwable $e) {
|
||||
$redisInfo['status'] = 'Fehler: ' . $e->getMessage();
|
||||
}
|
||||
|
||||
return new ViewResult(
|
||||
template: 'admin/redis',
|
||||
template: 'redis',
|
||||
metaData: new MetaData('Redis Information', 'Redis Information'),
|
||||
data: [
|
||||
'title' => 'Redis Information',
|
||||
'redis' => $redisInfo
|
||||
'redis' => $redisInfo,
|
||||
'current_year' => $this->clock->now()->format('Y'),
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -272,25 +323,32 @@ final readonly class Dashboard
|
||||
}
|
||||
|
||||
$value = (int) $memoryLimit;
|
||||
$unit = strtolower($memoryLimit[strlen($memoryLimit)-1]);
|
||||
$unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]);
|
||||
|
||||
switch($unit) {
|
||||
switch ($unit) {
|
||||
case 'g':
|
||||
$value *= 1024;
|
||||
// no break
|
||||
case 'm':
|
||||
$value *= 1024;
|
||||
// no break
|
||||
case 'k':
|
||||
$value *= 1024;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function getLoadedExtensions(): array
|
||||
{
|
||||
$extensions = get_loaded_extensions();
|
||||
sort($extensions);
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
|
||||
@@ -299,6 +357,7 @@ final readonly class Dashboard
|
||||
try {
|
||||
if ($this->container->has(SessionManager::class)) {
|
||||
$sessionManager = $this->container->get(SessionManager::class);
|
||||
|
||||
// Diese Methode müsste implementiert werden
|
||||
return $sessionManager->getActiveSessionCount();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user