我正在为我的Java应用程序测试Dropwizard指标。这是一些示例代码。
private static Slf4jReporter reporter = createReporter();
MetricRegistry registry = SharedMetricRegistries.getOrCreate(Test.class.getName());
final Timer timer = registry.timer(name(Test.class, "duration"));
final Timer.Context context = timer.time();
Thread.sleep(2000);
context.stop();
reporter.report();
reporter.report();
两次调用 reporter.report(); 时,它将两次记录同一度量。为了避免这种情况,我编写了一种创建报告者新实例的方法。
static void refreshReporter() {
SharedMetricRegistries.remove(Test.class.getName());
reporter = createReporter();
}
private static Slf4jReporter createReporter() {
return Slf4jReporter
.forRegistry(SharedMetricRegistries.getOrCreate(Test.class.getName()))
.convertDurationsTo(TimeUnit.MILLISECONDS)
.convertRatesTo(TimeUnit.SECONDS)
.outputTo(LOGGER)
.filter((name, metric) -> metric instanceof Timer && name.contains("duration"))
.build();
}
一旦我报告并刷新报告者,使用此按钮,就不会再显示相同的指标。
context.stop();
reporter.report();
refreshReporter();
reporter.report();
这种方法的问题是,如果我在多线程程序中运行它,如果在Timer上下文调用context.stop()之前刷新报告程序,它将丢失下次我打电话给report.report()时没有报告。
因此,有一种很好的方法来确保一旦报告了计时器,便将其从注册表中删除,以便下次调用该报告时,仅记录以前未报告的指标。
在此基础上,以下情况将为Timer生成日志,这些日志为“空”,因为在报告发生之前上下文尚未停止。
reporter.report(); //Thread 1 does this first
context.stop(); // Thread 2 does this after reporter.report() is called
reporter.report(); // Thread 2 does this after context.stop()
此输出为:
Test - type=TIMER, name=Test.duration, count=0, min=0.0, max=0.0, mean=0.0...
Test - type=TIMER, name=Test.duration, count=1, min=2027.758347, max=2027.758347, mean=2027.758347...
在这种情况下,我不想报告尚未“停止”的指标。