com.bazaarvoice.ostrich.metrics.Metrics Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ostrich-core Show documentation
Show all versions of ostrich-core Show documentation
Core classes that form Ostrich
package com.bazaarvoice.ostrich.metrics;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import java.io.Closeable;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A thin wrapper implementation around Yammer Metrics for use by SOA. This wrapper adds the following functionality:
*
* The ability to control what {@link MetricRegistry} instance is used for SOA metrics via the constructor. This gives
* us the ability in the future to isolate the SOA metrics from the end user's application metrics as well as publish
* them somewhere differently from the end user's application metrics.
*/
public abstract class Metrics implements Closeable {
/**
* Create a metrics instance that corresponds to a class. This is useful for cases where a single instance handles
* many different services at the same time. For example a ServiceRegistry.
*/
public static ClassMetrics forClass(MetricRegistry metrics, Class> cls) {
return new ClassMetrics(metrics, cls);
}
/**
* Create a metrics instance that corresponds to a single instance of a class. This is useful for cases where there
* exists one instance per service. For example in a ServicePool.
*/
public static InstanceMetrics forInstance(MetricRegistry metrics, Object instance, String serviceName) {
return new InstanceMetrics(metrics, instance, serviceName);
}
public static final class ClassMetrics implements Closeable {
private final MetricRegistry _metrics;
private final Class> _class;
private final String _prefix;
private final Set _names = Sets.newHashSet();
ClassMetrics(MetricRegistry metrics, Class> cls) {
_metrics = checkNotNull(metrics);
_class = checkNotNull(cls);
_prefix = MetricRegistry.name(_class);
}
public synchronized Gauge gauge(String serviceName, String name, Gauge metric) {
checkNotNullOrEmpty(serviceName);
checkNotNullOrEmpty(name);
checkNotNull(metric);
return _metrics.register(name(serviceName, name), metric);
}
public synchronized Counter counter(String serviceName, String name) {
checkNotNullOrEmpty(serviceName);
checkNotNullOrEmpty(name);
return _metrics.counter(name(serviceName, name));
}
public synchronized Histogram histogram(String serviceName, String name) {
checkNotNullOrEmpty(serviceName);
checkNotNullOrEmpty(name);
return _metrics.histogram(name(serviceName, name));
}
public synchronized Meter meter(String serviceName, String name) {
checkNotNullOrEmpty(serviceName);
checkNotNullOrEmpty(name);
return _metrics.meter(name(serviceName, name));
}
public synchronized Timer timer(String serviceName, String name) {
checkNotNullOrEmpty(serviceName);
checkNotNullOrEmpty(name);
return _metrics.timer(name(serviceName, name));
}
@Override
public synchronized void close() {
for (String name : _names) {
_metrics.remove(name);
}
_names.clear();
}
@VisibleForTesting
String name(String serviceName, String name) {
String fullName = MetricRegistry.name(_prefix, serviceName, name);
_names.add(fullName);
return fullName;
}
}
public static class InstanceMetrics implements Closeable {
private final MetricRegistry _metrics;
private final Object _instance;
private final String _serviceName;
private final String _prefix;
private final String _instanceCounterName;
private final Counter _instanceCounter;
private final Set _names = Sets.newHashSet();
InstanceMetrics(MetricRegistry metrics, Object instance, String serviceName) {
_metrics = checkNotNull(metrics);
_instance = checkNotNull(instance);
_serviceName = checkNotNullOrEmpty(serviceName);
_prefix = MetricRegistry.name(_instance.getClass());
_instanceCounterName = name("num-instances");
_instanceCounter = counter("num-instances");
_instanceCounter.inc();
}
@SuppressWarnings("unchecked")
public synchronized Gauge gauge(String name, Gauge gauge) {
checkNotNullOrEmpty(name);
checkNotNull(gauge);
// Unfortunately register doesn't call getOrAdd (probably a bug in metrics), and instead goes through
// a code path that throws an exception if this metric already exists.
String fullName = name(name);
Gauge metric = (Gauge) _metrics.getMetrics().get(fullName);
if (metric == null) {
metric = _metrics.register(fullName, gauge);
}
return metric;
}
public synchronized Counter counter(String name) {
checkNotNullOrEmpty(name);
return _metrics.counter(name(name));
}
public synchronized Histogram histogram(String name) {
checkNotNullOrEmpty(name);
return _metrics.histogram(name(name));
}
public synchronized Meter meter(String name) {
checkNotNullOrEmpty(name);
return _metrics.meter(name(name));
}
public synchronized Timer timer(String name) {
checkNotNullOrEmpty(name);
return _metrics.timer(name(name));
}
@Override
public synchronized void close() {
_instanceCounter.dec();
if (_instanceCounter.getCount() == 0) {
_metrics.remove(_instanceCounterName);
}
for (String name : _names) {
_metrics.remove(name);
}
_names.clear();
}
@VisibleForTesting
Counter getInstanceCounter() {
return _instanceCounter;
}
@VisibleForTesting
String name(String name) {
String fullName = MetricRegistry.name(_prefix, _serviceName, name);
_names.add(fullName);
return fullName;
}
}
private static String checkNotNullOrEmpty(String string) {
checkNotNull(string);
checkArgument(!Strings.isNullOrEmpty(string));
return string;
}
}