Z czego najlepiej skorzystać do śledzenia propagowanego do wielu serwisów?

0

Cześć pytanie o tracing w appce spring bootowej. Jest to nowa apka, którą robimy od zera i potrzebuję dodać tracing do logów.

Mamy eventy w Azure Event Hubs, które na razie (bo nie mamy jeszcze proda - trochę taka zabaw póki co) - generujemy ręcznie poprzez feature Azurowy "Data Generator", gdzie możemy podać jsona i dodać do "kolejki", a w naszej appce spring bootowej consumer sobie je pobiera i wywołuje odpowiednią akcję. Gdzieś w środku logiki uderzamy webclientem do zewnętrznego serwisu.
Jeszcze nie wiadomo w jaki sposób docelowo będą generowane te eventy.

Co potrzebuję:

  1. Dodać trace id (minimum z wymagań) i jakiś correlation id, te dane muszą być propagowane do każdego z serwisów.

I teraz pytanie, z czego najlepiej skorzystać?
Czytam o Spring Cloud Sleuth oraz Micrometer. Lead coś wspominał, żeby obczaić czy Micrometer nie wystarczy lub coś innego niż Sleuth, ale z tego co ja czytam to Micrometer chyba nie jest do tracingu.

  1. Potrzebuję zastanowić się jak to zrobić w dwóch przypadkach:
  • dla obecnej sytuacji, gdzie generujemy event ręcznie z jsonem - raczej w tym przypadku to nie my powinniśmy generować trace id itd, tylko już po stronie consumera w logice?
  • Jeśli jest jakiś producent w appce, który generuje eventy - wtedy już producent będzie tworzył trace id/ correlation id itp.

Powiedzmy, że mam pomysł na otrzymywanie eventu w formie obiektu:

class Request<T> {
    String traceId;
    String correlationId;
    T request; //tutaj json z danymi
}

czy odpalając całe flow w spring appce dla tego eventu, zaczynając od consumera, który wywołuje jakąś logikę (.handle(event)) powinienem do każdej metody przekazywać ten traceId, correlationId, żeby przy uderzeniu do zewnętrznego serwisu posłać te dane?
Nie za bardzo wiem jak to ma działać :)

Będę wdzięczny za jakąkolwiek pomoc, nawet wskazówkę typu "poczytaj o".

1
mirek_dev napisał(a):

Java to nie mój świat więc odpowiedź z punktu widzenia architektury.

czy odpalając całe flow w spring appce dla tego eventu, zaczynając od consumera, który wywołuje jakąś logikę (.handle(event)) powinienem do każdej metody przekazywać ten traceId, correlationId, żeby przy uderzeniu do zewnętrznego serwisu posłać te dane?

Nie musisz nic robić. Dodajesz odpowiednie SDK/bibliotekę do swoich serwisów/aplikacji i kontekst tworzony jest automatycznie przez bibliotekę w momencie otrzymania pierwszego requestu i propagowany w dół do kolejnych serwisów tworząc span. To się nazywa instrumentacja. Do kontekstu możesz oczywiście dodawać swoje informacje jak parametry zapytania, id-ki, itp jeśli ma to sens z punktu widzenia późniejszej analizy logów.

screenshot-20231103090815.png

Jak nie możesz/nie chcesz zrobić instrumentacji aplikacji możesz skorzystać z sidecar proxy, polegającego na uruchomieniu obok aplikacji specjalnego kontenera, który odpowiada za komunikację z narzędziem do observability. Tutaj przykład użycia DAPR

screenshot-20231103091406.png

1

Pytanie gdzie w Azure ten serwis java będziesz uruchamiał, Azure App Service czy AKS oferuja distributed tracing i open telemetry https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable?tabs=java. IMHO raczej powinienieś skorzystać z tego co oferuje Azure niż wynajdywać "koło na nowo".

0

