Append unit to prometheus metric names (#5400)
This commit is contained in:
		
							parent
							
								
									951221efcc
								
							
						
					
					
						commit
						4d034b08e8
					
				|  | @ -14,6 +14,9 @@ dependencies { | |||
|   implementation(project(":sdk-extensions:autoconfigure-spi")) | ||||
| 
 | ||||
|   compileOnly("com.sun.net.httpserver:http") | ||||
|   compileOnly("com.google.auto.value:auto-value-annotations") | ||||
| 
 | ||||
|   annotationProcessor("com.google.auto.value:auto-value") | ||||
| 
 | ||||
|   testImplementation(project(":semconv")) | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,6 +15,8 @@ class NameSanitizer implements Function<String, String> { | |||
| 
 | ||||
|   static final NameSanitizer INSTANCE = new NameSanitizer(); | ||||
| 
 | ||||
|   static final Pattern SANITIZE_CONSECUTIVE_UNDERSCORES = Pattern.compile("[_]{2,}"); | ||||
| 
 | ||||
|   private static final Pattern SANITIZE_PREFIX_PATTERN = Pattern.compile("^[^a-zA-Z_:]"); | ||||
|   private static final Pattern SANITIZE_BODY_PATTERN = Pattern.compile("[^a-zA-Z0-9_:]"); | ||||
| 
 | ||||
|  | @ -36,8 +38,11 @@ class NameSanitizer implements Function<String, String> { | |||
|   } | ||||
| 
 | ||||
|   private static String sanitizeMetricName(String metricName) { | ||||
|     return SANITIZE_BODY_PATTERN | ||||
|         .matcher(SANITIZE_PREFIX_PATTERN.matcher(metricName).replaceFirst("_")) | ||||
|     return SANITIZE_CONSECUTIVE_UNDERSCORES | ||||
|         .matcher( | ||||
|             SANITIZE_BODY_PATTERN | ||||
|                 .matcher(SANITIZE_PREFIX_PATTERN.matcher(metricName).replaceFirst("_")) | ||||
|                 .replaceAll("_")) | ||||
|         .replaceAll("_"); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,98 @@ | |||
| /* | ||||
|  * Copyright The OpenTelemetry Authors | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  */ | ||||
| 
 | ||||
| package io.opentelemetry.exporter.prometheus; | ||||
| 
 | ||||
| import com.google.auto.value.AutoValue; | ||||
| import io.opentelemetry.api.internal.StringUtils; | ||||
| import io.opentelemetry.sdk.metrics.data.MetricData; | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
| import java.util.function.BiFunction; | ||||
| import javax.annotation.concurrent.Immutable; | ||||
| 
 | ||||
| /** A class that maps a raw metric name to Prometheus equivalent name. */ | ||||
| class PrometheusMetricNameMapper implements BiFunction<MetricData, PrometheusType, String> { | ||||
| 
 | ||||
|   static final PrometheusMetricNameMapper INSTANCE = new PrometheusMetricNameMapper(); | ||||
| 
 | ||||
|   private final Map<ImmutableMappingKey, String> cache = new ConcurrentHashMap<>(); | ||||
|   private final BiFunction<MetricData, PrometheusType, String> delegate; | ||||
| 
 | ||||
|   // private constructor - prevent external object initialization | ||||
|   private PrometheusMetricNameMapper() { | ||||
|     this(PrometheusMetricNameMapper::mapToPrometheusName); | ||||
|   } | ||||
| 
 | ||||
|   // Visible for testing | ||||
|   PrometheusMetricNameMapper(BiFunction<MetricData, PrometheusType, String> delegate) { | ||||
|     this.delegate = delegate; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|   public String apply(MetricData rawMetric, PrometheusType prometheusType) { | ||||
|     return cache.computeIfAbsent( | ||||
|         createKeyForCacheMapping(rawMetric, prometheusType), | ||||
|         metricData -> delegate.apply(rawMetric, prometheusType)); | ||||
|   } | ||||
| 
 | ||||
|   private static String mapToPrometheusName(MetricData rawMetric, PrometheusType prometheusType) { | ||||
|     String name = NameSanitizer.INSTANCE.apply(rawMetric.getName()); | ||||
|     String prometheusEquivalentUnit = | ||||
|         PrometheusUnitsHelper.getEquivalentPrometheusUnit(rawMetric.getUnit()); | ||||
|     // append prometheus unit if not null or empty. | ||||
|     if (!StringUtils.isNullOrEmpty(prometheusEquivalentUnit) | ||||
|         && !name.contains(prometheusEquivalentUnit)) { | ||||
|       name = name + "_" + prometheusEquivalentUnit; | ||||
|     } | ||||
| 
 | ||||
|     // special case - counter | ||||
|     if (prometheusType == PrometheusType.COUNTER && !name.contains("total")) { | ||||
|       name = name + "_total"; | ||||
|     } | ||||
|     // special case - gauge | ||||
|     if (rawMetric.getUnit().equals("1") | ||||
|         && prometheusType == PrometheusType.GAUGE | ||||
|         && !name.contains("ratio")) { | ||||
|       name = name + "_ratio"; | ||||
|     } | ||||
|     return name; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Creates a suitable mapping key to be used for maintaining mapping between raw metric and its | ||||
|    * equivalent Prometheus name. | ||||
|    * | ||||
|    * @param metricData the metric data for which the mapping is to be created. | ||||
|    * @param prometheusType the prometheus type to which the metric is to be mapped. | ||||
|    * @return an {@link ImmutableMappingKey} that can be used as a key for mapping between metric | ||||
|    *     data and its prometheus equivalent name. | ||||
|    */ | ||||
|   private static ImmutableMappingKey createKeyForCacheMapping( | ||||
|       MetricData metricData, PrometheusType prometheusType) { | ||||
|     return ImmutableMappingKey.create( | ||||
|         metricData.getName(), metricData.getUnit(), prometheusType.name()); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Objects of this class acts as mapping keys for Prometheus metric mapping cache used in {@link | ||||
|    * PrometheusMetricNameMapper}. | ||||
|    */ | ||||
|   @Immutable | ||||
|   @AutoValue | ||||
|   abstract static class ImmutableMappingKey { | ||||
|     static ImmutableMappingKey create( | ||||
|         String rawMetricName, String rawMetricUnit, String prometheusType) { | ||||
|       return new AutoValue_PrometheusMetricNameMapper_ImmutableMappingKey( | ||||
|           rawMetricName, rawMetricUnit, prometheusType); | ||||
|     } | ||||
| 
 | ||||
|     abstract String rawMetricName(); | ||||
| 
 | ||||
|     abstract String rawMetricUnit(); | ||||
| 
 | ||||
|     abstract String prometheusType(); | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,224 @@ | |||
| /* | ||||
|  * Copyright The OpenTelemetry Authors | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  */ | ||||
| 
 | ||||
| package io.opentelemetry.exporter.prometheus; | ||||
| 
 | ||||
| import static io.opentelemetry.exporter.prometheus.NameSanitizer.SANITIZE_CONSECUTIVE_UNDERSCORES; | ||||
| 
 | ||||
| import io.opentelemetry.api.internal.StringUtils; | ||||
| import java.util.regex.Pattern; | ||||
| 
 | ||||
| /** | ||||
|  * A utility class that contains helper function(s) to aid conversion from OTLP to Prometheus units. | ||||
|  * | ||||
|  * @see <a | ||||
|  *     href="https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#units-and-base-units">OpenMetrics | ||||
|  *     specification for units</a> | ||||
|  * @see <a href="https://prometheus.io/docs/practices/naming/#base-units">Prometheus best practices | ||||
|  *     for units</a> | ||||
|  */ | ||||
| final class PrometheusUnitsHelper { | ||||
| 
 | ||||
|   private static final Pattern INVALID_CHARACTERS_PATTERN = Pattern.compile("[^a-zA-Z0-9]"); | ||||
|   private static final Pattern CHARACTERS_BETWEEN_BRACES_PATTERN = Pattern.compile("\\{(.*?)}"); | ||||
|   private static final Pattern SANITIZE_LEADING_UNDERSCORES = Pattern.compile("^_+"); | ||||
|   private static final Pattern SANITIZE_TRAILING_UNDERSCORES = Pattern.compile("_+$"); | ||||
| 
 | ||||
|   private PrometheusUnitsHelper() { | ||||
|     // Prevent object creation for utility classes | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * A utility function that returns the equivalent Prometheus name for the provided OTLP metric | ||||
|    * unit. | ||||
|    * | ||||
|    * @param rawMetricUnitName The raw metric unit for which Prometheus metric unit needs to be | ||||
|    *     computed. | ||||
|    * @return the computed Prometheus metric unit equivalent of the OTLP metric un | ||||
|    */ | ||||
|   static String getEquivalentPrometheusUnit(String rawMetricUnitName) { | ||||
|     if (StringUtils.isNullOrEmpty(rawMetricUnitName)) { | ||||
|       return rawMetricUnitName; | ||||
|     } | ||||
|     // Drop units specified between curly braces | ||||
|     String convertedMetricUnitName = removeUnitPortionInBraces(rawMetricUnitName); | ||||
|     // Handling for the "per" unit(s), e.g. foo/bar -> foo_per_bar | ||||
|     convertedMetricUnitName = convertRateExpressedToPrometheusUnit(convertedMetricUnitName); | ||||
|     // Converting abbreviated unit names to full names | ||||
|     return cleanUpString(getPrometheusUnit(convertedMetricUnitName)); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * This method is used to convert the units expressed as a rate via '/' symbol in their name to | ||||
|    * their expanded text equivalent. For instance, km/h => km_per_hour. The method operates on the | ||||
|    * input by splitting it in 2 parts - before and after '/' symbol and will attempt to expand any | ||||
|    * known unit abbreviation in both parts. Unknown abbreviations & unsupported characters will | ||||
|    * remain unchanged in the final output of this function. | ||||
|    * | ||||
|    * @param rateExpressedUnit The rate unit input that needs to be converted to its text equivalent. | ||||
|    * @return The text equivalent of unit expressed as rate. If the input does not contain '/', the | ||||
|    *     function returns it as-is. | ||||
|    */ | ||||
|   private static String convertRateExpressedToPrometheusUnit(String rateExpressedUnit) { | ||||
|     if (!rateExpressedUnit.contains("/")) { | ||||
|       return rateExpressedUnit; | ||||
|     } | ||||
|     String[] rateEntities = rateExpressedUnit.split("/", 2); | ||||
|     // Only convert rate expressed units if it's a valid expression | ||||
|     if (rateEntities[1].equals("")) { | ||||
|       return rateExpressedUnit; | ||||
|     } | ||||
|     return getPrometheusUnit(rateEntities[0]) + "_per_" + getPrometheusPerUnit(rateEntities[1]); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * This method drops all characters enclosed within '{}' (including the curly braces) by replacing | ||||
|    * them with an empty string. Note that this method will not produce the intended effect if there | ||||
|    * are nested curly braces within the outer enclosure of '{}'. | ||||
|    * | ||||
|    * <p>For instance, {packet{s}s} => s}. | ||||
|    * | ||||
|    * @param unit The input unit from which text within curly braces needs to be removed. | ||||
|    * @return The resulting unit after removing the text within '{}'. | ||||
|    */ | ||||
|   private static String removeUnitPortionInBraces(String unit) { | ||||
|     return CHARACTERS_BETWEEN_BRACES_PATTERN.matcher(unit).replaceAll(""); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Replaces all characters that are not a letter or a digit with '_' to make the resulting string | ||||
|    * Prometheus compliant. This method also removes leading and trailing underscores - this is done | ||||
|    * to keep the resulting unit similar to what is produced from the collector's implementation. | ||||
|    * | ||||
|    * @param string The string input that needs to be made Prometheus compliant. | ||||
|    * @return the cleaned-up Prometheus compliant string. | ||||
|    */ | ||||
|   private static String cleanUpString(String string) { | ||||
|     return SANITIZE_LEADING_UNDERSCORES | ||||
|         .matcher( | ||||
|             SANITIZE_TRAILING_UNDERSCORES | ||||
|                 .matcher( | ||||
|                     SANITIZE_CONSECUTIVE_UNDERSCORES | ||||
|                         .matcher(INVALID_CHARACTERS_PATTERN.matcher(string).replaceAll("_")) | ||||
|                         .replaceAll("_")) | ||||
|                 .replaceAll("")) | ||||
|         .replaceAll(""); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * This method retrieves the expanded Prometheus unit name for known abbreviations. OTLP metrics | ||||
|    * use the c/s notation as specified at <a href="https://ucum.org/ucum.html">UCUM</a>. The list of | ||||
|    * mappings is adopted from <a | ||||
|    * href="https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/9a9d4778bbbf242dba233db28e2fbcfda3416959/pkg/translator/prometheus/normalize_name.go#L30">OpenTelemetry | ||||
|    * Collector Contrib</a>. | ||||
|    * | ||||
|    * @param unitAbbreviation The unit that name that needs to be expanded/converted to Prometheus | ||||
|    *     units. | ||||
|    * @return The expanded/converted unit name if known, otherwise returns the input unit name as-is. | ||||
|    */ | ||||
|   private static String getPrometheusUnit(String unitAbbreviation) { | ||||
|     switch (unitAbbreviation) { | ||||
|         // Time | ||||
|       case "d": | ||||
|         return "days"; | ||||
|       case "h": | ||||
|         return "hours"; | ||||
|       case "min": | ||||
|         return "minutes"; | ||||
|       case "s": | ||||
|         return "seconds"; | ||||
|       case "ms": | ||||
|         return "milliseconds"; | ||||
|       case "us": | ||||
|         return "microseconds"; | ||||
|       case "ns": | ||||
|         return "nanoseconds"; | ||||
|         // Bytes | ||||
|       case "By": | ||||
|         return "bytes"; | ||||
|       case "KiBy": | ||||
|         return "kibibytes"; | ||||
|       case "MiBy": | ||||
|         return "mebibytes"; | ||||
|       case "GiBy": | ||||
|         return "gibibytes"; | ||||
|       case "TiBy": | ||||
|         return "tibibytes"; | ||||
|       case "KBy": | ||||
|         return "kilobytes"; | ||||
|       case "MBy": | ||||
|         return "megabytes"; | ||||
|       case "GBy": | ||||
|         return "gigabytes"; | ||||
|       case "TBy": | ||||
|         return "terabytes"; | ||||
|       case "B": | ||||
|         return "bytes"; | ||||
|       case "KB": | ||||
|         return "kilobytes"; | ||||
|       case "MB": | ||||
|         return "megabytes"; | ||||
|       case "GB": | ||||
|         return "gigabytes"; | ||||
|       case "TB": | ||||
|         return "terabytes"; | ||||
|         // SI | ||||
|       case "m": | ||||
|         return "meters"; | ||||
|       case "V": | ||||
|         return "volts"; | ||||
|       case "A": | ||||
|         return "amperes"; | ||||
|       case "J": | ||||
|         return "joules"; | ||||
|       case "W": | ||||
|         return "watts"; | ||||
|       case "g": | ||||
|         return "grams"; | ||||
|         // Misc | ||||
|       case "Cel": | ||||
|         return "celsius"; | ||||
|       case "Hz": | ||||
|         return "hertz"; | ||||
|       case "1": | ||||
|         return ""; | ||||
|       case "%": | ||||
|         return "percent"; | ||||
|       case "$": | ||||
|         return "dollars"; | ||||
|       default: | ||||
|         return unitAbbreviation; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * This method retrieves the expanded Prometheus unit name to be used with "per" units for known | ||||
|    * units. For example: s => per second (singular) | ||||
|    * | ||||
|    * @param perUnitAbbreviation The unit abbreviation used in a 'per' unit. | ||||
|    * @return The expanded unit equivalent to be used in 'per' unit if the input is a known unit, | ||||
|    *     otherwise returns the input as-is. | ||||
|    */ | ||||
|   private static String getPrometheusPerUnit(String perUnitAbbreviation) { | ||||
|     switch (perUnitAbbreviation) { | ||||
|       case "s": | ||||
|         return "second"; | ||||
|       case "m": | ||||
|         return "minute"; | ||||
|       case "h": | ||||
|         return "hour"; | ||||
|       case "d": | ||||
|         return "day"; | ||||
|       case "w": | ||||
|         return "week"; | ||||
|       case "mo": | ||||
|         return "month"; | ||||
|       case "y": | ||||
|         return "year"; | ||||
|       default: | ||||
|         return perUnitAbbreviation; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -118,7 +118,7 @@ abstract class Serializer { | |||
|         continue; | ||||
|       } | ||||
|       PrometheusType prometheusType = PrometheusType.forMetric(metric); | ||||
|       String metricName = metricName(metric.getName(), prometheusType); | ||||
|       String metricName = PrometheusMetricNameMapper.INSTANCE.apply(metric, prometheusType); | ||||
|       // Skip metrics which do not pass metricNameFilter | ||||
|       if (!metricNameFilter.test(metricName)) { | ||||
|         continue; | ||||
|  | @ -650,14 +650,6 @@ abstract class Serializer { | |||
|     return Collections.emptyList(); | ||||
|   } | ||||
| 
 | ||||
|   private static String metricName(String rawMetricName, PrometheusType type) { | ||||
|     String name = NameSanitizer.INSTANCE.apply(rawMetricName); | ||||
|     if (type == PrometheusType.COUNTER && !name.endsWith("_total")) { | ||||
|       name = name + "_total"; | ||||
|     } | ||||
|     return name; | ||||
|   } | ||||
| 
 | ||||
|   private static double getExemplarValue(ExemplarData exemplar) { | ||||
|     return exemplar instanceof DoubleExemplarData | ||||
|         ? ((DoubleExemplarData) exemplar).getValue() | ||||
|  |  | |||
|  | @ -9,7 +9,12 @@ import static org.assertj.core.api.Assertions.assertThat; | |||
| 
 | ||||
| import java.util.concurrent.atomic.AtomicInteger; | ||||
| import java.util.function.Function; | ||||
| import java.util.stream.Stream; | ||||
| import org.junit.jupiter.api.Assertions; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.params.ParameterizedTest; | ||||
| import org.junit.jupiter.params.provider.Arguments; | ||||
| import org.junit.jupiter.params.provider.MethodSource; | ||||
| 
 | ||||
| class NameSanitizerTest { | ||||
| 
 | ||||
|  | @ -27,4 +32,32 @@ class NameSanitizerTest { | |||
|     assertThat(sanitizer.apply(labelName)).isEqualTo("http.name1"); | ||||
|     assertThat(count).hasValue(1); | ||||
|   } | ||||
| 
 | ||||
|   @ParameterizedTest | ||||
|   @MethodSource("provideMetricNamesForTest") | ||||
|   void testSanitizerCleansing(String unsanitizedName, String sanitizedName) { | ||||
|     Assertions.assertEquals(sanitizedName, NameSanitizer.INSTANCE.apply(unsanitizedName)); | ||||
|   } | ||||
| 
 | ||||
|   private static Stream<Arguments> provideMetricNamesForTest() { | ||||
|     return Stream.of( | ||||
|         // valid name - already sanitized | ||||
|         Arguments.of( | ||||
|             "active_directory_ds_replication_network_io", | ||||
|             "active_directory_ds_replication_network_io"), | ||||
|         // consecutive underscores | ||||
|         Arguments.of("cpu_sp__d_hertz", "cpu_sp_d_hertz"), | ||||
|         // leading and trailing underscores - should be fine | ||||
|         Arguments.of("_cpu_speed_hertz_", "_cpu_speed_hertz_"), | ||||
|         // unsupported characters replaced | ||||
|         Arguments.of("metric_unit_$1000", "metric_unit_1000"), | ||||
|         // multiple unsupported characters - whitespace | ||||
|         Arguments.of("sample_me%%$$$_count_ !!@unit include", "sample_me_count_unit_include"), | ||||
|         // metric names cannot start with a number | ||||
|         Arguments.of("1_some_metric_name", "_some_metric_name"), | ||||
|         // metric names can have : | ||||
|         Arguments.of("sample_metric_name__:_per_meter", "sample_metric_name_:_per_meter"), | ||||
|         // Illegal characters | ||||
|         Arguments.of("cpu_sp$$d_hertz", "cpu_sp_d_hertz")); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -236,7 +236,7 @@ class PrometheusHttpServerTest { | |||
|                 InstrumentationScopeInfo.create("scope1"), | ||||
|                 "foo", | ||||
|                 "description1", | ||||
|                 "unit1", | ||||
|                 "unit", | ||||
|                 ImmutableSumData.create( | ||||
|                     /* isMonotonic= */ true, | ||||
|                     AggregationTemporality.CUMULATIVE, | ||||
|  | @ -248,7 +248,7 @@ class PrometheusHttpServerTest { | |||
|                 InstrumentationScopeInfo.create("scope2"), | ||||
|                 "foo", | ||||
|                 "description2", | ||||
|                 "unit2", | ||||
|                 "unit", | ||||
|                 ImmutableSumData.create( | ||||
|                     /* isMonotonic= */ true, | ||||
|                     AggregationTemporality.CUMULATIVE, | ||||
|  | @ -259,9 +259,9 @@ class PrometheusHttpServerTest { | |||
|             ImmutableMetricData.createLongGauge( | ||||
|                 resource, | ||||
|                 InstrumentationScopeInfo.create("scope3"), | ||||
|                 "foo_total", | ||||
|                 "unused", | ||||
|                 "foo_unit_total", | ||||
|                 "unused", | ||||
|                 "unit", | ||||
|                 ImmutableGaugeData.create( | ||||
|                     Collections.singletonList( | ||||
|                         ImmutableLongPointData.create(123, 456, Attributes.empty(), 3)))))); | ||||
|  | @ -283,13 +283,13 @@ class PrometheusHttpServerTest { | |||
|                 + "otel_scope_info{otel_scope_name=\"scope2\"} 1\n" | ||||
|                 + "# TYPE foo_total counter\n" | ||||
|                 + "# HELP foo_total description1\n" | ||||
|                 + "foo_total{otel_scope_name=\"scope1\"} 1.0 0\n" | ||||
|                 + "foo_total{otel_scope_name=\"scope2\"} 2.0 0\n"); | ||||
|                 + "foo_unit_total{otel_scope_name=\"scope1\"} 1.0 0\n" | ||||
|                 + "foo_unit_total{otel_scope_name=\"scope2\"} 2.0 0\n"); | ||||
| 
 | ||||
|     // Validate conflict warning message | ||||
|     assertThat(logs.getEvents()).hasSize(1); | ||||
|     logs.assertContains( | ||||
|         "Metric conflict(s) detected. Multiple metrics with same name but different type: [foo_total]"); | ||||
|         "Metric conflict(s) detected. Multiple metrics with same name but different type: [foo_unit_total]"); | ||||
| 
 | ||||
|     // Make another request and confirm warning is only logged once | ||||
|     client.get("/").aggregate().join(); | ||||
|  |  | |||
|  | @ -0,0 +1,163 @@ | |||
| /* | ||||
|  * Copyright The OpenTelemetry Authors | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  */ | ||||
| 
 | ||||
| package io.opentelemetry.exporter.prometheus; | ||||
| 
 | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.DELTA_HISTOGRAM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.DOUBLE_GAUGE; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.MONOTONIC_CUMULATIVE_LONG_SUM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.SUMMARY; | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||||
| 
 | ||||
| import io.opentelemetry.sdk.metrics.data.MetricData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableMetricData; | ||||
| import java.util.concurrent.atomic.AtomicInteger; | ||||
| import java.util.function.BiFunction; | ||||
| import java.util.stream.Stream; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.params.ParameterizedTest; | ||||
| import org.junit.jupiter.params.provider.Arguments; | ||||
| import org.junit.jupiter.params.provider.MethodSource; | ||||
| 
 | ||||
| class PrometheusMetricNameMapperTest { | ||||
| 
 | ||||
|   @Test | ||||
|   void prometheusMetricNameMapperCaching() { | ||||
|     AtomicInteger count = new AtomicInteger(); | ||||
|     BiFunction<MetricData, PrometheusType, String> delegate = | ||||
|         (metricData, prometheusType) -> | ||||
|             String.join( | ||||
|                 "_", | ||||
|                 metricData.getName(), | ||||
|                 prometheusType.name(), | ||||
|                 Integer.toString(count.incrementAndGet())); | ||||
|     PrometheusMetricNameMapper mapper = new PrometheusMetricNameMapper(delegate); | ||||
| 
 | ||||
|     assertThat(mapper.apply(MONOTONIC_CUMULATIVE_LONG_SUM, PrometheusType.GAUGE)) | ||||
|         .isEqualTo("monotonic.cumulative.long.sum_GAUGE_1"); | ||||
|     assertThat(mapper.apply(MONOTONIC_CUMULATIVE_LONG_SUM, PrometheusType.GAUGE)) | ||||
|         .isEqualTo("monotonic.cumulative.long.sum_GAUGE_1"); | ||||
|     assertThat(mapper.apply(MONOTONIC_CUMULATIVE_LONG_SUM, PrometheusType.GAUGE)) | ||||
|         .isEqualTo("monotonic.cumulative.long.sum_GAUGE_1"); | ||||
|     assertThat(mapper.apply(MONOTONIC_CUMULATIVE_LONG_SUM, PrometheusType.GAUGE)) | ||||
|         .isEqualTo("monotonic.cumulative.long.sum_GAUGE_1"); | ||||
|     assertThat(mapper.apply(MONOTONIC_CUMULATIVE_LONG_SUM, PrometheusType.GAUGE)) | ||||
|         .isEqualTo("monotonic.cumulative.long.sum_GAUGE_1"); | ||||
|     assertThat(count).hasValue(1); | ||||
|   } | ||||
| 
 | ||||
|   @ParameterizedTest | ||||
|   @MethodSource("provideRawMetricDataForTest") | ||||
|   void metricNameSerializationTest(MetricData metricData, String expectedSerializedName) { | ||||
|     assertEquals( | ||||
|         expectedSerializedName, | ||||
|         PrometheusMetricNameMapper.INSTANCE.apply( | ||||
|             metricData, PrometheusType.forMetric(metricData))); | ||||
|   } | ||||
| 
 | ||||
|   private static Stream<Arguments> provideRawMetricDataForTest() { | ||||
|     return Stream.of( | ||||
|         // special case for gauge | ||||
|         Arguments.of(createSampleMetricData("sample", "1", PrometheusType.GAUGE), "sample_ratio"), | ||||
|         // special case for gauge with drop - metric unit should match "1" to be converted to | ||||
|         // "ratio" | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("sample", "1{dropped}", PrometheusType.GAUGE), "sample"), | ||||
|         // Gauge without "1" as unit | ||||
|         Arguments.of(createSampleMetricData("sample", "unit", PrometheusType.GAUGE), "sample_unit"), | ||||
|         // special case with counter | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("sample", "unit", PrometheusType.COUNTER), "sample_unit_total"), | ||||
|         // special case unit "1", but no gauge - "1" is dropped | ||||
|         Arguments.of(createSampleMetricData("sample", "1", PrometheusType.COUNTER), "sample_total"), | ||||
|         // units expressed as numbers other than 1 are retained | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("sample", "2", PrometheusType.COUNTER), "sample_2_total"), | ||||
|         // metric name with unsupported characters | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("s%%ple", "%/m", PrometheusType.SUMMARY), | ||||
|             "s_ple_percent_per_minute"), | ||||
|         // metric name with dropped portions | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("s%%ple", "%/m", PrometheusType.SUMMARY), | ||||
|             "s_ple_percent_per_minute"), | ||||
|         // metric unit as a number other than 1 is not treated specially | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("metric_name", "2", PrometheusType.SUMMARY), "metric_name_2"), | ||||
|         // metric unit is not appended if the name already contains the unit | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("metric_name_total", "total", PrometheusType.COUNTER), | ||||
|             "metric_name_total"), | ||||
|         // metric unit is not appended if the name already contains the unit - special case for | ||||
|         // total with non-counter type | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("metric_name_total", "total", PrometheusType.SUMMARY), | ||||
|             "metric_name_total"), | ||||
|         // metric unit not appended if present in metric name - special case for ratio | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("metric_name_ratio", "1", PrometheusType.GAUGE), | ||||
|             "metric_name_ratio"), | ||||
|         // metric unit not appended if present in metric name - special case for ratio - unit not | ||||
|         // gauge | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("metric_name_ratio", "1", PrometheusType.SUMMARY), | ||||
|             "metric_name_ratio"), | ||||
|         // metric unit is not appended if the name already contains the unit - unit can be anywhere | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("metric_hertz", "hertz", PrometheusType.GAUGE), "metric_hertz"), | ||||
|         // metric unit is not appended if the name already contains the unit - applies to every unit | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("metric_hertz_total", "hertz_total", PrometheusType.COUNTER), | ||||
|             "metric_hertz_total"), | ||||
|         // metric unit is not appended if the name already contains the unit - order matters | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("metric_total_hertz", "hertz_total", PrometheusType.COUNTER), | ||||
|             "metric_total_hertz_hertz_total"), | ||||
|         // metric name cannot start with a number | ||||
|         Arguments.of( | ||||
|             createSampleMetricData("2_metric_name", "By", PrometheusType.SUMMARY), | ||||
|             "_metric_name_bytes")); | ||||
|   } | ||||
| 
 | ||||
|   static MetricData createSampleMetricData( | ||||
|       String metricName, String metricUnit, PrometheusType prometheusType) { | ||||
|     switch (prometheusType) { | ||||
|       case SUMMARY: | ||||
|         return ImmutableMetricData.createDoubleSummary( | ||||
|             SUMMARY.getResource(), | ||||
|             SUMMARY.getInstrumentationScopeInfo(), | ||||
|             metricName, | ||||
|             SUMMARY.getDescription(), | ||||
|             metricUnit, | ||||
|             SUMMARY.getSummaryData()); | ||||
|       case COUNTER: | ||||
|         return ImmutableMetricData.createLongSum( | ||||
|             MONOTONIC_CUMULATIVE_LONG_SUM.getResource(), | ||||
|             MONOTONIC_CUMULATIVE_LONG_SUM.getInstrumentationScopeInfo(), | ||||
|             metricName, | ||||
|             MONOTONIC_CUMULATIVE_LONG_SUM.getDescription(), | ||||
|             metricUnit, | ||||
|             MONOTONIC_CUMULATIVE_LONG_SUM.getLongSumData()); | ||||
|       case GAUGE: | ||||
|         return ImmutableMetricData.createDoubleGauge( | ||||
|             DOUBLE_GAUGE.getResource(), | ||||
|             DOUBLE_GAUGE.getInstrumentationScopeInfo(), | ||||
|             metricName, | ||||
|             DOUBLE_GAUGE.getDescription(), | ||||
|             metricUnit, | ||||
|             DOUBLE_GAUGE.getDoubleGaugeData()); | ||||
|       case HISTOGRAM: | ||||
|         return ImmutableMetricData.createDoubleHistogram( | ||||
|             DELTA_HISTOGRAM.getResource(), | ||||
|             DELTA_HISTOGRAM.getInstrumentationScopeInfo(), | ||||
|             metricName, | ||||
|             DELTA_HISTOGRAM.getDescription(), | ||||
|             metricUnit, | ||||
|             DELTA_HISTOGRAM.getHistogramData()); | ||||
|     } | ||||
|     throw new IllegalArgumentException(); | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,115 @@ | |||
| /* | ||||
|  * Copyright The OpenTelemetry Authors | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  */ | ||||
| 
 | ||||
| package io.opentelemetry.exporter.prometheus; | ||||
| 
 | ||||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||||
| 
 | ||||
| import java.util.stream.Stream; | ||||
| import org.junit.jupiter.params.ParameterizedTest; | ||||
| import org.junit.jupiter.params.provider.Arguments; | ||||
| import org.junit.jupiter.params.provider.MethodSource; | ||||
| 
 | ||||
| class PrometheusUnitsHelperTest { | ||||
| 
 | ||||
|   @ParameterizedTest | ||||
|   @MethodSource("providePrometheusOTelUnitEquivalentPairs") | ||||
|   public void testPrometheusUnitEquivalency(String otlpUnit, String prometheusUnit) { | ||||
|     assertEquals(prometheusUnit, PrometheusUnitsHelper.getEquivalentPrometheusUnit(otlpUnit)); | ||||
|   } | ||||
| 
 | ||||
|   private static Stream<Arguments> providePrometheusOTelUnitEquivalentPairs() { | ||||
|     return Stream.of( | ||||
|         // Simple expansion - storage Bytes | ||||
|         Arguments.of("By", "bytes"), | ||||
|         Arguments.of("B", "bytes"), | ||||
|         // Simple expansion - storage KB | ||||
|         Arguments.of("KB", "kilobytes"), | ||||
|         Arguments.of("KBy", "kilobytes"), | ||||
|         // Simple expansion - storage MB | ||||
|         Arguments.of("MB", "megabytes"), | ||||
|         Arguments.of("MBy", "megabytes"), | ||||
|         // Simple expansion - storage GB | ||||
|         Arguments.of("GB", "gigabytes"), | ||||
|         Arguments.of("GBy", "gigabytes"), | ||||
|         // Simple expansion - storage TB | ||||
|         Arguments.of("TB", "terabytes"), | ||||
|         Arguments.of("TBy", "terabytes"), | ||||
|         // Simple expansion - storage KiBy | ||||
|         Arguments.of("KiBy", "kibibytes"), | ||||
|         // Simple expansion - storage MiBy | ||||
|         Arguments.of("MiBy", "mebibytes"), | ||||
|         // Simple expansion - storage GiBy | ||||
|         Arguments.of("GiBy", "gibibytes"), | ||||
|         // Simple expansion - storage TiBy | ||||
|         Arguments.of("TiBy", "tibibytes"), | ||||
|         // Simple expansion - Time unit d | ||||
|         Arguments.of("d", "days"), | ||||
|         // Simple expansion - Time unit h | ||||
|         Arguments.of("h", "hours"), | ||||
|         // Simple expansion - Time unit s | ||||
|         Arguments.of("s", "seconds"), | ||||
|         // Simple expansion - Time unit ms | ||||
|         Arguments.of("ms", "milliseconds"), | ||||
|         // Simple expansion - Time unit us | ||||
|         Arguments.of("us", "microseconds"), | ||||
|         // Simple expansion - Time unit ns | ||||
|         Arguments.of("ns", "nanoseconds"), | ||||
|         // Simple expansion - Time unit min | ||||
|         Arguments.of("min", "minutes"), | ||||
|         // Simple expansion - special symbol - % | ||||
|         Arguments.of("%", "percent"), | ||||
|         // Simple expansion - special symbols - $ | ||||
|         Arguments.of("$", "dollars"), | ||||
|         // Simple expansion - frequency | ||||
|         Arguments.of("Hz", "hertz"), | ||||
|         // Simple expansion - temperature | ||||
|         Arguments.of("Cel", "celsius"), | ||||
|         // Unit not found - Case sensitive | ||||
|         Arguments.of("S", "S"), | ||||
|         // Special case - 1 | ||||
|         Arguments.of("1", ""), | ||||
|         // Special Case - Drop metric units in {} | ||||
|         Arguments.of("{packets}", ""), | ||||
|         // Special Case - Dropped metric units only in {} | ||||
|         Arguments.of("{packets}V", "volts"), | ||||
|         // Special Case - Dropped metric units with 'per' unit handling applicable | ||||
|         Arguments.of("{scanned}/{returned}", ""), | ||||
|         // Special Case - Dropped metric units with 'per' unit handling applicable | ||||
|         Arguments.of("{objects}/s", "per_second"), | ||||
|         // Units expressing rate - 'per' units, both units expanded | ||||
|         Arguments.of("m/s", "meters_per_second"), | ||||
|         // Units expressing rate - per minute | ||||
|         Arguments.of("m/m", "meters_per_minute"), | ||||
|         // Units expressing rate - per day | ||||
|         Arguments.of("A/d", "amperes_per_day"), | ||||
|         // Units expressing rate - per week | ||||
|         Arguments.of("W/w", "watts_per_week"), | ||||
|         // Units expressing rate - per month | ||||
|         Arguments.of("J/mo", "joules_per_month"), | ||||
|         // Units expressing rate - per year | ||||
|         Arguments.of("TB/y", "terabytes_per_year"), | ||||
|         // Units expressing rate - 'per' units, both units unknown | ||||
|         Arguments.of("v/v", "v_per_v"), | ||||
|         // Units expressing rate - 'per' units, first unit unknown | ||||
|         Arguments.of("km/h", "km_per_hour"), | ||||
|         // Units expressing rate - 'per' units, 'per' unit unknown | ||||
|         Arguments.of("g/g", "grams_per_g"), | ||||
|         // Misc - unit containing known abbreviations improperly formatted | ||||
|         Arguments.of("watts_W", "watts_W"), | ||||
|         // Unsupported symbols | ||||
|         Arguments.of("°F", "F"), | ||||
|         // Unsupported symbols - multiple | ||||
|         Arguments.of("unit+=.:,!* & #unused", "unit_unused"), | ||||
|         // Unsupported symbols - 'per' units | ||||
|         Arguments.of("__test $/°C", "test_per_C"), | ||||
|         // Unsupported symbols - whitespace | ||||
|         Arguments.of("\t", ""), | ||||
|         // Null unit | ||||
|         Arguments.of(null, null), | ||||
|         // Misc - unit cleanup - no case match special char | ||||
|         Arguments.of("$1000", "1000")); | ||||
|   } | ||||
| } | ||||
|  | @ -5,350 +5,32 @@ | |||
| 
 | ||||
| package io.opentelemetry.exporter.prometheus; | ||||
| 
 | ||||
| import static io.opentelemetry.api.common.AttributeKey.stringKey; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.CUMULATIVE_HISTOGRAM_NO_ATTRIBUTES; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.CUMULATIVE_HISTOGRAM_SINGLE_ATTRIBUTE; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.DELTA_DOUBLE_SUM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.DELTA_HISTOGRAM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.DELTA_LONG_SUM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.DOUBLE_GAUGE; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.DOUBLE_GAUGE_MULTIPLE_ATTRIBUTES; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.DOUBLE_GAUGE_NO_ATTRIBUTES; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.LONG_GAUGE; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.MONOTONIC_CUMULATIVE_DOUBLE_SUM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.MONOTONIC_CUMULATIVE_DOUBLE_SUM_WITH_SUFFIX_TOTAL; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.MONOTONIC_CUMULATIVE_LONG_SUM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.NON_MONOTONIC_CUMULATIVE_DOUBLE_SUM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.NON_MONOTONIC_CUMULATIVE_LONG_SUM; | ||||
| import static io.opentelemetry.exporter.prometheus.TestConstants.SUMMARY; | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| 
 | ||||
| import io.opentelemetry.api.common.AttributeKey; | ||||
| import io.opentelemetry.api.common.Attributes; | ||||
| import io.opentelemetry.api.trace.SpanContext; | ||||
| import io.opentelemetry.api.trace.TraceFlags; | ||||
| import io.opentelemetry.api.trace.TraceState; | ||||
| import io.opentelemetry.sdk.common.InstrumentationScopeInfo; | ||||
| import io.opentelemetry.sdk.metrics.data.AggregationTemporality; | ||||
| import io.opentelemetry.sdk.metrics.data.MetricData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoubleExemplarData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoublePointData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableGaugeData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableHistogramData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableHistogramPointData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableLongPointData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableMetricData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableSumData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryPointData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableValueAtQuantile; | ||||
| import io.opentelemetry.sdk.resources.Resource; | ||||
| import java.io.ByteArrayOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.UncheckedIOException; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import org.junit.jupiter.api.Test; | ||||
| 
 | ||||
| class SerializerTest { | ||||
| 
 | ||||
|   private static final AttributeKey<String> TYPE = stringKey("type"); | ||||
| 
 | ||||
|   private static final MetricData MONOTONIC_CUMULATIVE_DOUBLE_SUM = | ||||
|       ImmutableMetricData.createDoubleSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "monotonic.cumulative.double.sum", | ||||
|           "description", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mcds"), | ||||
|                       5)))); | ||||
| 
 | ||||
|   private static final MetricData MONOTONIC_CUMULATIVE_DOUBLE_SUM_WITH_SUFFIX_TOTAL = | ||||
|       ImmutableMetricData.createDoubleSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "monotonic.cumulative.double.sum.suffix.total", | ||||
|           "description", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mcds"), | ||||
|                       5)))); | ||||
|   private static final MetricData NON_MONOTONIC_CUMULATIVE_DOUBLE_SUM = | ||||
|       ImmutableMetricData.createDoubleSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "non.monotonic.cumulative.double.sum", | ||||
|           "description", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ false, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "nmcds"), | ||||
|                       5)))); | ||||
|   private static final MetricData DELTA_DOUBLE_SUM = | ||||
|       ImmutableMetricData.createDoubleSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "delta.double.sum", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.DELTA, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mdds"), | ||||
|                       5)))); | ||||
|   private static final MetricData MONOTONIC_CUMULATIVE_LONG_SUM = | ||||
|       ImmutableMetricData.createLongSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "monotonic.cumulative.long.sum", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableLongPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mcls"), | ||||
|                       5)))); | ||||
|   private static final MetricData NON_MONOTONIC_CUMULATIVE_LONG_SUM = | ||||
|       ImmutableMetricData.createLongSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "non.monotonic.cumulative.long_sum", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ false, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableLongPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "nmcls"), | ||||
|                       5)))); | ||||
|   private static final MetricData DELTA_LONG_SUM = | ||||
|       ImmutableMetricData.createLongSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "delta.long.sum", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.DELTA, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableLongPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mdls"), | ||||
|                       5)))); | ||||
| 
 | ||||
