diff --git a/jaeger-core/src/main/java/com/uber/jaeger/Configuration.java b/jaeger-core/src/main/java/com/uber/jaeger/Configuration.java index a6bc0bb2b..9ee4a9d54 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/Configuration.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/Configuration.java @@ -15,9 +15,9 @@ package com.uber.jaeger; import com.uber.jaeger.metrics.Metrics; -import com.uber.jaeger.metrics.NullStatsReporter; +import com.uber.jaeger.metrics.MetricsFactory; +import com.uber.jaeger.metrics.NoopMetricsFactory; import com.uber.jaeger.metrics.StatsFactory; -import com.uber.jaeger.metrics.StatsFactoryImpl; import com.uber.jaeger.propagation.B3TextMapCodec; import com.uber.jaeger.propagation.Codec; import com.uber.jaeger.propagation.CompositeCodec; @@ -168,7 +168,7 @@ public enum Propagation { /** * A interface that wraps an underlying metrics generator in order to report Jaeger's metrics. */ - private StatsFactory statsFactory; + private MetricsFactory metricsFactory; /** * lazy singleton Tracer initialized in getTracer() method. @@ -212,7 +212,7 @@ private Configuration( } this.codecConfig = codecConfig; - statsFactory = new StatsFactoryImpl(new NullStatsReporter()); + metricsFactory = new NoopMetricsFactory(); } public static Configuration fromEnv() { @@ -224,7 +224,7 @@ public static Configuration fromEnv() { } public Tracer.Builder getTracerBuilder() { - Metrics metrics = new Metrics(statsFactory); + Metrics metrics = new Metrics(metricsFactory); Reporter reporter = reporterConfig.getReporter(metrics); Sampler sampler = samplerConfig.createSampler(serviceName, metrics); Tracer.Builder builder = new Tracer.Builder(serviceName, @@ -251,16 +251,30 @@ public synchronized void closeTracer() { } /** - * @param statsFactory the factory - * @deprecated Use {@link #setStatsFactory(StatsFactory)} instead + * @see #setMetricsFactory(MetricsFactory) + * @param statsFactory the StatsFactory to use on the Tracer to be built + * @deprecated Use {@link #setMetricsFactory(MetricsFactory)} instead */ @Deprecated public void setStatsFactor(StatsFactory statsFactory) { - this.statsFactory = statsFactory; + this.metricsFactory = statsFactory; } + /** + * @see #setMetricsFactory(MetricsFactory) + * @param statsFactory the StatsFactory to use on the Tracer to be built + * @deprecated Use {@link #setMetricsFactory(MetricsFactory)} instead + */ + @Deprecated public void setStatsFactory(StatsFactory statsFactory) { - this.statsFactory = statsFactory; + this.metricsFactory = statsFactory; + } + + /** + * @param metricsFactory the MetricsFactory to use on the Tracer to be built + */ + public void setMetricsFactory(MetricsFactory metricsFactory) { + this.metricsFactory = metricsFactory; } /** diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/InMemoryMetricsFactory.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/InMemoryMetricsFactory.java new file mode 100644 index 000000000..764dbc5a2 --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/InMemoryMetricsFactory.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017, The Jaeger Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License 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.uber.jaeger.metrics; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +/** + * An ephemeral metrics factory, storing data in memory. This metrics factory is not meant to be used for production + * purposes. + */ +public class InMemoryMetricsFactory implements MetricsFactory { + private Map counters = new ConcurrentHashMap(); + private Map timers = new ConcurrentHashMap(); + private Map gauges = new ConcurrentHashMap(); + + @Override + public Counter createCounter(String name, Map tags) { + final AtomicLong value = new AtomicLong(0); + counters.put(Metrics.addTagsToMetricName(name, tags), value); + + return new Counter() { + @Override + public void inc(long delta) { + value.addAndGet(delta); + } + }; + } + + @Override + public Timer createTimer(final String name, final Map tags) { + final AtomicLong value = new AtomicLong(0); + timers.put(Metrics.addTagsToMetricName(name, tags), value); + + return new Timer() { + @Override + public void durationMicros(long time) { + value.addAndGet(time); + } + }; + } + + @Override + public Gauge createGauge(final String name, final Map tags) { + final AtomicLong value = new AtomicLong(0); + gauges.put(Metrics.addTagsToMetricName(name, tags), value); + + return new Gauge() { + @Override + public void update(long amount) { + value.addAndGet(amount); + } + }; + } + + /** + * Returns the counter value information for the counter with the given metric name. + * Note that the metric name is not the counter name, as a metric name usually includes the tags. + * + * @see Metrics#addTagsToMetricName(String, Map) + * @param name the metric name, which includes the tags + * @return the counter value or -1, if no counter exists for the given metric name + */ + public long getCounter(String name) { + return getValue(counters, name); + } + + /** + * Returns the current value for the gauge with the given metric name. Note that the metric name is not the gauge + * name, as a metric name usually includes the tags. + * + * @see Metrics#addTagsToMetricName(String, Map) + * @param name the metric name, which includes the tags + * @return the gauge value or -1, if no gauge exists for the given metric name + */ + public long getGauge(String name) { + return getValue(gauges, name); + } + + /** + * Returns the current accumulated timing information for the timer with the given metric name. + * Note that the metric name is not the timer name, as a metric name usually includes the tags. + * + * @see Metrics#addTagsToMetricName(String, Map) + * @param name the metric name, which includes the tags + * @return the timer value or -1, if no timer exists for the given metric name + */ + public long getTimer(String name) { + return getValue(timers, name); + } + + private long getValue(Map collection, String name) { + AtomicLong value = collection.get(name); + if (null == value) { + return -1; + } else { + return value.get(); + } + } +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/InMemoryStatsReporter.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/InMemoryStatsReporter.java index aab1ef60f..8f4fe57da 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/metrics/InMemoryStatsReporter.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/InMemoryStatsReporter.java @@ -17,6 +17,10 @@ import java.util.HashMap; import java.util.Map; +/** + * @deprecated Use {@link InMemoryMetricsFactory} instead + */ +@Deprecated public class InMemoryStatsReporter implements StatsReporter { public Map counters = new HashMap(); public Map gauges = new HashMap(); diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java index f35061beb..be0cb3117 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java @@ -25,6 +25,14 @@ public class Metrics { public Metrics(StatsFactory factory) { + createMetrics(factory); + } + + public Metrics(MetricsFactory factory) { + createMetrics(factory); + } + + private void createMetrics(MetricsFactory factory) { for (Field field : Metrics.class.getDeclaredFields()) { if (!Counter.class.isAssignableFrom(field.getType()) && !Timer.class.isAssignableFrom(field.getType()) @@ -90,6 +98,7 @@ public static String addTagsToMetricName(String name, Map tags) return sb.toString(); } + @Deprecated public static Metrics fromStatsReporter(StatsReporter reporter) { return new Metrics(new StatsFactoryImpl(reporter)); } diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/MetricsFactory.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/MetricsFactory.java new file mode 100644 index 000000000..56d702109 --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/MetricsFactory.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, The Jaeger Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License 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.uber.jaeger.metrics; + +import java.util.Map; + +/** + * Provides a standardized way to create metrics-related objects, like {@link Counter}, {@link Timer} and {@link Gauge}. + * + */ +public interface MetricsFactory { + /** + * Creates a counter with the given gauge name and set of tags. The actual metric name is a combination of those two + * values. The counter starts at 0. + * + * @see Metrics#addTagsToMetricName(String, Map) + * @param name the counter name + * @param tags the tags to add to the counter + * @return a {@link Counter} with a metric name following the counter name and tags + */ + Counter createCounter(String name, Map tags); + + /** + * Creates a timer with the given timer name and set of tags. The actual metric name is a combination of those two + * values. The timer starts at 0. + * + * @see Metrics#addTagsToMetricName(String, Map) + * @param name the timer name + * @param tags the tags to add to the timer + * @return a {@link Timer} with a metric name following the counter name and tags + */ + Timer createTimer(String name, Map tags); + + /** + * Creates a gauge with the given gauge name and set of tags. The actual metric name is a combination of those two + * values. The timer starts at 0. + * + * @see Metrics#addTagsToMetricName(String, Map) + * @param name the gauge name + * @param tags the tags to add to the gauge + * @return a {@link Gauge} with a metric name following the gauge name and tags + */ + Gauge createGauge(String name, Map tags); +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/NoopMetricsFactory.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/NoopMetricsFactory.java new file mode 100644 index 000000000..6bffda9fa --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/NoopMetricsFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, The Jaeger Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License 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.uber.jaeger.metrics; + +import java.util.Map; + +/** + * A metrics factory that implements NOOP counters, timers and gauges. + */ +public class NoopMetricsFactory implements MetricsFactory { + @Override + public Counter createCounter(String name, Map tags) { + return new Counter() { + @Override + public void inc(long delta) { + } + }; + } + + @Override + public Timer createTimer(final String name, final Map tags) { + return new Timer() { + @Override + public void durationMicros(long time) { + } + }; + } + + @Override + public Gauge createGauge(final String name, final Map tags) { + return new Gauge() { + @Override + public void update(long amount) { + } + }; + } +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/NullStatsReporter.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/NullStatsReporter.java index c277895da..e26119a12 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/metrics/NullStatsReporter.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/NullStatsReporter.java @@ -16,6 +16,12 @@ import java.util.Map; +/** + * A stats reporter that is NOOP. + * + * @deprecated Use {@link NoopMetricsFactory} instead + */ +@Deprecated public class NullStatsReporter implements StatsReporter { @Override public void incCounter(String name, long delta, Map tags) {} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsFactory.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsFactory.java index 12c2b59ac..267173f8e 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsFactory.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsFactory.java @@ -14,12 +14,9 @@ package com.uber.jaeger.metrics; -import java.util.Map; - -public interface StatsFactory { - Counter createCounter(String name, Map tags); - - Timer createTimer(String name, Map tags); - - Gauge createGauge(String name, Map tags); +/** + * @deprecated Use {@link MetricsFactory} instead + */ +@Deprecated +public interface StatsFactory extends MetricsFactory { } diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsFactoryImpl.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsFactoryImpl.java index e9ce603ce..9b9bd487a 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsFactoryImpl.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsFactoryImpl.java @@ -16,6 +16,12 @@ import java.util.Map; +/** + * A {@link StatsFactory} backed by a {@link StatsReporter}. + * + * @deprecated Use {@link MetricsFactory} instead + */ +@Deprecated public class StatsFactoryImpl implements StatsFactory { private final StatsReporter reporter; diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsReporter.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsReporter.java index fb11857ba..c7294690a 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsReporter.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/StatsReporter.java @@ -16,6 +16,10 @@ import java.util.Map; +/** + * @deprecated Use {@link MetricsFactory} instead + */ +@Deprecated public interface StatsReporter { void incCounter(String name, long delta, Map tags); diff --git a/jaeger-core/src/test/java/com/uber/jaeger/TracerTest.java b/jaeger-core/src/test/java/com/uber/jaeger/TracerTest.java index c866e2a8c..5fd5bda9a 100644 --- a/jaeger-core/src/test/java/com/uber/jaeger/TracerTest.java +++ b/jaeger-core/src/test/java/com/uber/jaeger/TracerTest.java @@ -22,8 +22,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import com.uber.jaeger.metrics.InMemoryMetricsFactory; import com.uber.jaeger.metrics.InMemoryStatsReporter; import com.uber.jaeger.metrics.Metrics; +import com.uber.jaeger.metrics.MetricsFactory; +import com.uber.jaeger.metrics.StatsFactory; import com.uber.jaeger.metrics.StatsFactoryImpl; import com.uber.jaeger.propagation.Injector; import com.uber.jaeger.reporters.InMemoryReporter; @@ -41,14 +44,14 @@ public class TracerTest { Tracer tracer; - InMemoryStatsReporter metricsReporter; + InMemoryMetricsFactory metricsFactory; @Before public void setUp() throws Exception { - metricsReporter = new InMemoryStatsReporter(); + metricsFactory = new InMemoryMetricsFactory(); tracer = new Tracer.Builder("TracerTestService", new InMemoryReporter(), new ConstSampler(true)) - .withStatsReporter(metricsReporter) + .withMetrics(new Metrics(metricsFactory)) .build(); } @@ -64,12 +67,10 @@ public void testBuildSpan() { public void testTracerMetrics() { String expectedOperation = "fry"; tracer.buildSpan(expectedOperation).start(); - assertEquals( - 1L, metricsReporter.counters.get("jaeger:started_spans.sampled=y").longValue()); - assertNull(metricsReporter.counters.get("jaeger:started_spans.sampled=n")); - assertEquals( - 1L, metricsReporter.counters.get("jaeger:traces.sampled=y.state=started").longValue()); - assertNull(metricsReporter.counters.get("jaeger:traces.sampled=n.state=started")); + assertEquals(1, metricsFactory.getCounter("jaeger:started_spans.sampled=y")); + assertEquals(0, metricsFactory.getCounter("jaeger:started_spans.sampled=n")); + assertEquals(1, metricsFactory.getCounter("jaeger:traces.sampled=y.state=started")); + assertEquals(0, metricsFactory.getCounter("jaeger:traces.sampled=n.state=started")); } @Test @@ -79,7 +80,7 @@ public void testRegisterInjector() { Tracer tracer = new Tracer.Builder("TracerTestService", new InMemoryReporter(), new ConstSampler(true)) - .withStatsReporter(metricsReporter) + .withMetrics(new Metrics(new InMemoryMetricsFactory())) .registerInjector(Format.Builtin.TEXT_MAP, injector) .build(); Span span = (Span) tracer.buildSpan("leela").start(); @@ -118,18 +119,15 @@ public void testBuilderIsNotServerRpc() { @Test public void testWithBaggageRestrictionManager() { - metricsReporter = new InMemoryStatsReporter(); - Metrics metrics = new Metrics(new StatsFactoryImpl(metricsReporter)); tracer = new Tracer.Builder("TracerTestService", new InMemoryReporter(), new ConstSampler(true)) - .withMetrics(metrics) + .withMetrics(new Metrics(metricsFactory)) .build(); Span span = (Span) tracer.buildSpan("some-operation").start(); final String key = "key"; tracer.setBaggage(span, key, "value"); - assertEquals( - 1L, metricsReporter.counters.get("jaeger:baggage_updates.result=ok").longValue()); + assertEquals(1, metricsFactory.getCounter("jaeger:baggage_updates.result=ok")); } @Test @@ -173,12 +171,9 @@ public void testSpanContextNotSampled() { Span first = (Span) tracer.buildSpan(expectedOperation).start(); tracer.buildSpan(expectedOperation).asChildOf(first.context().withFlags((byte) 0)).start(); - assertEquals( - 1L, metricsReporter.counters.get("jaeger:started_spans.sampled=y").longValue()); - assertEquals( - 1L, metricsReporter.counters.get("jaeger:started_spans.sampled=n").longValue()); - assertEquals( - 1L, metricsReporter.counters.get("jaeger:traces.sampled=y.state=started").longValue()); - assertNull(metricsReporter.counters.get("jaeger:traces.sampled=n.state=started")); + assertEquals(1, metricsFactory.getCounter("jaeger:started_spans.sampled=y")); + assertEquals(1, metricsFactory.getCounter("jaeger:started_spans.sampled=n")); + assertEquals(1, metricsFactory.getCounter("jaeger:traces.sampled=y.state=started")); + assertEquals(0, metricsFactory.getCounter("jaeger:traces.sampled=n.state=started")); } } diff --git a/jaeger-core/src/test/java/com/uber/jaeger/metrics/InMemoryMetricsFactoryTest.java b/jaeger-core/src/test/java/com/uber/jaeger/metrics/InMemoryMetricsFactoryTest.java new file mode 100644 index 000000000..d84068145 --- /dev/null +++ b/jaeger-core/src/test/java/com/uber/jaeger/metrics/InMemoryMetricsFactoryTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2017, The Jaeger Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License 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.uber.jaeger.metrics; + +import static org.junit.Assert.assertEquals; + +import com.uber.jaeger.Tracer; +import com.uber.jaeger.reporters.InMemoryReporter; +import com.uber.jaeger.samplers.ConstSampler; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; + +public class InMemoryMetricsFactoryTest { + + @Test + public void metricNameIsUsedForCounter() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + InMemoryMetricsFactory inMemoryMetricsFactory = new InMemoryMetricsFactory(); + inMemoryMetricsFactory.createCounter("thecounter", tags); + + assertEquals(-1, inMemoryMetricsFactory.getCounter("thecounter")); + assertEquals(0, inMemoryMetricsFactory.getCounter(Metrics.addTagsToMetricName("thecounter", tags))); + } + + @Test + public void counterValueIsIncreased() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + InMemoryMetricsFactory inMemoryMetricsFactory = new InMemoryMetricsFactory(); + Counter counter = inMemoryMetricsFactory.createCounter("thecounter", tags); + assertEquals(0, inMemoryMetricsFactory.getCounter(Metrics.addTagsToMetricName("thecounter", tags))); + + counter.inc(1); + + assertEquals(1, inMemoryMetricsFactory.getCounter(Metrics.addTagsToMetricName("thecounter", tags))); + } + + @Test + public void metricNameIsUsedForTimer() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + InMemoryMetricsFactory inMemoryMetricsFactory = new InMemoryMetricsFactory(); + inMemoryMetricsFactory.createTimer("thetimer", tags); + + assertEquals(-1, inMemoryMetricsFactory.getTimer("thetimer")); + assertEquals(0, inMemoryMetricsFactory.getTimer(Metrics.addTagsToMetricName("thetimer", tags))); + } + + @Test + public void timerValueIsIncreased() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + InMemoryMetricsFactory inMemoryMetricsFactory = new InMemoryMetricsFactory(); + Timer timer = inMemoryMetricsFactory.createTimer("thetimer", tags); + assertEquals(0, inMemoryMetricsFactory.getTimer(Metrics.addTagsToMetricName("thetimer", tags))); + + timer.durationMicros(1); + + assertEquals(1, inMemoryMetricsFactory.getTimer(Metrics.addTagsToMetricName("thetimer", tags))); + } + + @Test + public void metricNameIsUsedForGauge() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + InMemoryMetricsFactory inMemoryMetricsFactory = new InMemoryMetricsFactory(); + inMemoryMetricsFactory.createGauge("thegauge", tags); + + assertEquals(-1, inMemoryMetricsFactory.getGauge("thegauge")); + assertEquals(0, inMemoryMetricsFactory.getGauge(Metrics.addTagsToMetricName("thegauge", tags))); + } + + @Test + public void gaugeValueIsIncreased() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + InMemoryMetricsFactory inMemoryMetricsFactory = new InMemoryMetricsFactory(); + Gauge gauge = inMemoryMetricsFactory.createGauge("thegauge", tags); + assertEquals(0, inMemoryMetricsFactory.getGauge(Metrics.addTagsToMetricName("thegauge", tags))); + + gauge.update(1); + + assertEquals(1, inMemoryMetricsFactory.getGauge(Metrics.addTagsToMetricName("thegauge", tags))); + } + + @Test + public void canBeUsedWithMetrics() { + InMemoryMetricsFactory metricsFactory = new InMemoryMetricsFactory(); + Tracer tracer = + new Tracer.Builder("metricsFactoryTest", new InMemoryReporter(), new ConstSampler(true)) + .withMetrics(new Metrics(metricsFactory)) + .build(); + + tracer.buildSpan("theoperation").start(); + assertEquals(1, metricsFactory.getCounter("jaeger:started_spans.sampled=y")); + assertEquals(0, metricsFactory.getCounter("jaeger:started_spans.sampled=n")); + assertEquals(1, metricsFactory.getCounter("jaeger:traces.sampled=y.state=started")); + assertEquals(0, metricsFactory.getCounter("jaeger:traces.sampled=n.state=started")); + } +} diff --git a/jaeger-core/src/test/java/com/uber/jaeger/metrics/MetricsTest.java b/jaeger-core/src/test/java/com/uber/jaeger/metrics/MetricsTest.java index f4e42ae8d..9641f7359 100644 --- a/jaeger-core/src/test/java/com/uber/jaeger/metrics/MetricsTest.java +++ b/jaeger-core/src/test/java/com/uber/jaeger/metrics/MetricsTest.java @@ -16,61 +16,38 @@ import static org.junit.Assert.assertEquals; -import org.junit.After; +import java.util.HashMap; +import java.util.Map; import org.junit.Before; import org.junit.Test; public class MetricsTest { - InMemoryStatsReporter metricsReporter; + InMemoryMetricsFactory metricsFactory; Metrics metrics; @Before - public void setUp() throws Exception { - metricsReporter = new InMemoryStatsReporter(); - metrics = new Metrics(new StatsFactoryImpl(metricsReporter)); - } - - @After - public void tearDown() { - metricsReporter.reset(); + public void setUp() { + metricsFactory = new InMemoryMetricsFactory(); + metrics = new Metrics(metricsFactory); } @Test - public void testCounterWithoutExplicitTags() throws Exception { + public void testCounterWithoutExplicitTags() { metrics.tracesJoinedSampled.inc(1); - - Object[] metricNames = metricsReporter.counters.keySet().toArray(); - String metricName = (String) metricNames[0]; - long expectedAmount = metricsReporter.counters.get(metricName); - - assertEquals(metricNames.length, 1); - assertEquals(expectedAmount, 1); - assertEquals("jaeger:traces.sampled=y.state=joined", metricName); - } - - @Test - public void testCounterWithExplicitTags() throws Exception { - metrics.tracesJoinedSampled.inc(1); - - Object[] metricNames = metricsReporter.counters.keySet().toArray(); - String metricName = (String) metricNames[0]; - long expectedAmount = metricsReporter.counters.get(metricName); - - assertEquals(metricNames.length, 1); - assertEquals(expectedAmount, 1); - assertEquals("jaeger:traces.sampled=y.state=joined", metricName); + assertEquals(1, metricsFactory.getCounter("jaeger:traces.sampled=y.state=joined")); } @Test public void testGaugeWithoutExplicitTags() { metrics.reporterQueueLength.update(1); + assertEquals(1, metricsFactory.getGauge("jaeger:reporter_queue_length")); + } - Object[] metricNames = metricsReporter.gauges.keySet().toArray(); - String metricName = (String) metricNames[0]; - long expectedAmount = metricsReporter.gauges.get(metricName); - - assertEquals(metricNames.length, 1); - assertEquals(1L, expectedAmount, 0.00001); - assertEquals("jaeger:reporter_queue_length", metricName); + @Test + public void testAddTagsToMetricName() { + Map tags = new HashMap<>(); + tags.put("foo", "bar"); + assertEquals("thecounter.foo=bar", Metrics.addTagsToMetricName("thecounter", tags)); + assertEquals("jaeger:thecounter.foo=bar", Metrics.addTagsToMetricName("jaeger:thecounter", tags)); } } diff --git a/jaeger-core/src/test/java/com/uber/jaeger/metrics/NoopMetricsFactoryTest.java b/jaeger-core/src/test/java/com/uber/jaeger/metrics/NoopMetricsFactoryTest.java new file mode 100644 index 000000000..828b5bb5a --- /dev/null +++ b/jaeger-core/src/test/java/com/uber/jaeger/metrics/NoopMetricsFactoryTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017, The Jaeger Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License 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.uber.jaeger.metrics; + +import com.uber.jaeger.Tracer; +import com.uber.jaeger.reporters.InMemoryReporter; +import com.uber.jaeger.samplers.ConstSampler; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; + +/** + * This test is to ensure we have a NOOP implementation that won't crash when used for real. + * + * @see InMemoryMetricsFactoryTest + */ +public class NoopMetricsFactoryTest { + + @Test + public void metricNameIsUsedForCounter() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + NoopMetricsFactory metricsFactory = new NoopMetricsFactory(); + metricsFactory.createCounter("thecounter", tags); + } + + @Test + public void counterValueIsIncreased() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + NoopMetricsFactory metricsFactory = new NoopMetricsFactory(); + Counter counter = metricsFactory.createCounter("thecounter", tags); + counter.inc(1); + } + + @Test + public void metricNameIsUsedForTimer() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + NoopMetricsFactory metricsFactory = new NoopMetricsFactory(); + metricsFactory.createTimer("thetimer", tags); + } + + @Test + public void timerValueIsIncreased() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + NoopMetricsFactory metricsFactory = new NoopMetricsFactory(); + Timer timer = metricsFactory.createTimer("thetimer", tags); + timer.durationMicros(1); + } + + @Test + public void metricNameIsUsedForGauge() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + NoopMetricsFactory metricsFactory = new NoopMetricsFactory(); + metricsFactory.createGauge("thegauge", tags); + } + + @Test + public void gaugeValueIsIncreased() { + Map tags = new HashMap<>(1); + tags.put("foo", "bar"); + + NoopMetricsFactory metricsFactory = new NoopMetricsFactory(); + Gauge gauge = metricsFactory.createGauge("thegauge", tags); + gauge.update(1); + } + + @Test + public void canBeUsedWithMetrics() { + NoopMetricsFactory metricsFactory = new NoopMetricsFactory(); + Tracer tracer = + new Tracer.Builder("metricsFactoryTest", new InMemoryReporter(), new ConstSampler(true)) + .withMetrics(new Metrics(metricsFactory)) + .build(); + + tracer.buildSpan("theoperation").start(); + } +} diff --git a/jaeger-dropwizard/src/main/java/com/uber/jaeger/dropwizard/Configuration.java b/jaeger-dropwizard/src/main/java/com/uber/jaeger/dropwizard/Configuration.java index f5f9189f2..97b625cfa 100644 --- a/jaeger-dropwizard/src/main/java/com/uber/jaeger/dropwizard/Configuration.java +++ b/jaeger-dropwizard/src/main/java/com/uber/jaeger/dropwizard/Configuration.java @@ -47,6 +47,6 @@ public synchronized Tracer getTracer() { } public void setMetricRegistry(MetricRegistry metricRegistry) { - setStatsFactory(new StatsFactory(metricRegistry)); + setMetricsFactory(new StatsFactory(metricRegistry)); } } diff --git a/jaeger-dropwizard/src/main/java/com/uber/jaeger/dropwizard/StatsFactory.java b/jaeger-dropwizard/src/main/java/com/uber/jaeger/dropwizard/StatsFactory.java index 10d6c9bca..894f14a6e 100644 --- a/jaeger-dropwizard/src/main/java/com/uber/jaeger/dropwizard/StatsFactory.java +++ b/jaeger-dropwizard/src/main/java/com/uber/jaeger/dropwizard/StatsFactory.java @@ -17,10 +17,11 @@ import com.codahale.metrics.MetricRegistry; import com.uber.jaeger.metrics.Counter; import com.uber.jaeger.metrics.Gauge; +import com.uber.jaeger.metrics.MetricsFactory; import com.uber.jaeger.metrics.Timer; import java.util.Map; -public class StatsFactory implements com.uber.jaeger.metrics.StatsFactory { +public class StatsFactory implements MetricsFactory { private final MetricRegistry registry; public StatsFactory(MetricRegistry registry) {