counter('http_requests_total', 1234, 'Total HTTP requests', ['method' => 'GET', 'status' => '200']); $collection->gauge('memory_usage_bytes', 67108864, 'Memory usage in bytes'); $formatter = new PrometheusFormatter(); $output = $formatter->format($collection); expect($output)->toContain('# HELP http_requests_total Total HTTP requests'); expect($output)->toContain('# TYPE http_requests_total counter'); expect($output)->toContain('http_requests_total{method="GET",status="200"} 1234'); expect($output)->toContain('# HELP memory_usage_bytes Memory usage in bytes'); expect($output)->toContain('# TYPE memory_usage_bytes gauge'); expect($output)->toContain('memory_usage_bytes 67108864'); }); it('formats metrics in OpenMetrics format', function () { $collection = new MetricsCollection(); $collection->counter('http_requests_total', 1234, 'Total HTTP requests', ['method' => 'GET']); $formatter = new OpenMetricsFormatter(); $output = $formatter->format($collection); expect($output)->toContain('# HELP http_requests_total Total HTTP requests'); expect($output)->toContain('# TYPE http_requests_total counter'); expect($output)->toContain('http_requests_total{method="GET"} 1234'); expect($output)->toContain('# EOF'); }); it('formats metrics in JSON format', function () { $collection = new MetricsCollection(); $collection->counter('requests', 100, 'Request count', ['endpoint' => '/api']); $formatter = new JsonFormatter(); $output = $formatter->format($collection); $data = json_decode($output, true); expect($data)->toHaveKey('timestamp'); expect($data)->toHaveKey('metrics'); expect($data['metrics'])->toHaveCount(1); expect($data['metrics'][0])->toMatchArray([ 'name' => 'requests', 'value' => 100, 'type' => 'counter', 'help' => 'Request count', 'labels' => ['endpoint' => '/api'], ]); }); it('formats metrics in StatsD format', function () { $collection = new MetricsCollection(); $collection->counter('api.requests', 42); $collection->gauge('memory.usage', 1024.5, null, ['host' => 'server1']); $formatter = new StatsDFormatter(); $output = $formatter->format($collection); $lines = explode("\n", $output); expect($lines)->toContain('api.requests:42|c'); expect($lines)->toContain('memory.usage:1024.5|g|#host:server1'); }); it('handles histogram metrics correctly', function () { $collection = new MetricsCollection(); $collection->histogram( 'http_request_duration', [ '0.1' => 100, '0.5' => 200, '1.0' => 250, '+Inf' => 300, ], 150.5, 300, 'HTTP request duration in seconds' ); $formatter = new PrometheusFormatter(); $output = $formatter->format($collection); expect($output)->toContain('# TYPE http_request_duration histogram'); expect($output)->toContain('http_request_duration_bucket{le="0.1"} 100'); expect($output)->toContain('http_request_duration_bucket{le="0.5"} 200'); expect($output)->toContain('http_request_duration_bucket{le="1.0"} 250'); expect($output)->toContain('http_request_duration_bucket{le="+Inf"} 300'); expect($output)->toContain('http_request_duration_sum 150.5'); expect($output)->toContain('http_request_duration_count 300'); }); it('escapes special characters in labels', function () { $collection = new MetricsCollection(); $collection->counter('test', 1, null, [ 'path' => '/api/test"quotes"', 'description' => "Line\nbreak", ]); $formatter = new PrometheusFormatter(); $output = $formatter->format($collection); expect($output)->toContain('path="/api/test\\"quotes\\""'); expect($output)->toContain('description="Line\\nbreak"'); }); it('converts metrics collection to array', function () { $collection = new MetricsCollection(); $collection->counter('test', 42, 'Test metric', ['env' => 'prod']); $array = $collection->toArray(); expect($array)->toHaveKey('timestamp'); expect($array)->toHaveKey('metrics'); expect($array['metrics'])->toHaveCount(1); expect($array['metrics'][0])->toMatchArray([ 'name' => 'test', 'value' => 42, 'type' => 'counter', 'help' => 'Test metric', 'labels' => ['env' => 'prod'], ]); });