|   private static final MetricData DOUBLE_GAUGE = | ||||
|       ImmutableMetricData.createDoubleGauge( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "double.gauge", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableGaugeData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, 1633950672000000000L, Attributes.of(TYPE, "dg"), 5)))); | ||||
|   private static final MetricData LONG_GAUGE = | ||||
|       ImmutableMetricData.createLongGauge( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "long.gauge", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableGaugeData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableLongPointData.create( | ||||
|                       1633947011000000000L, 1633950672000000000L, Attributes.of(TYPE, "lg"), 5)))); | ||||
|   private static final MetricData SUMMARY = | ||||
|       ImmutableMetricData.createDoubleSummary( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "summary", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSummaryData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableSummaryPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "s"), | ||||
|                       5, | ||||
|                       7, | ||||
|                       Arrays.asList( | ||||
|                           ImmutableValueAtQuantile.create(0.9, 0.1), | ||||
|                           ImmutableValueAtQuantile.create(0.99, 0.3)))))); | ||||
|   private static final MetricData DELTA_HISTOGRAM = | ||||
|       ImmutableMetricData.createDoubleHistogram( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "delta.histogram", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableHistogramData.create( | ||||
|               AggregationTemporality.DELTA, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableHistogramPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.empty(), | ||||
|                       1.0, | ||||
|                       /* hasMin= */ false, | ||||
|                       0, | ||||
|                       /* hasMax= */ false, | ||||
|                       0, | ||||
|                       Collections.emptyList(), | ||||
|                       Collections.singletonList(2L), | ||||
|                       Collections.emptyList())))); | ||||
|   private static final MetricData CUMULATIVE_HISTOGRAM_NO_ATTRIBUTES = | ||||
|       ImmutableMetricData.createDoubleHistogram( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "cumulative.histogram.no.attributes", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableHistogramData.create( | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableHistogramPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.empty(), | ||||
|                       1.0, | ||||
|                       /* hasMin= */ false, | ||||
|                       0, | ||||
|                       /* hasMax= */ false, | ||||
|                       0, | ||||
|                       Collections.emptyList(), | ||||
|                       Collections.singletonList(2L), | ||||
|                       Collections.singletonList( | ||||
|                           ImmutableDoubleExemplarData.create( | ||||
|                               Attributes.empty(), | ||||
|                               TimeUnit.MILLISECONDS.toNanos(1L), | ||||
|                               SpanContext.create( | ||||
|                                   "00000000000000000000000000000001", | ||||
|                                   "0000000000000002", | ||||
|                                   TraceFlags.getDefault(), | ||||
|                                   TraceState.getDefault()), | ||||
|                               /* value= */ 4)))))); | ||||
|   private static final MetricData CUMULATIVE_HISTOGRAM_SINGLE_ATTRIBUTE = | ||||
|       ImmutableMetricData.createDoubleHistogram( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "cumulative.histogram.single.attribute", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableHistogramData.create( | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableHistogramPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "hs"), | ||||
|                       1.0, | ||||
|                       /* hasMin= */ false, | ||||
|                       0, | ||||
|                       /* hasMax= */ false, | ||||
|                       0, | ||||
|                       Collections.emptyList(), | ||||
|                       Collections.singletonList(2L), | ||||
|                       Collections.singletonList( | ||||
|                           ImmutableDoubleExemplarData.create( | ||||
|                               Attributes.empty(), | ||||
|                               TimeUnit.MILLISECONDS.toNanos(1L), | ||||
|                               SpanContext.create( | ||||
|                                   "00000000000000000000000000000001", | ||||
|                                   "0000000000000002", | ||||
|                                   TraceFlags.getDefault(), | ||||
|                                   TraceState.getDefault()), | ||||
|                               /* value= */ 4)))))); | ||||
|   private static final MetricData DOUBLE_GAUGE_NO_ATTRIBUTES = | ||||
|       ImmutableMetricData.createDoubleGauge( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "double.gauge.no.attributes", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableGaugeData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, 1633950672000000000L, Attributes.empty(), 7)))); | ||||
|   private static final MetricData DOUBLE_GAUGE_MULTIPLE_ATTRIBUTES = | ||||
|       ImmutableMetricData.createDoubleGauge( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "double.gauge.multiple.attributes", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableGaugeData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "dgma", stringKey("animal"), "bear"), | ||||
|                       8)))); | ||||
| 
 | ||||
