@ -16,22 +16,24 @@ import static java.util.Arrays.asList;
import static java.util.Collections.singleton ;
import static java.util.Collections.singleton ;
import tech.pegasys.pantheon.metrics.LabelledMetric ;
import tech.pegasys.pantheon.metrics.LabelledMetric ;
import tech.pegasys.pantheon.metrics.MetricCategory ;
import tech.pegasys.pantheon.metrics.MetricsSystem ;
import tech.pegasys.pantheon.metrics.MetricsSystem ;
import tech.pegasys.pantheon.metrics.Observation ;
import tech.pegasys.pantheon.metrics.Observation ;
import tech.pegasys.pantheon.metrics.OperationTimer ;
import tech.pegasys.pantheon.metrics.OperationTimer ;
import tech.pegasys.pantheon.metrics.Pantheon MetricCategory ;
import tech.pegasys.pantheon.metrics.Standard MetricCategory ;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem ;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem ;
import java.util.ArrayList ;
import java.util.ArrayList ;
import java.util.Collection ;
import java.util.Collection ;
import java.util.Collections ;
import java.util.Collections ;
import java.util.EnumSet ;
import java.util.List ;
import java.util.List ;
import java.util.Map ;
import java.util.Map ;
import java.util.Set ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.function.DoubleSupplier ;
import java.util.function.DoubleSupplier ;
import java.util.stream.Stream ;
import java.util.stream.Stream ;
import com.google.common.collect.ImmutableSet ;
import io.prometheus.client.Collector ;
import io.prometheus.client.Collector ;
import io.prometheus.client.Collector.MetricFamilySamples ;
import io.prometheus.client.Collector.MetricFamilySamples ;
import io.prometheus.client.Collector.MetricFamilySamples.Sample ;
import io.prometheus.client.Collector.MetricFamilySamples.Sample ;
@ -48,34 +50,33 @@ import io.prometheus.client.hotspot.ThreadExports;
public class PrometheusMetricsSystem implements MetricsSystem {
public class PrometheusMetricsSystem implements MetricsSystem {
private static final String PANTHEON_PREFIX = "pantheon_" ;
private final Map < MetricCategory , Collection < Collector > > collectors = new ConcurrentHashMap < > ( ) ;
private final Map < PantheonMetricCategory , Collection < Collector > > collectors =
new ConcurrentHashMap < > ( ) ;
private final CollectorRegistry registry = new CollectorRegistry ( true ) ;
private final CollectorRegistry registry = new CollectorRegistry ( true ) ;
private final Map < String , LabelledMetric < tech . pegasys . pantheon . metrics . Counter > > cachedCounters =
private final Map < String , LabelledMetric < tech . pegasys . pantheon . metrics . Counter > > cachedCounters =
new ConcurrentHashMap < > ( ) ;
new ConcurrentHashMap < > ( ) ;
private final Map < String , LabelledMetric < tech . pegasys . pantheon . metrics . OperationTimer > >
private final Map < String , LabelledMetric < tech . pegasys . pantheon . metrics . OperationTimer > >
cachedTimers = new ConcurrentHashMap < > ( ) ;
cachedTimers = new ConcurrentHashMap < > ( ) ;
private final EnumSet < PantheonMetricCategory > enabledCategories =
private final Set < MetricCategory > enabledCategories ;
EnumSet . allOf ( PantheonMetricCategory . class ) ;
PrometheusMetricsSystem ( ) { }
PrometheusMetricsSystem ( final Set < MetricCategory > enabledCategories ) {
this . enabledCategories = ImmutableSet . copyOf ( enabledCategories ) ;
}
public static MetricsSystem init ( final MetricsConfiguration metricsConfiguration ) {
public static MetricsSystem init ( final MetricsConfiguration metricsConfiguration ) {
if ( ! metricsConfiguration . isEnabled ( ) & & ! metricsConfiguration . isPushEnabled ( ) ) {
if ( ! metricsConfiguration . isEnabled ( ) & & ! metricsConfiguration . isPushEnabled ( ) ) {
return new NoOpMetricsSystem ( ) ;
return new NoOpMetricsSystem ( ) ;
}
}
final PrometheusMetricsSystem metricsSystem = new PrometheusMetricsSystem ( ) ;
final PrometheusMetricsSystem metricsSystem =
metricsSystem . enabledCategories . retainAll ( metricsConfiguration . getMetricCategories ( ) ) ;
new PrometheusMetricsSystem ( metricsConfiguration . getMetricCategories ( ) ) ;
if ( metricsSystem . enabledCategories . contains ( Pantheon MetricCategory. PROCESS ) ) {
if ( metricsSystem . isCategoryEnabled ( Standard MetricCategory. PROCESS ) ) {
metricsSystem . collectors . put (
metricsSystem . collectors . put (
Pantheon MetricCategory. PROCESS ,
Standard MetricCategory. PROCESS ,
singleton ( new StandardExports ( ) . register ( metricsSystem . registry ) ) ) ;
singleton ( new StandardExports ( ) . register ( metricsSystem . registry ) ) ) ;
}
}
if ( metricsSystem . enabledCategories . contains ( Pantheon MetricCategory. JVM ) ) {
if ( metricsSystem . isCategoryEnabled ( Standard MetricCategory. JVM ) ) {
metricsSystem . collectors . put (
metricsSystem . collectors . put (
Pantheon MetricCategory. JVM ,
Standard MetricCategory. JVM ,
asList (
asList (
new MemoryPoolsExports ( ) . register ( metricsSystem . registry ) ,
new MemoryPoolsExports ( ) . register ( metricsSystem . registry ) ,
new BufferPoolsExports ( ) . register ( metricsSystem . registry ) ,
new BufferPoolsExports ( ) . register ( metricsSystem . registry ) ,
@ -88,7 +89,7 @@ public class PrometheusMetricsSystem implements MetricsSystem {
@Override
@Override
public LabelledMetric < tech . pegasys . pantheon . metrics . Counter > createLabelledCounter (
public LabelledMetric < tech . pegasys . pantheon . metrics . Counter > createLabelledCounter (
final Pantheon MetricCategory category ,
final MetricCategory category ,
final String name ,
final String name ,
final String help ,
final String help ,
final String . . . labelNames ) {
final String . . . labelNames ) {
@ -96,7 +97,7 @@ public class PrometheusMetricsSystem implements MetricsSystem {
return cachedCounters . computeIfAbsent (
return cachedCounters . computeIfAbsent (
metricName ,
metricName ,
( k ) - > {
( k ) - > {
if ( enabledCategories . contains ( category ) ) {
if ( isCategoryEnabled ( category ) ) {
final Counter counter = Counter . build ( metricName , help ) . labelNames ( labelNames ) . create ( ) ;
final Counter counter = Counter . build ( metricName , help ) . labelNames ( labelNames ) . create ( ) ;
addCollectorUnchecked ( category , counter ) ;
addCollectorUnchecked ( category , counter ) ;
return new PrometheusCounter ( counter ) ;
return new PrometheusCounter ( counter ) ;
@ -108,7 +109,7 @@ public class PrometheusMetricsSystem implements MetricsSystem {
@Override
@Override
public LabelledMetric < OperationTimer > createLabelledTimer (
public LabelledMetric < OperationTimer > createLabelledTimer (
final Pantheon MetricCategory category ,
final MetricCategory category ,
final String name ,
final String name ,
final String help ,
final String help ,
final String . . . labelNames ) {
final String . . . labelNames ) {
@ -116,7 +117,7 @@ public class PrometheusMetricsSystem implements MetricsSystem {
return cachedTimers . computeIfAbsent (
return cachedTimers . computeIfAbsent (
metricName ,
metricName ,
( k ) - > {
( k ) - > {
if ( enabledCategories . contains ( category ) ) {
if ( isCategoryEnabled ( category ) ) {
final Summary summary =
final Summary summary =
Summary . build ( metricName , help )
Summary . build ( metricName , help )
. quantile ( 0 . 2 , 0 . 02 )
. quantile ( 0 . 2 , 0 . 02 )
@ -137,25 +138,28 @@ public class PrometheusMetricsSystem implements MetricsSystem {
@Override
@Override
public void createGauge (
public void createGauge (
final Pantheon MetricCategory category ,
final MetricCategory category ,
final String name ,
final String name ,
final String help ,
final String help ,
final DoubleSupplier valueSupplier ) {
final DoubleSupplier valueSupplier ) {
final String metricName = convertToPrometheusName ( category , name ) ;
final String metricName = convertToPrometheusName ( category , name ) ;
if ( enabledCategories . contains ( category ) ) {
if ( isCategoryEnabled ( category ) ) {
final Collector collector = new CurrentValueCollector ( metricName , help , valueSupplier ) ;
final Collector collector = new CurrentValueCollector ( metricName , help , valueSupplier ) ;
addCollectorUnchecked ( category , collector ) ;
addCollectorUnchecked ( category , collector ) ;
}
}
}
}
public void addCollector ( final PantheonMetricCategory category , final Collector metric ) {
private boolean isCategoryEnabled ( final MetricCategory category ) {
if ( enabledCategories . contains ( category ) ) {
return enabledCategories . contains ( category ) ;
}
public void addCollector ( final MetricCategory category , final Collector metric ) {
if ( isCategoryEnabled ( category ) ) {
addCollectorUnchecked ( category , metric ) ;
addCollectorUnchecked ( category , metric ) ;
}
}
}
}
private void addCollectorUnchecked (
private void addCollectorUnchecked ( final MetricCategory category , final Collector metric ) {
final PantheonMetricCategory category , final Collector metric ) {
metric . register ( registry ) ;
metric . register ( registry ) ;
collectors
collectors
. computeIfAbsent ( category , key - > Collections . newSetFromMap ( new ConcurrentHashMap < > ( ) ) )
. computeIfAbsent ( category , key - > Collections . newSetFromMap ( new ConcurrentHashMap < > ( ) ) )
@ -163,22 +167,25 @@ public class PrometheusMetricsSystem implements MetricsSystem {
}
}
@Override
@Override
public Stream < Observation > streamObservations ( final Pantheon MetricCategory category ) {
public Stream < Observation > streamObservations ( final MetricCategory category ) {
return collectors . getOrDefault ( category , Collections . emptySet ( ) ) . stream ( )
return collectors . getOrDefault ( category , Collections . emptySet ( ) ) . stream ( )
. flatMap ( collector - > collector . collect ( ) . stream ( ) )
. flatMap ( collector - > collector . collect ( ) . stream ( ) )
. flatMap ( familySamples - > convertSamplesToObservations ( category , familySamples ) ) ;
. flatMap ( familySamples - > convertSamplesToObservations ( category , familySamples ) ) ;
}
}
@Override
public Stream < Observation > streamObservations ( ) {
return collectors . keySet ( ) . stream ( ) . flatMap ( this : : streamObservations ) ;
}
private Stream < Observation > convertSamplesToObservations (
private Stream < Observation > convertSamplesToObservations (
final PantheonMetricCategory category , final MetricFamilySamples familySamples ) {
final MetricCategory category , final MetricFamilySamples familySamples ) {
return familySamples . samples . stream ( )
return familySamples . samples . stream ( )
. map ( sample - > createObservationFromSample ( category , sample , familySamples ) ) ;
. map ( sample - > createObservationFromSample ( category , sample , familySamples ) ) ;
}
}
private Observation createObservationFromSample (
private Observation createObservationFromSample (
final PantheonMetricCategory category ,
final MetricCategory category , final Sample sample , final MetricFamilySamples familySamples ) {
final Sample sample ,
final MetricFamilySamples familySamples ) {
if ( familySamples . type = = Type . HISTOGRAM ) {
if ( familySamples . type = = Type . HISTOGRAM ) {
return convertHistogramSampleNamesToLabels ( category , sample , familySamples ) ;
return convertHistogramSampleNamesToLabels ( category , sample , familySamples ) ;
}
}
@ -193,9 +200,7 @@ public class PrometheusMetricsSystem implements MetricsSystem {
}
}
private Observation convertHistogramSampleNamesToLabels (
private Observation convertHistogramSampleNamesToLabels (
final PantheonMetricCategory category ,
final MetricCategory category , final Sample sample , final MetricFamilySamples familySamples ) {
final Sample sample ,
final MetricFamilySamples familySamples ) {
final List < String > labelValues = new ArrayList < > ( sample . labelValues ) ;
final List < String > labelValues = new ArrayList < > ( sample . labelValues ) ;
if ( sample . name . endsWith ( "_bucket" ) ) {
if ( sample . name . endsWith ( "_bucket" ) ) {
labelValues . add ( labelValues . size ( ) - 1 , "bucket" ) ;
labelValues . add ( labelValues . size ( ) - 1 , "bucket" ) ;
@ -210,9 +215,7 @@ public class PrometheusMetricsSystem implements MetricsSystem {
}
}
private Observation convertSummarySampleNamesToLabels (
private Observation convertSummarySampleNamesToLabels (
final PantheonMetricCategory category ,
final MetricCategory category , final Sample sample , final MetricFamilySamples familySamples ) {
final Sample sample ,
final MetricFamilySamples familySamples ) {
final List < String > labelValues = new ArrayList < > ( sample . labelValues ) ;
final List < String > labelValues = new ArrayList < > ( sample . labelValues ) ;
if ( sample . name . endsWith ( "_sum" ) ) {
if ( sample . name . endsWith ( "_sum" ) ) {
labelValues . add ( "sum" ) ;
labelValues . add ( "sum" ) ;
@ -228,21 +231,17 @@ public class PrometheusMetricsSystem implements MetricsSystem {
labelValues ) ;
labelValues ) ;
}
}
public static String convertToPrometheusName (
public String convertToPrometheusName ( final MetricCategory category , final String name ) {
final PantheonMetricCategory category , final String name ) {
return prometheusPrefix ( category ) + name ;
return prometheusPrefix ( category ) + name ;
}
}
private String convertFromPrometheusName (
private String convertFromPrometheusName ( final MetricCategory category , final String metricName ) {
final PantheonMetricCategory category , final String metricName ) {
final String prefix = prometheusPrefix ( category ) ;
final String prefix = prometheusPrefix ( category ) ;
return metricName . startsWith ( prefix ) ? metricName . substring ( prefix . length ( ) ) : metricName ;
return metricName . startsWith ( prefix ) ? metricName . substring ( prefix . length ( ) ) : metricName ;
}
}
private static String prometheusPrefix ( final PantheonMetricCategory category ) {
private String prometheusPrefix ( final MetricCategory category ) {
return category . isPantheonSpecific ( )
return category . getAppliationPrefix ( ) . orElse ( "" ) + category . getName ( ) + "_" ;
? PANTHEON_PREFIX + category . getName ( ) + "_"
: category . getName ( ) + "_" ;
}
}
CollectorRegistry getRegistry ( ) {
CollectorRegistry getRegistry ( ) {