adding ConsoleReporter,Log4jMetricsReporter

This commit is contained in:
Mark Wolters
2023-10-11 09:52:15 -04:00
committed by Jonathan Shook
parent e92ce60739
commit 32b13c0134
6 changed files with 547 additions and 364 deletions

View File

@@ -16,18 +16,25 @@
package io.nosqlbench.engine.core.lifecycle;
import com.codahale.metrics.*;
import com.codahale.metrics.ConsoleReporter.Builder;
import com.codahale.metrics.Counting;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricAttribute;
import com.codahale.metrics.MetricFilter;
import io.nosqlbench.api.engine.metrics.instruments.*;
import io.nosqlbench.api.engine.metrics.reporters.ConsoleReporter;
import io.nosqlbench.api.engine.metrics.reporters.Log4JMetricsReporter;
import io.nosqlbench.api.engine.metrics.reporters.Log4JMetricsReporter.LoggingLevel;
import io.nosqlbench.components.NBBuilders;
import io.nosqlbench.components.NBComponent;
import io.nosqlbench.components.NBComponentTraversal;
import io.nosqlbench.components.NBFinders;
import io.nosqlbench.engine.core.metrics.NBMetricsSummary;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class ExecutionMetricsResult extends ExecutionResult {
@@ -53,71 +60,71 @@ public class ExecutionMetricsResult extends ExecutionResult {
super(startedAt, endedAt, iolog, error);
}
public String getMetricsSummary() {
public String getMetricsSummary(NBComponent component) {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
try (final PrintStream ps = new PrintStream(os)) {
// TODO: metrics
// final Builder builder = ConsoleReporter.forRegistry(ActivityMetrics.getMetricRegistry())
// .convertDurationsTo(TimeUnit.MICROSECONDS)
// .convertRatesTo(TimeUnit.SECONDS)
// .filter(MetricFilter.ALL)
// .outputTo(ps);
// final Set<MetricAttribute> disabled = new HashSet<>(ExecutionMetricsResult.INTERVAL_ONLY_METRICS);
// if (60000 > this.getElapsedMillis()) disabled.addAll(ExecutionMetricsResult.OVER_ONE_MINUTE_METRICS);
// builder.disabledMetricAttributes(disabled);
// final ConsoleReporter consoleReporter = builder.build();
// consoleReporter.report();
// consoleReporter.close();
final NBBuilders.ConsoleReporterBuilder builder = new NBBuilders.ConsoleReporterBuilder(component, ps);
final Set<MetricAttribute> disabled = new HashSet<>(ExecutionMetricsResult.INTERVAL_ONLY_METRICS);
if (60000 > this.getElapsedMillis()) disabled.addAll(ExecutionMetricsResult.OVER_ONE_MINUTE_METRICS);
builder.disabledMetricAttributes(disabled);
final ConsoleReporter consoleReporter = builder.build();
consoleReporter.report();
consoleReporter.close();
}
final String result = os.toString(StandardCharsets.UTF_8);
return result;
}
public void reportToConsole() {
final String summaryReport = this.getMetricsSummary();
public void reportToConsole(NBComponent component) {
final String summaryReport = this.getMetricsSummary(component);
System.out.println(summaryReport);
}
public void reportMetricsSummaryTo(final PrintStream out) {
out.println(this.getMetricsSummary());
public void reportMetricsSummaryTo(NBComponent component, final PrintStream out) {
out.println(this.getMetricsSummary(component));
}
public void reportMetricsSummaryToLog() {
public void reportMetricsSummaryToLog(NBComponent component) {
ExecutionResult.logger.debug("-- WARNING: Metrics which are taken per-interval (like histograms) will not have --");
ExecutionResult.logger.debug("-- active data on this last report. (The workload has already stopped.) Record --");
ExecutionResult.logger.debug("-- metrics to an external format to see values for each reporting interval. --");
ExecutionResult.logger.debug("-- BEGIN METRICS DETAIL --");
// TODO: metrics
// final Log4JMetricsReporter reporter = Log4JMetricsReporter.forRegistry(ActivityMetrics.getMetricRegistry())
// .withLoggingLevel(LoggingLevel.DEBUG)
// .convertDurationsTo(TimeUnit.MICROSECONDS)
// .convertRatesTo(TimeUnit.SECONDS)
// .filter(MetricFilter.ALL)
// .outputTo(ExecutionResult.logger)
// .build();
// reporter.report();
// reporter.close();
final Log4JMetricsReporter reporter = new NBBuilders.Log4jReporterBuilder(component)
.withLoggingLevel(Log4JMetricsReporter.LoggingLevel.DEBUG)
.filter(MetricFilter.ALL)
.outputTo(ExecutionResult.logger)
.build();
reporter.report(NBFinders.allMetricsWithType(NBMetricGauge.class, component),
NBFinders.allMetricsWithType(NBMetricCounter.class, component),
NBFinders.allMetricsWithType(NBMetricHistogram.class, component),
NBFinders.allMetricsWithType(NBMetricMeter.class, component),
NBFinders.allMetricsWithType(NBMetricTimer.class, component));
reporter.close();
ExecutionResult.logger.debug("-- END METRICS DETAIL --");
}
public void reportMetricsCountsTo(final PrintStream printStream) {
public void reportMetricsCountsTo(NBComponent component, final PrintStream printStream) {
final StringBuilder sb = new StringBuilder();
// TODO: metrics
// ActivityMetrics.getMetricRegistry().getMetrics().forEach((k, v) -> {
// if (v instanceof Counting counting) {
// final long count = counting.getCount();
// if (0 < count) NBMetricsSummary.summarize(sb, k, v);
// } else if (v instanceof Gauge<?> gauge) {
// final Object value = gauge.getValue();
// if (value instanceof Number n) if (0 != n.doubleValue()) NBMetricsSummary.summarize(sb, k, v);
// }
// });
//
Iterator<NBComponent> allMetrics = NBComponentTraversal.traverseBreadth(component);
allMetrics.forEachRemaining(m -> {
for (NBMetric metric : m.findComponentMetrics("")) {
if (metric instanceof Counting counting) {
final long count = counting.getCount();
if (0 < count) {
NBMetricsSummary.summarize(sb, metric.getLabels().linearizeAsMetrics(), metric);
}
} else if (metric instanceof Gauge<?> gauge) {
final Object value = gauge.getValue();
if (value instanceof Number n) if (0 != n.doubleValue()) {
NBMetricsSummary.summarize(sb, metric.getLabels().linearizeAsMetrics(), metric);
}
}
}
});
printStream.println("-- BEGIN NON-ZERO metric counts (run longer for full report):");
printStream.print(sb);
printStream.println("-- END NON-ZERO metric counts:");
}
}

View File

@@ -16,6 +16,7 @@
package io.nosqlbench.engine.core.lifecycle.scenario.execution;
import io.nosqlbench.components.NBComponent;
import io.nosqlbench.engine.core.lifecycle.ExecutionMetricsResult;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -29,7 +30,7 @@ import java.util.Map;
public class ScenarioSummary {
private final static Logger logger = LogManager.getLogger(ScenarioSummary.class);
private static void doReportSummaries(final String reportSummaryTo, final ExecutionMetricsResult result, Map<String,String> subs) {
private static void doReportSummaries(NBComponent scenario, final String reportSummaryTo, final ExecutionMetricsResult result, Map<String,String> subs) {
final List<PrintStream> fullChannels = new ArrayList<>();
final List<PrintStream> briefChannels = new ArrayList<>();
final String[] destinationSpecs = reportSummaryTo.split(", *");
@@ -69,8 +70,9 @@ public class ScenarioSummary {
briefChannels.add(out);
}
}
fullChannels.forEach(result::reportMetricsSummaryTo);
// briefChannels.forEach(result::reportCountsTo);
for (PrintStream fullChannel : fullChannels) {
result.reportMetricsSummaryTo(scenario, fullChannel);
}
}
}

View File

@@ -0,0 +1,224 @@
/*
* Copyright (c) 2023 nosqlbench
*
* 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.nosqlbench.api.engine.metrics.reporters;
import com.codahale.metrics.Timer;
import com.codahale.metrics.*;
import io.nosqlbench.api.engine.metrics.instruments.*;
import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.components.NBComponent;
import io.nosqlbench.components.NBFinders;
import io.nosqlbench.components.PeriodicTaskComponent;
import java.io.PrintStream;
import java.text.DateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class ConsoleReporter extends PeriodicTaskComponent {
private static final int CONSOLE_WIDTH = 80;
private final PrintStream output;
private final Locale locale = Locale.US;
private final Clock clock = Clock.defaultClock();
private final DateFormat dateFormat;
private final Set<MetricAttribute> disabledMetricAttributes;
private final String rateUnit;
private final long rateFactor;
private final String durationUnit = TimeUnit.NANOSECONDS.toString().toLowerCase(Locale.US);
private final long durationFactor = TimeUnit.NANOSECONDS.toNanos(1);
public ConsoleReporter(NBComponent node, NBLabels extraLabels, int seconds, boolean oneLastTime,
PrintStream output, Set<MetricAttribute> disabledMetricAttributes) {
super(node, extraLabels, seconds, oneLastTime);
this.output = output;
this.dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.MEDIUM,
locale);
dateFormat.setTimeZone(TimeZone.getDefault());
this.disabledMetricAttributes = disabledMetricAttributes;
String s = TimeUnit.NANOSECONDS.toString().toLowerCase(Locale.US);
rateUnit = s.substring(0, s.length() - 1);
this.rateFactor = TimeUnit.NANOSECONDS.toSeconds(1);
}
@Override
protected void task() {
report();
}
public void report() {
report(NBFinders.allMetricsWithType(NBMetricGauge.class, getParent()),
NBFinders.allMetricsWithType(NBMetricCounter.class, getParent()),
NBFinders.allMetricsWithType(NBMetricHistogram.class, getParent()),
NBFinders.allMetricsWithType(NBMetricMeter.class, getParent()),
NBFinders.allMetricsWithType(NBMetricTimer.class, getParent())
);
}
public void report(List<NBMetricGauge> gauges,
List<NBMetricCounter> counters,
List<NBMetricHistogram> histograms,
List<NBMetricMeter> meters,
List<NBMetricTimer> timers) {
final String dateTime = dateFormat.format(new Date(clock.getTime()));
printWithBanner(dateTime, '=');
output.println();
if (!gauges.isEmpty()) {
printWithBanner("-- Gauges", '-');
for (NBMetricGauge gauge : gauges) {
output.println(gauge.getLabels().linearizeAsMetrics());
printGauge(gauge);
}
output.println();
}
if (!counters.isEmpty()) {
printWithBanner("-- Counters", '-');
for (NBMetricCounter counter : counters) {
output.println(counter.getLabels().linearizeAsMetrics());
printCounter(counter);
}
output.println();
}
if (!histograms.isEmpty()) {
printWithBanner("-- Histograms", '-');
for (NBMetricHistogram histogram : histograms) {
output.println(histogram.getLabels().linearizeAsMetrics());
printHistogram(histogram);
}
output.println();
}
if (!meters.isEmpty()) {
printWithBanner("-- Meters", '-');
for (NBMetricMeter meter : meters) {
output.println(meter.getLabels().linearizeAsMetrics());
printMeter(meter);
}
output.println();
}
if (!timers.isEmpty()) {
printWithBanner("-- Timers", '-');
for (NBMetricTimer timer : timers) {
output.println(timer.getLabels().linearizeAsMetrics());
printTimer(timer);
}
output.println();
}
output.println();
output.flush();
}
private void printMeter(Meter meter) {
printIfEnabled(MetricAttribute.COUNT, String.format(locale, " count = %d", meter.getCount()));
printIfEnabled(MetricAttribute.MEAN_RATE, String.format(locale, " mean rate = %2.2f events/%s", convertRate(meter.getMeanRate()), getRateUnit()));
printIfEnabled(MetricAttribute.M1_RATE, String.format(locale, " 1-minute rate = %2.2f events/%s", convertRate(meter.getOneMinuteRate()), getRateUnit()));
printIfEnabled(MetricAttribute.M5_RATE, String.format(locale, " 5-minute rate = %2.2f events/%s", convertRate(meter.getFiveMinuteRate()), getRateUnit()));
printIfEnabled(MetricAttribute.M15_RATE, String.format(locale, " 15-minute rate = %2.2f events/%s", convertRate(meter.getFifteenMinuteRate()), getRateUnit()));
}
private void printCounter(Counter counter) {
output.printf(locale, " count = %d%n", counter.getCount());
}
private void printGauge(Gauge<?> gauge) {
output.printf(locale, " value = %s%n", gauge.getValue());
}
private void printHistogram(Histogram histogram) {
printIfEnabled(MetricAttribute.COUNT, String.format(locale, " count = %d", histogram.getCount()));
Snapshot snapshot = histogram.getSnapshot();
printIfEnabled(MetricAttribute.MIN, String.format(locale, " min = %d", snapshot.getMin()));
printIfEnabled(MetricAttribute.MAX, String.format(locale, " max = %d", snapshot.getMax()));
printIfEnabled(MetricAttribute.MEAN, String.format(locale, " mean = %2.2f", snapshot.getMean()));
printIfEnabled(MetricAttribute.STDDEV, String.format(locale, " stddev = %2.2f", snapshot.getStdDev()));
printIfEnabled(MetricAttribute.P50, String.format(locale, " median = %2.2f", snapshot.getMedian()));
printIfEnabled(MetricAttribute.P75, String.format(locale, " 75%% <= %2.2f", snapshot.get75thPercentile()));
printIfEnabled(MetricAttribute.P95, String.format(locale, " 95%% <= %2.2f", snapshot.get95thPercentile()));
printIfEnabled(MetricAttribute.P98, String.format(locale, " 98%% <= %2.2f", snapshot.get98thPercentile()));
printIfEnabled(MetricAttribute.P99, String.format(locale, " 99%% <= %2.2f", snapshot.get99thPercentile()));
printIfEnabled(MetricAttribute.P999, String.format(locale, " 99.9%% <= %2.2f", snapshot.get999thPercentile()));
}
private void printTimer(Timer timer) {
final Snapshot snapshot = timer.getSnapshot();
printIfEnabled(MetricAttribute.COUNT, String.format(locale, " count = %d", timer.getCount()));
printIfEnabled(MetricAttribute.MEAN_RATE, String.format(locale, " mean rate = %2.2f calls/%s", convertRate(timer.getMeanRate()), getRateUnit()));
printIfEnabled(MetricAttribute.M1_RATE, String.format(locale, " 1-minute rate = %2.2f calls/%s", convertRate(timer.getOneMinuteRate()), getRateUnit()));
printIfEnabled(MetricAttribute.M5_RATE, String.format(locale, " 5-minute rate = %2.2f calls/%s", convertRate(timer.getFiveMinuteRate()), getRateUnit()));
printIfEnabled(MetricAttribute.M15_RATE, String.format(locale, " 15-minute rate = %2.2f calls/%s", convertRate(timer.getFifteenMinuteRate()), getRateUnit()));
printIfEnabled(MetricAttribute.MIN, String.format(locale, " min = %2.2f %s", convertDuration(snapshot.getMin()), getDurationUnit()));
printIfEnabled(MetricAttribute.MAX, String.format(locale, " max = %2.2f %s", convertDuration(snapshot.getMax()), getDurationUnit()));
printIfEnabled(MetricAttribute.MEAN, String.format(locale, " mean = %2.2f %s", convertDuration(snapshot.getMean()), getDurationUnit()));
printIfEnabled(MetricAttribute.STDDEV, String.format(locale, " stddev = %2.2f %s", convertDuration(snapshot.getStdDev()), getDurationUnit()));
printIfEnabled(MetricAttribute.P50, String.format(locale, " median = %2.2f %s", convertDuration(snapshot.getMedian()), getDurationUnit()));
printIfEnabled(MetricAttribute.P75, String.format(locale, " 75%% <= %2.2f %s", convertDuration(snapshot.get75thPercentile()), getDurationUnit()));
printIfEnabled(MetricAttribute.P95, String.format(locale, " 95%% <= %2.2f %s", convertDuration(snapshot.get95thPercentile()), getDurationUnit()));
printIfEnabled(MetricAttribute.P98, String.format(locale, " 98%% <= %2.2f %s", convertDuration(snapshot.get98thPercentile()), getDurationUnit()));
printIfEnabled(MetricAttribute.P99, String.format(locale, " 99%% <= %2.2f %s", convertDuration(snapshot.get99thPercentile()), getDurationUnit()));
printIfEnabled(MetricAttribute.P999, String.format(locale, " 99.9%% <= %2.2f %s", convertDuration(snapshot.get999thPercentile()), getDurationUnit()));
}
private void printWithBanner(String s, char c) {
output.print(s);
output.print(' ');
for (int i = 0; i < (CONSOLE_WIDTH - s.length() - 1); i++) {
output.print(c);
}
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 (getDisabledMetricAttributes().contains(type)) {
return;
}
output.println(status);
}
private Set<MetricAttribute> getDisabledMetricAttributes() {
return disabledMetricAttributes;
}
protected String getRateUnit() {
return rateUnit;
}
protected double convertRate(double rate) {
return rate * rateFactor;
}
protected String getDurationUnit() {
return durationUnit;
}
protected double convertDuration(double duration) {
return duration / durationFactor;
}
}

View File

@@ -17,13 +17,15 @@
package io.nosqlbench.api.engine.metrics.reporters;
import com.codahale.metrics.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import io.nosqlbench.api.engine.metrics.instruments.*;
import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.components.NBBuilders;
import io.nosqlbench.components.NBComponent;
import io.nosqlbench.components.NBFinders;
import io.nosqlbench.components.PeriodicTaskComponent;
import org.apache.logging.log4j.Marker;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
@@ -32,222 +34,59 @@ import java.util.concurrent.TimeUnit;
* was built to allow for consolidating internal logging dependencies
* to log4j only.
*/
public class Log4JMetricsReporter extends ScheduledReporter {
/**
* Returns a new {@link Builder} for .
*
* @param registry the registry to report
* @return a {@link Builder} instance for a
*/
public static Builder forRegistry(final MetricRegistry registry) {
return new Builder(registry);
}
public class Log4JMetricsReporter extends PeriodicTaskComponent {
public enum LoggingLevel { TRACE, DEBUG, INFO, WARN, ERROR }
/**
* A builder for {@link Log4JMetricsReporter} instances. Defaults to logging to {@code metrics}, not
* using a marker, converting rates to events/second, converting durations to milliseconds, and
* not filtering metrics.
*/
public static class Builder {
private final MetricRegistry registry;
private Logger logger;
private LoggingLevel loggingLevel;
private Marker marker;
private String prefix;
private TimeUnit rateUnit;
private TimeUnit durationUnit;
private MetricFilter filter;
private ScheduledExecutorService executor;
private boolean shutdownExecutorOnStop;
private Builder(final MetricRegistry registry) {
this.registry = registry;
logger = LogManager.getLogger("metrics");
marker = null;
prefix = "";
rateUnit = TimeUnit.SECONDS;
durationUnit = TimeUnit.MILLISECONDS;
filter = MetricFilter.ALL;
loggingLevel = LoggingLevel.INFO;
executor = null;
shutdownExecutorOnStop = true;
}
/**
* Specifies whether or not, the executor (used for reporting) will be stopped with same time with reporter.
* Default value is true.
* Setting this parameter to false, has the sense in combining with providing external managed executor via {@link #scheduleOn(ScheduledExecutorService)}.
*
* @param shutdownExecutorOnStop if true, then executor will be stopped in same time with this reporter
* @return {@code this}
*/
public Builder shutdownExecutorOnStop(final boolean shutdownExecutorOnStop) {
this.shutdownExecutorOnStop = shutdownExecutorOnStop;
return this;
}
/**
* Specifies the executor to use while scheduling reporting of metrics.
* Default value is null.
* Null value leads to executor will be auto created on start.
*
* @param executor the executor to use while scheduling reporting of metrics.
* @return {@code this}
*/
public Builder scheduleOn(final ScheduledExecutorService executor) {
this.executor = executor;
return this;
}
/**
* Log metrics to the given logger.
*
* @param logger an SLF4J {@link Logger}
* @return {@code this}
*/
public Builder outputTo(final Logger logger) {
this.logger = logger;
return this;
}
/**
* Mark all logged metrics with the given marker.
*
* @param marker an SLF4J {@link Marker}
* @return {@code this}
*/
public Builder markWith(final Marker marker) {
this.marker = marker;
return this;
}
/**
* Prefix all metric names with the given string.
*
* @param prefix the prefix for all metric names
* @return {@code this}
*/
public Builder prefixedWith(final String prefix) {
this.prefix = prefix;
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;
}
/**
* Use Logging Level when reporting.
*
* @param loggingLevel a (@link Slf4jReporter.LoggingLevel}
* @return {@code this}
*/
public Builder withLoggingLevel(final LoggingLevel loggingLevel) {
this.loggingLevel = loggingLevel;
return this;
}
/**
* Builds a {@link Log4JMetricsReporter} with the given properties.
*
* @return a {@link Log4JMetricsReporter}
*/
public Log4JMetricsReporter build() {
final LoggerProxy loggerProxy;
switch (this.loggingLevel) {
case TRACE:
loggerProxy = new TraceLoggerProxy(this.logger);
break;
case INFO:
loggerProxy = new InfoLoggerProxy(this.logger);
break;
case WARN:
loggerProxy = new WarnLoggerProxy(this.logger);
break;
case ERROR:
loggerProxy = new ErrorLoggerProxy(this.logger);
break;
default:
case DEBUG:
loggerProxy = new DebugLoggerProxy(this.logger);
break;
}
return new Log4JMetricsReporter(this.registry, loggerProxy, this.marker, this.prefix, this.rateUnit, this.durationUnit, this.filter, this.executor, this.shutdownExecutorOnStop);
}
}
private final LoggerProxy loggerProxy;
private final NBBuilders.LoggerProxy loggerProxy;
private final Marker marker;
private final String prefix;
private final TimeUnit rateUnit = TimeUnit.NANOSECONDS;
private final TimeUnit durationUnit = TimeUnit.NANOSECONDS;
private final long durationFactor = TimeUnit.NANOSECONDS.toNanos(1);
private final long rateFactor = TimeUnit.NANOSECONDS.toSeconds(1);
private Log4JMetricsReporter(final MetricRegistry registry,
final LoggerProxy loggerProxy,
final Marker marker,
final String prefix,
final TimeUnit rateUnit,
final TimeUnit durationUnit,
final MetricFilter filter,
final ScheduledExecutorService executor,
final boolean shutdownExecutorOnStop) {
super(registry, "logger-reporter", filter, rateUnit, durationUnit, executor, shutdownExecutorOnStop);
public Log4JMetricsReporter(final NBComponent component,
final NBBuilders.LoggerProxy loggerProxy,
final Marker marker,
final MetricFilter filter,
final NBLabels extraLabels,
final int seconds,
final boolean oneLastTime) {
super(component, extraLabels, seconds, oneLastTime);
this.loggerProxy = loggerProxy;
this.marker = marker;
this.prefix = prefix;
}
@Override
@SuppressWarnings("rawtypes")
public void report(final SortedMap<String, Gauge> gauges,
final SortedMap<String, Counter> counters,
final SortedMap<String, Histogram> histograms,
final SortedMap<String, Meter> meters,
final SortedMap<String, Timer> timers) {
protected void task() {
report(NBFinders.allMetricsWithType(NBMetricGauge.class, getParent()),
NBFinders.allMetricsWithType(NBMetricCounter.class, getParent()),
NBFinders.allMetricsWithType(NBMetricHistogram.class, getParent()),
NBFinders.allMetricsWithType(NBMetricMeter.class, getParent()),
NBFinders.allMetricsWithType(NBMetricTimer.class, getParent())
);
}
public void report( List<NBMetricGauge> gauges,
List<NBMetricCounter> counters,
List<NBMetricHistogram> histograms,
List<NBMetricMeter> meters,
List<NBMetricTimer> timers) {
if (this.loggerProxy.isEnabled(this.marker)) {
for (final Map.Entry<String, Gauge> entry : gauges.entrySet())
this.logGauge(entry.getKey(), entry.getValue());
for (NBMetricGauge gauge : gauges)
this.logGauge(gauge.getLabels().linearizeAsMetrics(), gauge);
for (final Map.Entry<String, Counter> entry : counters.entrySet())
this.logCounter(entry.getKey(), entry.getValue());
for (NBMetricCounter counter : counters)
this.logCounter(counter.getLabels().linearizeAsMetrics(), counter);
for (final Map.Entry<String, Histogram> entry : histograms.entrySet())
this.logHistogram(entry.getKey(), entry.getValue());
for (NBMetricHistogram histogram : histograms)
this.logHistogram(histogram.getLabels().linearizeAsMetrics(), histogram);
for (final Map.Entry<String, Meter> entry : meters.entrySet())
this.logMeter(entry.getKey(), entry.getValue());
for (NBMetricMeter meter : meters)
this.logMeter(meter.getLabels().linearizeAsMetrics(), meter);
for (final Map.Entry<String, Timer> entry : timers.entrySet())
this.logTimer(entry.getKey(), entry.getValue());
for (NBMetricTimer timer : timers)
this.logTimer(timer.getLabels().linearizeAsMetrics(), timer);
}
}
@@ -275,7 +114,14 @@ public class Log4JMetricsReporter extends ScheduledReporter {
this.convertRate(timer.getFiveMinuteRate()),
this.convertRate(timer.getFifteenMinuteRate()),
this.getRateUnit(),
this.getDurationUnit());
this.durationUnit);
}
protected double convertDuration(double duration) {
return duration / durationFactor;
}
protected double convertRate(double rate) {
return rate * rateFactor;
}
private void logMeter(final String name, final Meter meter) {
@@ -319,111 +165,12 @@ public class Log4JMetricsReporter extends ScheduledReporter {
this.loggerProxy.log(this.marker, "type={}, name={}, value={}", "GAUGE", this.prefix(name), gauge.getValue());
}
@Override
protected String getRateUnit() {
return "events/" + super.getRateUnit();
return "events/" + rateUnit;
}
private String prefix(final String... components) {
return MetricRegistry.name(this.prefix, components);
}
/* private class to allow logger configuration */
abstract static class LoggerProxy {
protected final Logger logger;
protected LoggerProxy(final Logger logger) {
this.logger = logger;
}
abstract void log(Marker marker, String format, Object... arguments);
abstract boolean isEnabled(Marker marker);
}
/* private class to allow logger configuration */
private static class DebugLoggerProxy extends LoggerProxy {
public DebugLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.debug(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isDebugEnabled(marker);
}
}
/* private class to allow logger configuration */
private static class TraceLoggerProxy extends LoggerProxy {
public TraceLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.trace(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isTraceEnabled(marker);
}
}
/* private class to allow logger configuration */
private static class InfoLoggerProxy extends LoggerProxy {
public InfoLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.info(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isInfoEnabled(marker);
}
}
/* private class to allow logger configuration */
private static class WarnLoggerProxy extends LoggerProxy {
public WarnLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.warn(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isWarnEnabled(marker);
}
}
/* private class to allow logger configuration */
private static class ErrorLoggerProxy extends LoggerProxy {
public ErrorLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.error(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isErrorEnabled(marker);
}
return NBLabels.forKV((Object[]) components).linearizeAsMetrics();
}
}

View File

@@ -37,6 +37,16 @@ import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.api.shutdown.NBShutdownHook;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.codahale.metrics.MetricAttribute;
import com.codahale.metrics.MetricFilter;
import io.nosqlbench.api.csvoutput.CsvOutputPluginWriter;
import io.nosqlbench.api.engine.metrics.reporters.*;
import io.nosqlbench.api.files.FileAccess;
import io.nosqlbench.api.optimizers.BobyqaOptimizerInstance;
import org.apache.logging.log4j.Marker;
import java.io.PrintStream;
import java.util.Set;
import java.nio.file.Path;
import java.util.Arrays;
@@ -126,15 +136,11 @@ public class NBBuilders {
return reporter;
}
// public ExamplePlugin getExamplePlugin(final NBComponent component) {
// return new ExamplePlugin(component);
// }
public BobyqaOptimizerInstance bobyqaOptimizer() {
return new BobyqaOptimizerInstance(base);
}
public FileAccess fileAccess(String filename) {
public FileAccess fileAccess() {
return new FileAccess();
}
@@ -154,6 +160,190 @@ public class NBBuilders {
return new NBShutdownHook(component);
}
public static class Log4jReporterBuilder {
private final NBComponent component;
private Logger logger = LogManager.getLogger(Log4JMetricsReporter.class);
private Log4JMetricsReporter.LoggingLevel loggingLevel = Log4JMetricsReporter.LoggingLevel.INFO;
private Marker marker;
private MetricFilter filter= new MetricInstanceFilter();
private boolean oneLastTime = false;
private NBLabels labels;
private int interval = 1;
public Log4jReporterBuilder(NBComponent component) {
this.component = component;
}
public Log4jReporterBuilder oneLastTime(final boolean oneLastTime) {
this.oneLastTime = oneLastTime;
return this;
}
public Log4jReporterBuilder interval(final int interval) {
this.interval = interval;
return this;
}
public Log4jReporterBuilder outputTo(final Logger logger) {
this.logger = logger;
return this;
}
public Log4jReporterBuilder markWith(final Marker marker) {
this.marker = marker;
return this;
}
public Log4jReporterBuilder labels(final NBLabels labels) {
this.labels = labels;
return this;
}
public Log4jReporterBuilder filter(final MetricFilter filter) {
this.filter = filter;
return this;
}
public Log4jReporterBuilder withLoggingLevel(final Log4JMetricsReporter.LoggingLevel loggingLevel) {
this.loggingLevel = loggingLevel;
return this;
}
public Log4JMetricsReporter build() {
final LoggerProxy loggerProxy = switch (this.loggingLevel) {
case TRACE -> new TraceLoggerProxy(this.logger);
case INFO -> new InfoLoggerProxy(this.logger);
case WARN -> new WarnLoggerProxy(this.logger);
case ERROR -> new ErrorLoggerProxy(this.logger);
default -> new DebugLoggerProxy(this.logger);
};
return new Log4JMetricsReporter(this.component, loggerProxy, this.marker, this.filter, this.labels, this.interval, this.oneLastTime);
}
}
/* private class to allow logger configuration */
public abstract static class LoggerProxy {
protected final Logger logger;
protected LoggerProxy(final Logger logger) {
this.logger = logger;
}
public abstract void log(Marker marker, String format, Object... arguments);
public abstract boolean isEnabled(Marker marker);
}
/* private class to allow logger configuration */
private static class DebugLoggerProxy extends LoggerProxy {
public DebugLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.debug(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isDebugEnabled(marker);
}
}
/* private class to allow logger configuration */
private static class TraceLoggerProxy extends LoggerProxy {
public TraceLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.trace(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isTraceEnabled(marker);
}
}
/* private class to allow logger configuration */
private static class InfoLoggerProxy extends LoggerProxy {
public InfoLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.info(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isInfoEnabled(marker);
}
}
/* private class to allow logger configuration */
private static class WarnLoggerProxy extends LoggerProxy {
public WarnLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.warn(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isWarnEnabled(marker);
}
}
/* private class to allow logger configuration */
private static class ErrorLoggerProxy extends LoggerProxy {
public ErrorLoggerProxy(final Logger logger) {
super(logger);
}
@Override
public void log(final Marker marker, final String format, final Object... arguments) {
this.logger.error(marker, format, arguments);
}
@Override
public boolean isEnabled(final Marker marker) {
return this.logger.isErrorEnabled(marker);
}
}
public static class ConsoleReporterBuilder {
private final NBComponent component;
private final PrintStream output;
private NBLabels labels = null;
private int interval = 1;
private boolean oneLastTime = false;
private Set<MetricAttribute> disabledMetricAttributes = Set.of();
public ConsoleReporterBuilder(NBComponent component, PrintStream output) {
this.component = component;
this.output = output;
}
public ConsoleReporterBuilder labels(NBLabels labels) {
this.labels = labels;
return this;
}
public ConsoleReporterBuilder interval(int interval) {
this.interval = interval;
return this;
}
public ConsoleReporterBuilder oneLastTime(boolean oneLastTime) {
this.oneLastTime = oneLastTime;
return this;
}
public ConsoleReporterBuilder disabledMetricAttributes(Set<MetricAttribute> disabledMetricAttributes) {
this.disabledMetricAttributes = disabledMetricAttributes;
return this;
}
public ConsoleReporter build() {
return new ConsoleReporter(component, labels, interval, oneLastTime, output, disabledMetricAttributes);
}
}
public static class CsvOutputWriterBuilder {
private final NBComponent component;
@@ -204,7 +394,7 @@ public class NBBuilders {
return this;
}
public CsvReporter build() {
return new CsvReporter(component, reportTo, interval, filter);
return new CsvReporter(component, reportTo, interval, filter, labels);
}
}

View File

@@ -57,6 +57,19 @@ public class NBFinders {
}
}
public static <T extends NBMetric> List<T> allMetricsWithType(Class<T> clazz, NBComponent component) {
Iterator<NBComponent> tree = NBComponentTraversal.traverseBreadth(component);
List<NBMetric> found = new ArrayList<>();
while (tree.hasNext()) {
NBComponent c = tree.next();
for (NBMetric metric : c.getComponentMetrics()) {
if (clazz.isAssignableFrom(metric.getClass())) {
found.add(metric);
}
}
}
return (List<T>) found;
}
public NBMetricGauge gauge(String pattern) {
return oneMetricWithType(pattern, NBMetricGauge.class);