@@ -75,87 +75,20 @@ void testDuplicateNames_differentLabels_producesValidOutput() throws IOException
7575 writer .write (out , snapshots );
7676 String output = out .toString (UTF_8 );
7777
78- System .out .println ("=== Duplicate Names (Different Labels) Output ===" );
79- System .out .println (output );
80- System .out .println ("=== End Output ===\n " );
81-
82- // Verify output contains both metrics
83- assertThat (output ).contains ("api_responses_total{" );
84- assertThat (output ).contains ("outcome=\" SUCCESS\" " );
85- assertThat (output ).contains ("outcome=\" FAILURE\" " );
86- assertThat (output ).contains ("error=\" TIMEOUT\" " );
87- assertThat (output ).contains (" 100" );
88- assertThat (output ).contains (" 10" );
89-
90- // Verify TYPE declaration appears (may appear multiple times)
91- assertThat (output ).contains ("# TYPE api_responses_total counter" );
92-
93- // Count how many times the metric name appears in data lines
94- long metricLines =
95- output .lines ().filter (line -> line .startsWith ("api_responses_total{" )).count ();
96- assertThat (metricLines ).isEqualTo (2 );
97- }
98-
99- @ Test
100- void testDuplicateNames_sameLabels_throwsException () {
101- PrometheusRegistry registry = new PrometheusRegistry ();
102-
103- // Counter 1
104- registry .register (
105- new Collector () {
106- @ Override
107- public MetricSnapshot collect () {
108- return CounterSnapshot .builder ()
109- .name ("api_responses" )
110- .help ("API responses" )
111- .dataPoint (
112- CounterSnapshot .CounterDataPointSnapshot .builder ()
113- .labels (Labels .of ("uri" , "/hello" , "outcome" , "SUCCESS" ))
114- .value (100 )
115- .build ())
116- .build ();
117- }
118-
119- @ Override
120- public String getPrometheusName () {
121- return "api_responses_total" ;
122- }
123- });
124-
125- // Counter 2: SAME labels, different value - this should cause an exception during scrape
126- registry .register (
127- new Collector () {
128- @ Override
129- public MetricSnapshot collect () {
130- return CounterSnapshot .builder ()
131- .name ("api_responses" )
132- .help ("API responses" )
133- .dataPoint (
134- CounterSnapshot .CounterDataPointSnapshot .builder ()
135- .labels (Labels .of ("uri" , "/hello" , "outcome" , "SUCCESS" ))
136- .value (50 )
137- .build ())
138- .build ();
139- }
140-
141- @ Override
142- public String getPrometheusName () {
143- return "api_responses_total" ;
144- }
145- });
146-
147- // Scraping should throw exception due to duplicate time series (same name + same labels)
148- assertThatThrownBy (registry ::scrape )
149- .isInstanceOf (IllegalArgumentException .class )
150- .hasMessageContaining ("Duplicate labels detected" )
151- .hasMessageContaining ("api_responses" );
78+ String expected = """
79+ # HELP api_responses_total API responses
80+ # TYPE api_responses_total counter
81+ api_responses_total{error="TIMEOUT",outcome="FAILURE",uri="/hello"} 10.0
82+ api_responses_total{outcome="SUCCESS",uri="/hello"} 100.0
83+ """ ;
84+
85+ assertThat (output ).isEqualTo (expected );
15286 }
15387
15488 @ Test
15589 void testDuplicateNames_multipleDataPoints_producesValidOutput () throws IOException {
15690 PrometheusRegistry registry = new PrometheusRegistry ();
15791
158- // Counter 1: Multiple data points
15992 registry .register (
16093 new Collector () {
16194 @ Override
@@ -182,7 +115,6 @@ public String getPrometheusName() {
182115 }
183116 });
184117
185- // Counter 2: Multiple data points with additional error label
186118 registry .register (
187119 new Collector () {
188120 @ Override
@@ -211,112 +143,94 @@ public String getPrometheusName() {
211143 }
212144 });
213145
214- // Scrape and write to text format
215146 MetricSnapshots snapshots = registry .scrape ();
216147 ByteArrayOutputStream out = new ByteArrayOutputStream ();
217148 PrometheusTextFormatWriter writer = PrometheusTextFormatWriter .create ();
218149 writer .write (out , snapshots );
219150 String output = out .toString (UTF_8 );
220151
221- System .out .println ("=== Duplicate Names (Multiple Data Points) Output ===" );
222- System .out .println (output );
223- System .out .println ("=== End Output ===\n " );
152+ String expected = """
153+ # HELP api_responses_total API responses
154+ # TYPE api_responses_total counter
155+ api_responses_total{error="NOT_FOUND",outcome="FAILURE",uri="/world"} 5.0
156+ api_responses_total{error="TIMEOUT",outcome="FAILURE",uri="/hello"} 10.0
157+ api_responses_total{outcome="SUCCESS",uri="/hello"} 100.0
158+ api_responses_total{outcome="SUCCESS",uri="/world"} 200.0
159+ """ ;
160+ assertThat (output ).isEqualTo (expected );
224161
225- long metricLines =
226- output .lines ().filter (line -> line .startsWith ("api_responses_total{" )).count ();
227- assertThat (metricLines ).isEqualTo (4 );
228-
229- assertThat (output ).contains (" 100" );
230- assertThat (output ).contains (" 200" );
231- assertThat (output ).contains (" 10" );
232- assertThat (output ).contains (" 5" );
233162 }
234163
235164 @ Test
236- void testBackwardCompatibility_strictModeWorksAsExpected () throws IOException {
237- PrometheusRegistry registry = new PrometheusRegistry (); // Strict mode
238-
239- registry .register (
240- new Collector () {
241- @ Override
242- public MetricSnapshot collect () {
243- return CounterSnapshot .builder ()
244- .name ("requests" )
245- .help ("Request counter" )
246- .dataPoint (
247- CounterSnapshot .CounterDataPointSnapshot .builder ()
248- .labels (Labels .of ("method" , "GET" ))
249- .value (100 )
250- .build ())
251- .build ();
252- }
253-
254- @ Override
255- public String getPrometheusName () {
256- return "requests_total" ;
257- }
258- });
259-
260- registry .register (
261- new Collector () {
262- @ Override
263- public MetricSnapshot collect () {
264- return GaugeSnapshot .builder ()
265- .name ("active_requests" )
266- .help ("Active requests gauge" )
267- .dataPoint (
268- GaugeSnapshot .GaugeDataPointSnapshot .builder ()
269- .labels (Labels .of ("method" , "POST" ))
270- .value (50 )
271- .build ())
272- .build ();
273- }
274-
275- @ Override
276- public String getPrometheusName () {
277- return "active_requests" ;
278- }
279- });
165+ void testOpenMetricsFormat_withDuplicateNames () throws IOException {
166+ PrometheusRegistry registry = getPrometheusRegistry ();
280167
281168 MetricSnapshots snapshots = registry .scrape ();
282169 ByteArrayOutputStream out = new ByteArrayOutputStream ();
283- PrometheusTextFormatWriter writer = PrometheusTextFormatWriter . create ( );
170+ OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter ( false , false );
284171 writer .write (out , snapshots );
285172 String output = out .toString (UTF_8 );
286173
287- System .out .println ("=== Backward Compatibility (Strict Mode) Output ===" );
288- System .out .println (output );
289- System .out .println ("=== End Output ===\n " );
290-
291- // Verify both metrics appear with unique names
292- assertThat (output ).contains ("# TYPE requests_total counter" );
293- assertThat (output ).contains ("# TYPE active_requests gauge" );
294- assertThat (output ).contains ("requests_total{" );
295- assertThat (output ).contains ("active_requests{" );
174+ String expected = """
175+ # TYPE api_responses counter
176+ # HELP api_responses API responses
177+ api_responses_total{error="TIMEOUT",outcome="FAILURE",uri="/hello"} 10.0
178+ api_responses_total{outcome="SUCCESS",uri="/hello"} 100.0
179+ # EOF
180+ """ ;
181+ assertThat (output ).isEqualTo (expected );
296182 }
297183
298184 @ Test
299- void testOpenMetricsFormat_withDuplicateNames () throws IOException {
300- PrometheusRegistry registry = getPrometheusRegistry ();
301-
302- MetricSnapshots snapshots = registry .scrape ();
303- ByteArrayOutputStream out = new ByteArrayOutputStream ();
304- OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter (false , false );
305- writer .write (out , snapshots );
306- String output = out .toString (UTF_8 );
185+ void testDuplicateNames_sameLabels_throwsException () {
186+ PrometheusRegistry registry = new PrometheusRegistry ();
307187
308- System .out .println ("=== OpenMetrics Format with Duplicate Names ===" );
309- System .out .println (output );
310- System .out .println ("=== End Output ===\n " );
188+ registry .register (
189+ new Collector () {
190+ @ Override
191+ public MetricSnapshot collect () {
192+ return CounterSnapshot .builder ()
193+ .name ("api_responses" )
194+ .help ("API responses" )
195+ .dataPoint (
196+ CounterSnapshot .CounterDataPointSnapshot .builder ()
197+ .labels (Labels .of ("uri" , "/hello" , "outcome" , "SUCCESS" ))
198+ .value (100 )
199+ .build ())
200+ .build ();
201+ }
202+
203+ @ Override
204+ public String getPrometheusName () {
205+ return "api_responses_total" ;
206+ }
207+ });
311208
312- assertThat (output ).contains ("# TYPE api_responses counter" );
313- assertThat (output ).contains ("api_responses_total{" );
314- assertThat (output ).contains ("outcome=\" SUCCESS\" " );
315- assertThat (output ).contains ("outcome=\" FAILURE\" " );
316- assertThat (output ).contains ("# EOF" );
209+ registry .register (
210+ new Collector () {
211+ @ Override
212+ public MetricSnapshot collect () {
213+ return CounterSnapshot .builder ()
214+ .name ("api_responses" )
215+ .help ("API responses" )
216+ .dataPoint (
217+ CounterSnapshot .CounterDataPointSnapshot .builder ()
218+ .labels (Labels .of ("uri" , "/hello" , "outcome" , "SUCCESS" ))
219+ .value (50 )
220+ .build ())
221+ .build ();
222+ }
223+
224+ @ Override
225+ public String getPrometheusName () {
226+ return "api_responses_total" ;
227+ }
228+ });
317229
318- long metricLines =
319- output .lines ().filter (line -> line .startsWith ("api_responses_total{" )).count ();
320- assertThat (metricLines ).isEqualTo (2 );
230+ // Scraping should throw exception due to duplicate time series (same name + same labels)
231+ assertThatThrownBy (registry ::scrape )
232+ .isInstanceOf (IllegalArgumentException .class )
233+ .hasMessageContaining ("Duplicate labels detected" )
234+ .hasMessageContaining ("api_responses" );
321235 }
322236}
0 commit comments