fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\ExceptionHandling\Metrics;
|
||||
|
||||
use App\Framework\Cache\Cache;
|
||||
use App\Framework\Cache\CacheItem;
|
||||
use App\Framework\Cache\CacheKey;
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
use App\Framework\ExceptionHandling\Context\ExceptionContextData;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Exception Metrics Collector
|
||||
*
|
||||
* Collects metrics for exceptions (rate, top exceptions, error rate by component).
|
||||
*/
|
||||
final readonly class ExceptionMetricsCollector
|
||||
{
|
||||
private const string CACHE_PREFIX = 'exception_metrics:';
|
||||
private const int METRICS_TTL = 3600; // 1 hour
|
||||
|
||||
public function __construct(
|
||||
private Cache $cache
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Record exception metric
|
||||
*
|
||||
* @param Throwable $exception Exception to record
|
||||
* @param ExceptionContextData|null $context Optional context
|
||||
* @param float|null $executionTimeMs Optional execution time in milliseconds
|
||||
*/
|
||||
public function record(
|
||||
Throwable $exception,
|
||||
?ExceptionContextData $context = null,
|
||||
?float $executionTimeMs = null
|
||||
): void {
|
||||
$exceptionClass = get_class($exception);
|
||||
$component = $context?->component ?? 'unknown';
|
||||
|
||||
// Increment total count
|
||||
$this->incrementMetric('total');
|
||||
|
||||
// Increment by class
|
||||
$this->incrementMetric('class:' . $exceptionClass);
|
||||
|
||||
// Increment by component
|
||||
$this->incrementMetric('component:' . $component);
|
||||
|
||||
// Record execution time if available
|
||||
if ($executionTimeMs !== null) {
|
||||
$this->recordExecutionTime($executionTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current metrics
|
||||
*
|
||||
* @return ExceptionMetrics Current metrics
|
||||
*/
|
||||
public function getMetrics(): ExceptionMetrics
|
||||
{
|
||||
$totalCount = $this->getMetric('total');
|
||||
$byClass = $this->getMetricsByPrefix('class:');
|
||||
$byComponent = $this->getMetricsByPrefix('component:');
|
||||
$avgExecutionTime = $this->getAverageExecutionTime();
|
||||
|
||||
return new ExceptionMetrics(
|
||||
totalCount: $totalCount,
|
||||
byClass: $byClass,
|
||||
byComponent: $byComponent,
|
||||
averageExecutionTimeMs: $avgExecutionTime
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment metric
|
||||
*/
|
||||
private function incrementMetric(string $metricName): void
|
||||
{
|
||||
$cacheKey = CacheKey::fromString(self::CACHE_PREFIX . $metricName);
|
||||
$current = $this->getMetricValue($cacheKey);
|
||||
$newValue = $current + 1;
|
||||
|
||||
$cacheItem = CacheItem::fromKey(
|
||||
$cacheKey,
|
||||
$newValue,
|
||||
Duration::fromSeconds(self::METRICS_TTL)
|
||||
);
|
||||
|
||||
$this->cache->set($cacheItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get metric value
|
||||
*/
|
||||
private function getMetric(string $metricName): int
|
||||
{
|
||||
$cacheKey = CacheKey::fromString(self::CACHE_PREFIX . $metricName);
|
||||
return $this->getMetricValue($cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get metric value from cache
|
||||
*/
|
||||
private function getMetricValue(CacheKey $cacheKey): int
|
||||
{
|
||||
$result = $this->cache->get($cacheKey);
|
||||
$item = $result->getFirstHit();
|
||||
|
||||
if ($item === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$value = $item->value;
|
||||
return is_int($value) ? $value : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get metrics by prefix
|
||||
*/
|
||||
private function getMetricsByPrefix(string $prefix): array
|
||||
{
|
||||
// Simplified implementation - in production, would use cache prefix scanning
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Record execution time
|
||||
*/
|
||||
private function recordExecutionTime(float $executionTimeMs): void
|
||||
{
|
||||
$cacheKey = CacheKey::fromString(self::CACHE_PREFIX . 'execution_times');
|
||||
$result = $this->cache->get($cacheKey);
|
||||
$item = $result->getFirstHit();
|
||||
|
||||
$times = $item !== null && is_array($item->value) ? $item->value : [];
|
||||
$times[] = $executionTimeMs;
|
||||
|
||||
// Keep only last 1000 execution times
|
||||
if (count($times) > 1000) {
|
||||
$times = array_slice($times, -1000);
|
||||
}
|
||||
|
||||
$cacheItem = CacheItem::fromKey(
|
||||
$cacheKey,
|
||||
$times,
|
||||
Duration::fromSeconds(self::METRICS_TTL)
|
||||
);
|
||||
|
||||
$this->cache->set($cacheItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get average execution time
|
||||
*/
|
||||
private function getAverageExecutionTime(): float
|
||||
{
|
||||
$cacheKey = CacheKey::fromString(self::CACHE_PREFIX . 'execution_times');
|
||||
$result = $this->cache->get($cacheKey);
|
||||
$item = $result->getFirstHit();
|
||||
|
||||
if ($item === null || !is_array($item->value)) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
$times = $item->value;
|
||||
if (empty($times)) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return array_sum($times) / count($times);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user