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

Java 使用DropWizard计时器查找代码块的执行时间,java,timer,dropwizard,metrics,codahale-metrics,Java,Timer,Dropwizard,Metrics,Codahale Metrics,通过这个问题,我理解了计时器的概念。但是,有没有一种方法可以记录每次调用代码块时代码块的执行时间?我不想要这个计时器的平均速率和东西,因为这个方法调用得不那么频繁,但调用时需要相当长的时间。有没有办法打印每个调用的执行时间?还有,我怎样才能得到以下问题的答案 我如何调查这些值出现峰值的原因 我如何知道最长时间事件何时发生,以便查看日志并查看可能的原因 任何帮助都将不胜感激。我不知道是否有办法获取计时器上下文对象,但我有另一个想法。你说过这个方法不常被调用。为什么不使用DynamicFeature

通过这个问题,我理解了计时器的概念。但是,有没有一种方法可以记录每次调用代码块时代码块的执行时间?我不想要这个计时器的平均速率和东西,因为这个方法调用得不那么频繁,但调用时需要相当长的时间。有没有办法打印每个调用的执行时间?还有,我怎样才能得到以下问题的答案

  • 我如何调查这些值出现峰值的原因
  • 我如何知道最长时间事件何时发生,以便查看日志并查看可能的原因
    任何帮助都将不胜感激。

    我不知道是否有办法获取计时器上下文对象,但我有另一个想法。你说过这个方法不常被调用。为什么不使用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);
            }
        }
    }
    
    @GET
    @ExecutionTime
    public String getExcpensiveCalculation(@QueryParam("number") @DefaultValue("1") IntegerParam number) {
        return getCalculation(number);
    }
    
    environment.jersey().register(ExecutionTimeFeature.class);
    
    步骤3:创建注释

    @Target({ ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ExecutionTime {
    }
    
    步骤4:为资源添加注释

    @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);
            }
        }
    }
    
    @GET
    @ExecutionTime
    public String getExcpensiveCalculation(@QueryParam("number") @DefaultValue("1") IntegerParam number) {
        return getCalculation(number);
    }
    
    environment.jersey().register(ExecutionTimeFeature.class);
    
    步骤5:注册功能

    @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);
            }
        }
    }
    
    @GET
    @ExecutionTime
    public String getExcpensiveCalculation(@QueryParam("number") @DefaultValue("1") IntegerParam number) {
        return getCalculation(number);
    }
    
    environment.jersey().register(ExecutionTimeFeature.class);
    


    参考资料:

    要报告准确的代码块执行时间,可以使用

    它可以保持累积的时间值,这些时间值可以通过导数转换为图形上的峰值。 以石墨函数为例(注意,这不是“真”导数,只是值差)

    但这种方法不适合频繁事件,扩展性不强。在高负载的情况下,配合更好

    简单java助手:

    timed(字符串metricName,可运行正文){
    计数器计数器=metricsRegistry.Counter(metricName);
    long t=System.currentTimeMillis();
    试一试{
    body.run();
    最后{
    counter.inc(System.currentTimeMillis()-t);
    }
    }
    
    我不知道为什么你的答案被否决;但你的答案为我提供了一个完美的模板,当时我不想使用复杂的Dropwizard计量。