monitorowanie przez micrometer + spring

0

Troche nie rozumiem monitorowania aplikacji przez micrometer, a mam zrobić coś takiego: mierzyć czas komunikacji z każdym komponentem zewnęrznym np. baza, Rabbit, inny mikroserwis.

Chodzi głównie o mierzenie czasu poprzez timer.record(mierzonaFunkcja())

To mam zrobić ręcznie na każdej funkcji, czy micrometer sam mierzy funkcje gdy odwoluje sie do innej cześci niz aktualna aplikacja i wypluwa zapisy do loga?

0

Część rzeczy działa out of the box (https://github.com/micrometer-metrics/micrometer/issues/584), inne wymagają dodatkowych modułów, niektóre pewnie będziesz musiał ręcznie wyrzeźbić.
Sam akurat z mikrometra nie korzystałem więc więcej nie powiem.

1

Samo się nic nie dzieje ;) Spring robi trochę własnych metryk, ale to w zasadzie tyle. Customowe metryki musisz zrobić samemu, czyli podbijać countery w odpowiednich miejscach albo wrappować niektóre wywołania w timer żeby zmierzyć czas trwania.
Metryki są przecież biznesowe więc trudno oczekiwać że jakoś magicznie będą się robić same, bo niby skad ktoś miałby wiedzieć co chcesz zliczać albo mierzyć?

0

w sumie mam zrobić coś podobnego jak tutaj:
https://www.baeldung.com/micrometer(punkt 4.3)

        SimpleMeterRegistry registry = new SimpleMeterRegistry();
        Timer timer = registry.timer("app.event");
        timer.record(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(1500);
            } catch (InterruptedException ignored) { }
        });

        timer.record(3000, MILLISECONDS);

tylko w tym timerze musiałbym umieścić chyba tą metodę która się łączy do innego mikroserwisu

0
  1. Spring ma domyślnie meter registry wystawione, mozesz je sobie wstrzyknąć.
  2. Potrzebujesz skonfigurować trochę properties, np. gdzie te metryki mają być wysyłane
  3. Osobiście polecam zrobić klasę która opakowuje ci te metryki a tam np. pod timer zrobić coś takiego:
    private <T> Try<T> measureTime(Callable<T> callable, Timer timer) {
        return Try.of(()->timer.recordCallable(callable));
    }

I potem w tej swojej klasie masz metodę:

    public <T> Try<T> measureSomeBusinessOperation(Callable<T> callable) {
        return measureTime(callable, someOperationTimer);
    }

A z kodu wołasz to jakimś myMetrics.measureSomeBusinessOperation(this::someMethodIWantToMeasure)

0

coś nie umiem znaleźć tego springowego meter registry, możesz nakierować jakims artykułem?. Ogólnie chodzi mi tylko o czas wykonania danego requestu, a ten czas bede logował po zakończeniu requestu.
Ogólnie też nie wiem dlaczego musze tutaj zastosować micrometer, a nie zwykły timer, jeśli ma być to tylko czas.

Ale w sumie taki timer udostępnia chyba więcej danych, więc więcej rzeczy moge zalogować

0

@mariusz00 co to jest zwykły timer? Bo rozumiesz chyba ze metryki nie są do pisania do logów tylko do zbierania i plotowania w jakiejś grafanie?

  1. Wrzucasz zależność na jakieś io.micrometer:micrometer-registry-elastic
  2. Ustawiasz:
management.metrics.export.elastic.host=http://gdzie.stoi.twoj.elastik:9200
management.metrics.export.elastic.enabled=true
management.metrics.export.elastic.step=1m
management.metrics.web.server.request.autotime.enabled=true
management.metrics.export.elastic.index=nazwa-indeksu

W samej aplikacji robisz jakiegos:

    @Bean
    MyMetrics myMetrics(MeterRegistry meterRegistry) {
        return new MyMetrics(meterRegistry);
    }

Gdzie masz:

class MyMetrics {
    public MyMetrics (MeterRegistry meterRegistry) {
        someTimer= Timer.builder("some.metric.name").register(meterRegistry);
}

I jak coś pomierzysz tym timerem to raz na minutę poleci do elastika. Potem w grafanie robisz sobie wykresy z tego, np.:

screenshot-20210609220930.png

0

W sumie nie myślałem o tym w ten sposób, troche poukładałeś mi informacje na temat metryk.
Chodzi o to, że otrzymałem takie polecenie:

Gdy zaczniesz wysyłać request to trzeba rozpocząć liczenie, a gdy otrzymasz response to trzeba zakończyć liczenie. Celem jest to, aby mierzyć czas odpowiedzi komponentów zewnętrznych, bo w przypadku długich odpowiedzi VoiceBotServices będziemy mogli się obronić pokazując wykresy, że inne komponenty długo odpowiadały.

Patrząc na powyższy cytat, dlatego chciałem informacje na temat wykonania danego requestu zalogować (gdy w razie jakiś problemów móc się tym podeprzeć)

1

No to musisz metrykę zapiąć na metodzie, która woła klienta HTTP. Spring Boot ogarnia z paczki (jak masz dodane stosowne zależności i autokonfiguracje) adnotacje Micrometerowe takie, jak np. @Timed

1

@mariusz00 no ok i gdzie jest problem dokładnie? Pokazałem wyżej jak skonfigurować metryki. Masz teraz taki timer i mierzysz nim jakąś funkcje i tyle. Osobiście nie polecam zabawy w Aspekty i wole robić takie rzeczy "ręcznie", ale to bez większej różnicy.

0

W sumie bardziej chodziło mi o rozjasnienie tematu, bo pierwszy raz to robie. Myślałem, że taki timer to bardziej skomplikowana rzecz. Ale w sumie to chyba zależy co się chce osiągnąć takimi metrykami

Ale dzięki @Shalom, pokazałeś jak to powinno wyglądać przy pełnych metrykach i późniejszym wykresie.
@Charles_Ray też dzięki

Mi póki co starczy timer aby kontrolować wysyłanie requesta

0

Jeżeli sam odpalasz timera, to nie zapomnij o odpowiedniej obsłudze wyjątków i błędów :) takie ręczne odpalenie ma te przewagę nad adnotacją, że jesteś w stanie raportować czasy per statusy odpowiedzi. Sam timer nie ma świadomości statusów HTTP, co oczywiste. zakładam że interesują Cię głównie 2xx

0

mógłbyś rozwinąć "w stanie raportować czasy per statusy odpowiedzi" ?

Nie jestem do końca pewny czy ten try catch dobrze skontruowałem.
wyjątek ConnectionCustomerServiceException przechwytuje mi handler poprzez @ControllerAdvice
Chyba, że myślimy o tym samym, na tę chwilę zrobiłem tak, że po otrzymaniu odpowiedzi loguje w ten sposób:

        ResponseEntity<T> response = timer.record(() -> {
            try {
                return new RestTemplate().exchange(url, HttpMethod.GET, request, returnTypeFromResponse);
            } catch (RestClientException exception) {
                throw new ConnectionCustomerServiceException();
            }
        });

log.info("Connection has been invoked. Response status: \"{}\", connection took: \"{}\" miliseconds.",
            response.getStatusCodeValue(), timer.totalTime(TimeUnit.MILLISECONDS));

1 użytkowników online, w tym zalogowanych: 0, gości: 1