docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
namespace App\Framework\Console\Analytics;
use App\Framework\Console\Analytics\Repository\CommandUsageRepository;
use App\Framework\Console\Analytics\ValueObjects\Period;
use App\Framework\Console\Analytics\ValueObjects\UsageStatistics;
use DateTimeImmutable;
final readonly class AnalyticsService
{
public function __construct(
private CommandUsageRepository $repository
) {
}
public function getCommandStatistics(string $commandName, ?DateTimeImmutable $since = null): UsageStatistics
{
return $this->repository->getUsageStatistics($commandName, $since);
}
public function getPopularCommands(int $limit = 10, ?DateTimeImmutable $since = null): array
{
return $this->repository->getPopularCommands($limit, $since);
}
public function getCommandTrends(
string $commandName,
Period $period = Period::DAILY,
?DateTimeImmutable $start = null,
?DateTimeImmutable $end = null
): array {
$start ??= new DateTimeImmutable('-30 days');
$end ??= new DateTimeImmutable();
return $this->repository->getTrendData($commandName, $period, $start, $end);
}
public function getAllCommandNames(): array
{
return $this->repository->getAllCommandNames();
}
public function cleanupOldData(int $daysToKeep = 90): int
{
$cutoffDate = new DateTimeImmutable("-{$daysToKeep} days");
return $this->repository->cleanup($cutoffDate);
}
public function getOverallStatistics(?DateTimeImmutable $since = null): array
{
$commands = $this->getAllCommandNames();
$statistics = [];
foreach ($commands as $commandName) {
$statistics[$commandName] = $this->getCommandStatistics($commandName, $since);
}
return $statistics;
}
public function getMostFailingCommands(int $limit = 10, ?DateTimeImmutable $since = null): array
{
$commands = $this->getAllCommandNames();
$failingCommands = [];
foreach ($commands as $commandName) {
$stats = $this->getCommandStatistics($commandName, $since);
if ($stats->totalExecutions > 0) {
$failingCommands[] = [
'command_name' => $commandName,
'failure_rate' => $stats->getFailureRate(),
'total_executions' => $stats->totalExecutions,
'failed_executions' => $stats->failedExecutions,
];
}
}
// Sort by failure rate descending
usort($failingCommands, function ($a, $b) {
return $b['failure_rate']->getValue() <=> $a['failure_rate']->getValue();
});
return array_slice($failingCommands, 0, $limit);
}
public function getSlowestCommands(int $limit = 10, ?DateTimeImmutable $since = null): array
{
$commands = $this->getAllCommandNames();
$slowCommands = [];
foreach ($commands as $commandName) {
$stats = $this->getCommandStatistics($commandName, $since);
if ($stats->totalExecutions > 0) {
$slowCommands[] = [
'command_name' => $commandName,
'average_execution_time' => $stats->averageExecutionTime,
'max_execution_time' => $stats->maxExecutionTime,
'total_executions' => $stats->totalExecutions,
];
}
}
// Sort by average execution time descending
usort($slowCommands, function ($a, $b) {
return $b['average_execution_time']->toMilliseconds() <=>
$a['average_execution_time']->toMilliseconds();
});
return array_slice($slowCommands, 0, $limit);
}
public function getUsageByHour(?DateTimeImmutable $since = null): array
{
$commands = $this->getAllCommandNames();
$hourlyUsage = array_fill(0, 24, 0);
foreach ($commands as $commandName) {
$stats = $this->getCommandStatistics($commandName, $since);
if ($stats->hourlyDistribution) {
foreach ($stats->hourlyDistribution as $hour => $count) {
$hourlyUsage[$hour] += $count;
}
}
}
return $hourlyUsage;
}
public function getCommandHealthScore(string $commandName, ?DateTimeImmutable $since = null): float
{
$stats = $this->getCommandStatistics($commandName, $since);
if ($stats->totalExecutions === 0) {
return 0.0;
}
// Health score based on success rate (70%) and performance (30%)
$successScore = $stats->getSuccessRate()->getValue() / 100;
// Performance score: inverse of execution time (normalized)
$avgTimeMs = $stats->averageExecutionTime->toMilliseconds();
$performanceScore = $avgTimeMs > 0 ? min(1.0, 1000 / $avgTimeMs) : 1.0;
return ($successScore * 0.7) + ($performanceScore * 0.3);
}
}