-
Notifications
You must be signed in to change notification settings - Fork 798
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Brian Brazil <[email protected]>
- Loading branch information
1 parent
92d34e3
commit 37fa7fb
Showing
7 changed files
with
306 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
simpleclient/src/main/java/io/prometheus/client/Info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package io.prometheus.client; | ||
|
||
import io.prometheus.client.CKMSQuantiles.Quantile; | ||
|
||
import java.io.Closeable; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.TreeMap; | ||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
/** | ||
* Info metric, key-value pairs. | ||
* | ||
* Examples of Info include, build information, version information, and potential target metadata, | ||
* The first provided state will be the default. | ||
* | ||
* <p> | ||
* Example enumeration: | ||
* <pre> | ||
* {@code | ||
* class YourClass { | ||
* static final Info buildInfo = Info.build() | ||
* .name("your_build_info").help("Build information.") | ||
* .register(); | ||
* | ||
* void func() { | ||
* // Your code here. | ||
* buildInfo.info("branch", "HEAD", "version", "1.2.3", "revision", "e0704b"); | ||
* } | ||
* } | ||
* } | ||
* </pre> | ||
*/ | ||
public class Info extends SimpleCollector<Info.Child> implements Counter.Describable { | ||
|
||
Info(Builder b) { | ||
super(b); | ||
} | ||
|
||
public static class Builder extends SimpleCollector.Builder<Builder, Info> { | ||
@Override | ||
public Info create() { | ||
if (!unit.isEmpty()) { | ||
throw new IllegalStateException("Info metrics cannot have a unit."); | ||
} | ||
return new Info(this); | ||
} | ||
} | ||
|
||
/** | ||
* Return a Builder to allow configuration of a new Info. Ensures required fields are provided. | ||
* | ||
* @param name The name of the metric | ||
* @param help The help string of the metric | ||
*/ | ||
public static Builder build(String name, String help) { | ||
return new Builder().name(name).help(help); | ||
} | ||
|
||
/** | ||
* Return a Builder to allow configuration of a new Info. | ||
*/ | ||
public static Builder build() { | ||
return new Builder(); | ||
} | ||
|
||
@Override | ||
protected Child newChild() { | ||
return new Child(labelNames); | ||
} | ||
|
||
|
||
/** | ||
* The value of a single Info. | ||
* <p> | ||
* <em>Warning:</em> References to a Child become invalid after using | ||
* {@link SimpleCollector#remove} or {@link SimpleCollector#clear}. | ||
*/ | ||
public static class Child { | ||
|
||
private Map<String, String> value = Collections.emptyMap(); | ||
private List<String> labelNames; | ||
|
||
private Child(List<String> labelNames) { | ||
this.labelNames = labelNames; | ||
} | ||
|
||
/** | ||
* Set the info. | ||
*/ | ||
public void info(Map<String, String> v) { | ||
for (String key : v.keySet()) { | ||
checkMetricLabelName(key); | ||
} | ||
for (String label : labelNames) { | ||
if (v.containsKey(label)) { | ||
throw new IllegalArgumentException("Info and its value cannot have the same label name."); | ||
} | ||
} | ||
this.value = v; | ||
} | ||
/** | ||
* Set the info. | ||
* | ||
* @param v labels as pairs of key values | ||
*/ | ||
public void info(String... v) { | ||
if (v.length % 2 != 0) { | ||
throw new IllegalArgumentException("An even number of arguments must be passed"); | ||
} | ||
Map<String, String> m = new TreeMap<String, String>(); | ||
for (int i = 0; i < v.length; i+=2) { | ||
m.put(v[i], v[i+1]); | ||
} | ||
info(m); | ||
} | ||
|
||
/** | ||
* Get the info. | ||
*/ | ||
public Map<String, String> get() { | ||
return value; | ||
} | ||
} | ||
|
||
// Convenience methods. | ||
/** | ||
* Set the info on the info with no labels. | ||
*/ | ||
public void info(String... v) { | ||
noLabelsChild.info(v); | ||
} | ||
|
||
/** | ||
* Set the info on the info with no labels. | ||
* | ||
* @param v labels as pairs of key values | ||
*/ | ||
public void info(Map<String, String> v) { | ||
noLabelsChild.info(v); | ||
} | ||
|
||
/** | ||
* Get the the info. | ||
*/ | ||
public Map<String, String> get() { | ||
return noLabelsChild.get(); | ||
} | ||
|
||
@Override | ||
public List<MetricFamilySamples> collect() { | ||
List<MetricFamilySamples.Sample> samples = new ArrayList<MetricFamilySamples.Sample>(); | ||
for(Map.Entry<List<String>, Child> c: children.entrySet()) { | ||
Map<String, String> v = c.getValue().get(); | ||
List<String> names = new ArrayList<String>(labelNames); | ||
List<String> values = new ArrayList<String>(c.getKey()); | ||
for(Map.Entry<String, String> l: v.entrySet()) { | ||
names.add(l.getKey()); | ||
values.add(l.getValue()); | ||
} | ||
samples.add(new MetricFamilySamples.Sample(fullname + "_info", names, values, 1.0)); | ||
} | ||
|
||
return familySamplesList(Type.INFO, samples); | ||
} | ||
|
||
@Override | ||
public List<MetricFamilySamples> describe() { | ||
return Collections.singletonList( | ||
new MetricFamilySamples(fullname, Type.INFO, help, Collections.<MetricFamilySamples.Sample>emptyList())); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
simpleclient/src/test/java/io/prometheus/client/InfoTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package io.prometheus.client; | ||
|
||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import static java.util.Arrays.asList; | ||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
|
||
public class InfoTest { | ||
|
||
CollectorRegistry registry; | ||
Info noLabels, labels; | ||
|
||
@Before | ||
public void setUp() { | ||
registry = new CollectorRegistry(); | ||
noLabels = Info.build().name("nolabels").help("help").register(registry); | ||
labels = Info.build().name("labels").help("help").labelNames("l").register(registry); | ||
} | ||
|
||
private Double getInfo(String metric, String... labels) { | ||
String[] names = new String[labels.length / 2]; | ||
String[] values = new String[labels.length / 2]; | ||
for (int i = 0; i < labels.length; i+=2) { | ||
names[i/2] = labels[i]; | ||
values[i/2] = labels[i+1]; | ||
} | ||
return registry.getSampleValue(metric + "_info", names, values); | ||
} | ||
|
||
@Test | ||
public void testInfo() { | ||
assertEquals(null, getInfo("nolabels", "foo", "bar")); | ||
noLabels.info("foo", "bar"); | ||
assertEquals(1.0, getInfo("nolabels", "foo", "bar"), .001); | ||
noLabels.info("foo", "bar", "baz", "meh"); | ||
assertEquals(null, getInfo("nolabels", "foo", "bar")); | ||
assertEquals(1.0, getInfo("nolabels", "baz", "meh", "foo", "bar"), .001); | ||
} | ||
|
||
@Test | ||
public void testDefaultValue() { | ||
assertEquals(1.0, getInfo("nolabels"), .001); | ||
} | ||
|
||
@Test | ||
public void testLabels() { | ||
assertEquals(null, getInfo("labels", "l", "a", "foo", "bar")); | ||
assertEquals(null, getInfo("labels", "l", "b", "baz", "meh")); | ||
labels.labels("a").info("foo", "bar"); | ||
assertEquals(1.0, getInfo("labels", "l", "a", "foo", "bar"), .001); | ||
assertEquals(null, getInfo("labels", "l", "b", "baz", "meh")); | ||
labels.labels("b").info("baz", "meh"); | ||
assertEquals(1.0, getInfo("labels", "l", "a", "foo", "bar"), .001); | ||
assertEquals(1.0, getInfo("labels", "l", "b", "baz", "meh"), .001); | ||
|
||
assertEquals(null, getInfo("nolabels", "l", "a")); | ||
assertEquals(null, getInfo("nolabels", "l", "b")); | ||
} | ||
|
||
@Test(expected=IllegalArgumentException.class) | ||
public void testDuplicateNameLabelThrows() { | ||
Info i = Info.build().name("labels").help("help").labelNames("l").create(); | ||
i.labels("a").info("l", "bar"); | ||
} | ||
|
||
@Test(expected=IllegalArgumentException.class) | ||
public void testOddInfoThrows() { | ||
Info i = Info.build().name("labels").help("help").create(); | ||
i.info("odd"); | ||
} | ||
|
||
@Test(expected=IllegalStateException.class) | ||
public void testUnitThrows() { | ||
Info.build().unit("seconds").name("nolabels").help("help").create(); | ||
} | ||
|
||
@Test | ||
public void testCollect() { | ||
labels.labels("a").info("foo", "bar", "baz", "meh"); | ||
List<Collector.MetricFamilySamples> mfs = labels.collect(); | ||
|
||
ArrayList<Collector.MetricFamilySamples.Sample> samples = new ArrayList<Collector.MetricFamilySamples.Sample>(); | ||
samples.add(new Collector.MetricFamilySamples.Sample("labels_info", asList("l", "baz", "foo"), asList("a", "meh", "bar"), 1.0)); | ||
Collector.MetricFamilySamples mfsFixture = new Collector.MetricFamilySamples("labels", Collector.Type.INFO, "help", samples); | ||
|
||
assertEquals(1, mfs.size()); | ||
assertEquals(mfsFixture, mfs.get(0)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters