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:
126
src/Framework/Metrics/Formatters/OpenMetricsFormatter.php
Normal file
126
src/Framework/Metrics/Formatters/OpenMetricsFormatter.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Metrics\Formatters;
|
||||
|
||||
use App\Framework\Metrics\Metric;
|
||||
use App\Framework\Metrics\MetricsCollection;
|
||||
use App\Framework\Metrics\MetricSuffix;
|
||||
use App\Framework\Metrics\MetricType;
|
||||
|
||||
/**
|
||||
* Formats metrics in OpenMetrics format
|
||||
* OpenMetrics is a CNCF standard that extends Prometheus format
|
||||
* @see https://openmetrics.io/
|
||||
*/
|
||||
final readonly class OpenMetricsFormatter implements MetricsFormatter
|
||||
{
|
||||
public function format(MetricsCollection $metrics): string
|
||||
{
|
||||
$output = [];
|
||||
$processedMetrics = [];
|
||||
|
||||
foreach ($metrics->getMetrics() as $metricName => $metricGroup) {
|
||||
// Skip if already processed
|
||||
if (isset($processedMetrics[$metricName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$firstMetric = $metricGroup[0];
|
||||
$baseName = MetricSuffix::getBaseName($metricName);
|
||||
|
||||
// HELP line (required in OpenMetrics)
|
||||
$help = $firstMetric->help ?? 'No description provided';
|
||||
$output[] = sprintf('# HELP %s %s', $baseName, $help);
|
||||
|
||||
// TYPE line (required in OpenMetrics)
|
||||
$type = $this->determineMetricType($metricName, $firstMetric->type);
|
||||
$output[] = sprintf('# TYPE %s %s', $baseName, $type->value);
|
||||
|
||||
// UNIT line (OpenMetrics specific, optional)
|
||||
if ($firstMetric->unit !== null) {
|
||||
$output[] = sprintf('# UNIT %s %s', $baseName, $firstMetric->unit);
|
||||
}
|
||||
|
||||
// Add metric values
|
||||
foreach ($metricGroup as $metric) {
|
||||
$output[] = $this->formatMetric($metric);
|
||||
}
|
||||
|
||||
$processedMetrics[$metricName] = true;
|
||||
|
||||
// Mark related metrics as processed
|
||||
if ($type === MetricType::HISTOGRAM) {
|
||||
foreach (MetricSuffix::histogramSuffixes() as $suffix) {
|
||||
$processedMetrics[$suffix->addTo($baseName)] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OpenMetrics requires EOF marker
|
||||
$output[] = '# EOF';
|
||||
|
||||
return implode("\n", $output) . "\n";
|
||||
}
|
||||
|
||||
private function formatMetric(Metric $metric): string
|
||||
{
|
||||
$labels = $metric->getFormattedLabels();
|
||||
$name = $metric->name;
|
||||
|
||||
// OpenMetrics doesn't append unit to metric name (uses UNIT metadata instead)
|
||||
|
||||
$line = sprintf('%s%s %s', $name, $labels, $this->formatValue($metric->value));
|
||||
|
||||
// Add timestamp if present (seconds with fractional part for OpenMetrics)
|
||||
if ($metric->timestamp !== null) {
|
||||
$line .= ' ' . number_format($metric->timestamp->toFloat(), 3, '.', '');
|
||||
}
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
private function formatValue(float $value): string
|
||||
{
|
||||
// Handle special float values (OpenMetrics spec)
|
||||
if (is_infinite($value)) {
|
||||
return $value > 0 ? '+Inf' : '-Inf';
|
||||
}
|
||||
|
||||
if (is_nan($value)) {
|
||||
return 'NaN';
|
||||
}
|
||||
|
||||
// Use scientific notation for very large/small numbers
|
||||
if (abs($value) >= 1e10 || (abs($value) < 1e-10 && $value != 0)) {
|
||||
return sprintf('%e', $value);
|
||||
}
|
||||
|
||||
// Regular formatting
|
||||
$formatted = sprintf('%.10f', $value);
|
||||
$formatted = rtrim($formatted, '0');
|
||||
$formatted = rtrim($formatted, '.');
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
private function determineMetricType(string $name, MetricType $type): MetricType
|
||||
{
|
||||
if (MetricSuffix::hasHistogramSuffix($name)) {
|
||||
return MetricType::HISTOGRAM;
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
public function getContentType(): string
|
||||
{
|
||||
return 'application/openmetrics-text; version=1.0.0; charset=utf-8';
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'openmetrics';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user