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

- 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:
2025-11-09 14:46:15 +01:00
parent 85c369e846
commit 36ef2a1e2c
1366 changed files with 104925 additions and 28719 deletions

View File

@@ -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);
}
}