Merge "Adding Histogram and Timer support" from Amnon

"This series modified the Histogram support to get all of its statistic from the
 API.  By doing that not only the sample will be accurate but also the on going
 statistics of count, sum, min, max mean and std.

 It also adds a Timer support, Timer are defined in the yammer library and uses
 a Histogram that is been updated regularly.  The Timer implementation in the
 series would use the APITimer that uses the API.

 Current code that uses Timer and Histogram was modified to use the updated
 implementation with a URL."
This commit is contained in:
Pekka Enberg 2015-07-28 11:29:42 +03:00
commit 975de276b1
9 changed files with 435 additions and 136 deletions

View File

@ -31,6 +31,7 @@ import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder; import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.yammer.metrics.core.HistogramValues;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
@ -485,4 +486,37 @@ public class APIClient {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }
public JsonObject getJsonObj(String string,
MultivaluedMap<String, String> queryParams) {
if (string.equals("")) {
return null;
}
JsonReader reader = getReader(string, queryParams);
JsonObject res = reader.readObject();
reader.close();
return res;
}
public HistogramValues getHistogramValue(String url,
MultivaluedMap<String, String> queryParams) {
HistogramValues res = new HistogramValues();
JsonObject obj = getJsonObj(url, queryParams);
res.count = obj.getJsonNumber("count").longValue();
res.max = obj.getJsonNumber("max").longValue();
res.min = obj.getJsonNumber("min").longValue();
res.sum = obj.getJsonNumber("sum").longValue();
res.variance = obj.getJsonNumber("variance").doubleValue();
res.svariance = obj.getJsonNumber("svariance").doubleValue();
JsonArray arr = obj.getJsonArray("sample");
res.sample = new long[arr.size()];
for (int i = 0; i < arr.size(); i++) {
res.sample[i] = arr.getJsonNumber(i).longValue();
}
return res;
}
public HistogramValues getHistogramValue(String url) {
return getHistogramValue(url, null);
}
} }

View File