|   @Test | ||||
|   void prometheus004() { | ||||
|     // Same output as prometheus client library except for these changes which are compatible with | ||||
|  | @ -387,19 +69,19 @@ class SerializerTest { | |||
|                 + "monotonic_cumulative_double_sum_suffix_total{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"mcds\"} 5.0 1633950672000\n" | ||||
|                 + "# TYPE non_monotonic_cumulative_double_sum gauge\n" | ||||
|                 + "# HELP non_monotonic_cumulative_double_sum description\n" | ||||
|                 + "non_monotonic_cumulative_double_sum{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"nmcds\"} 5.0 1633950672000\n" | ||||
|                 + "non_monotonic_cumulative_double_sum_seconds{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"nmcds\"} 5.0 1633950672000\n" | ||||
|                 + "# TYPE monotonic_cumulative_long_sum_total counter\n" | ||||
|                 + "# HELP monotonic_cumulative_long_sum_total unused\n" | ||||
|                 + "monotonic_cumulative_long_sum_total{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"mcls\"} 5.0 1633950672000\n" | ||||
|                 + "# TYPE non_monotonic_cumulative_long_sum gauge\n" | ||||
|                 + "# HELP non_monotonic_cumulative_long_sum unused\n" | ||||
|                 + "non_monotonic_cumulative_long_sum{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"nmcls\"} 5.0 1633950672000\n" | ||||
|                 + "non_monotonic_cumulative_long_sum_seconds{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"nmcls\"} 5.0 1633950672000\n" | ||||
|                 + "# TYPE double_gauge gauge\n" | ||||
|                 + "# HELP double_gauge unused\n" | ||||
|                 + "double_gauge{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"dg\"} 5.0 1633950672000\n" | ||||
|                 + "double_gauge_ratio{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"dg\"} 5.0 1633950672000\n" | ||||
|                 + "# TYPE long_gauge gauge\n" | ||||
|                 + "# HELP long_gauge unused\n" | ||||
|                 + "long_gauge{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"lg\"} 5.0 1633950672000\n" | ||||
|                 + "long_gauge_ratio{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"lg\"} 5.0 1633950672000\n" | ||||
|                 + "# TYPE summary summary\n" | ||||
|                 + "# HELP summary unused\n" | ||||
|                 + "summary_count{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"s\"} 5.0 1633950672000\n" | ||||
|  | @ -418,10 +100,10 @@ class SerializerTest { | |||
|                 + "cumulative_histogram_single_attribute_bucket{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"hs\",le=\"+Inf\"} 2.0 1633950672000\n" | ||||
|                 + "# TYPE double_gauge_no_attributes gauge\n" | ||||
|                 + "# HELP double_gauge_no_attributes unused\n" | ||||
|                 + "double_gauge_no_attributes{otel_scope_name=\"full\",otel_scope_version=\"version\"} 7.0 1633950672000\n" | ||||
|                 + "double_gauge_no_attributes_ratio{otel_scope_name=\"full\",otel_scope_version=\"version\"} 7.0 1633950672000\n" | ||||
|                 + "# TYPE double_gauge_multiple_attributes gauge\n" | ||||
|                 + "# HELP double_gauge_multiple_attributes unused\n" | ||||
|                 + "double_gauge_multiple_attributes{otel_scope_name=\"full\",otel_scope_version=\"version\",animal=\"bear\",type=\"dgma\"} 8.0 1633950672000\n"); | ||||
|                 + "double_gauge_multiple_attributes_ratio{otel_scope_name=\"full\",otel_scope_version=\"version\",animal=\"bear\",type=\"dgma\"} 8.0 1633950672000\n"); | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
|  | @ -458,19 +140,19 @@ class SerializerTest { | |||
|                 + "monotonic_cumulative_double_sum_suffix_total{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"mcds\"} 5.0 1633950672.000\n" | ||||
|                 + "# TYPE non_monotonic_cumulative_double_sum gauge\n" | ||||
|                 + "# HELP non_monotonic_cumulative_double_sum description\n" | ||||
|                 + "non_monotonic_cumulative_double_sum{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"nmcds\"} 5.0 1633950672.000\n" | ||||
|                 + "non_monotonic_cumulative_double_sum_seconds{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"nmcds\"} 5.0 1633950672.000\n" | ||||
|                 + "# TYPE monotonic_cumulative_long_sum counter\n" | ||||
|                 + "# HELP monotonic_cumulative_long_sum unused\n" | ||||
|                 + "monotonic_cumulative_long_sum_total{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"mcls\"} 5.0 1633950672.000\n" | ||||
|                 + "# TYPE non_monotonic_cumulative_long_sum gauge\n" | ||||
|                 + "# HELP non_monotonic_cumulative_long_sum unused\n" | ||||
|                 + "non_monotonic_cumulative_long_sum{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"nmcls\"} 5.0 1633950672.000\n" | ||||
|                 + "non_monotonic_cumulative_long_sum_seconds{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"nmcls\"} 5.0 1633950672.000\n" | ||||
|                 + "# TYPE double_gauge gauge\n" | ||||
|                 + "# HELP double_gauge unused\n" | ||||
|                 + "double_gauge{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"dg\"} 5.0 1633950672.000\n" | ||||
|                 + "double_gauge_ratio{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"dg\"} 5.0 1633950672.000\n" | ||||
|                 + "# TYPE long_gauge gauge\n" | ||||
|                 + "# HELP long_gauge unused\n" | ||||
|                 + "long_gauge{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"lg\"} 5.0 1633950672.000\n" | ||||
|                 + "long_gauge_ratio{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"lg\"} 5.0 1633950672.000\n" | ||||
|                 + "# TYPE summary summary\n" | ||||
|                 + "# HELP summary unused\n" | ||||
|                 + "summary_count{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"s\"} 5.0 1633950672.000\n" | ||||
|  | @ -489,10 +171,10 @@ class SerializerTest { | |||
|                 + "cumulative_histogram_single_attribute_bucket{otel_scope_name=\"full\",otel_scope_version=\"version\",type=\"hs\",le=\"+Inf\"} 2.0 1633950672.000 # {span_id=\"0000000000000002\",trace_id=\"00000000000000000000000000000001\"} 4.0 0.001\n" | ||||
|                 + "# TYPE double_gauge_no_attributes gauge\n" | ||||
|                 + "# HELP double_gauge_no_attributes unused\n" | ||||
|                 + "double_gauge_no_attributes{otel_scope_name=\"full\",otel_scope_version=\"version\"} 7.0 1633950672.000\n" | ||||
|                 + "double_gauge_no_attributes_ratio{otel_scope_name=\"full\",otel_scope_version=\"version\"} 7.0 1633950672.000\n" | ||||
|                 + "# TYPE double_gauge_multiple_attributes gauge\n" | ||||
|                 + "# HELP double_gauge_multiple_attributes unused\n" | ||||
|                 + "double_gauge_multiple_attributes{otel_scope_name=\"full\",otel_scope_version=\"version\",animal=\"bear\",type=\"dgma\"} 8.0 1633950672.000\n" | ||||
|                 + "double_gauge_multiple_attributes_ratio{otel_scope_name=\"full\",otel_scope_version=\"version\",animal=\"bear\",type=\"dgma\"} 8.0 1633950672.000\n" | ||||
|                 + "# EOF\n"); | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,360 @@ | |||
| /* | ||||
|  * Copyright The OpenTelemetry Authors | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  */ | ||||
| 
 | ||||
| package io.opentelemetry.exporter.prometheus; | ||||
| 
 | ||||
| import static io.opentelemetry.api.common.AttributeKey.stringKey; | ||||
| 
 | ||||
| import io.opentelemetry.api.common.AttributeKey; | ||||
| import io.opentelemetry.api.common.Attributes; | ||||
| import io.opentelemetry.api.trace.SpanContext; | ||||
| import io.opentelemetry.api.trace.TraceFlags; | ||||
| import io.opentelemetry.api.trace.TraceState; | ||||
| import io.opentelemetry.sdk.common.InstrumentationScopeInfo; | ||||
| import io.opentelemetry.sdk.metrics.data.AggregationTemporality; | ||||
| import io.opentelemetry.sdk.metrics.data.MetricData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoubleExemplarData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoublePointData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableGaugeData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableHistogramData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableHistogramPointData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableLongPointData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableMetricData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableSumData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryPointData; | ||||
| import io.opentelemetry.sdk.metrics.internal.data.ImmutableValueAtQuantile; | ||||
| import io.opentelemetry.sdk.resources.Resource; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| 
 | ||||
| /** A helper class encapsulating immutable static data that can be shared across all the tests. */ | ||||
| class TestConstants { | ||||
| 
 | ||||
|   private TestConstants() { | ||||
|     // Private constructor to prevent instantiation | ||||
|   } | ||||
| 
 | ||||
|   private static final AttributeKey<String> TYPE = stringKey("type"); | ||||
| 
 | ||||
|   static final MetricData MONOTONIC_CUMULATIVE_DOUBLE_SUM = | ||||
|       ImmutableMetricData.createDoubleSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "monotonic.cumulative.double.sum", | ||||
|           "description", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mcds"), | ||||
|                       5)))); | ||||
| 
 | ||||