jak chcesz dodac tracing do twoich logow w nowej appce spring bootowej, to rzeczywiscie spring cloud sleuth jest pierwsza opcja. to narzedzie automatycznie dodaje do logow trace id i span id, co pozwala na sledzenie requestow przez caly system. Micrometer, z drugiej strony, jest bardziej do metryk niz tracingu, wiec masz racje, ze to nie calkiem to. w obecnej sytuacji, gdzie eventy generujecie recznie, trace id i correlation id moglby byc dodawane po stronie consumera, ale to tez zalezy od tego, jak zbudujesz proces. jesli mozesz modyfikowac jsona przy generowaniu eventu, to spoko, mozna by tam wpisac trace id, ale jesli nie, to consumer powinien to zrobic odbierajac event. jezeli chodzi o producenta eventow w appce, to wtedy faktycznie on powinien byc odpowiedzialny za generowanie trace id i correlation id. to by zapewnilo, ze kazdy event wysylany do kolejki juz ma potrzebne info do sledzenia. twoja klasa Request wyglada na dobry start. wrzucenie traceId i correlationId tam jest rozsadne, bo to pozwoli ci latwo przekazywac te informacje przez rozne warstwy aplikacji. i tak, przy kazdym wywolaniu metody czy serwisu zewnetrznego, powinienes przekazywac te id, zeby moc pozniej je znalezc w logach i zrozumiec, co sie dzieje w systemie. jesli chodzi o propagowanie tych id, to nie musisz robic tego recznie. spring cloud sleuth wspolpracuje z webclientem springa, wiec jezeli go uzywasz do komunikacji z zewnetrznymi serwisami, sleuth powinien sobie z tym poradzic i przekazywac trace id automatycznie.czytaj o spring cloud sleuth i jak integruje sie z innymi narzedziami do logowania i monitoringu. moze tez warto rzucic okiem na opentracing lub opentelemetry, ktore to sa szersze standardy tracingu i moga byc uzyteczne, szczegolnie jezeli twoja aplikacja bedzie rosna w przyszlosci. jeszcze jedno: nie zapomnij, zeby kazde id bylo unikalne i zeby je odpowiednio generowac - zazwyczaj uzywa sie do tego uuid. tak wiec to nie jest az takie trudne, jak moze sie wydawac na poczatku. troche konfiguracji, troche czytania dokumentacji i powinienes dac rade to ogarnac. 😊 keep calm :)

0

co oznacza w tym kontekście tracing do logów?

Chodzi o to żeby te logi gdzieś się wysyłały, akumulowaly i dawały się łatwo i przejrzyście przeszukiwać i potem obrabiać?

0

Z tego: https://github.com/opentracing
Do tego podłączysz takie toole do wizualizacji jakie się będą podobać.

Jak firma ma $$$ to można kupić gotowca od DataDog lub SumoLogic lub Splunk.

0

Jestem ciekaw jak to ogarnąłeś @mirek_dev + po co Ci correlationid jeśli masz już traceId.

0
markone_dev napisał(a):

czy odpalając całe flow w spring appce dla tego eventu, zaczynając od consumera, który wywołuje jakąś logikę (.handle(event)) powinienem do każdej metody przekazywać ten traceId, correlationId, żeby przy uderzeniu do zewnętrznego serwisu posłać te dane?

Nie musisz nic robić. Dodajesz odpowiednie SDK/bibliotekę do swoich serwisów/aplikacji i kontekst tworzony jest automatycznie przez bibliotekę w momencie otrzymania pierwszego requestu i propagowany w dół do kolejnych serwisów tworząc span. To się nazywa instrumentacja.

A napisać test pod to możesz jak?

3
Riddle napisał(a):
markone_dev napisał(a):

czy odpalając całe flow w spring appce dla tego eventu, zaczynając od consumera, który wywołuje jakąś logikę (.handle(event)) powinienem do każdej metody przekazywać ten traceId, correlationId, żeby przy uderzeniu do zewnętrznego serwisu posłać te dane?

Nie musisz nic robić. Dodajesz odpowiednie SDK/bibliotekę do swoich serwisów/aplikacji i kontekst tworzony jest automatycznie przez bibliotekę w momencie otrzymania pierwszego requestu i propagowany w dół do kolejnych serwisów tworząc span. To się nazywa instrumentacja.

