All Downloads are FREE. Search and download functionalities are using the official Maven repository.
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.wavefront.agent.logsharvesting.FlushProcessor Maven / Gradle / Ivy
package com.wavefront.agent.logsharvesting;
import com.tdunning.math.stats.AVLTreeDigest;
import com.tdunning.math.stats.Centroid;
import com.tdunning.math.stats.TDigest;
import com.wavefront.common.MetricsToTimeseries;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Counter;
import com.yammer.metrics.core.DeltaCounter;
import com.yammer.metrics.core.Gauge;
import com.yammer.metrics.core.Histogram;
import com.yammer.metrics.core.Metered;
import com.yammer.metrics.core.MetricName;
import com.yammer.metrics.core.MetricProcessor;
import com.yammer.metrics.core.Sampling;
import com.yammer.metrics.core.Summarizable;
import com.yammer.metrics.core.Timer;
import com.yammer.metrics.core.WavefrontHistogram;
import com.yammer.metrics.stats.Snapshot;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import wavefront.report.HistogramType;
/**
* Wrapper for {@link com.yammer.metrics.core.MetricProcessor}. It provides additional support for
* Delta Counters and WavefrontHistogram.
*
* @author Mori Bellamy ([email protected] )
*/
public class FlushProcessor implements MetricProcessor {
private final Counter sentCounter =
Metrics.newCounter(new MetricName("logsharvesting", "", "sent"));
private final Counter histogramCounter =
Metrics.newCounter(new MetricName("logsharvesting", "", "histograms-sent"));
private final Supplier currentMillis;
private final boolean useWavefrontHistograms;
private final boolean reportEmptyHistogramStats;
/**
* Create new FlushProcessor instance
*
* @param currentMillis {@link Supplier} of time (in milliseconds)
* @param useWavefrontHistograms export data in {@link com.yammer.metrics.core.WavefrontHistogram}
* format
* @param reportEmptyHistogramStats enable legacy {@link com.yammer.metrics.core.Histogram}
* behavior and send zero values for every stat
*/
FlushProcessor(
Supplier currentMillis,
boolean useWavefrontHistograms,
boolean reportEmptyHistogramStats) {
this.currentMillis = currentMillis;
this.useWavefrontHistograms = useWavefrontHistograms;
this.reportEmptyHistogramStats = reportEmptyHistogramStats;
}
@Override
public void processMeter(MetricName name, Metered meter, FlushProcessorContext context) {
throw new UnsupportedOperationException();
}
@Override
public void processCounter(MetricName name, Counter counter, FlushProcessorContext context) {
long count;
// handle delta counter
if (counter instanceof DeltaCounter) {
count = DeltaCounter.processDeltaCounter((DeltaCounter) counter);
if (count == 0) return; // do not report 0-value delta counters
} else {
count = counter.count();
}
context.report(count);
sentCounter.inc();
}
@Override
public void processHistogram(
MetricName name, Histogram histogram, FlushProcessorContext context) {
if (histogram instanceof WavefrontHistogram) {
WavefrontHistogram wavefrontHistogram = (WavefrontHistogram) histogram;
if (useWavefrontHistograms) {
// export Wavefront histograms in its native format
if (wavefrontHistogram.count() == 0) return;
for (WavefrontHistogram.MinuteBin bin : wavefrontHistogram.bins(true)) {
if (bin.getDist().size() == 0) continue;
int size = bin.getDist().centroids().size();
List centroids = new ArrayList<>(size);
List counts = new ArrayList<>(size);
for (Centroid centroid : bin.getDist().centroids()) {
centroids.add(centroid.mean());
counts.add(centroid.count());
}
context.report(
wavefront.report.Histogram.newBuilder()
.setDuration(60_000)
. // minute bins
setType(HistogramType.TDIGEST)
.setBins(centroids)
.setCounts(counts)
.build(),
bin.getMinMillis());
histogramCounter.inc();
}
} else {
// convert Wavefront histogram to Yammer-style histogram
TDigest tDigest = new AVLTreeDigest(100);
List bins = wavefrontHistogram.bins(true);
bins.stream().map(WavefrontHistogram.MinuteBin::getDist).forEach(tDigest::add);
context.reportSubMetric(
tDigest.centroids().stream().mapToLong(Centroid::count).sum(), "count");
Summarizable summarizable =
new Summarizable() {
@Override
public double max() {
return tDigest.centroids().stream()
.map(Centroid::mean)
.max(Comparator.naturalOrder())
.orElse(Double.NaN);
}
@Override
public double min() {
return tDigest.centroids().stream()
.map(Centroid::mean)
.min(Comparator.naturalOrder())
.orElse(Double.NaN);
}
@Override
public double mean() {
Centroid mean =
tDigest.centroids().stream()
.reduce(
(x, y) ->
new Centroid(
x.mean() + (y.mean() * y.count()), x.count() + y.count()))
.orElse(null);
return mean == null || tDigest.centroids().size() == 0
? Double.NaN
: mean.mean() / mean.count();
}
@Override
public double stdDev() {
return Double.NaN;
}
@Override
public double sum() {
return Double.NaN;
}
};
for (Map.Entry entry :
MetricsToTimeseries.explodeSummarizable(summarizable, reportEmptyHistogramStats)
.entrySet()) {
if (!entry.getValue().isNaN()) {
context.reportSubMetric(entry.getValue(), entry.getKey());
}
}
Sampling sampling =
() ->
new Snapshot(new double[0]) {
@Override
public double get75thPercentile() {
return tDigest.quantile(.75);
}
@Override
public double get95thPercentile() {
return tDigest.quantile(.95);
}
@Override
public double get98thPercentile() {
return tDigest.quantile(.98);
}
@Override
public double get999thPercentile() {
return tDigest.quantile(.999);
}
@Override
public double get99thPercentile() {
return tDigest.quantile(.99);
}
@Override
public double getMedian() {
return tDigest.quantile(.50);
}
@Override
public double getValue(double quantile) {
return tDigest.quantile(quantile);
}
@Override
public double[] getValues() {
return new double[0];
}
@Override
public int size() {
return (int) tDigest.size();
}
};
for (Map.Entry entry :
MetricsToTimeseries.explodeSampling(sampling, reportEmptyHistogramStats).entrySet()) {
if (!entry.getValue().isNaN()) {
context.reportSubMetric(entry.getValue(), entry.getKey());
}
}
sentCounter.inc();
}
} else {
context.reportSubMetric(histogram.count(), "count");
for (Map.Entry entry :
MetricsToTimeseries.explodeSummarizable(histogram, reportEmptyHistogramStats)
.entrySet()) {
if (!entry.getValue().isNaN()) {
context.reportSubMetric(entry.getValue(), entry.getKey());
}
}
for (Map.Entry entry :
MetricsToTimeseries.explodeSampling(histogram, reportEmptyHistogramStats).entrySet()) {
if (!entry.getValue().isNaN()) {
context.reportSubMetric(entry.getValue(), entry.getKey());
}
}
sentCounter.inc();
histogram.clear();
}
}
@Override
public void processTimer(MetricName name, Timer timer, FlushProcessorContext context) {
throw new UnsupportedOperationException();
}
@Override
public void processGauge(MetricName name, Gauge> gauge, FlushProcessorContext context) {
@SuppressWarnings("unchecked")
ChangeableGauge changeableGauge = (ChangeableGauge) gauge;
Double value = changeableGauge.value();
if (value == null || value.isInfinite() || value.isNaN()) return;
context.report(value);
sentCounter.inc();
}
}