
com.github.jjagged.metrics.reporting.StatsDReporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of metrics-statsd Show documentation
Show all versions of metrics-statsd Show documentation
Statsd reporter for codahale/metrics with support for tags.
The newest version!
/**
* Copyright (C) 2014 metrics-statsd contributors
*
* 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.github.jjagged.metrics.reporting;
import com.github.jjagged.metrics.reporting.statsd.StatsD;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.TimeUnit;
/**
* A reporter which publishes metric values to a StatsD server.
*
* @see StatsD
*/
@NotThreadSafe
public class StatsDReporter extends ScheduledReporter {
private static final Logger LOG = LoggerFactory.getLogger(StatsDReporter.class);
private final StatsD statsD;
private final String prefix;
private final String[] tags;
private StatsDReporter(final MetricRegistry registry, final StatsD statsD,
final String prefix, final String[] tags, final TimeUnit rateUnit,
final TimeUnit durationUnit, final MetricFilter filter) {
super(registry, "statsd-reporter", filter, rateUnit, durationUnit);
this.statsD = statsD;
this.prefix = prefix;
this.tags = tags;
}
/**
* Returns a new {@link Builder} for {@link StatsDReporter}.
*
* @param registry
* the registry to report
* @return a {@link Builder} instance for a {@link StatsDReporter}
*/
public static Builder forRegistry(final MetricRegistry registry) {
return new Builder(registry);
}
/**
* A builder for {@link StatsDReporter} instances. Defaults to not using a
* prefix, no tags, converting rates to events/second, converting durations to
* milliseconds, and not filtering metrics.
*/
@NotThreadSafe
public static final class Builder {
private final MetricRegistry registry;
private String prefix;
private String[] tags;
private TimeUnit rateUnit;
private TimeUnit durationUnit;
private MetricFilter filter;
private Builder(final MetricRegistry registry) {
this.registry = registry;
this.prefix = null;
this.tags = null;
this.rateUnit = TimeUnit.SECONDS;
this.durationUnit = TimeUnit.MILLISECONDS;
this.filter = MetricFilter.ALL;
}
/**
* Prefix all metric names with the given string.
*
* @param prefix
* the prefix for all metric names
* @return {@code this}
*/
public Builder prefixedWith(@Nullable final String prefix) {
this.prefix = prefix;
return this;
}
/**
* Add all given tags to all metrics
* @param tags the tags for all metrics
* @return {@code this}
*/
public Builder withTags(@Nullable final String... tags) {
this.tags = tags;
return this;
}
/**
* Convert rates to the given time unit.
*
* @param rateUnit
* a unit of time
* @return {@code this}
*/
public Builder convertRatesTo(final TimeUnit rateUnit) {
this.rateUnit = rateUnit;
return this;
}
/**
* Convert durations to the given time unit.
*
* @param durationUnit
* a unit of time
* @return {@code this}
*/
public Builder convertDurationsTo(final TimeUnit durationUnit) {
this.durationUnit = durationUnit;
return this;
}
/**
* Only report metrics which match the given filter.
*
* @param filter
* a {@link MetricFilter}
* @return {@code this}
*/
public Builder filter(final MetricFilter filter) {
this.filter = filter;
return this;
}
/**
* Builds a {@link StatsDReporter} with the given properties, sending
* metrics to StatsD at the given host and port.
*
* @param host
* the hostname of the StatsD server.
* @param port
* the port of the StatsD server. This is typically 8125.
* @return a {@link StatsDReporter}
*/
public StatsDReporter build(final String host, final int port) {
return build(new StatsD(host, port));
}
/**
* Builds a {@link StatsDReporter} with the given properties, sending
* metrics using the given {@link StatsD} client.
*
* @param statsD
* a {@link StatsD} client
* @return a {@link StatsDReporter}
*/
public StatsDReporter build(final StatsD statsD) {
return new StatsDReporter(registry, statsD, prefix, tags, rateUnit,
durationUnit, filter);
}
}
@Override
@SuppressWarnings("rawtypes")
// Metrics 3.0 interface specifies the raw Gauge type
public void report(final SortedMap gauges,
final SortedMap counters,
final SortedMap histograms,
final SortedMap meters,
final SortedMap timers) {
try {
statsD.connect();
for (Map.Entry entry : gauges.entrySet()) {
reportGauge(entry.getKey(), entry.getValue());
}
for (Map.Entry entry : counters.entrySet()) {
reportCounter(entry.getKey(), entry.getValue());
}
for (Map.Entry entry : histograms.entrySet()) {
reportHistogram(entry.getKey(), entry.getValue());
}
for (Map.Entry entry : meters.entrySet()) {
reportMetered(entry.getKey(), entry.getValue());
}
for (Map.Entry entry : timers.entrySet()) {
reportTimer(entry.getKey(), entry.getValue());
}
} catch (IOException e) {
LOG.warn("Unable to report to StatsD", statsD, e);
} finally {
try {
statsD.close();
} catch (IOException e) {
LOG.debug("Error disconnecting from StatsD", statsD, e);
}
}
}
private void reportTimer(final String name, final Timer timer) {
final Snapshot snapshot = timer.getSnapshot();
statsD.send(prefix(name, "max"), formatNumber(convertDuration(snapshot.getMax())), tags);
statsD.send(prefix(name, "mean"), formatNumber(convertDuration(snapshot.getMean())), tags);
statsD.send(prefix(name, "min"), formatNumber(convertDuration(snapshot.getMin())), tags);
statsD.send(prefix(name, "stddev"), formatNumber(convertDuration(snapshot.getStdDev())), tags);
statsD.send(prefix(name, "p50"), formatNumber(convertDuration(snapshot.getMedian())), tags);
statsD.send(prefix(name, "p75"), formatNumber(convertDuration(snapshot.get75thPercentile())), tags);
statsD.send(prefix(name, "p95"), formatNumber(convertDuration(snapshot.get95thPercentile())), tags);
statsD.send(prefix(name, "p98"), formatNumber(convertDuration(snapshot.get98thPercentile())), tags);
statsD.send(prefix(name, "p99"), formatNumber(convertDuration(snapshot.get99thPercentile())), tags);
statsD.send(prefix(name, "p999"), formatNumber(convertDuration(snapshot.get999thPercentile())), tags);
reportMetered(name, timer);
}
private void reportMetered(final String name, final Metered meter) {
statsD.send(prefix(name, "count"), formatNumber(meter.getCount()), tags);
statsD.send(prefix(name, "m1_rate"), formatNumber(convertRate(meter.getOneMinuteRate())), tags);
statsD.send(prefix(name, "m5_rate"), formatNumber(convertRate(meter.getFiveMinuteRate())), tags);
statsD.send(prefix(name, "m15_rate"), formatNumber(convertRate(meter.getFifteenMinuteRate())), tags);
statsD.send(prefix(name, "mean_rate"), formatNumber(convertRate(meter.getMeanRate())), tags);
}
private void reportHistogram(final String name, final Histogram histogram) {
final Snapshot snapshot = histogram.getSnapshot();
statsD.send(prefix(name, "count"), formatNumber(histogram.getCount()), tags);
statsD.send(prefix(name, "max"), formatNumber(snapshot.getMax()), tags);
statsD.send(prefix(name, "mean"), formatNumber(snapshot.getMean()), tags);
statsD.send(prefix(name, "min"), formatNumber(snapshot.getMin()), tags);
statsD.send(prefix(name, "stddev"), formatNumber(snapshot.getStdDev()), tags);
statsD.send(prefix(name, "p50"), formatNumber(snapshot.getMedian()), tags);
statsD.send(prefix(name, "p75"), formatNumber(snapshot.get75thPercentile()), tags);
statsD.send(prefix(name, "p95"), formatNumber(snapshot.get95thPercentile()), tags);
statsD.send(prefix(name, "p98"), formatNumber(snapshot.get98thPercentile()), tags);
statsD.send(prefix(name, "p99"), formatNumber(snapshot.get99thPercentile()), tags);
statsD.send(prefix(name, "p999"), formatNumber(snapshot.get999thPercentile()), tags);
}
private void reportCounter(final String name, final Counter counter) {
statsD.send(prefix(name), formatNumber(counter.getCount()), tags);
}
@SuppressWarnings("rawtypes")
// Metrics 3.0 passes us the raw Gauge type
private void reportGauge(final String name, final Gauge gauge) {
final String value = format(gauge.getValue());
if (value != null) {
statsD.send(prefix(name), value, tags);
}
}
@Nullable
private String format(final Object o) {
if (o instanceof Float) {
return formatNumber(((Float) o).doubleValue());
} else if (o instanceof Double) {
return formatNumber((Double) o);
} else if (o instanceof Byte) {
return formatNumber(((Byte) o).longValue());
} else if (o instanceof Short) {
return formatNumber(((Short) o).longValue());
} else if (o instanceof Integer) {
return formatNumber(((Integer) o).longValue());
} else if (o instanceof Long) {
return formatNumber((Long) o);
} else if (o instanceof BigInteger) {
return formatNumber((BigInteger) o);
} else if (o instanceof BigDecimal) {
return formatNumber(((BigDecimal) o).doubleValue());
}
return null;
}
private String prefix(final String... components) {
return MetricRegistry.name(prefix, components);
}
private String formatNumber(final BigInteger n) {
return String.valueOf(n);
}
private String formatNumber(final long n) {
return Long.toString(n);
}
private String formatNumber(final double v) {
return String.format(Locale.US, "%2.2f", v);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy