wake-up-neo.com

Wie Servicemethoden mit Spring Boot 2 und Mikrometer gemessen werden

Ich habe mein erstes Projekt mit Spring Boot 2 (RC1) gestartet. Dank der bereits guten Dokumentation war dies von Spring Boot 1.x nicht zu schwierig.

Aber jetzt, wo ich Metriken integrieren möchte, stolpere ich. Soweit ich aktuell feststellen konnte, gibt es nur Dokumentation zu den standardmäßig ausgelieferten Metriken. Ich möchte aber auch die Ausführungszeit auf Service-Ebene sowie die in Dynamodb verwendete Zeit messen.

[~ # ~] edit [~ # ~] Ich suche nach einer Lösung mit dem Mikrometer, der Bibliothek, die in der neuen Aktuatorbibliothek verwendet wird, die mit der Feder geliefert wird -boot 2.

Gibt es eine Anleitung, wie das gemacht werden soll? Aus this Ich habe gelesen, dass es für beliebige Spring Beans noch keine einfache annotationsbasierte Lösung gibt. Könnte an o. Gib mir ein Beispiel/einen Link zur Dokumentation, wie eine Methode wie die folgende gemessen werden könnte.

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

Hier ist ein kleines Beispiel, das Sie zum Laufen bringen soll. Es gibt weitere Varianten von Timer.record(), die hier nicht angezeigt werden. (Auch: Feldinjektion wird nur der Kürze halber verwendet.) Sie müssen den aufgerufenen Methodennamen nicht in ein Tag einfügen. Sie können es auch zum Teil des Metriknamens selbst machen. Ich wollte nur zeigen, was Sie tun können.

Update 2018-03-12: Stand von Micrometer 1.0.0 Ein TimedAspect wurde eingeführt, damit Sie auch den @Timed Anmerkung. Im Moment müssen Sie Bean selbst registrieren. (Sie müssen jedoch vorsichtig sein, wenn Sie benutzerdefinierte @Timed Anmerkungen zu Ihren Spring-MVC- oder Jersey-Ressourcen.) Dies wurde bereits von Michal Stepan in einem Follow-up erwähnt Antwort .

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();
    }

}

Wenn Sie sich für Prometheus entscheiden, erhalten Sie am Ende so etwas:

# 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
12
mweirauch

@io.micrometer.core.annotation.Timed Annotation scheint bei benutzerdefinierten Aufrufen aufgrund der Einschränkung des Gültigkeitsbereichs nicht in Ordnung zu sein. Es wird im Link in Ihrer Frage erwähnt.

Sie müssen einen Aspekt manuell einrichten:

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

So verfahren Sie wie folgt:

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

wird darin enden, dass GET_CARS metrisch in /actuator/metrics (Standard) Endpunkt.

18
Michal Stepan