Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
268
src/Framework/Telemetry/Adapters/PerformanceCollectorAdapter.php
Normal file
268
src/Framework/Telemetry/Adapters/PerformanceCollectorAdapter.php
Normal file
@@ -0,0 +1,268 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user