diff --git a/README.md b/README.md
index a6a754c..c80c7c5 100644
--- a/README.md
+++ b/README.md
@@ -1724,6 +1724,31 @@ Dependencies:
```
+Note that ```metrics-facade-prometheus``` uses
+```xml
+
+ io.prometheus
+ simpleclient_common
+ ...
+
+```
+
+In case of conflict between the ```simpleclient_common``` version used in ```Metrics Facade``` and the one used in your project, you can resolve it with ```dependency.exclusions``` or any other available means. For example, see ```metrics-facade-samples/pom.xml```:
+```xml
+
+ com.ringcentral.platform.metrics
+ metrics-facade-prometheus
+ ${project.version}
+
+
+
+ io.prometheus
+ simpleclient_common
+
+
+
+```
+
Example:
```java
MetricRegistry registry = new DefaultMetricRegistry();
diff --git a/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/reporters/prometheus/PrometheusMetricsExporter.java b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/reporters/prometheus/PrometheusMetricsExporter.java
index debd642..c126cd7 100644
--- a/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/reporters/prometheus/PrometheusMetricsExporter.java
+++ b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/reporters/prometheus/PrometheusMetricsExporter.java
@@ -3,19 +3,27 @@
import com.ringcentral.platform.metrics.MetricRegistry;
import com.ringcentral.platform.metrics.names.MetricName;
import com.ringcentral.platform.metrics.reporters.MetricsExporter;
-import com.ringcentral.platform.metrics.samples.*;
-import com.ringcentral.platform.metrics.samples.prometheus.*;
+import com.ringcentral.platform.metrics.samples.CompositeInstanceSamplesProvider;
+import com.ringcentral.platform.metrics.samples.InstanceSamplesProvider;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusInstanceSample;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusInstanceSamplesProvider;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusSample;
+import com.ringcentral.platform.metrics.samples.prometheus.collectorRegistry.SimpleCollectorRegistryPrometheusInstanceSamplesProvider;
import com.ringcentral.platform.metrics.utils.StringBuilderWriter;
+import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.common.TextFormat;
import org.slf4j.Logger;
-import java.io.*;
+import java.io.IOException;
+import java.io.Writer;
import java.util.*;
import static com.ringcentral.platform.metrics.reporters.prometheus.PrometheusMetricsExporter.Format.PROMETHEUS_TEXT_O_O_4;
-import static io.prometheus.client.Collector.*;
-import static java.lang.String.*;
-import static java.util.Collections.*;
+import static io.prometheus.client.Collector.MetricFamilySamples;
+import static io.prometheus.client.Collector.sanitizeMetricName;
+import static java.lang.String.join;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.enumeration;
import static java.util.stream.Collectors.toList;
import static org.slf4j.LoggerFactory.getLogger;
@@ -48,6 +56,12 @@ public PrometheusMetricsExporter(MetricRegistry registry) {
this(new PrometheusInstanceSamplesProvider(registry));
}
+ public PrometheusMetricsExporter(MetricRegistry registry, CollectorRegistry... collectorRegistries) {
+ this(
+ new PrometheusInstanceSamplesProvider(registry),
+ new SimpleCollectorRegistryPrometheusInstanceSamplesProvider(collectorRegistries));
+ }
+
public PrometheusMetricsExporter(
MetricRegistry registry,
boolean convertNameToLowercase,
@@ -200,10 +214,7 @@ private void exportInstanceSample(PrometheusInstanceSample is, Map {
String sampleName = name;
- if (s.hasNameSuffix()) {
- sampleName +=
- convertNameToLowercase ?
- sanitizeMetricName(s.nameSuffix()).toLowerCase(locale) :
- sanitizeMetricName(s.nameSuffix());
+ if (s.hasName()) {
+ sampleName = buildName(s.name());
+ } else if (s.hasNameSuffix()) {
+ sampleName += buildNameSuffix(s);
}
return new MetricFamilySamples.Sample(
@@ -229,6 +239,17 @@ private MetricFamilySamples toMetricFamilySamples(PrometheusInstanceSample is) {
.collect(toList()));
}
+ private String buildName(MetricName name) {
+ final var sanitizedName = sanitizeMetricName(join(NAME_PARTS_DELIMITER, name));
+ return convertNameToLowercase ? sanitizedName.toLowerCase(locale) : sanitizedName;
+ }
+
+ private String buildNameSuffix(PrometheusSample ps) {
+ final var suffix = ps.nameSuffix();
+ final var sanitizedSuffix = sanitizeMetricName(suffix);
+ return convertNameToLowercase ? sanitizedSuffix.toLowerCase(locale) : sanitizedSuffix;
+ }
+
private static String helpFor(PrometheusInstanceSample is) {
return
is.hasDescription() ?
diff --git a/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusInstanceSamplesProviderBuilder.java b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusInstanceSamplesProviderBuilder.java
new file mode 100644
index 0000000..c83af94
--- /dev/null
+++ b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusInstanceSamplesProviderBuilder.java
@@ -0,0 +1,74 @@
+package com.ringcentral.platform.metrics.samples.prometheus;
+
+import com.ringcentral.platform.metrics.MetricRegistry;
+import com.ringcentral.platform.metrics.infoProviders.PredicativeMetricNamedInfoProvider;
+import com.ringcentral.platform.metrics.samples.InstanceSampleMaker;
+import com.ringcentral.platform.metrics.samples.InstanceSampleSpecProvider;
+import com.ringcentral.platform.metrics.samples.SampleMaker;
+import com.ringcentral.platform.metrics.samples.SampleSpecProvider;
+
+import static java.util.Objects.requireNonNull;
+
+public class PrometheusInstanceSamplesProviderBuilder {
+
+ private InstanceSampleSpecProvider instanceSampleSpecProvider;
+ private PredicativeMetricNamedInfoProvider> instanceSampleSpecModsProvider;
+ private InstanceSampleMaker instanceSampleMaker;
+ private SampleSpecProvider sampleSpecProvider;
+ private PredicativeMetricNamedInfoProvider> sampleSpecModsProvider;
+ private SampleMaker sampleMaker;
+ private final MetricRegistry metricRegistry;
+
+ public PrometheusInstanceSamplesProviderBuilder(MetricRegistry metricRegistry) {
+ this.metricRegistry = requireNonNull(metricRegistry);
+ this.instanceSampleSpecProvider = new PrometheusInstanceSampleSpecProvider();
+ this.instanceSampleMaker = new PrometheusInstanceSampleMaker();
+ this.sampleSpecProvider = new PrometheusSampleSpecProvider();
+ this.sampleMaker = new PrometheusSampleMaker();
+ }
+
+ public static PrometheusInstanceSamplesProviderBuilder prometheusInstanceSamplesProvider(MetricRegistry metricRegistry) {
+ return new PrometheusInstanceSamplesProviderBuilder(metricRegistry);
+ }
+
+ public PrometheusInstanceSamplesProviderBuilder instanceSampleSpecProvider(InstanceSampleSpecProvider instanceSampleSpecProvider) {
+ this.instanceSampleSpecProvider = requireNonNull(instanceSampleSpecProvider);
+ return this;
+ }
+
+ public PrometheusInstanceSamplesProviderBuilder instanceSampleSpecModsProvider(PredicativeMetricNamedInfoProvider> instanceSampleSpecModsProvider) {
+ this.instanceSampleSpecModsProvider = instanceSampleSpecModsProvider;
+ return this;
+ }
+
+ public PrometheusInstanceSamplesProviderBuilder instanceSampleMaker(InstanceSampleMaker instanceSampleMaker) {
+ this.instanceSampleMaker = requireNonNull(instanceSampleMaker);
+ return this;
+ }
+
+ public PrometheusInstanceSamplesProviderBuilder sampleSpecProvider(SampleSpecProvider sampleSpecProvider) {
+ this.sampleSpecProvider = requireNonNull(sampleSpecProvider);
+ return this;
+ }
+
+ public PrometheusInstanceSamplesProviderBuilder sampleSpecModsProvider(PredicativeMetricNamedInfoProvider> sampleSpecModsProvider) {
+ this.sampleSpecModsProvider = sampleSpecModsProvider;
+ return this;
+ }
+
+ public PrometheusInstanceSamplesProviderBuilder sampleMaker(SampleMaker sampleMaker) {
+ this.sampleMaker = requireNonNull(sampleMaker);
+ return this;
+ }
+
+ public PrometheusInstanceSamplesProvider build() {
+ return new PrometheusInstanceSamplesProvider(
+ instanceSampleSpecProvider,
+ instanceSampleSpecModsProvider,
+ instanceSampleMaker,
+ sampleSpecProvider,
+ sampleSpecModsProvider,
+ sampleMaker,
+ metricRegistry);
+ }
+}
diff --git a/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSample.java b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSample.java
index 052d51f..b08ac2b 100644
--- a/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSample.java
+++ b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSample.java
@@ -13,7 +13,7 @@ public class PrometheusSample implements Sample {
private final MetricName childInstanceSampleNameSuffix;
private final Collector.Type childInstanceSampleType;
-
+ private final MetricName name;
private final String nameSuffix;
private final List labelNames;
private final List labelValues;
@@ -22,6 +22,7 @@ public class PrometheusSample implements Sample {
public PrometheusSample(
MetricName childInstanceSampleNameSuffix,
Collector.Type childInstanceSampleType,
+ MetricName name,
String nameSuffix,
List labelNames,
List labelValues,
@@ -35,6 +36,7 @@ public PrometheusSample(
this.childInstanceSampleNameSuffix = childInstanceSampleNameSuffix;
this.childInstanceSampleType = childInstanceSampleType;
+ this.name = name;
this.nameSuffix = nameSuffix;
this.labelNames = labelNames != null ? labelNames : emptyList();
this.labelValues = labelValues != null ? labelValues : emptyList();
@@ -57,12 +59,21 @@ public PrometheusSample notBelongingToChildInstanceSample() {
return new PrometheusSample(
null,
null,
+ name,
nameSuffix,
labelNames,
labelValues,
value);
}
+ public boolean hasName() {
+ return name != null;
+ }
+
+ public MetricName name() {
+ return name;
+ }
+
public boolean hasNameSuffix() {
return nameSuffix != null;
}
diff --git a/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSampleMaker.java b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSampleMaker.java
index 1ed2d7b..ef26445 100644
--- a/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSampleMaker.java
+++ b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSampleMaker.java
@@ -93,6 +93,7 @@ public PrometheusSample makeSample(PrometheusSampleSpec spec, PrometheusInstance
return new PrometheusSample(
childInstanceSampleNameSuffix,
childInstanceSampleType,
+ null,
nameSuffix,
labelNames,
labelValues,
diff --git a/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/collectorRegistry/SimpleCollectorRegistryPrometheusInstanceSamplesProvider.java b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/collectorRegistry/SimpleCollectorRegistryPrometheusInstanceSamplesProvider.java
new file mode 100644
index 0000000..1942be5
--- /dev/null
+++ b/metrics-facade-prometheus/src/main/java/com/ringcentral/platform/metrics/samples/prometheus/collectorRegistry/SimpleCollectorRegistryPrometheusInstanceSamplesProvider.java
@@ -0,0 +1,154 @@
+package com.ringcentral.platform.metrics.samples.prometheus.collectorRegistry;
+
+import com.ringcentral.platform.metrics.names.MetricName;
+import com.ringcentral.platform.metrics.samples.InstanceSamplesProvider;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusInstanceSample;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusSample;
+import io.prometheus.client.Collector.MetricFamilySamples;
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.Predicate;
+
+import java.util.*;
+import java.util.function.Function;
+
+import static com.ringcentral.platform.metrics.utils.Preconditions.checkArgument;
+
+public class SimpleCollectorRegistryPrometheusInstanceSamplesProvider implements InstanceSamplesProvider<
+ PrometheusSample,
+ PrometheusInstanceSample> {
+
+ private final Function nameBuilder;
+ private final Predicate metricFamilyNameFilter;
+ private final Predicate metricFamilySampleNameFilter;
+ private final Collection extends CollectorRegistry> collectorRegistries;
+
+ /**
+ * @param collectorRegistries must be not empty
+ */
+ public SimpleCollectorRegistryPrometheusInstanceSamplesProvider(CollectorRegistry... collectorRegistries) {
+ this(null, collectorRegistries);
+ }
+
+ /**
+ * @param namePrefix the prefix to be prepended to each MetricFamilySample.name when building PrometheusInstanceSample.instanceName/name
+ * and to be prepended to each MetricFamilySample.Sample.name when building PrometheusSample.name.
+ * Optional
+ *
+ * @param collectorRegistries must be not empty
+ */
+ public SimpleCollectorRegistryPrometheusInstanceSamplesProvider(
+ MetricName namePrefix,
+ CollectorRegistry... collectorRegistries) {
+
+ this(namePrefix, null, null, List.of(collectorRegistries));
+ }
+
+ /**
+ * @param namePrefix the prefix to be prepended to each MetricFamilySample.name when building PrometheusInstanceSample.instanceName/name
+ * and to be prepended to each MetricFamilySample.Sample.name when building PrometheusSample.name.
+ * Optional
+ *
+ * @param metricFamilyNameFilter optional
+ * @param metricFamilySampleNameFilter optional
+ * @param collectorRegistries must be not empty
+ */
+ public SimpleCollectorRegistryPrometheusInstanceSamplesProvider(
+ MetricName namePrefix,
+ Predicate metricFamilyNameFilter,
+ Predicate metricFamilySampleNameFilter,
+ CollectorRegistry... collectorRegistries) {
+
+ this(namePrefix, metricFamilyNameFilter, metricFamilySampleNameFilter, List.of(collectorRegistries));
+ }
+
+ /**
+ * @param namePrefix the prefix to be prepended to each MetricFamilySample.name when building PrometheusInstanceSample.instanceName/name
+ * and to be prepended to each MetricFamilySample.Sample.name when building PrometheusSample.name.
+ * Optional
+ *
+ * @param metricFamilyNameFilter optional
+ * @param metricFamilySampleNameFilter optional
+ * @param collectorRegistries must be not empty
+ */
+ public SimpleCollectorRegistryPrometheusInstanceSamplesProvider(
+ MetricName namePrefix,
+ Predicate metricFamilyNameFilter,
+ Predicate metricFamilySampleNameFilter,
+ Collection extends CollectorRegistry> collectorRegistries) {
+
+ this(
+ n -> MetricName.of(namePrefix, n),
+ metricFamilyNameFilter,
+ metricFamilySampleNameFilter,
+ collectorRegistries);
+ }
+
+ /**
+ * @param nameBuilder the function to be applied to each MetricFamilySample.name when building PrometheusInstanceSample.instanceName/name
+ * and to be applied to each MetricFamilySample.Sample.name when building PrometheusSample.name.
+ * Optional
+ *
+ * @param metricFamilyNameFilter optional
+ * @param metricFamilySampleNameFilter optional
+ * @param collectorRegistries must be not empty
+ */
+ public SimpleCollectorRegistryPrometheusInstanceSamplesProvider(
+ Function nameBuilder,
+ Predicate metricFamilyNameFilter,
+ Predicate metricFamilySampleNameFilter,
+ Collection extends CollectorRegistry> collectorRegistries) {
+
+ this.nameBuilder = nameBuilder != null ? nameBuilder : MetricName::of;
+ this.metricFamilyNameFilter = metricFamilyNameFilter;
+ this.metricFamilySampleNameFilter = metricFamilySampleNameFilter;
+
+ checkArgument(
+ collectorRegistries != null && !collectorRegistries.isEmpty(),
+ "collectorRegistries is null or empty");
+
+ this.collectorRegistries = collectorRegistries;
+ }
+
+ @Override
+ public Set instanceSamples() {
+ Set result = new LinkedHashSet<>();
+ collectorRegistries.forEach(collectorRegistry -> processCollectorRegistry(collectorRegistry, result));
+ return result;
+ }
+
+ private void processCollectorRegistry(CollectorRegistry collectorRegistry, Set result) {
+ Enumeration fsEnumeration =
+ metricFamilyNameFilter != null ?
+ collectorRegistry.filteredMetricFamilySamples(metricFamilyNameFilter) :
+ collectorRegistry.metricFamilySamples();
+
+ while (fsEnumeration.hasMoreElements()) {
+ MetricFamilySamples fs = fsEnumeration.nextElement();
+ MetricName name = nameBuilder.apply(fs.name);
+ PrometheusInstanceSample instanceSample = new PrometheusInstanceSample(name, name, fs.help, fs.type);
+
+ fs.samples.forEach(fsSample -> {
+ if (metricFamilySampleNameFilter != null && !metricFamilySampleNameFilter.test(fsSample.name)) {
+ return;
+ }
+
+ MetricName sampleName = nameBuilder.apply(fsSample.name);
+
+ PrometheusSample sample = new PrometheusSample(
+ null,
+ null,
+ sampleName,
+ null,
+ fsSample.labelNames,
+ fsSample.labelValues,
+ fsSample.value);
+
+ instanceSample.add(sample);
+ });
+
+ if (!instanceSample.samples().isEmpty()) {
+ result.add(instanceSample);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/reporters/prometheus/PrometheusMetricsExporterTest.java b/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/reporters/prometheus/PrometheusMetricsExporterTest.java
index ae8ffc2..3a2d1bb 100644
--- a/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/reporters/prometheus/PrometheusMetricsExporterTest.java
+++ b/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/reporters/prometheus/PrometheusMetricsExporterTest.java
@@ -1,19 +1,27 @@
package com.ringcentral.platform.metrics.reporters.prometheus;
import com.ringcentral.platform.metrics.samples.InstanceSamplesProvider;
-import com.ringcentral.platform.metrics.samples.prometheus.*;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusInstanceSample;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusSample;
import io.prometheus.client.Collector;
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.Summary;
import org.junit.Test;
-import java.util.*;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
import static com.ringcentral.platform.metrics.names.MetricName.name;
-import static com.ringcentral.platform.metrics.reporters.prometheus.PrometheusMetricsExporter.Format.*;
-import static com.ringcentral.platform.metrics.samples.prometheus.PrometheusSampleMaker.*;
+import static com.ringcentral.platform.metrics.reporters.prometheus.PrometheusMetricsExporter.Format.OPENMETRICS_TEXT_1_0_0;
+import static com.ringcentral.platform.metrics.reporters.prometheus.PrometheusMetricsExporter.Format.PROMETHEUS_TEXT_O_O_4;
+import static com.ringcentral.platform.metrics.samples.prometheus.PrometheusSampleMaker.DEFAULT_MAX_CHILD_NAME_SUFFIX;
+import static com.ringcentral.platform.metrics.samples.prometheus.PrometheusSampleMaker.DEFAULT_MEAN_CHILD_NAME_SUFFIX;
import static java.util.Collections.emptyList;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
@SuppressWarnings("unchecked")
public class PrometheusMetricsExporterTest {
@@ -53,6 +61,7 @@ public void export() {
null,
null,
null,
+ null,
emptyList(),
emptyList(),
1.0));
@@ -69,6 +78,7 @@ public void export() {
null,
null,
null,
+ null,
List.of(DIMENSION_1, DIMENSION_2),
List.of("dimension_1_value", "dimension_2_value"),
2.0));
@@ -86,6 +96,7 @@ public void export() {
null,
null,
null,
+ null,
emptyList(),
emptyList(),
3.0));
@@ -102,6 +113,7 @@ public void export() {
null,
null,
null,
+ null,
List.of(DIMENSION_1, DIMENSION_2, DIMENSION_3),
List.of("dimension_1_value", "dimension_2_value", "dimension_3_value"),
4.0));
@@ -116,6 +128,7 @@ public void export() {
Collector.Type.SUMMARY);
instanceSample.add(new PrometheusSample(
+ null,
null,
null,
"_count",
@@ -127,6 +140,7 @@ public void export() {
DEFAULT_MAX_CHILD_NAME_SUFFIX,
Collector.Type.GAUGE,
null,
+ null,
emptyList(),
emptyList(),
6.0));
@@ -135,6 +149,7 @@ public void export() {
DEFAULT_MEAN_CHILD_NAME_SUFFIX,
Collector.Type.GAUGE,
null,
+ null,
emptyList(),
emptyList(),
7.0));
@@ -143,6 +158,7 @@ public void export() {
null,
null,
null,
+ null,
List.of("quantile"),
List.of("0.50"),
8.0));
@@ -151,6 +167,7 @@ public void export() {
null,
null,
null,
+ null,
List.of("quantile"),
List.of("0.75"),
9.0));
@@ -164,6 +181,7 @@ public void export() {
Collector.Type.SUMMARY);
instanceSample.add(new PrometheusSample(
+ null,
null,
null,
"_count",
@@ -175,6 +193,7 @@ public void export() {
DEFAULT_MAX_CHILD_NAME_SUFFIX,
Collector.Type.GAUGE,
null,
+ null,
List.of(DIMENSION_1, DIMENSION_2, DIMENSION_3),
List.of("dimension_1_value", "dimension_2_value", "dimension_3_value"),
11.0));
@@ -183,6 +202,7 @@ public void export() {
DEFAULT_MEAN_CHILD_NAME_SUFFIX,
Collector.Type.GAUGE,
null,
+ null,
List.of(DIMENSION_1, DIMENSION_2, DIMENSION_3),
List.of("dimension_1_value", "dimension_2_value", "dimension_3_value"),
12.0));
@@ -191,6 +211,7 @@ public void export() {
null,
null,
null,
+ null,
List.of(DIMENSION_1, DIMENSION_2, DIMENSION_3, "quantile"),
List.of("dimension_1_value", "dimension_2_value", "dimension_3_value", "0.50"),
13.0));
@@ -199,13 +220,27 @@ public void export() {
null,
null,
null,
+ null,
List.of(DIMENSION_1, DIMENSION_2, DIMENSION_3, "quantile"),
List.of("dimension_1_value", "dimension_2_value", "dimension_3_value", "0.75"),
14.0));
instanceSamples.add(instanceSample);
+ CollectorRegistry collectorRegistry = new CollectorRegistry(true);
+
+ Summary summary = Summary.build()
+ .name("summary")
+ .labelNames("label_1", "label_2")
+ .help("Summary from defaultRegistry")
+ .register(collectorRegistry);
+
+ summary.labels("label_1_value", "label_2_value").observe(10);
+ summary.labels("label_1_value", "label_2_value").observe(20);
+ summary.labels("label_1_value", "label_2_value").observe(30);
- PrometheusMetricsExporter exporter = new PrometheusMetricsExporter(PROMETHEUS_TEXT_O_O_4, instanceSamplesProvider);
+ PrometheusMetricsExporter exporter = new PrometheusMetricsExporter(
+ PROMETHEUS_TEXT_O_O_4,
+ instanceSamplesProvider);
assertThat(exporter.exportMetrics(), is(
"# HELP a Generated from metric instances with name counter.a\n" +
diff --git a/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusInstanceSampleTest.java b/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusInstanceSampleTest.java
index 64b15ff..0a24cf6 100644
--- a/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusInstanceSampleTest.java
+++ b/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusInstanceSampleTest.java
@@ -21,6 +21,7 @@ public void addingSamples() {
Collector.Type.UNKNOWN);
instanceSample.add(new PrometheusSample(
+ null,
null,
null,
"suffix_1",
@@ -31,6 +32,7 @@ public void addingSamples() {
instanceSample.add(new PrometheusSample(
name("childSuffix_1"),
Collector.Type.SUMMARY,
+ null,
"suffix_2",
List.of("dimension_1", "dimension_2"),
List.of("dimension_1_value", "dimension_2_value"),
@@ -40,6 +42,7 @@ public void addingSamples() {
name("childSuffix_2"),
Collector.Type.HISTOGRAM,
null,
+ null,
List.of("dimension_1"),
List.of("dimension_1_value"),
3.0));
@@ -47,12 +50,14 @@ public void addingSamples() {
instanceSample.add(new PrometheusSample(
name("childSuffix_1"),
Collector.Type.SUMMARY,
+ null,
"suffix_2",
List.of("dimension_1", "dimension_2"),
List.of("dimension_1_value", "dimension_2_value"),
4.0));
instanceSample.add(new PrometheusSample(
+ null,
null,
null,
"suffix_3",
@@ -65,6 +70,7 @@ public void addingSamples() {
check(
instanceSample.samples().get(0),
new PrometheusSample(
+ null,
null,
null,
"suffix_1",
@@ -75,6 +81,7 @@ public void addingSamples() {
check(
instanceSample.samples().get(1),
new PrometheusSample(
+ null,
null,
null,
"suffix_3",
@@ -92,6 +99,7 @@ public void addingSamples() {
check(
child.samples().get(0),
new PrometheusSample(
+ null,
null,
null,
"suffix_2",
@@ -102,6 +110,7 @@ public void addingSamples() {
check(
child.samples().get(1),
new PrometheusSample(
+ null,
null,
null,
"suffix_2",
@@ -119,6 +128,7 @@ public void addingSamples() {
null,
null,
null,
+ null,
List.of("dimension_1"),
List.of("dimension_1_value"),
3.0));
diff --git a/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSampleMakerTest.java b/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSampleMakerTest.java
index bff3a38..0f89bdc 100644
--- a/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSampleMakerTest.java
+++ b/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/PrometheusSampleMakerTest.java
@@ -65,6 +65,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -87,6 +88,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -109,6 +111,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -121,6 +124,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -133,6 +137,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -145,6 +150,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -157,6 +163,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -169,6 +176,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -188,6 +196,7 @@ public void makingSample() {
sampleSpec = new PrometheusSampleSpec(true, COUNT, 1.0);
expectedSample = new PrometheusSample(
+ null,
null,
null,
"_count",
@@ -200,6 +209,7 @@ public void makingSample() {
sampleSpec = new PrometheusSampleSpec(true, TOTAL_SUM, 1.0);
expectedSample = new PrometheusSample(
+ null,
null,
null,
"_sum",
@@ -215,6 +225,7 @@ public void makingSample() {
name("min"),
Collector.Type.GAUGE,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -227,6 +238,7 @@ public void makingSample() {
name("max"),
Collector.Type.GAUGE,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -239,6 +251,7 @@ public void makingSample() {
name("mean"),
Collector.Type.GAUGE,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -251,6 +264,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -263,6 +277,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name(), "quantile"),
List.of("value_1", "value_2", "0.5"),
1.0);
@@ -275,6 +290,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name(), "quantile"),
List.of("value_1", "value_2", "0.75"),
1.0);
@@ -284,6 +300,7 @@ public void makingSample() {
sampleSpec = new PrometheusSampleSpec(true, SEC_1_BUCKET, 1.0);
expectedSample = new PrometheusSample(
+ null,
null,
null,
"_bucket",
@@ -306,6 +323,7 @@ public void makingSample() {
sampleSpec = new PrometheusSampleSpec(true, COUNT, 1.0);
expectedSample = new PrometheusSample(
+ null,
null,
null,
"_count",
@@ -318,6 +336,7 @@ public void makingSample() {
sampleSpec = new PrometheusSampleSpec(true, TOTAL_SUM, 1.0);
expectedSample = new PrometheusSample(
+ null,
null,
null,
"_sum",
@@ -333,6 +352,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -345,6 +365,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -357,6 +378,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -369,6 +391,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -381,6 +404,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -393,6 +417,7 @@ public void makingSample() {
name("min"),
Collector.Type.GAUGE,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -405,6 +430,7 @@ public void makingSample() {
name("max"),
Collector.Type.GAUGE,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -417,6 +443,7 @@ public void makingSample() {
name("mean"),
Collector.Type.GAUGE,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -429,6 +456,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -441,6 +469,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name(), "quantile"),
List.of("value_1", "value_2", "0.5"),
1.0);
@@ -453,6 +482,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name(), "quantile"),
List.of("value_1", "value_2", "0.75"),
1.0);
@@ -465,6 +495,7 @@ public void makingSample() {
null,
null,
null,
+ null,
List.of(DIMENSION_1.name(), DIMENSION_2.name()),
List.of("value_1", "value_2"),
1.0);
@@ -474,6 +505,7 @@ public void makingSample() {
sampleSpec = new PrometheusSampleSpec(true, SEC_1_BUCKET, 1.0);
expectedSample = new PrometheusSample(
+ null,
null,
null,
"_bucket",
diff --git a/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/collectorRegistry/SimpleCollectorRegistryPrometheusInstanceSamplesProviderTest.java b/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/collectorRegistry/SimpleCollectorRegistryPrometheusInstanceSamplesProviderTest.java
new file mode 100644
index 0000000..097c33a
--- /dev/null
+++ b/metrics-facade-prometheus/src/test/java/com/ringcentral/platform/metrics/samples/prometheus/collectorRegistry/SimpleCollectorRegistryPrometheusInstanceSamplesProviderTest.java
@@ -0,0 +1,101 @@
+package com.ringcentral.platform.metrics.samples.prometheus.collectorRegistry;
+
+import com.ringcentral.platform.metrics.names.MetricName;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusInstanceSample;
+import com.ringcentral.platform.metrics.samples.prometheus.PrometheusSample;
+import io.prometheus.client.*;
+import org.junit.Test;
+
+import java.util.List;
+
+import static com.ringcentral.platform.metrics.names.MetricName.name;
+import static java.util.Comparator.comparing;
+import static java.util.stream.Collectors.toList;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.*;
+
+public class SimpleCollectorRegistryPrometheusInstanceSamplesProviderTest {
+
+ @Test
+ public void providingInstanceSamples() {
+ CollectorRegistry collectorRegistry = new CollectorRegistry(true);
+
+ SimpleCollectorRegistryPrometheusInstanceSamplesProvider instanceSamplesProvider = new SimpleCollectorRegistryPrometheusInstanceSamplesProvider(
+ name("defaultRegistry"), // optional prefix
+ new SampleNameFilter.Builder().nameMustNotStartWith("counter_1").build(), // optional filter
+ // A typical Prometheus collector adds a MetricsFamilySamples.Sample for its creation time.
+ // That sample has an unpredictable and hard to verify value.
+ // That's why we remove it with !sampleName.endsWith("created").
+ sampleName -> !sampleName.contains("summary") || !sampleName.endsWith("created"), // optional filter
+ collectorRegistry);
+
+ Counter counter_1 = Counter.build()
+ .name("counter_1")
+ .help("Counter 1 from defaultRegistry")
+ .register(collectorRegistry);
+
+ counter_1.inc(1);
+
+ Counter counter_2 = Counter.build()
+ .name("counter_2")
+ .help("Counter 2 from defaultRegistry")
+ .register(collectorRegistry);
+
+ counter_2.inc(2);
+
+ Summary summary = Summary.build()
+ .name("summary")
+ .labelNames("label_1", "label_2")
+ .help("Summary from defaultRegistry")
+ .register(collectorRegistry);
+
+ summary.labels("label_1_value", "label_2_value").observe(10);
+ summary.labels("label_1_value", "label_2_value").observe(20);
+ summary.labels("label_1_value", "label_2_value").observe(30);
+
+ List instanceSamples = instanceSamplesProvider.instanceSamples().stream()
+ .sorted(comparing(prometheusInstanceSample -> prometheusInstanceSample.name().toString()))
+ .collect(toList());
+
+ assertThat(instanceSamples.size(), is(2));
+
+ PrometheusInstanceSample instanceSample = instanceSamples.stream()
+ .filter(is -> is.name().lastPart().equals("counter_2"))
+ .findFirst().orElseThrow();
+
+ assertThat(instanceSample.instanceName(), is(name("defaultRegistry", "counter_2")));
+ assertThat(instanceSample.name(), is(name("defaultRegistry", "counter_2")));
+ assertThat(instanceSample.description(), is("Counter 2 from defaultRegistry"));
+ assertThat(instanceSample.type(), is(Collector.Type.COUNTER));
+ assertFalse(instanceSample.hasChildren());
+
+ List samples = instanceSample.samples();
+ assertThat(samples.size(), is(2));
+
+ PrometheusSample sample = samples.stream()
+ .filter(is -> is.name().lastPart().contains("total"))
+ .findFirst().orElseThrow();
+
+ assertNull(sample.childInstanceSampleNameSuffix());
+ assertNull(sample.childInstanceSampleType());
+ assertThat(sample.name(), is(MetricName.of("defaultRegistry", "counter_2_total")));
+ assertNull(sample.nameSuffix());
+ assertTrue(sample.labelNames().isEmpty());
+ assertTrue(sample.labelValues().isEmpty());
+ assertThat(sample.value(), is(2.0));
+
+ instanceSample = instanceSamples.stream()
+ .filter(is -> is.name().lastPart().equals("summary"))
+ .findFirst().orElseThrow();
+
+ assertThat(instanceSample.instanceName(), is(name("defaultRegistry", "summary")));
+ assertThat(instanceSample.name(), is(name("defaultRegistry", "summary")));
+ assertThat(instanceSample.description(), is("Summary from defaultRegistry"));
+ assertThat(instanceSample.type(), is(Collector.Type.SUMMARY));
+ assertFalse(instanceSample.hasChildren());
+
+ samples = instanceSample.samples();
+ assertThat(samples.size(), is(2));
+ }
+}
\ No newline at end of file
diff --git a/metrics-facade-samples/pom.xml b/metrics-facade-samples/pom.xml
index f3afe7c..f288501 100644
--- a/metrics-facade-samples/pom.xml
+++ b/metrics-facade-samples/pom.xml
@@ -15,7 +15,7 @@
metrics-facade-samples
- 0.10.0
+ 0.16.0
2.1.0-SNAPSHOT
1.7.3
@@ -37,6 +37,13 @@
com.ringcentral.platform.metrics
metrics-facade-prometheus
${project.version}
+
+
+
+ io.prometheus
+ simpleclient_common
+
+
@@ -72,6 +79,12 @@
jackson-databind
+
+ io.prometheus
+ simpleclient_common
+ ${prometheus.version}
+
+
io.prometheus
simpleclient
diff --git a/metrics-facade-samples/src/main/java/com/ringcentral/platform/metrics/samples/reporters/PrometheusMetricsExporterSample.java b/metrics-facade-samples/src/main/java/com/ringcentral/platform/metrics/samples/reporters/PrometheusMetricsExporterSample.java
index e9146e6..6dbd0bc 100644
--- a/metrics-facade-samples/src/main/java/com/ringcentral/platform/metrics/samples/reporters/PrometheusMetricsExporterSample.java
+++ b/metrics-facade-samples/src/main/java/com/ringcentral/platform/metrics/samples/reporters/PrometheusMetricsExporterSample.java
@@ -2,22 +2,30 @@
import com.ringcentral.platform.metrics.MetricRegistry;
import com.ringcentral.platform.metrics.defaultImpl.DefaultMetricRegistry;
-import com.ringcentral.platform.metrics.histogram.*;
+import com.ringcentral.platform.metrics.histogram.Histogram;
+import com.ringcentral.platform.metrics.histogram.HistogramInstance;
import com.ringcentral.platform.metrics.reporters.jmx.JmxMetricsReporter;
import com.ringcentral.platform.metrics.reporters.prometheus.PrometheusMetricsExporter;
import com.ringcentral.platform.metrics.samples.AbstractSample;
import com.ringcentral.platform.metrics.samples.prometheus.*;
+import com.ringcentral.platform.metrics.samples.prometheus.collectorRegistry.SimpleCollectorRegistryPrometheusInstanceSamplesProvider;
import com.ringcentral.platform.metrics.timer.Timer;
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.Counter;
+import io.prometheus.client.SampleNameFilter;
+import io.prometheus.client.Summary;
import java.util.Locale;
import static com.ringcentral.platform.metrics.dimensions.MetricDimensionValues.forDimensionValues;
import static com.ringcentral.platform.metrics.histogram.Histogram.*;
import static com.ringcentral.platform.metrics.histogram.configs.builders.HistogramConfigBuilder.withHistogram;
+import static com.ringcentral.platform.metrics.names.MetricName.name;
import static com.ringcentral.platform.metrics.names.MetricName.withName;
import static com.ringcentral.platform.metrics.names.MetricNameMask.*;
import static com.ringcentral.platform.metrics.predicates.DefaultMetricInstancePredicate.forMetricInstancesMatching;
import static com.ringcentral.platform.metrics.samples.prometheus.PrometheusInstanceSampleSpec.instanceSampleSpec;
+import static com.ringcentral.platform.metrics.samples.prometheus.PrometheusInstanceSamplesProviderBuilder.prometheusInstanceSamplesProvider;
import static com.ringcentral.platform.metrics.samples.prometheus.PrometheusSampleSpec.sampleSpec;
import static com.ringcentral.platform.metrics.timer.configs.builders.TimerConfigBuilder.withTimer;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -72,19 +80,40 @@ public static void main(String[] args) throws Exception {
PrometheusSampleMaker sampleMaker = new PrometheusSampleMaker();
- PrometheusInstanceSamplesProvider miSamplesProvider = new PrometheusInstanceSamplesProvider(
- miSampleSpecProvider,
- miSampleSpecModsProvider,
- miSampleMaker,
- sampleSpecProvider,
- sampleSpecModsProvider,
- sampleMaker,
- registry);
+ PrometheusInstanceSamplesProvider miSamplesProvider = prometheusInstanceSamplesProvider(registry)
+ .instanceSampleSpecProvider(miSampleSpecProvider)
+ .instanceSampleSpecModsProvider(miSampleSpecModsProvider)
+ .instanceSampleMaker(miSampleMaker)
+ .sampleSpecProvider(sampleSpecProvider)
+ .sampleSpecModsProvider(sampleSpecModsProvider)
+ .sampleMaker(sampleMaker)
+ .build();
PrometheusMetricsExporter exporter = new PrometheusMetricsExporter(
true,
Locale.ENGLISH,
- miSamplesProvider);
+ miSamplesProvider,
+ new SimpleCollectorRegistryPrometheusInstanceSamplesProvider(
+ name("defaultRegistry"), // optional prefix
+ new SampleNameFilter.Builder().nameMustNotStartWith("counter").build(), // optional filter
+ sampleName -> !sampleName.endsWith("created"), // optional filter
+ CollectorRegistry.defaultRegistry));
+
+ Counter defaultRegistry_Counter = Counter.build()
+ .name("counter")
+ .help("Counter from defaultRegistry")
+ .register();
+
+ defaultRegistry_Counter.inc(3);
+
+ Summary defaultRegistry_Summary = Summary.build()
+ .name("summary")
+ .help("Summary from defaultRegistry")
+ .register();
+
+ defaultRegistry_Summary.observe(10);
+ defaultRegistry_Summary.observe(20);
+ defaultRegistry_Summary.observe(30);
Histogram h = registry.histogram(
withName("Histogram"),
diff --git a/pom.xml b/pom.xml
index 1bd6e0a..3243818 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,18 @@
Gleb Smirnov
https://github.com/gleb4646
+
+
+ mairovichaa
+ Andrei Mairovich
+ https://github.com/mairovichaa
+
+
+
+ kkolyan
+ Nikolay Plekhanov
+ https://github.com/kkolyan
+