blob: bba8562907d3215c7b8fd206ab05a43abbbb40e8 [file] [log] [blame]
/*
* 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.
*/
package org.apache.hugegraph.metrics;
import java.io.IOException;
import java.util.Arrays;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
import org.apache.tinkerpop.shaded.jackson.core.Version;
import org.apache.tinkerpop.shaded.jackson.databind.Module;
import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleSerializers;
import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Snapshot;
import com.codahale.metrics.Timer;
/**
* Copy from com.codahale.metrics.json.MetricsModule
*/
public class MetricsModule extends Module {
private static final Version VERSION = new Version(1, 1, 0, "",
"org.apache.hugegraph",
"hugegraph-api");
@SuppressWarnings("rawtypes")
private static class GaugeSerializer extends StdSerializer<Gauge> {
private static final long serialVersionUID = -5347786455542725809L;
private GaugeSerializer() {
super(Gauge.class);
}
@Override
public void serialize(Gauge gauge, JsonGenerator json,
SerializerProvider provider) throws IOException {
json.writeStartObject();
final Object value;
try {
value = gauge.getValue();
json.writeObjectField("value", value);
} catch (RuntimeException e) {
json.writeObjectField("error", e.toString());
}
json.writeEndObject();
}
}
private static class CounterSerializer extends StdSerializer<Counter> {
private static final long serialVersionUID = -209508117719806468L;
private CounterSerializer() {
super(Counter.class);
}
@Override
public void serialize(Counter counter, JsonGenerator json,
SerializerProvider provider) throws IOException {
json.writeStartObject();
json.writeNumberField("count", counter.getCount());
json.writeEndObject();
}
}
private static class HistogramSerializer extends StdSerializer<Histogram> {
private static final long serialVersionUID = -775852382644934747L;
private final boolean showSamples;
private HistogramSerializer(boolean showSamples) {
super(Histogram.class);
this.showSamples = showSamples;
}
@Override
public void serialize(Histogram histogram, JsonGenerator json,
SerializerProvider provider) throws IOException {
json.writeStartObject();
final Snapshot snapshot = histogram.getSnapshot();
json.writeNumberField("count", histogram.getCount());
json.writeNumberField("min", snapshot.getMin());
json.writeNumberField("mean", snapshot.getMean());
json.writeNumberField("max", snapshot.getMax());
json.writeNumberField("stddev", snapshot.getStdDev());
json.writeNumberField("p50", snapshot.getMedian());
json.writeNumberField("p75", snapshot.get75thPercentile());
json.writeNumberField("p95", snapshot.get95thPercentile());
json.writeNumberField("p98", snapshot.get98thPercentile());
json.writeNumberField("p99", snapshot.get99thPercentile());
json.writeNumberField("p999", snapshot.get999thPercentile());
if (this.showSamples) {
json.writeObjectField("values", snapshot.getValues());
}
json.writeEndObject();
}
}
private static class MeterSerializer extends StdSerializer<Meter> {
private static final long serialVersionUID = 5418467941358294770L;
private final String rateUnit;
private final double rateFactor;
public MeterSerializer(TimeUnit rateUnit) {
super(Meter.class);
this.rateFactor = rateUnit.toSeconds(1);
this.rateUnit = calculateRateUnit(rateUnit, "events");
}
@Override
public void serialize(Meter meter, JsonGenerator json,
SerializerProvider provider) throws IOException {
json.writeStartObject();
json.writeNumberField("count", meter.getCount());
json.writeNumberField("mean_rate", meter.getMeanRate() *
this.rateFactor);
json.writeNumberField("m15_rate", meter.getFifteenMinuteRate() *
this.rateFactor);
json.writeNumberField("m5_rate", meter.getFiveMinuteRate() *
this.rateFactor);
json.writeNumberField("m1_rate", meter.getOneMinuteRate() *
this.rateFactor);
json.writeStringField("rate_unit", this.rateUnit);
json.writeEndObject();
}
}
private static class TimerSerializer extends StdSerializer<Timer> {
private static final long serialVersionUID = 6283520188524929099L;
private final String rateUnit;
private final double rateFactor;
private final String durationUnit;
private final double durationFactor;
private final boolean showSamples;
private TimerSerializer(TimeUnit rateUnit, TimeUnit durationUnit,
boolean showSamples) {
super(Timer.class);
this.rateUnit = calculateRateUnit(rateUnit, "calls");
this.rateFactor = rateUnit.toSeconds(1);
this.durationUnit = durationUnit.toString().toLowerCase(Locale.US);
this.durationFactor = 1.0 / durationUnit.toNanos(1);
this.showSamples = showSamples;
}
@Override
public void serialize(Timer timer, JsonGenerator json,
SerializerProvider provider) throws IOException {
json.writeStartObject();
final Snapshot snapshot = timer.getSnapshot();
json.writeNumberField("count", timer.getCount());
json.writeNumberField("min", snapshot.getMin() *
this.durationFactor);
json.writeNumberField("mean", snapshot.getMean() *
this.durationFactor);
json.writeNumberField("max", snapshot.getMax() *
this.durationFactor);
json.writeNumberField("stddev", snapshot.getStdDev() *
this.durationFactor);
json.writeNumberField("p50", snapshot.getMedian() *
this.durationFactor);
json.writeNumberField("p75", snapshot.get75thPercentile() *
this.durationFactor);
json.writeNumberField("p95", snapshot.get95thPercentile() *
this.durationFactor);
json.writeNumberField("p98", snapshot.get98thPercentile() *
this.durationFactor);
json.writeNumberField("p99", snapshot.get99thPercentile() *
this.durationFactor);
json.writeNumberField("p999", snapshot.get999thPercentile() *
this.durationFactor);
json.writeStringField("duration_unit", this.durationUnit);
if (this.showSamples) {
final long[] values = snapshot.getValues();
final double[] scaledValues = new double[values.length];
for (int i = 0; i < values.length; i++) {
scaledValues[i] = values[i] * this.durationFactor;
}
json.writeObjectField("values", scaledValues);
}
json.writeNumberField("mean_rate", timer.getMeanRate() *
this.rateFactor);
json.writeNumberField("m15_rate", timer.getFifteenMinuteRate() *
this.rateFactor);
json.writeNumberField("m5_rate", timer.getFiveMinuteRate() *
this.rateFactor);
json.writeNumberField("m1_rate", timer.getOneMinuteRate() *
this.rateFactor);
json.writeStringField("rate_unit", this.rateUnit);
json.writeEndObject();
}
}
private static class MetricRegistrySerializer
extends StdSerializer<MetricRegistry> {
private static final long serialVersionUID = 3717001164181726933L;
private final MetricFilter filter;
private MetricRegistrySerializer(MetricFilter filter) {
super(MetricRegistry.class);
this.filter = filter;
}
@Override
public void serialize(MetricRegistry registry, JsonGenerator json,
SerializerProvider provider) throws IOException {
json.writeStartObject();
json.writeStringField("version", VERSION.toString());
json.writeObjectField("gauges", registry.getGauges(this.filter));
json.writeObjectField("counters",
registry.getCounters(this.filter));
json.writeObjectField("histograms",
registry.getHistograms(this.filter));
json.writeObjectField("meters", registry.getMeters(this.filter));
json.writeObjectField("timers", registry.getTimers(this.filter));
json.writeEndObject();
}
}
private final TimeUnit rateUnit;
private final TimeUnit durationUnit;
private final boolean showSamples;
private final MetricFilter filter;
public MetricsModule(TimeUnit rateUnit, TimeUnit durationUnit,
boolean showSamples) {
this(rateUnit, durationUnit, showSamples, MetricFilter.ALL);
}
public MetricsModule(TimeUnit rateUnit, TimeUnit durationUnit,
boolean showSamples, MetricFilter filter) {
this.rateUnit = rateUnit;
this.durationUnit = durationUnit;
this.showSamples = showSamples;
this.filter = filter;
}
@Override
public String getModuleName() {
return "metrics";
}
@Override
public Version version() {
return VERSION;
}
@Override
public void setupModule(Module.SetupContext context) {
context.addSerializers(new SimpleSerializers(Arrays.asList(
new GaugeSerializer(),
new CounterSerializer(),
new HistogramSerializer(this.showSamples),
new MeterSerializer(this.rateUnit),
new TimerSerializer(this.rateUnit, this.durationUnit,
this.showSamples),
new MetricRegistrySerializer(this.filter)
)));
}
private static String calculateRateUnit(TimeUnit unit, String name) {
final String s = unit.toString().toLowerCase(Locale.US);
return name + '/' + s.substring(0, s.length() - 1);
}
}