option('top')); $limit = max(1, (int) $this->option('limit')); $files = array_values(array_filter(array_map('strval', (array) $this->option('file')))); $report = $reporter->report( filters: [ 'from' => $this->option('from') !== null ? (string) $this->option('from') : null, 'to' => $this->option('to') !== null ? (string) $this->option('to') : null, 'route' => $this->option('route') !== null ? (string) $this->option('route') : null, 'path' => $this->option('path') !== null ? (string) $this->option('path') : null, 'status' => $this->option('status') !== null ? (int) $this->option('status') : null, 'min_duration_ms' => $this->option('min-duration') !== null ? (int) $this->option('min-duration') : null, ], top: $top, limit: $limit, paths: $files !== [] ? $files : null, ); $this->info('Slow-Admin-Request-Report'); $this->newLine(); $this->line("Dateien: {$report['summary']['files']}"); $this->line("Requests: {$report['summary']['total_requests']}"); $this->line("Routen: {$report['summary']['unique_routes']}"); $this->line("Durchschnitt Dauer: {$report['summary']['average_duration_ms']} ms"); $this->line("Max. Dauer: {$report['summary']['max_duration_ms']} ms"); $this->line("Durchschnitt DB-Zeit: {$report['summary']['average_database_time_ms']} ms"); $this->line("Max. Query-Anzahl: {$report['summary']['max_query_count']}"); $this->renderTopTable('Top Routen', $report['top_routes']); $this->renderTopTable('Top Pfade', $report['top_paths']); $this->renderTopTable('Statuscodes', $report['status_codes']); $this->renderRequests('Langsamste Requests', $report['slowest_requests']); $this->renderRequests('Query-lastige Requests', $report['query_heavy_requests']); $this->renderSlowQueries($report['slow_queries']); $this->renderExplainPlans($report['explain_plans']); return self::SUCCESS; } /** * @param list> $rows */ private function renderTopTable(string $title, array $rows): void { if ($rows === []) { return; } $this->newLine(); $this->line($title); $this->table( ['Wert', 'Requests', 'Ø Dauer', 'Max Dauer', 'Ø DB', 'Queries'], collect($rows) ->map(fn (array $row): array => [ $row['value'], $row['requests'], $row['average_duration_ms'].' ms', $row['max_duration_ms'].' ms', $row['average_database_time_ms'].' ms', $row['total_queries'], ]) ->all() ); } /** * @param list> $rows */ private function renderRequests(string $title, array $rows): void { if ($rows === []) { return; } $this->newLine(); $this->line($title); $this->table( ['Zeit', 'Route', 'Pfad', 'Status', 'Dauer', 'DB', 'Queries'], collect($rows) ->map(fn (array $row): array => [ $row['timestamp'], $row['route_name'], $row['path'], $row['status_code'], $row['duration_ms'].' ms', $row['database_time_ms'].' ms', $row['query_count'], ]) ->all() ); } /** * @param list> $rows */ private function renderSlowQueries(array $rows): void { if ($rows === []) { return; } $this->newLine(); $this->line('Häufige Slow Queries'); $this->table( ['SQL', 'Vorkommen', 'Ø Zeit', 'Max Zeit'], collect($rows) ->map(fn (array $row): array => [ str($row['sql'])->limit(100)->toString(), $row['occurrences'], $row['average_time_ms'].' ms', $row['max_time_ms'].' ms', ]) ->all() ); } /** * @param list> $rows */ private function renderExplainPlans(array $rows): void { if ($rows === []) { return; } $this->newLine(); $this->line('EXPLAIN Top Slow Queries'); foreach ($rows as $row) { $this->line(str($row['sql'])->limit(120)->toString()); if ($row['error'] !== null) { $this->warn((string) $row['error']); continue; } $this->table( array_keys($row['plan'][0] ?? []), collect($row['plan'])->map(fn (array $planRow): array => array_values($planRow))->all() ); } } }