@@ -180,9 +180,10 @@ private void writeCounter(Writer writer, CounterSnapshot snapshot, EscapingSchem
180180 if (openMetrics2Properties .getSuffixes ()) {
181181 counterName = ensureSuffix (counterName , "_total" );
182182 }
183+ boolean nameValidLegacy = PrometheusNaming .isValidLegacyMetricName (counterName );
183184 writeMetadataWithName (writer , counterName , "counter" , metadata );
184185 for (CounterSnapshot .CounterDataPointSnapshot data : snapshot .getDataPoints ()) {
185- writeNameAndLabels (writer , counterName , null , data .getLabels (), scheme );
186+ writeNameAndLabels (writer , counterName , null , data .getLabels (), scheme , nameValidLegacy );
186187 writeDouble (writer , data .getValue ());
187188 if (data .hasScrapeTimestamp ()) {
188189 writer .write (' ' );
@@ -201,9 +202,10 @@ private void writeGauge(Writer writer, GaugeSnapshot snapshot, EscapingScheme sc
201202 throws IOException {
202203 MetricMetadata metadata = snapshot .getMetadata ();
203204 String name = getMetricName (metadata , scheme );
205+ boolean nameValidLegacy = PrometheusNaming .isValidLegacyMetricName (name );
204206 writeMetadataWithName (writer , name , "gauge" , metadata );
205207 for (GaugeSnapshot .GaugeDataPointSnapshot data : snapshot .getDataPoints ()) {
206- writeNameAndLabels (writer , name , null , data .getLabels (), scheme );
208+ writeNameAndLabels (writer , name , null , data .getLabels (), scheme , nameValidLegacy );
207209 writeDouble (writer , data .getValue ());
208210 if (exemplarsOnAllMetricTypesEnabled ) {
209211 writeScrapeTimestampAndExemplar (writer , data , data .getExemplar (), scheme );
@@ -219,40 +221,51 @@ private void writeHistogram(Writer writer, HistogramSnapshot snapshot, EscapingS
219221 openMetrics2Properties .getCompositeValues () || openMetrics2Properties .getNativeHistograms ();
220222 MetricMetadata metadata = snapshot .getMetadata ();
221223 String name = getMetricName (metadata , scheme );
224+ boolean nameValidLegacy = PrometheusNaming .isValidLegacyMetricName (name );
222225 if (!compositeHistogram && !openMetrics2Properties .getExemplarCompliance ()) {
223- writeClassicHistogram (writer , name , snapshot , scheme );
226+ writeClassicHistogram (writer , name , snapshot , scheme , nameValidLegacy );
224227 return ;
225228 }
226229 if (snapshot .isGaugeHistogram ()) {
227230 writeMetadataWithName (writer , name , "gaugehistogram" , metadata );
228231 for (HistogramSnapshot .HistogramDataPointSnapshot data : snapshot .getDataPoints ()) {
229232 if (openMetrics2Properties .getNativeHistograms () && data .hasNativeHistogramData ()) {
230- writeNativeHistogramDataPoint (writer , name , "gcount" , "gsum" , data , scheme , false );
233+ writeNativeHistogramDataPoint (
234+ writer , name , "gcount" , "gsum" , data , scheme , false , nameValidLegacy );
231235 } else {
232- writeCompositeHistogramDataPoint (writer , name , "gcount" , "gsum" , data , scheme , false );
236+ writeCompositeHistogramDataPoint (
237+ writer , name , "gcount" , "gsum" , data , scheme , false , nameValidLegacy );
233238 }
234239 }
235240 } else {
236241 writeMetadataWithName (writer , name , "histogram" , metadata );
237242 for (HistogramSnapshot .HistogramDataPointSnapshot data : snapshot .getDataPoints ()) {
238243 if (openMetrics2Properties .getNativeHistograms () && data .hasNativeHistogramData ()) {
239- writeNativeHistogramDataPoint (writer , name , "count" , "sum" , data , scheme , true );
244+ writeNativeHistogramDataPoint (
245+ writer , name , "count" , "sum" , data , scheme , true , nameValidLegacy );
240246 } else {
241- writeCompositeHistogramDataPoint (writer , name , "count" , "sum" , data , scheme , true );
247+ writeCompositeHistogramDataPoint (
248+ writer , name , "count" , "sum" , data , scheme , true , nameValidLegacy );
242249 }
243250 }
244251 }
245252 }
246253
247254 private void writeClassicHistogram (
248- Writer writer , String name , HistogramSnapshot snapshot , EscapingScheme scheme )
255+ Writer writer ,
256+ String name ,
257+ HistogramSnapshot snapshot ,
258+ EscapingScheme scheme ,
259+ boolean nameValidLegacy )
249260 throws IOException {
250261 if (snapshot .isGaugeHistogram ()) {
251262 writeMetadataWithName (writer , name , "gaugehistogram" , snapshot .getMetadata ());
252- writeClassicHistogramDataPoints (writer , name , "_gcount" , "_gsum" , snapshot , scheme );
263+ writeClassicHistogramDataPoints (
264+ writer , name , "_gcount" , "_gsum" , snapshot , scheme , nameValidLegacy );
253265 } else {
254266 writeMetadataWithName (writer , name , "histogram" , snapshot .getMetadata ());
255- writeClassicHistogramDataPoints (writer , name , "_count" , "_sum" , snapshot , scheme );
267+ writeClassicHistogramDataPoints (
268+ writer , name , "_count" , "_sum" , snapshot , scheme , nameValidLegacy );
256269 }
257270 }
258271
@@ -262,7 +275,8 @@ private void writeClassicHistogramDataPoints(
262275 String countSuffix ,
263276 String sumSuffix ,
264277 HistogramSnapshot snapshot ,
265- EscapingScheme scheme )
278+ EscapingScheme scheme ,
279+ boolean nameValidLegacy )
266280 throws IOException {
267281 String bucketName = name + "_bucket" ;
268282 for (HistogramSnapshot .HistogramDataPointSnapshot data : snapshot .getDataPoints ()) {
@@ -272,7 +286,14 @@ private void writeClassicHistogramDataPoints(
272286 for (int i = 0 ; i < buckets .size (); i ++) {
273287 cumulativeCount += buckets .getCount (i );
274288 writeNameAndLabels (
275- writer , bucketName , null , data .getLabels (), scheme , "le" , buckets .getUpperBound (i ));
289+ writer ,
290+ bucketName ,
291+ null ,
292+ data .getLabels (),
293+ scheme ,
294+ "le" ,
295+ buckets .getUpperBound (i ),
296+ nameValidLegacy );
276297 writeLong (writer , cumulativeCount );
277298 Exemplar exemplar ;
278299 if (i == 0 ) {
@@ -283,9 +304,10 @@ private void writeClassicHistogramDataPoints(
283304 writeScrapeTimestampAndExemplar (writer , data , exemplar , scheme );
284305 }
285306 if (data .hasCount () && data .hasSum ()) {
286- writeClassicCountAndSum (writer , name , data , countSuffix , sumSuffix , exemplars , scheme );
307+ writeClassicCountAndSum (
308+ writer , name , data , countSuffix , sumSuffix , exemplars , scheme , nameValidLegacy );
287309 }
288- writeClassicCreated (writer , name , data , scheme );
310+ writeClassicCreated (writer , name , data , scheme , nameValidLegacy );
289311 }
290312 }
291313
@@ -296,16 +318,17 @@ private void writeClassicCountAndSum(
296318 String countSuffix ,
297319 String sumSuffix ,
298320 Exemplars exemplars ,
299- EscapingScheme scheme )
321+ EscapingScheme scheme ,
322+ boolean nameValidLegacy )
300323 throws IOException {
301- writeNameAndLabels (writer , name , countSuffix , data .getLabels (), scheme );
324+ writeNameAndLabels (writer , name , countSuffix , data .getLabels (), scheme , nameValidLegacy );
302325 writeLong (writer , data .getCount ());
303326 if (exemplarsOnAllMetricTypesEnabled ) {
304327 writeScrapeTimestampAndExemplar (writer , data , exemplars .getLatest (), scheme );
305328 } else {
306329 writeScrapeTimestampAndExemplar (writer , data , null , scheme );
307330 }
308- writeNameAndLabels (writer , name , sumSuffix , data .getLabels (), scheme );
331+ writeNameAndLabels (writer , name , sumSuffix , data .getLabels (), scheme , nameValidLegacy );
309332 writeDouble (writer , data .getSum ());
310333 writeScrapeTimestampAndExemplar (writer , data , null , scheme );
311334 }
@@ -314,10 +337,11 @@ private void writeClassicCreated(
314337 Writer writer ,
315338 String name ,
316339 HistogramSnapshot .HistogramDataPointSnapshot data ,
317- EscapingScheme scheme )
340+ EscapingScheme scheme ,
341+ boolean nameValidLegacy )
318342 throws IOException {
319343 if (createdTimestampsEnabled && data .hasCreatedTimestamp ()) {
320- writeNameAndLabels (writer , name , "_created" , data .getLabels (), scheme );
344+ writeNameAndLabels (writer , name , "_created" , data .getLabels (), scheme , nameValidLegacy );
321345 writeOpenMetricsTimestamp (writer , data .getCreatedTimestampMillis ());
322346 if (data .hasScrapeTimestamp ()) {
323347 writer .write (' ' );
@@ -334,9 +358,10 @@ private void writeCompositeHistogramDataPoint(
334358 String sumKey ,
335359 HistogramSnapshot .HistogramDataPointSnapshot data ,
336360 EscapingScheme scheme ,
337- boolean includeStartTimestamp )
361+ boolean includeStartTimestamp ,
362+ boolean nameValidLegacy )
338363 throws IOException {
339- writeNameAndLabels (writer , name , null , data .getLabels (), scheme );
364+ writeNameAndLabels (writer , name , null , data .getLabels (), scheme , nameValidLegacy );
340365 writer .write ('{' );
341366 writer .write (countKey );
342367 writer .write (':' );
@@ -366,9 +391,10 @@ private void writeNativeHistogramDataPoint(
366391 String sumKey ,
367392 HistogramSnapshot .HistogramDataPointSnapshot data ,
368393 EscapingScheme scheme ,
369- boolean includeStartTimestamp )
394+ boolean includeStartTimestamp ,
395+ boolean nameValidLegacy )
370396 throws IOException {
371- writeNameAndLabels (writer , name , null , data .getLabels (), scheme );
397+ writeNameAndLabels (writer , name , null , data .getLabels (), scheme , nameValidLegacy );
372398 writer .write ('{' );
373399 writer .write (countKey );
374400 writer .write (':' );
@@ -489,6 +515,7 @@ private void writeSummary(Writer writer, SummarySnapshot snapshot, EscapingSchem
489515 om1Writer .writeSummary (writer , snapshot , scheme , name );
490516 return ;
491517 }
518+ boolean nameValidLegacy = PrometheusNaming .isValidLegacyMetricName (name );
492519 boolean metadataWritten = false ;
493520 for (SummarySnapshot .SummaryDataPointSnapshot data : snapshot .getDataPoints ()) {
494521 if (data .getQuantiles ().size () == 0 && !data .hasCount () && !data .hasSum ()) {
@@ -498,17 +525,18 @@ private void writeSummary(Writer writer, SummarySnapshot snapshot, EscapingSchem
498525 writeMetadataWithName (writer , name , "summary" , metadata );
499526 metadataWritten = true ;
500527 }
501- writeCompositeSummaryDataPoint (writer , name , data , scheme );
528+ writeCompositeSummaryDataPoint (writer , name , data , scheme , nameValidLegacy );
502529 }
503530 }
504531
505532 private void writeCompositeSummaryDataPoint (
506533 Writer writer ,
507534 String name ,
508535 SummarySnapshot .SummaryDataPointSnapshot data ,
509- EscapingScheme scheme )
536+ EscapingScheme scheme ,
537+ boolean nameValidLegacy )
510538 throws IOException {
511- writeNameAndLabels (writer , name , null , data .getLabels (), scheme );
539+ writeNameAndLabels (writer , name , null , data .getLabels (), scheme , nameValidLegacy );
512540 writer .write ('{' );
513541 boolean first = true ;
514542 if (data .hasCount ()) {
@@ -557,9 +585,10 @@ private void writeInfo(Writer writer, InfoSnapshot snapshot, EscapingScheme sche
557585 // OM2 spec: Info MetricFamily name MUST end in _info.
558586 // In OM2, TYPE/HELP use the same name as the data lines.
559587 String infoName = ensureSuffix (getMetricName (metadata , scheme ), "_info" );
588+ boolean nameValidLegacy = PrometheusNaming .isValidLegacyMetricName (infoName );
560589 writeMetadataWithName (writer , infoName , "info" , metadata );
561590 for (InfoSnapshot .InfoDataPointSnapshot data : snapshot .getDataPoints ()) {
562- writeNameAndLabels (writer , infoName , null , data .getLabels (), scheme );
591+ writeNameAndLabels (writer , infoName , null , data .getLabels (), scheme , nameValidLegacy );
563592 writer .write ("1" );
564593 writeScrapeTimestampAndExemplar (writer , data , null , scheme );
565594 }
@@ -605,9 +634,10 @@ private void writeUnknown(Writer writer, UnknownSnapshot snapshot, EscapingSchem
605634 throws IOException {
606635 MetricMetadata metadata = snapshot .getMetadata ();
607636 String name = getMetricName (metadata , scheme );
637+ boolean nameValidLegacy = PrometheusNaming .isValidLegacyMetricName (name );
608638 writeMetadataWithName (writer , name , "unknown" , metadata );
609639 for (UnknownSnapshot .UnknownDataPointSnapshot data : snapshot .getDataPoints ()) {
610- writeNameAndLabels (writer , name , null , data .getLabels (), scheme );
640+ writeNameAndLabels (writer , name , null , data .getLabels (), scheme , nameValidLegacy );
611641 writeDouble (writer , data .getValue ());
612642 if (exemplarsOnAllMetricTypesEnabled ) {
613643 writeScrapeTimestampAndExemplar (writer , data , data .getExemplar (), scheme );
@@ -622,9 +652,10 @@ private void writeNameAndLabels(
622652 String name ,
623653 @ Nullable String suffix ,
624654 Labels labels ,
625- EscapingScheme escapingScheme )
655+ EscapingScheme escapingScheme ,
656+ boolean nameValidLegacy )
626657 throws IOException {
627- writeNameAndLabels (writer , name , suffix , labels , escapingScheme , null , 0.0 );
658+ writeNameAndLabels (writer , name , suffix , labels , escapingScheme , null , 0.0 , nameValidLegacy );
628659 }
629660
630661 private void writeNameAndLabels (
@@ -634,16 +665,19 @@ private void writeNameAndLabels(
634665 Labels labels ,
635666 EscapingScheme escapingScheme ,
636667 @ Nullable String additionalLabelName ,
637- double additionalLabelValue )
668+ double additionalLabelValue ,
669+ boolean nameValidLegacy )
638670 throws IOException {
639671 boolean metricInsideBraces = false ;
640- // If the name does not pass the legacy validity check, we must put the
641- // metric name inside the braces.
642- if (!PrometheusNaming .isValidLegacyMetricName (name )) {
672+ // If the name does not pass the legacy validity check, we must put the metric name inside the
673+ // braces. Validity is scanned once per family by the caller (the metric name is constant across
674+ // all data points), not re-scanned for every series. A suffix built from legacy characters
675+ // (_total, _bucket, ...) does not change legacy validity, so the base-name check applies here.
676+ if (!nameValidLegacy ) {
643677 metricInsideBraces = true ;
644678 writer .write ('{' );
645679 }
646- writeName (writer , suffix != null ? name + suffix : name , NameType .Metric );
680+ writeName (writer , suffix != null ? name + suffix : name , NameType .Metric , nameValidLegacy );
647681 if (!labels .isEmpty () || additionalLabelName != null ) {
648682 writeLabels (
649683 writer ,
0 commit comments