From 4a2b4dbd49301e8ee80598317980c825dc5c0d56 Mon Sep 17 00:00:00 2001 From: kwasniew Date: Mon, 22 Sep 2025 11:16:57 +0200 Subject: [PATCH] feat: infinity representation serializable --- .../metrics/impact/batch-histogram.test.ts | 33 ++++++++++++++++--- .../metrics/impact/batch-histogram.ts | 16 +++++---- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/lib/features/metrics/impact/batch-histogram.test.ts b/src/lib/features/metrics/impact/batch-histogram.test.ts index 38a3f20e78..6e7e0e7019 100644 --- a/src/lib/features/metrics/impact/batch-histogram.test.ts +++ b/src/lib/features/metrics/impact/batch-histogram.test.ts @@ -26,7 +26,7 @@ describe('BatchHistogram', () => { { le: 1, count: 7 }, { le: 2.5, count: 9 }, { le: 5, count: 10 }, - { le: Number.POSITIVE_INFINITY, count: 10 }, + { le: '+Inf', count: 10 }, ], }, ); @@ -71,7 +71,7 @@ describe('BatchHistogram', () => { { le: 1, count: 4 }, { le: 2.5, count: 5 }, { le: 5, count: 5 }, - { le: Number.POSITIVE_INFINITY, count: 5 }, + { le: '+Inf', count: 5 }, ], }, ); @@ -87,7 +87,7 @@ describe('BatchHistogram', () => { { le: 1, count: 2 }, { le: 2.5, count: 3 }, { le: 5, count: 3 }, - { le: Number.POSITIVE_INFINITY, count: 3 }, + { le: '+Inf', count: 3 }, ], }, ); @@ -125,7 +125,7 @@ describe('BatchHistogram', () => { sum: 1.5, buckets: [ { le: 1, count: 2 }, - { le: Number.POSITIVE_INFINITY, count: 3 }, + { le: '+Inf', count: 3 }, ], }, ); @@ -137,7 +137,7 @@ describe('BatchHistogram', () => { sum: 3.0, buckets: [ { le: 1, count: 1 }, - { le: Number.POSITIVE_INFINITY, count: 2 }, + { le: '+Inf', count: 2 }, ], }, ); @@ -170,4 +170,27 @@ describe('BatchHistogram', () => { /test_histogram_count{app="my_app",service="web"} 2/, ); }); + + test('should handle "+Inf" string from SDK serialization', async () => { + histogram.recordBatch( + { client: 'sdk' }, + { + count: 5, + sum: 12.3, + buckets: [ + { le: 1, count: 3 }, + { le: '+Inf', count: 5 }, // String instead of Infinity + ], + }, + ); + + const metrics = await registry.metrics(); + + expect(metrics).toMatch(/test_histogram_bucket{client="sdk",le="1"} 3/); + expect(metrics).toMatch( + /test_histogram_bucket{client="sdk",le="\+Inf"} 5/, + ); + expect(metrics).toMatch(/test_histogram_sum{client="sdk"} 12\.3/); + expect(metrics).toMatch(/test_histogram_count{client="sdk"} 5/); + }); }); diff --git a/src/lib/features/metrics/impact/batch-histogram.ts b/src/lib/features/metrics/impact/batch-histogram.ts index ec9ed4a446..4b604c294b 100644 --- a/src/lib/features/metrics/impact/batch-histogram.ts +++ b/src/lib/features/metrics/impact/batch-histogram.ts @@ -1,7 +1,7 @@ import type { Registry } from 'prom-client'; interface BucketData { - le: number; + le: number | '+Inf'; count: number; } @@ -22,7 +22,7 @@ export class BatchHistogram { { count: number; sum: number; - buckets: Map; + buckets: Map; } > = new Map(); @@ -86,15 +86,17 @@ export class BatchHistogram { for (const [le, cumulativeCount] of Array.from( data.buckets.entries(), - ).sort((a, b) => a[0] - b[0])) { + ).sort((a, b) => { + // Sort buckets: numbers first (ascending), then '+Inf' last + if (a[0] === '+Inf') return 1; + if (b[0] === '+Inf') return -1; + return (a[0] as number) - (b[0] as number); + })) { values.push({ value: cumulativeCount, labels: { ...labels, - le: - le === Number.POSITIVE_INFINITY - ? '+Inf' - : le.toString(), + le: le.toString(), }, metricName: `${this.name}_bucket`, });