|   static final MetricData MONOTONIC_CUMULATIVE_DOUBLE_SUM_WITH_SUFFIX_TOTAL = | ||||
|       ImmutableMetricData.createDoubleSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "monotonic.cumulative.double.sum.suffix.total", | ||||
|           "description", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mcds"), | ||||
|                       5)))); | ||||
| 
 | ||||
|   static final MetricData NON_MONOTONIC_CUMULATIVE_DOUBLE_SUM = | ||||
|       ImmutableMetricData.createDoubleSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "non.monotonic.cumulative.double.sum", | ||||
|           "description", | ||||
|           "s", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ false, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "nmcds"), | ||||
|                       5)))); | ||||
| 
 | ||||
|   static final MetricData DELTA_DOUBLE_SUM = | ||||
|       ImmutableMetricData.createDoubleSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "delta.double.sum", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.DELTA, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mdds"), | ||||
|                       5)))); | ||||
| 
 | ||||
|   static final MetricData MONOTONIC_CUMULATIVE_LONG_SUM = | ||||
|       ImmutableMetricData.createLongSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "monotonic.cumulative.long.sum", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableLongPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mcls"), | ||||
|                       5)))); | ||||
| 
 | ||||
|   static final MetricData NON_MONOTONIC_CUMULATIVE_LONG_SUM = | ||||
|       ImmutableMetricData.createLongSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "non.monotonic.cumulative.long_sum", | ||||
|           "unused", | ||||
|           "s", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ false, | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableLongPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "nmcls"), | ||||
|                       5)))); | ||||
|   static final MetricData DELTA_LONG_SUM = | ||||
|       ImmutableMetricData.createLongSum( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "delta.long.sum", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSumData.create( | ||||
|               /* isMonotonic= */ true, | ||||
|               AggregationTemporality.DELTA, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableLongPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "mdls"), | ||||
|                       5)))); | ||||
| 
 | ||||
