Java 如何使用弹簧靴2和千分尺测量服务方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48704789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 02:54:35  来源:igfitidea点击:

How to measure service methods using spring boot 2 and micrometer

javaspringspring-bootspring-boot-actuator

提问by Christian Frommeyer

I started my first project on Spring Boot 2 (RC1). Thanks to the already good documentation this has not been to hard coming from Spring Boot 1.x.

我在 Spring Boot 2 (RC1) 上开始了我的第一个项目。多亏了已经很好的文档,从 Spring Boot 1.x 开始这并不难。

However now that I want to integrate metrics I'm stumbeling. As far as I was able to find currently there is only documentation for the metrics shipped by default. But I'd like to also measure service level execution time as well as the time used in dynamodb.

但是,现在我想集成指标,我很困惑。据我所知,目前只有默认提供的指标的文档。但我还想测量服务级别执行时间以及在 dynamodb 中使用的时间。

EDITI'm looking for a solution using Micrometer, the library used in the new actuator library shipped with spring-boot 2.

编辑我正在寻找使用 Micrometer 的解决方案,该库在 spring-boot 2 附带的新执行器库中使用。

Is there any guide on how this should be done? From thisI read that there is no easy annotation based solution for arbitrary spring beans yet. Could s.o. give me an example / link to documentation on how a method like below could be metered?

有没有关于如何做到这一点的指南?从这里我读到,对于任意 spring bean 还没有简单的基于注释的解决方案。可以给我一个示例/链接到有关如何计量如下方法的文档吗?

@Service
@Timed
public class MyService {
    public void doSomething() {
        ...;
    }
}

采纳答案by mweirauch

Here's a little sample which should get you going. There's more variants to Timer.record()which aren't shown here. (Also: Field injection only used for brevity.) You don't have to put the called methods name into a tag. You can also make it part of the metric name itself. Just wanted to show what you could do.

这是一个小示例,应该可以帮助您前进。Timer.record()此处未显示更多变体。(另外:字段注入只是为了简洁起见。)您不必将被调用的方法名称放入标签中。您还可以将其作为指标名称本身的一部分。只是想展示你能做什么。

Update 2018-03-12:As of Micrometer 1.0.0a TimedAspecthas been introduced so that you can also use the @Timedannotation. For now you need to register the Beanyourself. (You need to be cautious though when you have custom @Timedannotations on your Spring-MVC or Jersey resources.) This was already mentioned by Michal Stepanin a follow-up answer.

2018 年 3 月 12 日更新:已引入As of Micrometer 1.0.0a,TimedAspect以便您也可以使用@Timed注释。现在你需要Bean自己注册。(当您@Timed在 Spring-MVC 或 Jersey 资源上有自定义注释时,您需要谨慎。)Michal Stepan在后续回答中已经提到了这一点。

package io.github.mweirauch.micrometered.eval;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import io.micrometer.core.annotation.Timed;
import io.micrometer.core.aop.TimedAspect;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.Timer.Sample;

@Configuration
@EnableAspectJAutoProxy
public class TimingStuff {

    @Service
    static class MyService {

        @Autowired
        private MeterRegistry registry;

        public void helloManual() {
            // you can keep a ref to this; ok to call multiple times, though
            Timer timer = Timer.builder("myservice").tag("method", "manual").register(registry);

            // manually do the timing calculation
            long start = System.nanoTime();
            doSomething();
            timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
        }

        public void helloSupplier() {
            Timer timer = Timer.builder("myservice").tag("method", "supplier").register(registry);

            // execution of the method is timed internally
            timer.record(() -> doSomething());
        }

        public void helloSample() {
            Timer timer = Timer.builder("myservice").tag("method", "sample").register(registry);

            // records time taken between Sample creation and registering the
            // stop() with the given Timer
            Sample sample = Timer.start(registry);
            doSomething();
            sample.stop(timer);
        }

        // TimedAspect adds "class" and "method" tags
        @Timed(value = "myservice.aspect")
        public void helloAspect() {
            doSomething();
        }

        private void doSomething() {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                //
            }
        }

    }

    @Autowired
    private MyService myService;

    @Bean
    TimedAspect timedAspect(MeterRegistry registry) {
        return new TimedAspect(registry);
    }

    @Scheduled(fixedRate = 1000)
    public void postConstruct() {
        myService.helloManual();
        myService.helloSupplier();
        myService.helloSample();
        myService.helloAspect();
    }

}

In case you go for Prometheus, you'd end up with something like that:

如果你选择 Prometheus,你最终会得到这样的结果:

# HELP myservice_seconds  
# TYPE myservice_seconds summary
myservice_seconds_count{application="micrometered",method="manual",} 4.0
myservice_seconds_sum{application="micrometered",method="manual",} 0.200378014
myservice_seconds_max{application="micrometered",method="manual",} 0.050115291
myservice_seconds_count{application="micrometered",method="supplier",} 4.0
myservice_seconds_sum{application="micrometered",method="supplier",} 0.200393455
myservice_seconds_max{application="micrometered",method="supplier",} 0.05011635
myservice_seconds_count{application="micrometered",method="sample",} 4.0
myservice_seconds_sum{application="micrometered",method="sample",} 0.200527005
myservice_seconds_max{application="micrometered",method="sample",} 0.050250191
# HELP myservice_aspect_seconds  
# TYPE myservice_aspect_seconds summary
myservice_aspect_seconds_count{application="micrometered",class="io.github.mweirauch.micrometered.eval.TimingStuff$MyService",method="helloAspect",} 4.0
myservice_aspect_seconds_sum{application="micrometered",class="io.github.mweirauch.micrometered.eval.TimingStuff$MyService",method="helloAspect",} 0.201824272
myservice_aspect_seconds_max{application="micrometered",class="io.github.mweirauch.micrometered.eval.TimingStuff$MyService",method="helloAspect",} 0.051014296

回答by Michal Stepan

@io.micrometer.core.annotation.Timedannotation seems to be out of order for custom calls due to reduction of scope, at it is mentioned in link in your question.

@io.micrometer.core.annotation.Timed由于范围缩小,自定义调用的注释似乎不正常,在您的问题中的链接中提到。

You need to manually setup an Aspect:

您需要手动设置一个方面:

@Configuration
@EnableAspectJAutoProxy
public class AutoTimingConfiguration {
    @Bean
    public TimedAspect timedAspect(MeterRegistry registry) {
        return new TimedAspect(registry);
        }
}

This way method like this:

这种方法是这样的:

@Timed("GET_CARS")
public List<Car> getCars(){
        return Lists.newArrayList();
}

will result in GET_CARSmetric in /actuator/metrics(default) endpoint.

将导致(默认)端点中的GET_CARS指标/actuator/metrics