A napisać test pod to możesz jak?

A po co chcesz testować bibliotekę do Distributed Tracingu? log4j, NLoga, czy jUnit też testujesz? Zapinasz pod usługi, odpalasz system i patrzysz czy na dashboardzie wszystko jest jak należy.

0
markone_dev napisał(a):

A po co chcesz testować bibliotekę do Distributed Tracingu? log4j, NLoga, czy jUnit też testujesz? Zapinasz pod usługi, odpalasz system i patrzysz czy na dashboardzie wszystko jest jak należy.

Nie chcę testować biblioteki, tylko moje użycie tej biblioteki w mojej aplikacji.

Nie testuje springa, ale napisze test pod mój endpoint.

0
markone_dev napisał(a):
Riddle napisał(a):

...

A po co chcesz testować bibliotekę do Distributed Tracingu? log4j, NLoga, czy jUnit też testujesz? Zapinasz pod usługi, odpalasz system i patrzysz czy na dashboardzie wszystko jest jak należy.

Na upartego może, np. dla OpenTelemetry

  1. Uruchamia JVMa z agentem od telemetrii (taki agent wspiera różne biblioteki -> https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md )
  2. Robi custom exportera (np. https://javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-testing/1.12.0/io/opentelemetry/sdk/testing/exporter/InMemorySpanExporter.html )
  3. Inicjalizuje bibliotekę.
  4. Tworzy 3 serwisy: A,B,C. A woła B, a później C (mowa o komunikacji typu inter-process: po HTTP/gRPC/Kafka/... )
  5. Sprawdza czy w custom exporterze ma 3 spany.
  6. Open telemetry przetestowane ;-)
0
yarel napisał(a):
markone_dev napisał(a):
Riddle napisał(a):

...

A po co chcesz testować bibliotekę do Distributed Tracingu? log4j, NLoga, czy jUnit też testujesz? Zapinasz pod usługi, odpalasz system i patrzysz czy na dashboardzie wszystko jest jak należy.

Na upartego może, np. dla OpenTelemetry

  1. Uruchamia JVMa z agentem od telemetrii (taki agent wspiera różne biblioteki -> https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md )
  2. Robi custom exportera (np. https://javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-testing/1.12.0/io/opentelemetry/sdk/testing/exporter/InMemorySpanExporter.html )
  3. Inicjalizuje bibliotekę.
  4. Tworzy 3 serwisy: A,B,C. A woła B, a później C (mowa o komunikacji typu inter-process: po HTTP/gRPC/Kafka/... )
  5. Sprawdza czy w custom exporterze ma 3 spany.
  6. Open telemetry przetestowane ;-)

Brzmi jak paskudny test, który failuje przy pierwszej lepszej okazji.

0
Riddle napisał(a):

Brzmi jak paskudny test, który failuje przy pierwszej lepszej okazji.

No ale to nie ja chcę testować konkretną bibliotekę od telemetrii.

0
yarel napisał(a):
Riddle napisał(a):

Brzmi jak paskudny test, który failuje przy pierwszej lepszej okazji.

No ale to nie ja chcę testować konkretną bibliotekę od telemetrii.

Nie wierzę że to muszę mówic.

@markone_dev napisał: Nie musisz nic robić. Dodajesz odpowiednie SDK/bibliotekę do swoich serwisów/aplikacji. Tzn. że żeby to miało ręce i nogi to powinno się dać móc napisać failujący test, dodać bibliotekę która robi to co ma robić, i test teraz powinien przejść - ale nie powinien trwać 20 sekund żeby go wykonać, i powinien być wiarygodny - czyli np jak go odpalę 100 razy to ma przejść sto razy, a nie failować randomowo.

Poza tym, jak już mówiłem - nie chcę testować biblioteki - to jest zadanie jej twórców. Ja chcę napisać test pod moje aplikacje i serwisy, czy na pewno robią to co mają robić dzięki tej bibliotece.

