Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.circonus.metrics.CirconusReporter Maven / Gradle / Ivy
package com.circonus.metrics;
import com.codahale.metrics.Clock;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.codahale.metrics.Metered;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.ScheduledReporter;
import com.codahale.metrics.Snapshot;
import com.codahale.metrics.Timer;
import com.circonus.metrics.model.CirconusCounter;
import com.circonus.metrics.model.CirconusGauge;
import com.circonus.metrics.model.CirconusHistogram;
import com.circonus.metrics.transport.Transport;
import com.circonus.metrics.HistImpl;
import com.circonus.metrics.HistImplContainer;
import com.circonus.metrics.CirconusMetricRegistryAlaCoda;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.TimeUnit;
public class CirconusReporter extends ScheduledReporter {
private static final Logger LOG = LoggerFactory.getLogger(CirconusReporter.class);
private static final Expansion[] STATS_EXPANSIONS = { Expansion.MAX, Expansion.MEAN,
Expansion.MIN, Expansion.STD_DEV, Expansion.MEDIAN, Expansion.P75, Expansion.P95,
Expansion.P98, Expansion.P99, Expansion.P999 };
private static final Expansion[] RATE_EXPANSIONS = { Expansion.RATE_1_MINUTE,
Expansion.RATE_5_MINUTE, Expansion.RATE_15_MINUTE, Expansion.RATE_MEAN };
private final Transport transport;
private final Clock clock;
private final String host;
private final EnumSet expansions;
private final MetricNameFormatter metricNameFormatter;
private final List tags;
private final String prefix;
private final DynamicTagsCallback tagsCallback;
private final Boolean suppress_bad_analytics;
private Transport.Request request;
private CirconusReporter(MetricRegistry metricRegistry,
Transport transport,
MetricFilter filter,
Clock clock,
String host,
EnumSet expansions,
TimeUnit rateUnit,
TimeUnit durationUnit,
MetricNameFormatter metricNameFormatter,
List tags,
String prefix,
DynamicTagsCallback tagsCallback,
Boolean suppress) {
super(metricRegistry, "circonus-reporter", filter, rateUnit, durationUnit);
if(!(metricRegistry instanceof CirconusMetricRegistryAlaCoda)) {
LOG.warn("CirconusReporter started without a CirconusMetricRegistry(AlaCoda) so no real histograms.");
}
this.clock = clock;
this.host = host;
this.expansions = expansions;
this.metricNameFormatter = metricNameFormatter;
this.tags = (tags == null) ? new ArrayList() : tags;
this.transport = transport;
this.prefix = prefix;
this.tagsCallback = tagsCallback;
this.suppress_bad_analytics = suppress;
}
@Override
public void report(SortedMap gauges,
SortedMap counters,
SortedMap histograms,
SortedMap meters,
SortedMap timers) {
final long timestamp = clock.getTime() / 1000;
List newTags = tags;
if (tagsCallback != null) {
List dynamicTags = tagsCallback.getTags();
if (dynamicTags != null && ! dynamicTags.isEmpty()) {
newTags = TagUtils.mergeTags(tags, dynamicTags);
}
}
try {
request = transport.prepare();
for (Map.Entry entry : gauges.entrySet()) {
reportGauge(prefix(entry.getKey()), entry.getValue(), timestamp, newTags);
}
for (Map.Entry entry : counters.entrySet()) {
reportCounter(prefix(entry.getKey()), entry.getValue(), timestamp, newTags);
}
for (Map.Entry entry : histograms.entrySet()) {
reportHistogram(prefix(entry.getKey()), entry.getValue(), timestamp, newTags);
}
for (Map.Entry entry : meters.entrySet()) {
reportMetered(prefix(entry.getKey()), entry.getValue(), timestamp, newTags);
}
for (Map.Entry entry : timers.entrySet()) {
reportTimer(prefix(entry.getKey()), entry.getValue(), timestamp, newTags);
}
request.send();
} catch (Throwable e) {
LOG.error("Error reporting metrics to Circonus: " + e);
}
}
private void reportTimer(String name, Timer timer, long timestamp, List tags)
throws IOException {
final Snapshot snapshot = timer.getSnapshot();
LOG.debug("Timer[" +name + "] " + timer);
if(timer instanceof HistImplContainer) {
HistImpl take = ((HistImplContainer)timer).getHistImpl().copyAndReset();
LOG.debug("Adding Circonus Histogram to report: " + name);
request.addHistogram(new CirconusHistogram(
name, take, timestamp, host, tags));
if(suppress_bad_analytics) return;
}
double[] values = { snapshot.getMax(), snapshot.getMean(), snapshot.getMin(), snapshot.getStdDev(),
snapshot.getMedian(), snapshot.get75thPercentile(), snapshot.get95thPercentile(), snapshot.get98thPercentile(),
snapshot.get99thPercentile(), snapshot.get999thPercentile() };
for (int i = 0; i < STATS_EXPANSIONS.length; i++) {
if (expansions.contains(STATS_EXPANSIONS[i])) {
request.addGauge(new CirconusGauge(
appendExpansionSuffix(name, STATS_EXPANSIONS[i]),
toNumber(convertDuration(values[i])),
timestamp,
host,
tags));
}
}
reportMetered(name, timer, timestamp, tags);
}
private void reportMetered(String name, Metered meter, long timestamp, List tags)
throws IOException {
if (expansions.contains(Expansion.COUNT)) {
request.addGauge(new CirconusGauge(
appendExpansionSuffix(name, Expansion.COUNT),
meter.getCount(),
timestamp,
host,
tags));
}
double[] values = { meter.getOneMinuteRate(), meter.getFiveMinuteRate(),
meter.getFifteenMinuteRate(), meter.getMeanRate() };
for (int i = 0; i < RATE_EXPANSIONS.length; i++) {
if (expansions.contains(RATE_EXPANSIONS[i])) {
request.addGauge(new CirconusGauge(
appendExpansionSuffix(name, RATE_EXPANSIONS[i]),
toNumber(convertRate(values[i])),
timestamp,
host,
tags));
}
}
}
private void reportHistogram(String name, Histogram histogram, long timestamp, List tags)
throws IOException {
final Snapshot snapshot = histogram.getSnapshot();
if(histogram instanceof HistImplContainer) {
HistImpl take = ((HistImplContainer)histogram).getHistImpl().copyAndReset();
LOG.debug("Adding Circonus Histogram to report: " + name);
request.addHistogram(new CirconusHistogram(
name, take, timestamp, host, tags));
if(suppress_bad_analytics) return;
}
if (expansions.contains(Expansion.COUNT)) {
request.addGauge(new CirconusGauge(
appendExpansionSuffix(name, Expansion.COUNT),
histogram.getCount(),
timestamp,
host,
tags));
}
Number[] values = { snapshot.getMax(), snapshot.getMean(), snapshot.getMin(), snapshot.getStdDev(),
snapshot.getMedian(), snapshot.get75thPercentile(), snapshot.get95thPercentile(), snapshot.get98thPercentile(),
snapshot.get99thPercentile(), snapshot.get999thPercentile() };
for (int i = 0; i < STATS_EXPANSIONS.length; i++) {
if (expansions.contains(STATS_EXPANSIONS[i])) {
request.addGauge(new CirconusGauge(
appendExpansionSuffix(name, STATS_EXPANSIONS[i]),
toNumber(values[i]),
timestamp,
host,
tags));
}
}
}
private void reportCounter(String name, Counter counter, long timestamp, List tags)
throws IOException {
// A Metrics counter is actually a Circonus Gauge. Circonus Counters are for rates which is
// similar to the Metrics Meter type. Metrics counters have increment and decrement
// functionality, which implies they are instantaneously measurable, which implies they are
// actually a gauge. The Metrics documentation agrees, stating:
// "A counter is just a gauge for an AtomicLong instance. You can increment or decrement its
// value. For example, we may want a more efficient way of measuring the pending job in a queue"
request.addGauge(new CirconusGauge(metricNameFormatter.format(name), counter.getCount(),
timestamp, host, tags));
}
private void reportGauge(String name, Gauge gauge, long timestamp, List tags)
throws IOException {
final Number value = toNumber(gauge.getValue());
if (value != null) {
request.addGauge(new CirconusGauge(metricNameFormatter.format(name), value, timestamp, host,
tags));
}
}
private Number toNumber(Object o) {
if (o instanceof Number) {
return (Number) o;
}
return null;
}
private String appendExpansionSuffix(String name, Expansion expansion) {
return metricNameFormatter.format(name, expansion.toString());
}
private String prefix(String name) {
if (prefix == null) {
return name;
} else {
return String.format("%s.%s", prefix, name);
}
}
public static enum Expansion {
COUNT("count"),
RATE_MEAN("meanRate"),
RATE_1_MINUTE("1MinuteRate"),
RATE_5_MINUTE("5MinuteRate"),
RATE_15_MINUTE("15MinuteRate"),
MIN("min"),
MEAN("mean"),
MAX("max"),
STD_DEV("stddev"),
MEDIAN("median"),
P75("p75"),
P95("p95"),
P98("p98"),
P99("p99"),
P999("p999");
public static EnumSet ALL = EnumSet.allOf(Expansion.class);
private final String displayName;
private Expansion(String displayName) {
this.displayName = displayName;
}
@Override
public String toString() {
return displayName;
}
}
public static Builder forRegistry(MetricRegistry registry) {
return new Builder(registry);
}
public static class Builder {
private final MetricRegistry registry;
private String host;
private EnumSet expansions;
private Clock clock;
private TimeUnit rateUnit;
private TimeUnit durationUnit;
private MetricFilter filter;
private MetricNameFormatter metricNameFormatter;
private List tags;
private Transport transport;
private String prefix;
private DynamicTagsCallback tagsCallback;
private Boolean suppress_bad_analytics;
public Builder(MetricRegistry registry) {
this.registry = registry;
this.expansions = Expansion.ALL;
this.clock = Clock.defaultClock();
this.rateUnit = TimeUnit.SECONDS;
this.durationUnit = TimeUnit.MILLISECONDS;
this.filter = MetricFilter.ALL;
this.metricNameFormatter = new DefaultMetricNameFormatter();
this.tags = new ArrayList();
this.suppress_bad_analytics = true;
}
public Builder onlyCirconusAnalytics(Boolean suppress) {
this.suppress_bad_analytics = suppress;
return this;
}
public Builder withHost(String host) {
this.host = host;
return this;
}
public Builder withEC2Host() throws IOException {
this.host = AwsHelper.getEc2InstanceId();
return this;
}
public Builder withExpansions(EnumSet expansions) {
this.expansions = expansions;
return this;
}
public Builder withDynamicTagCallback(DynamicTagsCallback tagsCallback) {
this.tagsCallback = tagsCallback;
return this;
}
public Builder convertRatesTo(TimeUnit rateUnit) {
this.rateUnit = rateUnit;
return this;
}
/**
* Tags that would be sent to Circonus with each and every metrics. This could be used to set
* global metrics like version of the app, environment etc.
* @param tags List of tags eg: [env:prod, version:1.0.1, name:kafka_client] etc
*/
public Builder withTags(List tags) {
this.tags = tags;
return this;
}
/**
* Prefix all metric names with the given string.
*
* @param prefix The prefix for all metric names.
*/
public Builder withPrefix(String prefix) {
this.prefix = prefix;
return this;
}
public Builder withClock(Clock clock) {
this.clock = clock;
return this;
}
public Builder filter(MetricFilter filter) {
this.filter = filter;
return this;
}
public Builder withMetricNameFormatter(MetricNameFormatter formatter) {
this.metricNameFormatter = formatter;
return this;
}
public Builder convertDurationsTo(TimeUnit durationUnit) {
this.durationUnit = durationUnit;
return this;
}
/**
* The transport mechanism to push metrics to Circonus. Supports HTTPTrap.
*
* @see com.circonus.metrics.transport.HttpTransport
*/
public Builder withTransport(Transport transport) {
this.transport = transport;
return this;
}
public CirconusReporter build() {
if (transport == null) {
LOG.error("Transport for Circonus reporter is null. No recording!");
}
return new CirconusReporter(
this.registry,
this.transport,
this.filter,
this.clock,
this.host,
this.expansions,
this.rateUnit,
this.durationUnit,
this.metricNameFormatter,
this.tags,
this.prefix,
this.tagsCallback,
this.suppress_bad_analytics);
}
}
}