|   static final MetricData DOUBLE_GAUGE = | ||||
|       ImmutableMetricData.createDoubleGauge( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "double.gauge", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableGaugeData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, 1633950672000000000L, Attributes.of(TYPE, "dg"), 5)))); | ||||
|   static final MetricData LONG_GAUGE = | ||||
|       ImmutableMetricData.createLongGauge( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "long.gauge", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableGaugeData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableLongPointData.create( | ||||
|                       1633947011000000000L, 1633950672000000000L, Attributes.of(TYPE, "lg"), 5)))); | ||||
|   static final MetricData SUMMARY = | ||||
|       ImmutableMetricData.createDoubleSummary( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "summary", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableSummaryData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableSummaryPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "s"), | ||||
|                       5, | ||||
|                       7, | ||||
|                       Arrays.asList( | ||||
|                           ImmutableValueAtQuantile.create(0.9, 0.1), | ||||
|                           ImmutableValueAtQuantile.create(0.99, 0.3)))))); | ||||
| 
 | ||||
|   static final MetricData DELTA_HISTOGRAM = | ||||
|       ImmutableMetricData.createDoubleHistogram( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "delta.histogram", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableHistogramData.create( | ||||
|               AggregationTemporality.DELTA, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableHistogramPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.empty(), | ||||
|                       1.0, | ||||
|                       /* hasMin= */ false, | ||||
|                       0, | ||||
|                       /* hasMax= */ false, | ||||
|                       0, | ||||
|                       Collections.emptyList(), | ||||
|                       Collections.singletonList(2L), | ||||
|                       Collections.emptyList())))); | ||||
| 
 | ||||