2
Riddle napisał(a):

Poza tym, jak już mówiłem - nie chcę testować biblioteki - to jest zadanie jej twórców. Ja chcę napisać test pod moje aplikacje i serwisy, czy na pewno robią to co mają robić dzięki tej bibliotece.

Dla profilera też testy piszesz komponentów, żeby się upewnić, że robią to co mają robić dzięki profilerowi? Co według Ciebie robi taka instrumentacja/telemetria?

0
yarel napisał(a):

Dla profilera też testy piszesz komponentów, żeby się upewnić, że robią to co mają robić dzięki profilerowi?

Jeśli miałbym go dodać do code-base'u to tak. Ale nie dodaję, więc nie piszę.

Natomiast to o czym pisze @markone_dev, jak rozumiem ma zostać dopisane w kodzie w naszej aplikacji. A wszystko jest w naszej aplikacji, to my (a nie ktoś inny) będziemy zmieniać, a pod wszystko co my będziemy zmieniać - my powinniśmy napisać test.

  • Czy napiszę test pod to czy biblioteka działa poprawnie? Nie.
  • Czy napiszę test pod to czy biblioteka jest dodana w mojej aplikacji? Tak.
0

Jeśli miałbym go dodać do code-base'u to tak. Ale zazwyczaj nie dodaję, więc nie piszę.

O matko, znowu to samo skrajnie pedantyczne podejście do testowania całego świata. Ja dodaję sleutha + url do zipkina do parent poma i mam tracing między serwisami gotowy, jak ktoś ma ochotę na teoretyczne dywagacje "czy to na pewno pewno działa bo nie mogę spać w nocy jak nie napiszę testu" a nie ma ochoty spojrzeć na dashboard że faktycznie tak, to droga wolna, ale ja bym za to nie zapłacił.

Brzmi jak paskudny test, który failuje przy pierwszej lepszej okazji.

A to ciekawe, skąd taka opinia, jakieś argumenty może? Bo według mnie jest wręcz przeciwnie, odpalenie 3 procesów w pamięci i jakieś requesty HTTP między nimi po localhoście jest sekwencją bardzo powtarzalną.

1
kelog napisał(a):

jak ktoś ma ochotę na teoretyczne dywagacje "czy to na pewno pewno działa bo nie mogę spać w nocy jak nie napiszę testu" a nie ma ochoty spojrzeć na dashboard że faktycznie tak, to droga wolna, ale ja bym za to nie zapłacił.

Ja też nie mam ochoty na żądnego teroetyczne dywagacje, nie o to mi chodzi przecież.

kelog napisał(a):

O matko, znowu to samo skrajnie pedantyczne podejście do testowania całego świata.

Nie chodzi o żaden pedantyzm, tylko o pragmatyzm. Nie chodzi też o "upewnienia się że aplikacja działa", tylko o szybkie i rzetelne zreprodukowanie pożądanego zachowania na lokalu. Piszę przecież, już któryś raz że nie chcę testować biblioteki ani tymbardziej całego świata. Chcę napisać test tylko pod kawałek kodu który ja napiszę.

Jak widzę jakiś kawałek kodu albo bibliotekę, to nie chcę się musieć zastanawiać po co ona jest i co robi, i czy nadal jest używana, tylko chce odpalić test, który mi da givena, użyje libki, i powie co ma zwrócić.

kelog napisał(a):

Ja dodaję sleutha + url do zipkina do parent poma i mam tracing między serwisami gotowy,

Mam wrażenie że prezentuje bardzo pragmatyczne podejście: napisz jeden failujący test, dodaj libkę, test przechodzi, commit, deploy. Nie rozumiem co jest takiego "teoretycznego" albo "pedantycznego" w tym?

kelog napisał(a):

Brzmi jak paskudny test, który failuje przy pierwszej lepszej okazji.

A to ciekawe, skąd taka opinia, jakieś argumenty może? Bo według mnie jest wręcz przeciwnie, odpalenie 3 procesów w pamięci i jakieś requesty HTTP między nimi po localhoście jest sekwencją bardzo powtarzalną.

