All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.greptime.common.util.MetricReporter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2023 Greptime Team
 *
 * 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 io.greptime.common.util;

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.MetricAttribute;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Snapshot;
import com.codahale.metrics.Timer;
import java.io.PrintStream;
import java.text.DateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

/**
 * A reporter which outputs metrics to a {@link PrintStream}, like {@code System.out}.
 * 

* Fork form {@link com.codahale.metrics.ConsoleReporter} */ public class MetricReporter { /** * Returns a new {@link Builder} for {@link MetricReporter}. * * @param registry the registry to report * @return a {@link Builder} instance for a {@link MetricReporter} */ public static Builder forRegistry(MetricRegistry registry) { return new Builder(registry); } /** * Report the current values of all metrics in the registry. */ public void report() { synchronized (this) { report( this.registry.getGauges(this.filter), this.registry.getCounters(this.filter), this.registry.getHistograms(this.filter), this.registry.getMeters(this.filter), this.registry.getTimers(this.filter)); } } /** * A builder for {@link MetricReporter} instances. Defaults to using the default locale and * time zone, writing to {@code System.out}, converting rates to events/second, converting * durations to milliseconds, and not filtering metrics. */ @SuppressWarnings("unused") public static class Builder { private final MetricRegistry registry; private String prefix; private PrintStream output; private Locale locale; private Clock clock; private TimeZone timeZone; private TimeUnit rateUnit; private TimeUnit durationUnit; private MetricFilter filter; private Set disabledMetricAttributes; private Builder(MetricRegistry registry) { this.registry = registry; this.prefix = ""; this.output = System.out; this.locale = Locale.getDefault(); this.clock = Clock.defaultClock(); this.timeZone = TimeZone.getDefault(); this.rateUnit = TimeUnit.SECONDS; this.durationUnit = TimeUnit.MILLISECONDS; this.filter = MetricFilter.ALL; this.disabledMetricAttributes = Collections.emptySet(); } /** * Prefix all metric names with the given string. * * @param prefix the prefix for all banner names * @return {@code this} */ public Builder prefixedWith(String prefix) { this.prefix = prefix; return this; } /** * Write to the given {@link PrintStream}. * * @param output a {@link PrintStream} instance. * @return {@code this} */ public Builder outputTo(PrintStream output) { this.output = output; return this; } /** * Format numbers for the given {@link Locale}. * * @param locale a {@link Locale} * @return {@code this} */ public Builder formattedFor(Locale locale) { this.locale = locale; return this; } /** * Use the given {@link Clock} instance for the time. * * @param clock a {@link Clock} instance * @return {@code this} */ public Builder withClock(Clock clock) { this.clock = clock; return this; } /** * Use the given {@link TimeZone} for the time. * * @param timeZone a {@link TimeZone} * @return {@code this} */ public Builder formattedFor(TimeZone timeZone) { this.timeZone = timeZone; return this; } /** * Convert rates to the given time unit. * * @param rateUnit a unit of time * @return {@code this} */ public Builder convertRatesTo(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(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(MetricFilter filter) { this.filter = filter; return this; } /** * Don't report the passed metric attributes for all metrics (e.g. "p999", "stddev" or "m15"). * See {@link MetricAttribute}. * * @param disabledMetricAttributes a {@link MetricFilter} * @return {@code this} */ public Builder disabledMetricAttributes(Set disabledMetricAttributes) { this.disabledMetricAttributes = disabledMetricAttributes; return this; } /** * Builds a {@link MetricReporter} with the given properties. * * @return a {@link MetricReporter} */ public MetricReporter build() { return new MetricReporter( this.registry, this.output, this.prefix, this.locale, this.clock, this.timeZone, this.rateUnit, this.durationUnit, this.filter, this.disabledMetricAttributes); } } private static final int CONSOLE_WIDTH = 80; private final MetricRegistry registry; private final Set disabledMetricAttributes; private final MetricFilter filter; private final long durationFactor; private final String durationUnit; private final long rateFactor; private final String rateUnit; private final String prefix; private final PrintStream output; private final Locale locale; private final Clock clock; private final DateFormat dateFormat; private MetricReporter( MetricRegistry registry, PrintStream output, String prefix, Locale locale, Clock clock, TimeZone timeZone, TimeUnit rateUnit, TimeUnit durationUnit, MetricFilter filter, Set disabledMetricAttributes) { this.registry = registry; this.output = output; this.prefix = prefix; this.locale = locale; this.clock = clock; this.dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale); this.dateFormat.setTimeZone(timeZone); this.rateFactor = rateUnit.toSeconds(1); this.rateUnit = calculateRateUnit(rateUnit); this.durationFactor = durationUnit.toNanos(1); this.durationUnit = durationUnit.toString().toLowerCase(Locale.US); this.filter = filter; this.disabledMetricAttributes = disabledMetricAttributes != null ? disabledMetricAttributes : Collections.emptySet(); } @SuppressWarnings("rawtypes") public void report( SortedMap gauges, SortedMap counters, SortedMap histograms, SortedMap meters, SortedMap timers) { String dateTime = this.dateFormat.format(new Date(this.clock.getTime())); printWithBanner(dateTime, '='); this.output.println(); if (!gauges.isEmpty()) { printWithBanner("-- Gauges", '-'); for (Map.Entry entry : gauges.entrySet()) { this.output.println(entry.getKey()); printGauge(entry.getValue()); } this.output.println(); } if (!counters.isEmpty()) { printWithBanner("-- Counters", '-'); for (Map.Entry entry : counters.entrySet()) { this.output.println(entry.getKey()); printCounter(entry); } this.output.println(); } if (!histograms.isEmpty()) { printWithBanner("-- Histograms", '-'); for (Map.Entry entry : histograms.entrySet()) { this.output.println(entry.getKey()); printHistogram(entry.getValue()); } this.output.println(); } if (!meters.isEmpty()) { printWithBanner("-- Meters", '-'); for (Map.Entry entry : meters.entrySet()) { this.output.println(entry.getKey()); printMeter(entry.getValue()); } this.output.println(); } if (!timers.isEmpty()) { printWithBanner("-- Timers", '-'); for (Map.Entry entry : timers.entrySet()) { this.output.println(entry.getKey()); printTimer(entry.getValue()); } this.output.println(); } this.output.println(); this.output.flush(); } private void printMeter(Meter meter) { printIfEnabled(MetricAttribute.COUNT, String.format(this.locale, " count = %d", meter.getCount())); printIfEnabled( MetricAttribute.MEAN_RATE, String.format( this.locale, " mean rate = %2.2f events/%s", convertRate(meter.getMeanRate()), this.rateUnit)); printIfEnabled( MetricAttribute.M1_RATE, String.format( this.locale, " 1-minute rate = %2.2f events/%s", convertRate(meter.getOneMinuteRate()), this.rateUnit)); printIfEnabled( MetricAttribute.M5_RATE, String.format( this.locale, " 5-minute rate = %2.2f events/%s", convertRate(meter.getFiveMinuteRate()), this.rateUnit)); printIfEnabled( MetricAttribute.M15_RATE, String.format( this.locale, " 15-minute rate = %2.2f events/%s", convertRate(meter.getFifteenMinuteRate()), this.rateUnit)); } private void printCounter(Map.Entry entry) { this.output.printf( this.locale, " count = %d%n", entry.getValue().getCount()); } private void printGauge(Gauge gauge) { this.output.printf(this.locale, " value = %s%n", gauge.getValue()); } private void printHistogram(Histogram histogram) { printIfEnabled( MetricAttribute.COUNT, String.format(this.locale, " count = %d", histogram.getCount())); Snapshot snapshot = histogram.getSnapshot(); printIfEnabled(MetricAttribute.MIN, String.format(this.locale, " min = %d", snapshot.getMin())); printIfEnabled(MetricAttribute.MAX, String.format(this.locale, " max = %d", snapshot.getMax())); printIfEnabled( MetricAttribute.MEAN, String.format(this.locale, " mean = %2.2f", snapshot.getMean())); printIfEnabled( MetricAttribute.STDDEV, String.format(this.locale, " stddev = %2.2f", snapshot.getStdDev())); printIfEnabled( MetricAttribute.P50, String.format(this.locale, " median = %2.2f", snapshot.getMedian())); printIfEnabled( MetricAttribute.P75, String.format(this.locale, " 75%% <= %2.2f", snapshot.get75thPercentile())); printIfEnabled( MetricAttribute.P95, String.format(this.locale, " 95%% <= %2.2f", snapshot.get95thPercentile())); printIfEnabled( MetricAttribute.P98, String.format(this.locale, " 98%% <= %2.2f", snapshot.get98thPercentile())); printIfEnabled( MetricAttribute.P99, String.format(this.locale, " 99%% <= %2.2f", snapshot.get99thPercentile())); printIfEnabled( MetricAttribute.P999, String.format(this.locale, " 99.9%% <= %2.2f", snapshot.get999thPercentile())); } private void printTimer(Timer timer) { Snapshot snapshot = timer.getSnapshot(); printIfEnabled(MetricAttribute.COUNT, String.format(this.locale, " count = %d", timer.getCount())); printIfEnabled( MetricAttribute.MEAN_RATE, String.format( this.locale, " mean rate = %2.2f calls/%s", convertRate(timer.getMeanRate()), this.rateUnit)); printIfEnabled( MetricAttribute.M1_RATE, String.format( this.locale, " 1-minute rate = %2.2f calls/%s", convertRate(timer.getOneMinuteRate()), this.rateUnit)); printIfEnabled( MetricAttribute.M5_RATE, String.format( this.locale, " 5-minute rate = %2.2f calls/%s", convertRate(timer.getFiveMinuteRate()), this.rateUnit)); printIfEnabled( MetricAttribute.M15_RATE, String.format( this.locale, " 15-minute rate = %2.2f calls/%s", convertRate(timer.getFifteenMinuteRate()), this.rateUnit)); printIfEnabled( MetricAttribute.MIN, String.format( this.locale, " min = %2.2f %s", convertDuration(snapshot.getMin()), this.durationUnit)); printIfEnabled( MetricAttribute.MAX, String.format( this.locale, " max = %2.2f %s", convertDuration(snapshot.getMax()), this.durationUnit)); printIfEnabled( MetricAttribute.MEAN, String.format( this.locale, " mean = %2.2f %s", convertDuration(snapshot.getMean()), this.durationUnit)); printIfEnabled( MetricAttribute.STDDEV, String.format( this.locale, " stddev = %2.2f %s", convertDuration(snapshot.getStdDev()), this.durationUnit)); printIfEnabled( MetricAttribute.P50, String.format( this.locale, " median = %2.2f %s", convertDuration(snapshot.getMedian()), this.durationUnit)); printIfEnabled( MetricAttribute.P75, String.format( this.locale, " 75%% <= %2.2f %s", convertDuration(snapshot.get75thPercentile()), this.durationUnit)); printIfEnabled( MetricAttribute.P95, String.format( this.locale, " 95%% <= %2.2f %s", convertDuration(snapshot.get95thPercentile()), this.durationUnit)); printIfEnabled( MetricAttribute.P98, String.format( this.locale, " 98%% <= %2.2f %s", convertDuration(snapshot.get98thPercentile()), this.durationUnit)); printIfEnabled( MetricAttribute.P99, String.format( this.locale, " 99%% <= %2.2f %s", convertDuration(snapshot.get99thPercentile()), this.durationUnit)); printIfEnabled( MetricAttribute.P999, String.format( this.locale, " 99.9%% <= %2.2f %s", convertDuration(snapshot.get999thPercentile()), this.durationUnit)); } private void printWithBanner(String s, char c) { if (!this.prefix.isEmpty()) { this.output.print(this.prefix); this.output.print(' '); } this.output.print(s); this.output.print(' '); for (int i = 0; i < (CONSOLE_WIDTH - s.length() - 1); i++) { this.output.print(c); } this.output.println(); } /** * Print only if the attribute is enabled * * @param type Metric attribute * @param status Status to be logged */ private void printIfEnabled(MetricAttribute type, String status) { if (this.disabledMetricAttributes.contains(type)) { return; } this.output.println(status); } private String calculateRateUnit(TimeUnit unit) { String s = unit.toString().toLowerCase(Locale.US); return s.substring(0, s.length() - 1); } private double convertRate(double rate) { return rate * this.rateFactor; } private double convertDuration(double duration) { return duration / this.durationFactor; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy