Files
michaelschiemer/src/Framework/Telemetry/ValueObjects/Metric.php
Michael Schiemer 55a330b223 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
2025-08-11 20:13:26 +02:00

168 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Telemetry\ValueObjects;
use DateTimeImmutable;
/**
* Represents a telemetry metric (a measurable value)
*/
final class Metric
{
/**
* @param string $name Name of the metric
* @param float $value Value of the metric
* @param string $unit Unit of measurement (e.g., ms, bytes, count)
* @param string $type Type of metric (counter, gauge, histogram)
* @param DateTimeImmutable $timestamp Time when the metric was recorded
* @param array<string, mixed> $attributes Additional attributes for the metric
*/
public function __construct(
public readonly string $name,
public readonly float $value,
public readonly string $unit = '',
public readonly string $type = 'gauge',
public readonly DateTimeImmutable $timestamp = new DateTimeImmutable(),
public readonly array $attributes = []
) {
}
/**
* Convert the metric to an array
*
* @return array<string, mixed>
*/
public function toArray(): array
{
return [
'name' => $this->name,
'value' => $this->value,
'unit' => $this->unit,
'type' => $this->type,
'timestamp' => $this->timestamp->format('Y-m-d\TH:i:s.uP'),
'attributes' => $this->attributes,
];
}
/**
* Create a new instance with additional attributes
*
* @param array<string, mixed> $attributes
*/
public function withAttributes(array $attributes): self
{
return new self(
$this->name,
$this->value,
$this->unit,
$this->type,
$this->timestamp,
array_merge($this->attributes, $attributes)
);
}
/**
* Create a counter metric
*/
public static function counter(string $name, float $value, array $attributes = []): self
{
return new self(
$name,
$value,
'count',
'counter',
new DateTimeImmutable(),
$attributes
);
}
/**
* Create a gauge metric
*/
public static function gauge(string $name, float $value, string $unit = '', array $attributes = []): self
{
return new self(
$name,
$value,
$unit,
'gauge',
new DateTimeImmutable(),
$attributes
);
}
/**
* Create a histogram metric
*/
public static function histogram(string $name, float $value, string $unit = '', array $attributes = []): self
{
return new self(
$name,
$value,
$unit,
'histogram',
new DateTimeImmutable(),
$attributes
);
}
/**
* Get the formatted name for Prometheus
*/
public function getPrometheusName(): string
{
// Convert to Prometheus naming convention (lowercase with underscores)
return strtolower(str_replace(['.', '-', ' '], '_', $this->name));
}
/**
* Get the Prometheus metric type
*/
public function getPrometheusType(): string
{
return match($this->type) {
'counter' => 'counter',
'gauge' => 'gauge',
'histogram' => 'histogram',
default => 'untyped'
};
}
/**
* Get the Prometheus help text
*/
public function getPrometheusHelp(): string
{
$unitText = $this->unit ? " in {$this->unit}" : '';
return "{$this->name}{$unitText}";
}
/**
* Format the attributes as Prometheus labels
*/
public function getPrometheusLabels(): string
{
if (empty($this->attributes)) {
return '';
}
$labels = [];
foreach ($this->attributes as $key => $value) {
// Skip non-scalar values
if (is_scalar($value)) {
$escapedValue = str_replace(['\\', '"', "\n"], ['\\\\', '\\"', '\\n'], (string)$value);
$labels[] = "{$key}=\"{$escapedValue}\"";
}
}
if (empty($labels)) {
return '';
}
return '{' . implode(',', $labels) . '}';
}
}