No to jeśli tak, to super.

A jak długo się wykonuje taki test?

2
Riddle napisał(a):

Natomiast to o czym pisze @markone_dev, jak rozumiem ma zostać dopisane w kodzie w naszej aplikacji. A wszystko jest w naszej aplikacji, to my (a nie ktoś inny) będziemy zmieniać, a pod wszystko co my będziemy zmieniać - my powinniśmy napisać test.

Dalej nie wiem w czym jest problem... Jak zapisujesz logi aplikacji do pliku jUnit-em to piszesz pod loggera testy? Jak chcesz eksportować logi i metryki do Prometheusa to też będziesz pisał pod to testy?

Przecież użycie takiej biblioteki do Open Telemetry/Distributed Tracingu jak Jaeger, nie różni się od użycia w aplikacji najzwyklejszego loggera... Zwykle wystarcza wpięcie odpowiedniego serwisu/handlera w proces aplikacji w metodzie bootstrapującej aplikację, zgodnie z tym rysunkiem. Nic więcej nie trzeba robić. Dane same lecą tam gdzie wskażemy.

screenshot-20240325170629.png

0
markone_dev napisał(a):
Riddle napisał(a):

Natomiast to o czym pisze @markone_dev, jak rozumiem ma zostać dopisane w kodzie w naszej aplikacji. A wszystko jest w naszej aplikacji, to my (a nie ktoś inny) będziemy zmieniać, a pod wszystko co my będziemy zmieniać - my powinniśmy napisać test.

Jak zapisujesz logi aplikacji do pliku jUnit-em to piszesz pod loggera testy? Jak chcesz eksportować logi i metryki do Prometheusa to też będziesz pisał pod to testy?

Już pisałem kilka razy, ale napiszę kolejny: Jeśli wymaga to dodania kodu do aplikacji (np zacommitowania zmiany w kodzie), to tak. Jeśli nie, to nie.

markone_dev napisał(a):

Przecież użycie takiej biblioteki do Open Telemetry/Distributed Tracingu jak Jaeger, nie różni się od użycia w aplikacji najzwyklejszego loggera... Zwykle wystarcza wpięcie odpowiedniego serwisu/handlera w proces aplikacji w metodzie bootstrapującej aplikację, zgodnie z tym rysunkiem. Nic więcej nie trzeba robić.

No to jak napisać test pod dodanie serwisu w metodzie bootstrapującej?


Każda jedna taka dodatkowa zależność, to jest potencjalne miejsce do poprawy w aplikacji - dlatego że jak zacznie działać źle, to ktoś musi wejść i naprawić. I jak tak się dzieje, to lepiej mieć testy pod to. Poza tym, nie tylko jak coś nie działa, ale również jak trzeba zrobić update, refactor, dowolną zmianę.

Robiąc zmianę w takim miejscu masz dwa wyjścia:

  1. albo robisz zmianę, odpalasz apkę, i sprawdzasz "oczami" czy działa tak jak ma działać (zakładając że wiesz jak ma działać, bo np znasz requirement); albo w najgorszym wypadku nie masz tego postawionego lokalnie, więc musisz zrobić deploy na jakieś środowisko zewnętrzne i tam sprawdzić; albo jeszcze najgorszy case, robisz deploya na produkcję, i dopiero tam możesz zauważyć czy działa dobrze
  2. albo robisz zmianę i odpalasz test.

Powiedz mi jaka jest konkretnie zaleta pierwszego podejścia? Albo wada drugiego?

Proponuję zostawić temat, bo wątek nie był o tym w ogóle.

2
Riddle napisał(a):

Proponuję zostawić temat, bo wątek nie był o tym w ogóle.

Zgadzam się bo mamy inne spojrzenie na temat, ja uważam że takich rzeczy jak wpięcie i konfiguracja loggera czy biblioteki do OT w aplikacji nie trzeba testować, Ty uważasz, że trzeba. No i ok.

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