- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
269 lines
7.2 KiB
PHP
269 lines
7.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\Telemetry\Adapters;
|
|
|
|
use App\Framework\Performance\Contracts\PerformanceCollectorInterface;
|
|
use App\Framework\Performance\PerformanceCategory;
|
|
use App\Framework\Performance\PerformanceMetric;
|
|
use App\Framework\Telemetry\UnifiedTelemetryService;
|
|
|
|
/**
|
|
* Adapts the UnifiedTelemetryService to the PerformanceCollectorInterface
|
|
* This allows the telemetry system to be used as a drop-in replacement for the existing performance collector
|
|
*/
|
|
final class PerformanceCollectorAdapter implements PerformanceCollectorInterface
|
|
{
|
|
/**
|
|
* @var array<string, array{start: float, category: PerformanceCategory, context: array<string, mixed>}> Active timings
|
|
*/
|
|
private array $timings = [];
|
|
|
|
/**
|
|
* @var array<string, PerformanceMetric> Collected metrics
|
|
*/
|
|
private array $metrics = [];
|
|
|
|
/**
|
|
* @var float Start time of the request
|
|
*/
|
|
private float $requestStartTime;
|
|
|
|
/**
|
|
* @var int Start memory usage of the request
|
|
*/
|
|
private int $requestStartMemory;
|
|
|
|
/**
|
|
* @var bool Whether performance tracking is enabled
|
|
*/
|
|
private bool $enabled = true;
|
|
|
|
/**
|
|
* @param UnifiedTelemetryService $telemetryService Telemetry service to adapt
|
|
* @param PerformanceCollectorInterface $originalCollector Original collector for fallback
|
|
*/
|
|
public function __construct(
|
|
private readonly UnifiedTelemetryService $telemetryService,
|
|
private readonly PerformanceCollectorInterface $originalCollector
|
|
) {
|
|
$this->requestStartTime = $originalCollector->getTotalRequestTime();
|
|
$this->requestStartMemory = $originalCollector->getTotalRequestMemory();
|
|
}
|
|
|
|
/**
|
|
* Start timing an operation
|
|
*/
|
|
public function startTiming(string $key, PerformanceCategory $category, array $context = []): void
|
|
{
|
|
if (! $this->enabled) {
|
|
return;
|
|
}
|
|
|
|
// Record in original collector
|
|
$this->originalCollector->startTiming($key, $category, $context);
|
|
|
|
// Record in telemetry service
|
|
$this->telemetryService->startOperation(
|
|
$key,
|
|
$category->value,
|
|
$context
|
|
);
|
|
|
|
// Record locally for endTiming
|
|
$this->timings[$key] = [
|
|
'start' => microtime(true),
|
|
'category' => $category,
|
|
'context' => $context,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* End timing an operation
|
|
*/
|
|
public function endTiming(string $key): void
|
|
{
|
|
if (! $this->enabled || ! isset($this->timings[$key])) {
|
|
return;
|
|
}
|
|
|
|
// End in original collector
|
|
$this->originalCollector->endTiming($key);
|
|
|
|
// End in telemetry service
|
|
$this->telemetryService->endOperation($key);
|
|
|
|
// Calculate duration and record as metric
|
|
$duration = (microtime(true) - $this->timings[$key]['start']) * 1000;
|
|
$this->recordMetric(
|
|
"{$key}_duration",
|
|
$this->timings[$key]['category'],
|
|
$duration,
|
|
array_merge($this->timings[$key]['context'], ['unit' => 'ms'])
|
|
);
|
|
|
|
// Remove from active timings
|
|
unset($this->timings[$key]);
|
|
}
|
|
|
|
/**
|
|
* Measure a callable's execution time and memory usage
|
|
*/
|
|
public function measure(string $key, PerformanceCategory $category, callable $callback, array $context = []): mixed
|
|
{
|
|
if (! $this->enabled) {
|
|
return $callback();
|
|
}
|
|
|
|
// Use telemetry service's trace method
|
|
return $this->telemetryService->trace(
|
|
$key,
|
|
$category->value,
|
|
$callback,
|
|
$context
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Record a metric value
|
|
*/
|
|
public function recordMetric(string $key, PerformanceCategory $category, float $value, array $context = []): void
|
|
{
|
|
if (! $this->enabled) {
|
|
return;
|
|
}
|
|
|
|
// Record in original collector
|
|
$this->originalCollector->recordMetric($key, $category, $value, $context);
|
|
|
|
// Record in telemetry service
|
|
$unit = $context['unit'] ?? '';
|
|
$this->telemetryService->recordMetric(
|
|
$key,
|
|
$value,
|
|
$unit,
|
|
array_merge($context, ['category' => $category->value])
|
|
);
|
|
|
|
// Store locally
|
|
$this->metrics[$key] = PerformanceMetric::create($key, $category, $context)
|
|
->withValue($value);
|
|
}
|
|
|
|
/**
|
|
* Increment a counter
|
|
*/
|
|
public function increment(string $key, PerformanceCategory $category, int $amount = 1, array $context = []): void
|
|
{
|
|
if (! $this->enabled) {
|
|
return;
|
|
}
|
|
|
|
// Increment in original collector
|
|
$this->originalCollector->increment($key, $category, $amount, $context);
|
|
|
|
// Get current value or default to 0
|
|
$currentValue = 0;
|
|
if (isset($this->metrics[$key])) {
|
|
$currentValue = $this->metrics[$key]->getValue();
|
|
}
|
|
|
|
// Record new value
|
|
$this->recordMetric(
|
|
$key,
|
|
$category,
|
|
$currentValue + $amount,
|
|
array_merge($context, ['type' => 'counter'])
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all metrics, optionally filtered by category
|
|
*
|
|
* @return array<string, PerformanceMetric>
|
|
*/
|
|
public function getMetrics(?PerformanceCategory $category = null): array
|
|
{
|
|
// Get metrics from original collector
|
|
$originalMetrics = $this->originalCollector->getMetrics($category);
|
|
|
|
// Filter local metrics by category if needed
|
|
if ($category !== null) {
|
|
$filteredMetrics = [];
|
|
foreach ($this->metrics as $key => $metric) {
|
|
if ($metric->getCategory() === $category) {
|
|
$filteredMetrics[$key] = $metric;
|
|
}
|
|
}
|
|
|
|
return array_merge($originalMetrics, $filteredMetrics);
|
|
}
|
|
|
|
return array_merge($originalMetrics, $this->metrics);
|
|
}
|
|
|
|
/**
|
|
* Get a specific metric by key
|
|
*/
|
|
public function getMetric(string $key): ?PerformanceMetric
|
|
{
|
|
if (isset($this->metrics[$key])) {
|
|
return $this->metrics[$key];
|
|
}
|
|
|
|
return $this->originalCollector->getMetric($key);
|
|
}
|
|
|
|
/**
|
|
* Get total request time in milliseconds
|
|
*/
|
|
public function getTotalRequestTime(): float
|
|
{
|
|
return (microtime(true) - $this->requestStartTime) * 1000;
|
|
}
|
|
|
|
/**
|
|
* Get total request memory usage in bytes
|
|
*/
|
|
public function getTotalRequestMemory(): int
|
|
{
|
|
return memory_get_usage() - $this->requestStartMemory;
|
|
}
|
|
|
|
/**
|
|
* Get peak memory usage in bytes
|
|
*/
|
|
public function getPeakMemory(): int
|
|
{
|
|
return memory_get_peak_usage();
|
|
}
|
|
|
|
/**
|
|
* Reset all collected metrics
|
|
*/
|
|
public function reset(): void
|
|
{
|
|
$this->metrics = [];
|
|
$this->timings = [];
|
|
$this->originalCollector->reset();
|
|
}
|
|
|
|
/**
|
|
* Check if performance tracking is enabled
|
|
*/
|
|
public function isEnabled(): bool
|
|
{
|
|
return $this->enabled;
|
|
}
|
|
|
|
/**
|
|
* Enable or disable performance tracking
|
|
*/
|
|
public function setEnabled(bool $enabled): void
|
|
{
|
|
$this->enabled = $enabled;
|
|
$this->originalCollector->setEnabled($enabled);
|
|
}
|
|
}
|