// =================================================================================================
// Copyright 2013 Twitter, Inc.
// -------------------------------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this work except in compliance with the License.
// You may obtain a copy of the License in the LICENSE file, or at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =================================================================================================
package com.twitter.common.metrics;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Tests metric registry scoping.
*/
public class MetricsTest {
private static final double EPS = 1e-8;
private Metrics metrics;
@Before
public void setUp() {
metrics = Metrics.createDetached();
}
@Test
public void testEmpty() {
checkSamples(ImmutableMap.<String, Number>of());
}
@Test
public void testScoping() {
Counter foo = metrics.createCounter("foo");
foo.add(10);
checkSamples(ImmutableMap.<String, Number>of("foo", 10L));
MetricRegistry barScope = metrics.scope("bar");
Counter barFoo = barScope.createCounter("foo");
barFoo.add(2);
checkSamples(ImmutableMap.<String, Number>of("foo", 10L, "bar.foo", 2L));
MetricRegistry bazScope = barScope.scope("baz");
Counter bazFoo = bazScope.createCounter("foo");
bazFoo.add(3);
checkSamples(ImmutableMap.<String, Number>of("foo", 10L, "bar.foo", 2L, "bar.baz.foo", 3L));
}
@Test
public void testDetachedRoot() {
String name = "foo";
Long value = 10L;
Metrics detached = Metrics.createDetached();
Counter foo = detached.createCounter(name);
foo.add(value);
Long readValue = (Long) detached.sample().get(name);
assertEquals(readValue, value);
foo.increment();
Long readValue2 = (Long) detached.sample().get(name);
value += 1;
assertEquals(readValue2, value);
assertNull(Metrics.root().sample().get(name));
}
@Test(expected = IllegalArgumentException.class)
public void testOverwrite() {
Counter foo = metrics.createCounter("foo");
Counter foo2 = metrics.createCounter("foo");
}
@Test(expected = IllegalArgumentException.class)
public void testOverwrite2() {
try {
Counter foo = metrics.createCounter("foo");
// nb. we check for collisions on base-name of the histogram but perhaps we want
// to check the expanded quantile/etc names in the future.
HistogramInterface foo2 = metrics.createHistogram("foo");
} catch (IllegalArgumentException expected) {
Gauge foo = new AbstractGauge("foo") {
@Override
public Number read() {
return 12;
}
};
metrics.register(foo);
Counter foo2 = metrics.createCounter("foo");
}
}
@Test
public void testUnregisterByRef() {
// Counter
Counter counter = metrics.createCounter("counter");
assertTrue("Metrics contains counter", metrics.sample().containsKey(counter.getName()));
metrics.unregister(counter);
assertFalse("Metrics doesn't contains counter",
metrics.sample().containsKey(counter.getName()));
// Gauge
final long x = 1L;
Gauge<Number> gauge = new AbstractGauge<Number>("gauge") {
@Override public Number read() { return x; }
};
metrics.register(gauge);
assertTrue("Metrics contains gauge", metrics.sample().containsKey(gauge.getName()));
metrics.unregister(gauge);
assertFalse("Metrics doesn't contains gauge", metrics.sample().containsKey(gauge.getName()));
// Histogram
HistogramInterface histo = metrics.createHistogram("histo");
assertTrue("Metrics contains histo", metrics.sample().containsKey(
histo.getName() + ".count"));
metrics.unregister(histo);
assertFalse("Metrics doesn't contains histo", metrics.sample().containsKey(
histo.getName() + ".count"));
}
@Test
public void testUnregisterByName() {
// Counter
Counter counter = metrics.createCounter("counter");
assertTrue("Metrics contains counter", metrics.sample().containsKey(counter.getName()));
metrics.unregister("counter");
assertFalse("Metrics doesn't contains counter",
metrics.sample().containsKey(counter.getName()));
// Gauge
final long x = 1L;
Gauge<Number> gauge = new AbstractGauge<Number>("gauge") {
@Override public Number read() { return x; }
};
metrics.register(gauge);
assertTrue("Metrics contains gauge", metrics.sample().containsKey(gauge.getName()));
metrics.unregister(gauge.getName());
assertFalse("Metrics doesn't contains gauge", metrics.sample().containsKey(gauge.getName()));
// Histogram
HistogramInterface histo = metrics.createHistogram("histo");
assertTrue("Metrics contains histo", metrics.sample().containsKey(
histo.getName() + ".count"));
metrics.unregister(histo.getName());
assertFalse("Metrics doesn't contains histo", metrics.sample().containsKey(
histo.getName() + ".count"));
}
@Test
public void testUnregistrationOnScopedRegistry() {
String scope = "scope";
MetricRegistry registry = metrics.scope(scope);
// Counter
Counter counter = registry.createCounter("counter");
assertTrue("Metrics contains counter", metrics.sample().containsKey(counter.getName()));
registry.unregister(counter);
assertFalse("Metrics doesn't contains counter",
metrics.sample().containsKey(counter.getName()));
// Gauge
final long x = 1L;
Gauge<Number> gauge = registry.registerGauge(new AbstractGauge<Number>("gauge") {
@Override public Number read() { return x; }
});
assertTrue("Metrics contains gauge", metrics.sample().containsKey(gauge.getName()));
registry.unregister(gauge);
assertFalse("Metrics doesn't contains gauge", metrics.sample().containsKey(gauge.getName()));
// Histogram
HistogramInterface histo = registry.createHistogram("histo");
assertTrue("Metrics contains histo", metrics.sample().containsKey(
histo.getName() + ".count"));
registry.unregister(histo);
assertFalse("Metrics doesn't contains histo", metrics.sample().containsKey(
histo.getName() + ".count"));
Counter counterZ = registry.createCounter("counter_zzz");
assertTrue("Metrics contains counter", metrics.sample().containsKey(counterZ.getName()));
registry.unregister("counter_zzz");
assertFalse("Metrics doesn't contains counter",
metrics.sample().containsKey(counterZ.getName()));
}
private void checkSamples(Map<String, Number> expected) {
Map<String, Number> samples = Maps.newHashMap(metrics.sample());
for (Map.Entry<String, Number> expectedSample : expected.entrySet()) {
Number value = samples.remove(expectedSample.getKey());
assertNotNull(value);
assertEquals(expectedSample.getValue().doubleValue(), value.doubleValue(), EPS);
}
assertThat(metrics.sample(), is(expected));
}
}