@ -14,6 +14,7 @@ import com.yammer.metrics.core.Gauge;
import com.yammer.metrics.core.Histogram; import com.yammer.metrics.core.Histogram;
import com.yammer.metrics.core.Meter; import com.yammer.metrics.core.Meter;
import com.yammer.metrics.core.MetricName; import com.yammer.metrics.core.MetricName;
import com.yammer.metrics.core.APITimer;
import com.yammer.metrics.core.Timer; import com.yammer.metrics.core.Timer;
import com.yammer.metrics.reporting.JmxReporter; import com.yammer.metrics.reporting.JmxReporter;
@ -288,7 +289,7 @@ public class APIMetrics {
} }
/** /**
* Creates a new {@link com.yammer.metrics.core.Timer} and registers it * Creates a new {@link com.yammer.metrics.core.APITimer} and registers it
* under the given class and name. * under the given class and name.
* *
* @param klass * @param klass
@ -299,15 +300,15 @@ public class APIMetrics {
* the duration scale unit of the new timer * the duration scale unit of the new timer
* @param rateUnit * @param rateUnit
* the rate scale unit of the new timer * the rate scale unit of the new timer
* @return a new {@link com.yammer.metrics.core.Timer} * @return a new {@link com.yammer.metrics.core.APITimer}
*/ */
public static Timer newTimer(Class<?> klass, String name, public static Timer newTimer(String url, Class<?> klass, String name,
TimeUnit durationUnit, TimeUnit rateUnit) { TimeUnit durationUnit, TimeUnit rateUnit) {
return DEFAULT_REGISTRY.newTimer(klass, name, durationUnit, rateUnit); return DEFAULT_REGISTRY.newTimer(url, klass, name, durationUnit, rateUnit);
} }
/** /**
* Creates a new {@link com.yammer.metrics.core.Timer} and registers it * Creates a new {@link com.yammer.metrics.core.APITimer} and registers it
* under the given class and name, measuring elapsed time in milliseconds * under the given class and name, measuring elapsed time in milliseconds
* and invocations per second. * and invocations per second.
* *
@ -315,14 +316,14 @@ public class APIMetrics {
* the class which owns the metric * the class which owns the metric
* @param name * @param name
* the name of the metric * the name of the metric
* @return a new {@link com.yammer.metrics.core.Timer} * @return a new {@link com.yammer.metrics.core.APITimer}
*/ */
public static Timer newTimer(Class<?> klass, String name) { public static Timer newTimer(String url, Class<?> klass, String name) {
return DEFAULT_REGISTRY.newTimer(klass, name); return DEFAULT_REGISTRY.newTimer(url, klass, name);
} }
/** /**
* Creates a new {@link com.yammer.metrics.core.Timer} and registers it * Creates a new {@link com.yammer.metrics.core.APITimer} and registers it
* under the given class, name, and scope. * under the given class, name, and scope.
* *
* @param klass * @param klass
@ -335,16 +336,16 @@ public class APIMetrics {
* the duration scale unit of the new timer * the duration scale unit of the new timer
* @param rateUnit * @param rateUnit
* the rate scale unit of the new timer * the rate scale unit of the new timer
* @return a new {@link com.yammer.metrics.core.Timer} * @return a new {@link com.yammer.metrics.core.APITimer}
*/ */
public static Timer newTimer(Class<?> klass, String name, String scope, public static Timer newTimer(String url, Class<?> klass, String name, String scope,
TimeUnit durationUnit, TimeUnit rateUnit) { TimeUnit durationUnit, TimeUnit rateUnit) {
return DEFAULT_REGISTRY.newTimer(klass, name, scope, durationUnit, return DEFAULT_REGISTRY.newTimer(url, klass, name, scope, durationUnit,
rateUnit); rateUnit);
} }
/** /**
* Creates a new {@link com.yammer.metrics.core.Timer} and registers it * Creates a new {@link com.yammer.metrics.core.APITimer} and registers it
* under the given class, name, and scope, measuring elapsed time in * under the given class, name, and scope, measuring elapsed time in
* milliseconds and invocations per second. * milliseconds and invocations per second.
* *
@ -354,14 +355,14 @@ public class APIMetrics {
* the name of the metric * the name of the metric
* @param scope * @param scope
* the scope of the metric * the scope of the metric
* @return a new {@link com.yammer.metrics.core.Timer} * @return a new {@link com.yammer.metrics.core.APITimer}
*/ */
public static Timer newTimer(Class<?> klass, String name, String scope) { public static Timer newTimer(String url, Class<?> klass, String name, String scope) {
return DEFAULT_REGISTRY.newTimer(klass, name, scope); return DEFAULT_REGISTRY.newTimer(url, klass, name, scope);
} }
/** /**
* Creates a new {@link com.yammer.metrics.core.Timer} and registers it * Creates a new {@link com.yammer.metrics.core.APITimer} and registers it
* under the given metric name. * under the given metric name.
* *
* @param metricName * @param metricName
@ -370,11 +371,11 @@ public class APIMetrics {
* the duration scale unit of the new timer * the duration scale unit of the new timer
* @param rateUnit * @param rateUnit
* the rate scale unit of the new timer * the rate scale unit of the new timer
* @return a new {@link com.yammer.metrics.core.Timer} * @return a new {@link com.yammer.metrics.core.APITimer}
*/ */
public static Timer newTimer(MetricName metricName, TimeUnit durationUnit, public static Timer newTimer(String url, MetricName metricName, TimeUnit durationUnit,
TimeUnit rateUnit) { TimeUnit rateUnit) {
return DEFAULT_REGISTRY.newTimer(metricName, durationUnit, rateUnit); return DEFAULT_REGISTRY.newTimer(url, metricName, durationUnit, rateUnit);
} }
/** /**

View File

@ -6,24 +6,93 @@ package com.yammer.metrics.core;
* Modified by Cloudius Systems * Modified by Cloudius Systems
*/ */
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import com.cloudius.urchin.api.APIClient; import com.cloudius.urchin.api.APIClient;
import com.yammer.metrics.stats.Sample; import com.yammer.metrics.stats.Sample;
import com.yammer.metrics.stats.Snapshot; import com.yammer.metrics.stats.Snapshot;
public class APIHistogram extends Histogram { public class APIHistogram extends Histogram {
Field countField;
Field minField;
Field maxField;
Field sumField;
Field varianceField;
Field sampleField;
long last_update = 0; long last_update = 0;
static final long UPDATE_INTERVAL = 50; static final long UPDATE_INTERVAL = 50;
long updateInterval;
String url; String url;
private APIClient c = new APIClient(); private APIClient c = new APIClient();
public APIHistogram(String _url, Sample sample) { private void setFields() {
super(sample); try {
url = _url; minField = Histogram.class.getDeclaredField("min");
minField.setAccessible(true);
maxField = Histogram.class.getDeclaredField("max");
maxField.setAccessible(true);
sumField = Histogram.class.getDeclaredField("sum");
sumField.setAccessible(true);
varianceField = Histogram.class.getDeclaredField("variance");
varianceField.setAccessible(true);
sampleField = Histogram.class.getDeclaredField("sample");
sampleField.setAccessible(true);
countField = Histogram.class.getDeclaredField("count");
countField.setAccessible(true);
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
} }
public APIHistogram(String _url, SampleType type) { public AtomicLong getMin() throws IllegalArgumentException,
IllegalAccessException {
return (AtomicLong) minField.get(this);
}
public AtomicLong getMax() throws IllegalArgumentException,
IllegalAccessException {
return (AtomicLong) maxField.get(this);
}
public AtomicLong getSum() throws IllegalArgumentException,
IllegalAccessException {
return (AtomicLong) sumField.get(this);
}
public AtomicLong getCount() throws IllegalArgumentException,
IllegalAccessException {
return (AtomicLong) countField.get(this);
}
@SuppressWarnings("unchecked")
public AtomicReference<double[]> getVariance()
throws IllegalArgumentException, IllegalAccessException {
return (AtomicReference<double[]>) varianceField.get(this);
}
public Sample getSample() throws IllegalArgumentException,
IllegalAccessException {
return (Sample) sampleField.get(this);
}
public APIHistogram(String url, Sample sample) {
super(sample);
setFields();
this.url = url;
}
public APIHistogram(String url, SampleType type, long updateInterval) {
super(type); super(type);
url = _url; setFields();
this.url = url;
this.updateInterval = updateInterval;
}
public APIHistogram(String url, SampleType type) {
this(url, type, UPDATE_INTERVAL);
} }
public void update() { public void update() {
@ -33,9 +102,21 @@ public class APIHistogram extends Histogram {
} }
last_update = now; last_update = now;
clear(); clear();
long[] vals = c.getLongArrValue(url); HistogramValues vals = c.getHistogramValue(url);
for (long v : vals) { try {
update(v); for (long v : vals.sample) {
getSample().update(v);
}
getCount().set(vals.count);
getMax().set(vals.max);
getMin().set(vals.min);
getSum().set(vals.sum);
double[] newValue = new double[2];
newValue[0] = vals.variance;
newValue[1] = vals.svariance;
getVariance().getAndSet(newValue);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
} }
} }

View File

@ -23,18 +23,19 @@ import com.yammer.metrics.core.Histogram.SampleType;
*/ */
public class APIMetricsRegistry extends MetricsRegistry { public class APIMetricsRegistry extends MetricsRegistry {
Field field_metrics; Field fieldMetrics;
Field field_clock; Field fieldClock;
Field field_thread_pool; Field fieldThreadPool;
public APIMetricsRegistry() { public APIMetricsRegistry() {
try { try {
field_metrics = MetricsRegistry.class.getDeclaredField("metrics"); fieldMetrics = MetricsRegistry.class.getDeclaredField("metrics");
field_metrics.setAccessible(true); fieldMetrics.setAccessible(true);
field_clock = MetricsRegistry.class.getDeclaredField("clock"); fieldClock = MetricsRegistry.class.getDeclaredField("clock");
field_clock.setAccessible(true); fieldClock.setAccessible(true);
field_thread_pool = MetricsRegistry.class.getDeclaredField("threadPools"); fieldThreadPool = MetricsRegistry.class
field_thread_pool.setAccessible(true); .getDeclaredField("threadPools");
fieldThreadPool.setAccessible(true);
} catch (NoSuchFieldException | SecurityException e) { } catch (NoSuchFieldException | SecurityException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
@ -43,192 +44,319 @@ public class APIMetricsRegistry extends MetricsRegistry {
public ThreadPools getThreadPools() { public ThreadPools getThreadPools() {
try { try {
return (ThreadPools)field_thread_pool.get(this); return (ThreadPools) fieldThreadPool.get(this);
} catch (IllegalArgumentException | IllegalAccessException e) { } catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
public Clock getClock() { public Clock getClock() {
try { try {
return (Clock)field_clock.get(this); return (Clock) fieldClock.get(this);
} catch (IllegalArgumentException | IllegalAccessException e) { } catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public ConcurrentMap<MetricName, Metric> get_metrics() { public ConcurrentMap<MetricName, Metric> getMetrics() {
try { try {
return (ConcurrentMap<MetricName, Metric>)field_metrics.get(this); return (ConcurrentMap<MetricName, Metric>) fieldMetrics.get(this);
} catch (IllegalArgumentException | IllegalAccessException e) { } catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
/** /**
* Creates a new {@link Counter} and registers it under the given class and name. * Creates a new {@link Counter} and registers it under the given class and
* name.
* *
* @param klass the class which owns the metric * @param klass
* @param name the name of the metric * the class which owns the metric
* @param name
* the name of the metric
* @return a new {@link Counter} * @return a new {@link Counter}
*/ */
public Counter newCounter(String url, Class<?> klass, public Counter newCounter(String url, Class<?> klass, String name) {
String name) {
return newCounter(url, klass, name, null); return newCounter(url, klass, name, null);
} }
/** /**
* Creates a new {@link Counter} and registers it under the given class and name. * Creates a new {@link Counter} and registers it under the given class and
* name.
* *
* @param klass the class which owns the metric * @param klass
* @param name the name of the metric * the class which owns the metric
* @param scope the scope of the metric * @param name
* the name of the metric
* @param scope
* the scope of the metric
* @return a new {@link Counter} * @return a new {@link Counter}
*/ */
public Counter newCounter(String url, Class<?> klass, public Counter newCounter(String url, Class<?> klass, String name,
String name, String scope) {
String scope) {
return newCounter(url, createName(klass, name, scope)); return newCounter(url, createName(klass, name, scope));
} }
/** /**
* Creates a new {@link Counter} and registers it under the given metric name. * Creates a new {@link Counter} and registers it under the given metric
* name.
* *
* @param metricName the name of the metric * @param metricName
* the name of the metric
* @return a new {@link Counter} * @return a new {@link Counter}
*/ */
public Counter newCounter(String url, MetricName metricName) { public Counter newCounter(String url, MetricName metricName) {
return getOrAdd(metricName, new APICounter(url)); return getOrAdd(metricName, new APICounter(url));
} }
/** /**
* Creates a new {@link Meter} and registers it under the given class and name. * Creates a new {@link Meter} and registers it under the given class and
* name.
* *
* @param klass the class which owns the metric * @param klass
* @param name the name of the metric * the class which owns the metric
* @param eventType the plural name of the type of events the meter is measuring (e.g., {@code * @param name
* "requests"}) * the name of the metric
* @param unit the rate unit of the new meter * @param eventType
* the plural name of the type of events the meter is measuring
* (e.g., {@code "requests"})
* @param unit
* the rate unit of the new meter
* @return a new {@link Meter} * @return a new {@link Meter}
*/ */
public Meter newMeter(String url, Class<?> klass, public Meter newMeter(String url, Class<?> klass, String name,
String name, String eventType, TimeUnit unit) {
String eventType,
TimeUnit unit) {
return newMeter(url, klass, name, null, eventType, unit); return newMeter(url, klass, name, null, eventType, unit);
} }
/** /**
* Creates a new {@link Meter} and registers it under the given class, name, and scope. * Creates a new {@link Meter} and registers it under the given class, name,
* and scope.
* *
* @param klass the class which owns the metric * @param klass
* @param name the name of the metric * the class which owns the metric
* @param scope the scope of the metric * @param name
* @param eventType the plural name of the type of events the meter is measuring (e.g., {@code * the name of the metric
* "requests"}) * @param scope
* @param unit the rate unit of the new meter * the scope of the metric
* @param eventType
* the plural name of the type of events the meter is measuring
* (e.g., {@code "requests"})
* @param unit
* the rate unit of the new meter
* @return a new {@link Meter} * @return a new {@link Meter}
*/ */
public Meter newMeter(String url, public Meter newMeter(String url, Class<?> klass, String name,
Class<?> klass, String scope, String eventType, TimeUnit unit) {
String name,
String scope,
String eventType,
TimeUnit unit) {
return newMeter(url, createName(klass, name, scope), eventType, unit); return newMeter(url, createName(klass, name, scope), eventType, unit);
} }
private ScheduledExecutorService newMeterTickThreadPool() { private ScheduledExecutorService newMeterTickThreadPool() {
return getThreadPools().newScheduledThreadPool(2, "meter-tick"); return getThreadPools().newScheduledThreadPool(2, "meter-tick");
} }
/** /**
* Creates a new {@link Meter} and registers it under the given metric name. * Creates a new {@link Meter} and registers it under the given metric name.
* *
* @param metricName the name of the metric * @param metricName
* @param eventType the plural name of the type of events the meter is measuring (e.g., {@code * the name of the metric
* "requests"}) * @param eventType
* @param unit the rate unit of the new meter * the plural name of the type of events the meter is measuring
* (e.g., {@code "requests"})
* @param unit
* the rate unit of the new meter
* @return a new {@link Meter} * @return a new {@link Meter}
*/ */
public Meter newMeter(String url, MetricName metricName, public Meter newMeter(String url, MetricName metricName, String eventType,
String eventType, TimeUnit unit) {
TimeUnit unit) { final Metric existingMetric = getMetrics().get(metricName);
final Metric existingMetric = get_metrics().get(metricName);
if (existingMetric != null) { if (existingMetric != null) {
return (Meter) existingMetric; return (Meter) existingMetric;
} }
return getOrAdd(metricName, new APIMeter(url, newMeterTickThreadPool(), eventType, unit, getClock())); return getOrAdd(metricName, new APIMeter(url, newMeterTickThreadPool(),
eventType, unit, getClock()));
} }
/** /**
* Creates a new {@link Histogram} and registers it under the given class and name. * Creates a new {@link Histogram} and registers it under the given class
* and name.
* *
* @param klass the class which owns the metric * @param klass
* @param name the name of the metric * the class which owns the metric
* @param biased whether or not the histogram should be biased * @param name
* the name of the metric
* @param biased
* whether or not the histogram should be biased
* @return a new {@link Histogram} * @return a new {@link Histogram}
*/ */
public Histogram newHistogram(String url, Class<?> klass, public Histogram newHistogram(String url, Class<?> klass, String name,
String name, boolean biased) {
boolean biased) {
return newHistogram(url, klass, name, null, biased); return newHistogram(url, klass, name, null, biased);
} }
/** /**
* Creates a new {@link Histogram} and registers it under the given class, name, and scope. * Creates a new {@link Histogram} and registers it under the given class,
* name, and scope.
* *
* @param klass the class which owns the metric * @param klass
* @param name the name of the metric * the class which owns the metric
* @param scope the scope of the metric * @param name
* @param biased whether or not the histogram should be biased * the name of the metric
* @param scope
* the scope of the metric
* @param biased
* whether or not the histogram should be biased
* @return a new {@link Histogram} * @return a new {@link Histogram}
*/ */
public Histogram newHistogram(String url, Class<?> klass, public Histogram newHistogram(String url, Class<?> klass, String name,
String name, String scope, boolean biased) {
String scope,
boolean biased) {
return newHistogram(url, createName(klass, name, scope), biased); return newHistogram(url, createName(klass, name, scope), biased);
} }
/** /**
* Creates a new non-biased {@link Histogram} and registers it under the given class and name. * Creates a new non-biased {@link Histogram} and registers it under the
* given class and name.
* *
* @param klass the class which owns the metric * @param klass
* @param name the name of the metric * the class which owns the metric
* @param name
* the name of the metric
* @return a new {@link Histogram} * @return a new {@link Histogram}
*/ */
public Histogram newHistogram(String url, Class<?> klass, public Histogram newHistogram(String url, Class<?> klass, String name) {
String name) {
return newHistogram(url, klass, name, false); return newHistogram(url, klass, name, false);
} }
/** /**
* Creates a new non-biased {@link Histogram} and registers it under the given class, name, and * Creates a new non-biased {@link Histogram} and registers it under the
* scope. * given class, name, and scope.
* *
* @param klass the class which owns the metric * @param klass
* @param name the name of the metric * the class which owns the metric
* @param scope the scope of the metric * @param name
* the name of the metric
* @param scope
* the scope of the metric
* @return a new {@link Histogram} * @return a new {@link Histogram}
*/ */
public Histogram newHistogram(String url, Class<?> klass, public Histogram newHistogram(String url, Class<?> klass, String name,
String name, String scope) {
String scope) {
return newHistogram(url, klass, name, scope, false); return newHistogram(url, klass, name, scope, false);
} }
/** /**
* Creates a new {@link Histogram} and registers it under the given metric name. * Creates a new {@link Histogram} and registers it under the given metric
* name.
* *
* @param metricName the name of the metric * @param metricName
* @param biased whether or not the histogram should be biased * the name of the metric
* @param biased
* whether or not the histogram should be biased
* @return a new {@link Histogram} * @return a new {@link Histogram}
*/ */
public Histogram newHistogram(String url, MetricName metricName, public Histogram newHistogram(String url, MetricName metricName,
boolean biased) { boolean biased) {
return getOrAdd(metricName, return getOrAdd(metricName, new APIHistogram(url,
new APIHistogram(url, biased ? SampleType.BIASED : SampleType.UNIFORM)); biased ? SampleType.BIASED : SampleType.UNIFORM));
} }
/**
* Creates a new {@link Timer} and registers it under the given class and
* name, measuring elapsed time in milliseconds and invocations per second.
*
* @param klass
* the class which owns the metric
* @param name
* the name of the metric
* @return a new {@link Timer}
*/
public Timer newTimer(String url, Class<?> klass, String name) {
return newTimer(url, klass, name, null, TimeUnit.MILLISECONDS,
TimeUnit.SECONDS);
}
/**
* Creates a new {@link Timer} and registers it under the given class and
* name.
*
* @param klass
* the class which owns the metric
* @param name
* the name of the metric
* @param durationUnit
* the duration scale unit of the new timer
* @param rateUnit
* the rate scale unit of the new timer
* @return a new {@link Timer}
*/
public Timer newTimer(String url, Class<?> klass, String name,
TimeUnit durationUnit, TimeUnit rateUnit) {
return newTimer(url, klass, name, null, durationUnit, rateUnit);
}
/**
* Creates a new {@link Timer} and registers it under the given class, name,
* and scope, measuring elapsed time in milliseconds and invocations per
* second.
*
* @param klass
* the class which owns the metric
* @param name
* the name of the metric
* @param scope
* the scope of the metric
* @return a new {@link Timer}
*/
public Timer newTimer(String url, Class<?> klass, String name, String scope) {
return newTimer(url, klass, name, scope, TimeUnit.MILLISECONDS,
TimeUnit.SECONDS);
}
/**
* Creates a new {@link Timer} and registers it under the given class, name,
* and scope.
*
* @param klass
* the class which owns the metric
* @param name
* the name of the metric
* @param scope
* the scope of the metric
* @param durationUnit
* the duration scale unit of the new timer
* @param rateUnit
* the rate scale unit of the new timer
* @return a new {@link Timer}
*/
public Timer newTimer(String url, Class<?> klass, String name,
String scope, TimeUnit durationUnit, TimeUnit rateUnit) {
return newTimer(url, createName(klass, name, scope), durationUnit,
rateUnit);
}
/**
* Creates a new {@link Timer} and registers it under the given metric name.
*
* @param metricName
* the name of the metric
* @param durationUnit
* the duration scale unit of the new timer
* @param rateUnit
* the rate scale unit of the new timer
* @return a new {@link Timer}
*/
public Timer newTimer(String url, MetricName metricName,
TimeUnit durationUnit, TimeUnit rateUnit) {
final Metric existingMetric = getMetrics().get(metricName);
if (existingMetric != null) {
return (Timer) existingMetric;
}
return getOrAdd(metricName, new APITimer(url, newMeterTickThreadPool(),
durationUnit, rateUnit, getClock()));
}
} }

View File

@ -0,0 +1,44 @@
/*
* Copyright 2015 Cloudius Systems
*
*/
package com.yammer.metrics.core;
import java.lang.reflect.Field;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.yammer.metrics.core.Histogram.SampleType;
/**
* A timer metric which aggregates timing durations and provides duration
* statistics, plus throughput statistics via {@link Meter}.
*/
public class APITimer extends Timer {
public APITimer(String url, ScheduledExecutorService tickThread,
TimeUnit durationUnit, TimeUnit rateUnit) {
super(tickThread, durationUnit, rateUnit);
setHistogram(url);
}
public APITimer(String url, ScheduledExecutorService tickThread,
TimeUnit durationUnit, TimeUnit rateUnit, Clock clock) {
super(tickThread, durationUnit, rateUnit, clock);
setHistogram(url);
}
private void setHistogram(String url) {
Field histogram;
try {
histogram = Timer.class.getDeclaredField("histogram");
histogram.setAccessible(true);
histogram.set(this, new APIHistogram(url, SampleType.BIASED));
} catch (NoSuchFieldException | SecurityException
| IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,11 @@
package com.yammer.metrics.core;
public class HistogramValues {
public long count;
public long min;
public long max;
public long sum;
public double variance;
public double svariance;
public long sample[];
}

View File

@ -325,13 +325,13 @@ public class ColumnFamilyMetrics {
colUpdateTimeDeltaHistogram = createColumnFamilyHistogram( colUpdateTimeDeltaHistogram = createColumnFamilyHistogram(
"/column_family/metrics/col_update_time_delta_histogram", "/column_family/metrics/col_update_time_delta_histogram",
"ColUpdateTimeDeltaHistogram"); "ColUpdateTimeDeltaHistogram");
coordinatorReadLatency = Metrics.newTimer( coordinatorReadLatency = APIMetrics.newTimer("/column_family/metrics/coordinator/read/" + cfName,
factory.createMetricName("CoordinatorReadLatency"), factory.createMetricName("CoordinatorReadLatency"),
TimeUnit.MICROSECONDS, TimeUnit.SECONDS); TimeUnit.MICROSECONDS, TimeUnit.SECONDS);
coordinatorScanLatency = Metrics.newTimer( coordinatorScanLatency = APIMetrics.newTimer("/column_family/metrics/coordinator/scan/" + cfName,
factory.createMetricName("CoordinatorScanLatency"), factory.createMetricName("CoordinatorScanLatency"),
TimeUnit.MICROSECONDS, TimeUnit.SECONDS); TimeUnit.MICROSECONDS, TimeUnit.SECONDS);
waitingOnFreeMemtableSpace = Metrics.newTimer( waitingOnFreeMemtableSpace = APIMetrics.newTimer("/column_family/metrics/waiting_on_free_memtable/" + cfName,
factory.createMetricName("WaitingOnFreeMemtableSpace"), factory.createMetricName("WaitingOnFreeMemtableSpace"),
TimeUnit.MICROSECONDS, TimeUnit.SECONDS); TimeUnit.MICROSECONDS, TimeUnit.SECONDS);

View File

@ -77,10 +77,10 @@ public class CommitLogMetrics {
return c.getLongValue("/commitlog/metrics/total_commit_log_size"); return c.getLongValue("/commitlog/metrics/total_commit_log_size");
} }
}); });
waitingOnSegmentAllocation = APIMetrics.newTimer( waitingOnSegmentAllocation = APIMetrics.newTimer("/commit_log/metrics/waiting_on_segment_allocation",
factory.createMetricName("WaitingOnSegmentAllocation"), factory.createMetricName("WaitingOnSegmentAllocation"),
TimeUnit.MICROSECONDS, TimeUnit.SECONDS); TimeUnit.MICROSECONDS, TimeUnit.SECONDS);
waitingOnCommit = APIMetrics.newTimer( waitingOnCommit = APIMetrics.newTimer("/commit_log/metrics/waiting_on_commit",
factory.createMetricName("WaitingOnCommit"), factory.createMetricName("WaitingOnCommit"),
TimeUnit.MICROSECONDS, TimeUnit.SECONDS); TimeUnit.MICROSECONDS, TimeUnit.SECONDS);
} }

View File

@ -95,7 +95,7 @@ public class LatencyMetrics {
this.factory = factory; this.factory = factory;
this.namePrefix = namePrefix; this.namePrefix = namePrefix;
latency = APIMetrics.newTimer( latency = APIMetrics.newTimer(url + "/histogram",
factory.createMetricName(namePrefix + "Latency"), factory.createMetricName(namePrefix + "Latency"),
TimeUnit.MICROSECONDS, TimeUnit.SECONDS); TimeUnit.MICROSECONDS, TimeUnit.SECONDS);
totalLatency = APIMetrics.newCounter(url, totalLatency = APIMetrics.newCounter(url,