All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.prometheus.client.Collector Maven / Gradle / Ivy

There is a newer version: 0.16.0
Show newest version

package io.prometheus.client;

import java.util.List;
import java.util.regex.Pattern;

/**
 * A collector for a set of metrics.
 * 

* Normal users should use {@link Gauge}, {@link Counter}, {@link Summary} and {@link Histogram}. *

* Subclasssing Collector is for advanced uses, such as proxying metrics from another monitoring system. * It is it the responsibility of subclasses to ensure they produce valid metrics. * @see Exposition formats. */ public abstract class Collector { /** * Return all of the metrics of this Collector. */ public abstract List collect(); public enum Type { COUNTER, GAUGE, SUMMARY, HISTOGRAM, UNTYPED, } /** * A metric, and all of its samples. */ static public class MetricFamilySamples { public final String name; public final Type type; public final String help; public final List samples; public MetricFamilySamples(String name, Type type, String help, List samples) { this.name = name; this.type = type; this.help = help; this.samples = samples; } @Override public boolean equals(Object obj) { if (!(obj instanceof MetricFamilySamples)) { return false; } MetricFamilySamples other = (MetricFamilySamples) obj; return other.name.equals(name) && other.type.equals(type) && other.help.equals(help) && other.samples.equals(samples) ; } @Override public int hashCode() { int hash = 1; hash = 37 * hash + name.hashCode(); hash = 37 * hash + type.hashCode(); hash = 37 * hash + help.hashCode(); hash = 37 * hash + samples.hashCode(); return hash; } @Override public String toString() { return "Name: " + name + " Type: " + type + " Help: " + help + " Samples: " + samples; } /** * A single Sample, with a unique name and set of labels. */ public static class Sample { public final String name; public final List labelNames; public final List labelValues; // Must have same length as labelNames. public final double value; public Sample(String name, List labelNames, List labelValues, double value) { this.name = name; this.labelNames = labelNames; this.labelValues = labelValues; this.value = value; } @Override public boolean equals(Object obj) { if (!(obj instanceof Sample)) { return false; } Sample other = (Sample) obj; return other.name.equals(name) && other.labelNames.equals(labelNames) && other.labelValues.equals(labelValues) && other.value == value; } @Override public int hashCode() { int hash = 1; hash = 37 * hash + name.hashCode(); hash = 37 * hash + labelNames.hashCode(); hash = 37 * hash + labelValues.hashCode(); long d = Double.doubleToLongBits(value); hash = 37 * hash + (int)(d ^ (d >>> 32)); return hash; } @Override public String toString() { return "Name: " + name + " LabelNames: " + labelNames + " labelValues: " + labelValues + " Value: " + value; } } } /** * Register the Collector with the default registry. */ public T register() { return register(CollectorRegistry.defaultRegistry); } /** * Register the Collector with the given registry. */ public T register(CollectorRegistry registry) { registry.register(this); return (T)this; } public interface Describable { /** * Provide a list of metric families this Collector is expected to return. * * These should exclude the samples. This is used by the registry to * detect collisions and duplicate registrations. * * Usually custom collectors do not have to implement Describable. If * Describable is not implemented and the CollectorRegistry was created * with auto describe enabled (which is the case for the default registry) * then {@link collect} will be called at registration time instead of * describe. If this could cause problems, either implement a proper * describe, or if that's not practical have describe return an empty * list. */ List describe(); } /* Various utility functions for implementing Collectors. */ /** * Number of nanoseconds in a second. */ public static final double NANOSECONDS_PER_SECOND = 1E9; /** * Number of milliseconds in a second. */ public static final double MILLISECONDS_PER_SECOND = 1E3; private static final Pattern METRIC_NAME_RE = Pattern.compile("[a-zA-Z_:][a-zA-Z0-9_:]*"); private static final Pattern METRIC_LABEL_NAME_RE = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*"); private static final Pattern RESERVED_METRIC_LABEL_NAME_RE = Pattern.compile("__.*"); /** * Throw an exception if the metric name is invalid. */ protected static void checkMetricName(String name) { if (!METRIC_NAME_RE.matcher(name).matches()) { throw new IllegalArgumentException("Invalid metric name: " + name); } } 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_]"); /** * Sanitize metric name */ public static String sanitizeMetricName(String metricName) { return SANITIZE_BODY_PATTERN.matcher( SANITIZE_PREFIX_PATTERN.matcher(metricName).replaceFirst("_") ).replaceAll("_"); } /** * Throw an exception if the metric label name is invalid. */ protected static void checkMetricLabelName(String name) { if (!METRIC_LABEL_NAME_RE.matcher(name).matches()) { throw new IllegalArgumentException("Invalid metric label name: " + name); } if (RESERVED_METRIC_LABEL_NAME_RE.matcher(name).matches()) { throw new IllegalArgumentException("Invalid metric label name, reserved for internal use: " + name); } } /** * Convert a double to its string representation in Go. */ public static String doubleToGoString(double d) { if (d == Double.POSITIVE_INFINITY) { return "+Inf"; } if (d == Double.NEGATIVE_INFINITY) { return "-Inf"; } if (Double.isNaN(d)) { return "NaN"; } return Double.toString(d); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy