使用DropWizard计时器查找代码块的执行时间

4
我阅读了这个问题DropWizard Metrics Meters vs Timers,并理解了计时器的概念。但是有没有办法记录代码块的执行时间,每次调用都记录一次呢?我不需要这个计时器的平均速率等信息,因为这个方法不会经常被调用,但是当被调用时会花费相当长的时间。那么有没有办法打印每次调用的执行时间?此外,我该如何回答以下问题:
  1. 如何调查值突然上升的原因?
  2. 如何知道最大时间事件发生的时间,以便我可以查看日志并找出可能的原因?
非常感谢您的帮助。
2个回答

0

为了报告准确的代码块执行时间,可以使用计数器

它可以保持累积时间值,通过取导数可以将其转换为图形上的尖峰。例如,参见Graphite的derivative(..)函数(注意,这不是“真正”的导数,只是值的差异)。

然而,这种方法并不适用于频繁事件,也不太可扩展。在高负载情况下,计时器更适合。

简单的Java助手:

    timed(String metricName, Runnable body) {
        Counter counter = metricsRegistry.counter(metricName);
        long t = System.currentTimeMillis();
        try {
            body.run();
        finally {
            counter.inc(System.currentTimeMillis() - t);
        }
    }


0

我不知道是否有办法获取计时器上下文对象,但我有另一个想法。你说这个方法不太经常被调用。为什么不使用DynamicFeature并打印容器的执行时间?

下面我将展示如何实现这一点。我不确定它是否有效,我只是编码而没有任何测试,请尝试并根据需要更改它。如果ExecutionTimeFilter由于实现的接口需要拆分成两个单独的类,则相应更改即可。

步骤1:创建过滤器

@Provider
public class ExecutionTimeFilter implements ContainerRequestFilter, ContainerResponseFilter {
    public static final String EXECUTION_TIME_HEADER = "X-Execution-Time";

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        requestContext.getHeaders().add(EXECUTION_TIME_HEADER, ZonedDateTime.now().toString());
    }

        @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        ZonedDateTime executionStartHeader = ZonedDateTime.parse(requestContext.getHeaderString(EXECUTION_TIME_HEADER));
        Duration executionTime = Duration.between(executionStartHeader, ZonedDateTime.now());
        //you can also print some url informations or whatever you need; check out the informations from both mehtod params
        System.out.println("The execution time was:" + executionTime);
    }
}

步骤2:创建DynamicFeature

@Provider
public class ExecutionTimeFeature implements DynamicFeature {
    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {
        if (resourceInfo.getResourceMethod().getAnnotation(ExecutionTime.class) != null) {
            context.register(ExecutionTimeFilter.class);
        }
    }
}

步骤 3:创建注释

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExecutionTime {
}

步骤四:为您的资源添加注释

@GET
@ExecutionTime
public String getExcpensiveCalculation(@QueryParam("number") @DefaultValue("1") IntegerParam number) {
    return getCalculation(number);
}

步骤五:注册功能

environment.jersey().register(ExecutionTimeFeature.class);

参考资料:使用过滤器的Dropwizard动态功能


我不知道为什么你的答案被踩了,但当我不想使用复杂的Dropwizard计量时,你的答案为我提供了完美的模板。 - Madhur Bhaiya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接