diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..4fe83de --- /dev/null +++ b/NOTICE @@ -0,0 +1,11 @@ +Metrics +Copyright 2010-2013 Coda Hale and Yammer, Inc. + +This product includes software developed by Coda Hale and Yammer, Inc. + +This product includes code derived from the JSR-166 project (ThreadLocalRandom, Striped64, +LongAdder), which was released with the following comments: + + Written by Doug Lea with assistance from members of JCP JSR-166 + Expert Group and released to the public domain, as explained at + http://creativecommons.org/publicdomain/zero/1.0/ diff --git a/pom.xml b/pom.xml index 064814f..8e62694 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,16 @@ guava 18.0 + + com.yammer.metrics + metrics-core + 2.2.0 + + + com.google.collections + google-collections + 1.0 + diff --git a/src/main/java/com/cloudius/urchin/metrics/APIMetrics.java b/src/main/java/com/cloudius/urchin/metrics/APIMetrics.java new file mode 100644 index 0000000..380e136 --- /dev/null +++ b/src/main/java/com/cloudius/urchin/metrics/APIMetrics.java @@ -0,0 +1,397 @@ +package com.cloudius.urchin.metrics; + +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ + +import java.util.concurrent.TimeUnit; + +import com.yammer.metrics.core.APIMetricsRegistry; +import com.yammer.metrics.core.Counter; +import com.yammer.metrics.core.Gauge; +import com.yammer.metrics.core.Histogram; +import com.yammer.metrics.core.Meter; +import com.yammer.metrics.core.MetricName; +import com.yammer.metrics.core.Timer; +import com.yammer.metrics.reporting.JmxReporter; + +public class APIMetrics { + private static final APIMetricsRegistry DEFAULT_REGISTRY = new APIMetricsRegistry(); + private static final Thread SHUTDOWN_HOOK = new Thread() { + public void run() { + JmxReporter.shutdownDefault(); + } + }; + + static { + JmxReporter.startDefault(DEFAULT_REGISTRY); + Runtime.getRuntime().addShutdownHook(SHUTDOWN_HOOK); + } + + private APIMetrics() { /* unused */ + } + + /** + * Given a new {@link com.yammer.metrics.core.Gauge}, registers it under the + * given class and name. + * + * @param klass + * the class which owns the metric + * @param name + * the name of the metric + * @param metric + * the metric + * @param + * the type of the value returned by the metric + * @return {@code metric} + */ + public static Gauge newGauge(Class klass, String name, + Gauge metric) { + return DEFAULT_REGISTRY.newGauge(klass, name, metric); + } + + /** + * Given a new {@link com.yammer.metrics.core.Gauge}, registers it under the + * given class and name. + * + * @param klass + * the class which owns the metric + * @param name + * the name of the metric + * @param scope + * the scope of the metric + * @param metric + * the metric + * @param + * the type of the value returned by the metric + * @return {@code metric} + */ + public static Gauge newGauge(Class klass, String name, + String scope, Gauge metric) { + return DEFAULT_REGISTRY.newGauge(klass, name, scope, metric); + } + + /** + * Given a new {@link com.yammer.metrics.core.Gauge}, registers it under the + * given metric name. + * + * @param metricName + * the name of the metric + * @param metric + * the metric + * @param + * the type of the value returned by the metric + * @return {@code metric} + */ + public static Gauge newGauge(MetricName metricName, Gauge metric) { + return DEFAULT_REGISTRY.newGauge(metricName, metric); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Counter} and registers it + * under the given class and name. + * + * @param klass + * the class which owns the metric + * @param name + * the name of the metric + * @return a new {@link com.yammer.metrics.core.Counter} + */ + public static Counter newCounter(String url, Class klass, String name) { + return DEFAULT_REGISTRY.newCounter(url, klass, name); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Counter} 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 scope + * the scope of the metric + * @return a new {@link com.yammer.metrics.core.Counter} + */ + public static Counter newCounter(String url, Class klass, String name, + String scope) { + return DEFAULT_REGISTRY.newCounter(url, klass, name, scope); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Counter} and registers it + * under the given metric name. + * + * @param metricName + * the name of the metric + * @return a new {@link com.yammer.metrics.core.Counter} + */ + public static Counter newCounter(String url, MetricName metricName) { + return DEFAULT_REGISTRY.newCounter(url, metricName); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Histogram} 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 biased + * whether or not the histogram should be biased + * @return a new {@link com.yammer.metrics.core.Histogram} + */ + public static Histogram newHistogram(Class klass, String name, + boolean biased) { + return DEFAULT_REGISTRY.newHistogram(klass, name, biased); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Histogram} 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 biased + * whether or not the histogram should be biased + * @return a new {@link com.yammer.metrics.core.Histogram} + */ + public static Histogram newHistogram(Class klass, String name, + String scope, boolean biased) { + return DEFAULT_REGISTRY.newHistogram(klass, name, scope, biased); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Histogram} and registers it + * under the given metric name. + * + * @param metricName + * the name of the metric + * @param biased + * whether or not the histogram should be biased + * @return a new {@link com.yammer.metrics.core.Histogram} + */ + public static Histogram newHistogram(MetricName metricName, boolean biased) { + return DEFAULT_REGISTRY.newHistogram(metricName, biased); + } + + /** + * Creates a new non-biased {@link com.yammer.metrics.core.Histogram} and + * registers it under the given class and name. + * + * @param klass + * the class which owns the metric + * @param name + * the name of the metric + * @return a new {@link com.yammer.metrics.core.Histogram} + */ + public static Histogram newHistogram(Class klass, String name) { + return DEFAULT_REGISTRY.newHistogram(klass, name); + } + + /** + * Creates a new non-biased {@link com.yammer.metrics.core.Histogram} 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 + * @return a new {@link com.yammer.metrics.core.Histogram} + */ + public static Histogram newHistogram(Class klass, String name, + String scope) { + return DEFAULT_REGISTRY.newHistogram(klass, name, scope); + } + + /** + * Creates a new non-biased {@link com.yammer.metrics.core.Histogram} and + * registers it under the given metric name. + * + * @param metricName + * the name of the metric + * @return a new {@link com.yammer.metrics.core.Histogram} + */ + public static Histogram newHistogram(MetricName metricName) { + return newHistogram(metricName, false); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Meter} 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 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 com.yammer.metrics.core.Meter} + */ + public static Meter newMeter(String url, Class klass, String name, + String eventType, TimeUnit unit) { + return DEFAULT_REGISTRY.newMeter(url, klass, name, eventType, unit); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Meter} 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 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 com.yammer.metrics.core.Meter} + */ + public static Meter newMeter(String url, Class klass, String name, + String scope, String eventType, TimeUnit unit) { + return DEFAULT_REGISTRY.newMeter(url, klass, name, scope, eventType, + unit); + } + + /** + * Creates a new {@link com.yammer.metrics.core.Meter} and registers it + * under the given metric name. + * + * @param metricName + * the name 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 com.yammer.metrics.core.Meter} + */ + public static Meter newMeter(String url, MetricName metricName, + String eventType, TimeUnit unit) { + return DEFAULT_REGISTRY.newMeter(url, metricName, eventType, unit); + } + + /** + * Creates a new {@link com.yammer.metrics.core.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 com.yammer.metrics.core.Timer} + */ + public static Timer newTimer(Class klass, String name, + TimeUnit durationUnit, TimeUnit rateUnit) { + return DEFAULT_REGISTRY.newTimer(klass, name, durationUnit, rateUnit); + } + + /** + * Creates a new {@link com.yammer.metrics.core.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 com.yammer.metrics.core.Timer} + */ + public static Timer newTimer(Class klass, String name) { + return DEFAULT_REGISTRY.newTimer(klass, name); + } + + /** + * Creates a new {@link com.yammer.metrics.core.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 com.yammer.metrics.core.Timer} + */ + public static Timer newTimer(Class klass, String name, String scope, + TimeUnit durationUnit, TimeUnit rateUnit) { + return DEFAULT_REGISTRY.newTimer(klass, name, scope, durationUnit, + rateUnit); + } + + /** + * Creates a new {@link com.yammer.metrics.core.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 com.yammer.metrics.core.Timer} + */ + public static Timer newTimer(Class klass, String name, String scope) { + return DEFAULT_REGISTRY.newTimer(klass, name, scope); + } + + /** + * Creates a new {@link com.yammer.metrics.core.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 com.yammer.metrics.core.Timer} + */ + public static Timer newTimer(MetricName metricName, TimeUnit durationUnit, + TimeUnit rateUnit) { + return DEFAULT_REGISTRY.newTimer(metricName, durationUnit, rateUnit); + } + + /** + * Returns the (static) default registry. + * + * @return the metrics registry + */ + public static APIMetricsRegistry defaultRegistry() { + return DEFAULT_REGISTRY; + } + + /** + * Shuts down all thread pools for the default registry. + */ + public static void shutdown() { + DEFAULT_REGISTRY.shutdown(); + JmxReporter.shutdownDefault(); + Runtime.getRuntime().removeShutdownHook(SHUTDOWN_HOOK); + } + +} diff --git a/src/main/java/com/cloudius/urchin/metrics/DefaultNameFactory.java b/src/main/java/com/cloudius/urchin/metrics/DefaultNameFactory.java new file mode 100644 index 0000000..1c65fb5 --- /dev/null +++ b/src/main/java/com/cloudius/urchin/metrics/DefaultNameFactory.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ +package com.cloudius.urchin.metrics; + +import com.yammer.metrics.core.MetricName; + +/** + * MetricNameFactory that generates default MetricName of metrics. + */ +public class DefaultNameFactory implements MetricNameFactory { + public static final String GROUP_NAME = "org.apache.cassandra.metrics"; + + private final String type; + private final String scope; + + public DefaultNameFactory(String type) { + this(type, null); + } + + public DefaultNameFactory(String type, String scope) { + this.type = type; + this.scope = scope; + } + + public MetricName createMetricName(String metricName) { + return createMetricName(type, metricName, scope); + } + + public static MetricName createMetricName(String type, String metricName, + String scope) { + return new MetricName(GROUP_NAME, type, metricName, scope, + createDefaultMBeanName(type, metricName, scope)); + } + + protected static String createDefaultMBeanName(String type, String name, + String scope) { + final StringBuilder nameBuilder = new StringBuilder(); + nameBuilder.append(GROUP_NAME); + nameBuilder.append(":type="); + nameBuilder.append(type); + if (scope != null) { + nameBuilder.append(",scope="); + nameBuilder.append(scope); + } + if (name.length() > 0) { + nameBuilder.append(",name="); + nameBuilder.append(name); + } + return nameBuilder.toString(); + } +} diff --git a/src/main/java/com/cloudius/urchin/metrics/MetricNameFactory.java b/src/main/java/com/cloudius/urchin/metrics/MetricNameFactory.java new file mode 100644 index 0000000..3bd92e5 --- /dev/null +++ b/src/main/java/com/cloudius/urchin/metrics/MetricNameFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ + +package com.cloudius.urchin.metrics; + +import com.yammer.metrics.core.MetricName; + +public interface MetricNameFactory +{ + /** + * Create a qualified name from given metric name. + * + * @param metricName part of qualified name. + * @return new String with given metric name. + */ + MetricName createMetricName(String metricName); +} diff --git a/src/main/java/com/yammer/metrics/core/APICounter.java b/src/main/java/com/yammer/metrics/core/APICounter.java new file mode 100644 index 0000000..85ddc87 --- /dev/null +++ b/src/main/java/com/yammer/metrics/core/APICounter.java @@ -0,0 +1,29 @@ +package com.yammer.metrics.core; +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ + +import com.cloudius.urchin.api.APIClient; +import com.yammer.metrics.core.Counter; + +public class APICounter extends Counter { + String url; + private APIClient c = new APIClient(); + + public APICounter(String _url) { + super(); + url = _url; + } + /** + * Returns the counter's current value. + * + * @return the counter's current value + */ + public long count() { + return c.getLongValue(url); + } + + +} diff --git a/src/main/java/com/yammer/metrics/core/APIHistogram.java b/src/main/java/com/yammer/metrics/core/APIHistogram.java new file mode 100644 index 0000000..8ccdbb0 --- /dev/null +++ b/src/main/java/com/yammer/metrics/core/APIHistogram.java @@ -0,0 +1,112 @@ +package com.yammer.metrics.core; + +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ + +import com.cloudius.urchin.api.APIClient; +import com.yammer.metrics.stats.Sample; +import com.yammer.metrics.stats.Snapshot; + +public class APIHistogram extends Histogram { + long last_update = 0; + static final long UPDATE_INTERVAL = 50; + String url; + private APIClient c = new APIClient(); + + public APIHistogram(String _url, Sample sample) { + super(sample); + url = _url; + } + + public APIHistogram(String _url, SampleType type) { + super(type); + url = _url; + } + + public void update() { + long now = System.currentTimeMillis(); + if (now - last_update < UPDATE_INTERVAL) { + return; + } + last_update = now; + clear(); + long[] vals = c.getLongArrValue(url); + for (long v : vals) { + update(v); + } + } + + /** + * Returns the number of values recorded. + * + * @return the number of values recorded + */ + public long count() { + update(); + return super.count(); + } + + /* + * (non-Javadoc) + * + * @see com.yammer.metrics.core.Summarizable#max() + */ + @Override + public double max() { + update(); + return super.max(); + } + + /* + * (non-Javadoc) + * + * @see com.yammer.metrics.core.Summarizable#min() + */ + @Override + public double min() { + update(); + return super.min(); + } + + /* + * (non-Javadoc) + * + * @see com.yammer.metrics.core.Summarizable#mean() + */ + @Override + public double mean() { + update(); + return super.mean(); + } + + /* + * (non-Javadoc) + * + * @see com.yammer.metrics.core.Summarizable#stdDev() + */ + @Override + public double stdDev() { + update(); + return super.stdDev(); + } + + /* + * (non-Javadoc) + * + * @see com.yammer.metrics.core.Summarizable#sum() + */ + @Override + public double sum() { + update(); + return super.sum(); + } + + @Override + public Snapshot getSnapshot() { + update(); + return super.getSnapshot(); + } +} diff --git a/src/main/java/com/yammer/metrics/core/APIMeter.java b/src/main/java/com/yammer/metrics/core/APIMeter.java new file mode 100644 index 0000000..fc1a801 --- /dev/null +++ b/src/main/java/com/yammer/metrics/core/APIMeter.java @@ -0,0 +1,29 @@ +package com.yammer.metrics.core; + +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import com.cloudius.urchin.api.APIClient; + +public class APIMeter extends Meter { + String url; + private APIClient c = new APIClient(); + + public APIMeter(String _url, ScheduledExecutorService tickThread, + String eventType, TimeUnit rateUnit, Clock clock) { + super(tickThread, eventType, rateUnit, clock); + // TODO Auto-generated constructor stub + url = _url; + } + + @Override + public long count() { + return c.getLongValue(url); + } + +} diff --git a/src/main/java/com/yammer/metrics/core/APIMetricsRegistry.java b/src/main/java/com/yammer/metrics/core/APIMetricsRegistry.java new file mode 100644 index 0000000..b9242b0 --- /dev/null +++ b/src/main/java/com/yammer/metrics/core/APIMetricsRegistry.java @@ -0,0 +1,234 @@ +package com.yammer.metrics.core; + +import java.lang.reflect.Field; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import com.yammer.metrics.core.APICounter; +import com.yammer.metrics.core.APIMeter; +import com.yammer.metrics.core.Clock; +import com.yammer.metrics.core.Counter; +import com.yammer.metrics.core.Meter; +import com.yammer.metrics.core.Metric; +import com.yammer.metrics.core.MetricName; +import com.yammer.metrics.core.MetricsRegistry; +import com.yammer.metrics.core.ThreadPools; +import com.yammer.metrics.core.Histogram.SampleType; + +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ + +public class APIMetricsRegistry extends MetricsRegistry { + Field field_metrics; + Field field_clock; + Field field_thread_pool; + + public APIMetricsRegistry() { + try { + field_metrics = MetricsRegistry.class.getDeclaredField("metrics"); + field_metrics.setAccessible(true); + field_clock = MetricsRegistry.class.getDeclaredField("clock"); + field_clock.setAccessible(true); + field_thread_pool = MetricsRegistry.class.getDeclaredField("threadPools"); + field_thread_pool.setAccessible(true); + } catch (NoSuchFieldException | SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public ThreadPools getThreadPools() { + try { + return (ThreadPools)field_thread_pool.get(this); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + public Clock getClock() { + try { + return (Clock)field_clock.get(this); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + @SuppressWarnings("unchecked") + public ConcurrentMap get_metrics() { + try { + return (ConcurrentMap)field_metrics.get(this); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + /** + * Creates a new {@link Counter} and registers it under the given class and name. + * + * @param klass the class which owns the metric + * @param name the name of the metric + * @return a new {@link Counter} + */ + public Counter newCounter(String url, Class klass, + String name) { + return newCounter(url, klass, name, null); + } + + /** + * Creates a new {@link Counter} 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 scope the scope of the metric + * @return a new {@link Counter} + */ + public Counter newCounter(String url, Class klass, + String name, + String scope) { + return newCounter(url, createName(klass, name, scope)); + } + /** + * Creates a new {@link Counter} and registers it under the given metric name. + * + * @param metricName the name of the metric + * @return a new {@link Counter} + */ + public Counter newCounter(String url, MetricName metricName) { + return getOrAdd(metricName, new APICounter(url)); + } + + /** + * Creates a new {@link Meter} 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 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} + */ + public Meter newMeter(String url, Class klass, + String name, + String eventType, + TimeUnit unit) { + return newMeter(url, klass, name, null, eventType, unit); + } + + /** + * Creates a new {@link Meter} 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 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} + */ + public Meter newMeter(String url, + Class klass, + String name, + String scope, + String eventType, + TimeUnit unit) { + return newMeter(url, createName(klass, name, scope), eventType, unit); + } + + private ScheduledExecutorService newMeterTickThreadPool() { + return getThreadPools().newScheduledThreadPool(2, "meter-tick"); + } + /** + * Creates a new {@link Meter} and registers it under the given metric name. + * + * @param metricName the name 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} + */ + public Meter newMeter(String url, MetricName metricName, + String eventType, + TimeUnit unit) { + final Metric existingMetric = get_metrics().get(metricName); + if (existingMetric != null) { + return (Meter) existingMetric; + } + return getOrAdd(metricName, new APIMeter(url, newMeterTickThreadPool(), eventType, unit, getClock())); + } + + /** + * Creates a new {@link Histogram} 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 biased whether or not the histogram should be biased + * @return a new {@link Histogram} + */ + public Histogram newHistogram(String url, Class klass, + String name, + boolean biased) { + return newHistogram(url, klass, name, null, biased); + } + + /** + * Creates a new {@link Histogram} 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 biased whether or not the histogram should be biased + * @return a new {@link Histogram} + */ + public Histogram newHistogram(String url, Class klass, + String name, + String scope, + boolean 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. + * + * @param klass the class which owns the metric + * @param name the name of the metric + * @return a new {@link Histogram} + */ + public Histogram newHistogram(String url, Class klass, + String name) { + return newHistogram(url, klass, name, false); + } + + /** + * Creates a new non-biased {@link Histogram} 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 + * @return a new {@link Histogram} + */ + public Histogram newHistogram(String url, Class klass, + String name, + String scope) { + return newHistogram(url, klass, name, scope, false); + } + + /** + * Creates a new {@link Histogram} and registers it under the given metric name. + * + * @param metricName the name of the metric + * @param biased whether or not the histogram should be biased + * @return a new {@link Histogram} + */ + public Histogram newHistogram(String url, MetricName metricName, + boolean biased) { + return getOrAdd(metricName, + new APIHistogram(url, biased ? SampleType.BIASED : SampleType.UNIFORM)); + } +}