$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 */ 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 $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) . '}'; } }