|   static final MetricData CUMULATIVE_HISTOGRAM_NO_ATTRIBUTES = | ||||
|       ImmutableMetricData.createDoubleHistogram( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "cumulative.histogram.no.attributes", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableHistogramData.create( | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableHistogramPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.empty(), | ||||
|                       1.0, | ||||
|                       /* hasMin= */ false, | ||||
|                       0, | ||||
|                       /* hasMax= */ false, | ||||
|                       0, | ||||
|                       Collections.emptyList(), | ||||
|                       Collections.singletonList(2L), | ||||
|                       Collections.singletonList( | ||||
|                           ImmutableDoubleExemplarData.create( | ||||
|                               Attributes.empty(), | ||||
|                               TimeUnit.MILLISECONDS.toNanos(1L), | ||||
|                               SpanContext.create( | ||||
|                                   "00000000000000000000000000000001", | ||||
|                                   "0000000000000002", | ||||
|                                   TraceFlags.getDefault(), | ||||
|                                   TraceState.getDefault()), | ||||
|                               /* value= */ 4)))))); | ||||
| 
 | ||||
|   static final MetricData CUMULATIVE_HISTOGRAM_SINGLE_ATTRIBUTE = | ||||
|       ImmutableMetricData.createDoubleHistogram( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "cumulative.histogram.single.attribute", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableHistogramData.create( | ||||
|               AggregationTemporality.CUMULATIVE, | ||||
|               Collections.singletonList( | ||||
|                   ImmutableHistogramPointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "hs"), | ||||
|                       1.0, | ||||
|                       /* hasMin= */ false, | ||||
|                       0, | ||||
|                       /* hasMax= */ false, | ||||
|                       0, | ||||
|                       Collections.emptyList(), | ||||
|                       Collections.singletonList(2L), | ||||
|                       Collections.singletonList( | ||||
|                           ImmutableDoubleExemplarData.create( | ||||
|                               Attributes.empty(), | ||||
|                               TimeUnit.MILLISECONDS.toNanos(1L), | ||||
|                               SpanContext.create( | ||||
|                                   "00000000000000000000000000000001", | ||||
|                                   "0000000000000002", | ||||
|                                   TraceFlags.getDefault(), | ||||
|                                   TraceState.getDefault()), | ||||
|                               /* value= */ 4)))))); | ||||
| 
 | ||||
|   static final MetricData DOUBLE_GAUGE_NO_ATTRIBUTES = | ||||
|       ImmutableMetricData.createDoubleGauge( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "double.gauge.no.attributes", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableGaugeData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, 1633950672000000000L, Attributes.empty(), 7)))); | ||||
| 
 | ||||
|   static final MetricData DOUBLE_GAUGE_MULTIPLE_ATTRIBUTES = | ||||
|       ImmutableMetricData.createDoubleGauge( | ||||
|           Resource.create(Attributes.of(stringKey("kr"), "vr")), | ||||
|           InstrumentationScopeInfo.builder("full") | ||||
|               .setVersion("version") | ||||
|               .setAttributes(Attributes.of(stringKey("ks"), "vs")) | ||||
|               .build(), | ||||
|           "double.gauge.multiple.attributes", | ||||
|           "unused", | ||||
|           "1", | ||||
|           ImmutableGaugeData.create( | ||||
|               Collections.singletonList( | ||||
|                   ImmutableDoublePointData.create( | ||||
|                       1633947011000000000L, | ||||
|                       1633950672000000000L, | ||||
|                       Attributes.of(TYPE, "dgma", stringKey("animal"), "bear"), | ||||
|                       8)))); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue