Spring Boot Actuator 2 / 3

W poprzednim rozdziale omówiliśmy monitorowanie aplikacji Spring Boot 1.x. Teraz omówimy jak wygląda to zagadnienie w przypadku Spring Boota 2 i 3. Zmiany wprowadzone w Actuatorze w Spring Boot 2 są nadal aktualne w wersji 3.

Wprowadzenie Actuatora do projektu w Spring Boot 2 odbywa się poprzez dodanie odpowiedniej zależności:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Wstępna konfiguracja w pliku application.properties powinna wyglądać podobnie jak w przypadku wersji pierwszej, jednak trzeba mieć na uwadze, że zmieniły się nieco nazwy własności. Dodane zostało słowo server. Od teraz mamy:
management.server.port=8081 
management.server.address=127.0.0.1
Przypomnijmy, że w ten sposób określamy port, na którym będzie działała usługa. Ze względów bezpieczeństwa dobrze jest wybrać port inny niż ten, na którym pracuje nasza aplikacja. Dodatkowo możemy określić adres ip, z którego będzie można korzystać z usługi. To również jest zalecane.

W trakcie przeprowadzania testów warto jest włączyć wszystkie endpointy, gdyż domyślnie większość z nich jest wyłączona:
management.endpoints.web.exposure.include=*
Oczywiście musimy uważać, żeby takiego ustawienia nie wdrożyć niezabezpieczonego hasłem na produkcji, gdyż będzie to miało katastrofalne skutki w kontekście bezpieczeństwa.

Endpointy

Do Actuatora w wersji drugiej dostejmy się z poziomu przeglądarki używając url-a (na przykładzie znanego nam już endpointa health):
http://localhost:8081/actuator/health
W obecnej wersji mamy dostępnych kilka nowych endpointów, jednakże najpierw chcielibyśmy pokazać endpoint, którego nie opisaliśmy w wersji pierwszej, a jednak wydaje się być ważny. Jeśli w pliku application.properties zdefiniujemy własność logging.file lub logging.path wówczas możemy zajrzeć do naszych plików z logami bezpośrednio z poziomu konsoli webowej. Jest to szczególnie przydatne wtedy, gdy nie mamy dostępu do logów na produkcji z poziomu serwera.
  • logfile

    Wyświetla logi w przeglądarce jeśli została zdefiniowana własność logging.file lub logging.path:
    Spring Boot Actuator 2 / 3 - Wskaźnik logfile

Nowe Endpointy

Tak jak wspomnieliśmy nowy Actuator to również nowe endpointy. Nam wpadły w oko - endpoint pokazujący konfigurację zadań automatycznych (schedulerów) zdefiniowanych w aplikacji oraz odświeżony mechanizm śledzenia w postaci httptrace (w Spring Boot 3 — httpexchanges):
  • scheduledtasks

    Wyświetla schedulery z podziałem na typy wraz z podaniem ścieżki do klasy i metody, dla której dany scheduler jest zdefiniowany:
    Spring Boot Actuator 2 / 3 - Wskaźnik shceduledtasks
  • httptrace (w Spring Boot 3 — httpexchanges)

    Wyświetla informacje o ruchu w aplikacji, podobny do trace znanego z poprzedniej wersji Actuatora. Teraz jednak jest bardziej skondensowany (zawiera tylko kluczowe dane http), przez co jest bardziej przejrzysty:
    Spring Boot Actuator 2 / 3 - Wskaźnik shceduledtasks

Endpoint metrics

Nazwa tego endpointa występowała już co prawda w poprzedniej wersji, ale teraz mamy do czynienia z całkowicie nowym silnikiem ukrytym pod jego "maską". Actuator 2.x bazuje na rozwiązaniu Micrometer i dostarcza nam beana o nazwie MeterRegistry.
  • metrics

    Tak jak poprzednio wyświetla zbiór informacji o stanie zasobów oraz szereg innych danych diagnostycznych. W porównaniu do poprzedniej wersji informacje te zawierają więcej metadanych. Ze względu na ilość informacji zostały one podzielone na osobne sekcje, a więc odpalając sam endpoint metrics dostajemy teraz jedynie listę dostępnych metryk:
    Spring Boot Actuator 2 / 3 - Wskaźnik metrics
    I teraz jeśli interesuje nas na przykład bieżące zużycie procesora w trakcie wykonywania pracy przez aplikację wystarczy, że podamy odpowiednią nazwę własności w url-u (system.cpu.usage).
    Spring Boot Actuator 2 / 3 - Wskaźnik metrics dla CPU

Własny endpoint

Przygotowanie customowego endpointa w nowej wersji Actuatora wygląda zupełnie inaczej niż miało to miejsce wcześniej. Spowodowane jest to tym, że mechanizm całego Actuatora przestał współpracować tylko i wyłącznie z Spring MVC. Stał się niezależny od technologii. Wprowadzone zostały rozwiązania generyczne do tworzenia endpointów.
@Component
@Endpoint(id = "customParameters")
public class CustomParametersEndpoint {
 
    private Map customParamaters = new ConcurrentHashMap<>();
 
    public CustomParametersEndpoint() {
    	customParamaters.put("lastDeploymentAuthor", "SYSTEM");
    	customParamaters.put("lastDeploymentIssue", "RELEASE");
    }
    
    @ReadOperation
    public Map customParamaters() {
        return customParamaters;
    }
 
    @ReadOperation
    public String customParamater(@Selector String name) {
        return customParamaters.get(name);
    }
 
    @WriteOperation
    public void addParameter(@Selector String name, String value) {
    	customParamaters.put(name, value);
    }
 
    @DeleteOperation
    public void deleteParameter(@Selector String name) {
    	customParamaters.remove(name);
    } 
}
Klasa, to zwykły komponent Springa, ale już pozostałe adnotacje pochodzą z biblioteki spring-boot-actuator i są niezależne od frameworka. Można ich użyć zarówno ze Spring MVC jak i Spring Webflux-em, czy nawet z Jerseyem.

Nasz endpoint został stworzony do przechowywania parametrów definiowanych przez nas w celu gromadzenia dodatkowych informacji o pracy systemu. Dla przykładu wprowadziliśmy mapę z domyślnie ustawionymi wartościami lastDeploymentAuthor oraz lastDeploymentIssue. Następnie przygotowaliśmy metody wykorzystujące tą mapę, opisując je adnotacjami mapującymi konkretne metody HTTP:
  • @ReadOperation - GET

  • @WriteOperation - POST

  • @DeleteOperation - DELETE
Dodatkowo użyliśmy adnotacji @Selector, której zadaniem jest dopasowanie parametru metody do parametru w URL. Zobaczmy teraz jak będzie wyglądało pobranie wszystkich parametrów (metodą GET):
Spring Boot Actuator 2 / 3 - Metoda GET
Tak będzie wyglądało pobranie wartości parametru po jego nazwie (metodą GET):
Spring Boot Actuator 2 / 3 - Metoda GET z parametrem
A tak wykonamy zmianę wartości parametru (metodą POST):
Spring Boot Actuator 2 / 3 - Metoda POST
To co powinno zwrócić naszą uwagę to fakt, że nadal używamy nazwy parametru, który chcemy ustawić oraz to, że dane przesyłamy w postaci JSON-a, gdzie value to nazwa parametru w metodzie. W rezultacie wywołując ponownie metodę GET pobierającą wszystkie parametry powinniśmy uzyskać widok podobny do tego:
Spring Boot Actuator 2 / 3 - Wskaźnik metrics
Oczywiście jako parametr możemy przesłać również cały obiekt. Wówczas kolejne pola w JSON-ie będą mapowane na odpowiednie pola w obiekcie.

Na koniec zostaje nam metoda DELETE, ale jej nie będziemy już analizować. Wywołanie wygląda analogicznie do metody GET z parametrem.
Appa Notka. Dokumentacja Spring Boota wspomina, że aby powyższe "zabawy" z parametrami w ogóle zadziałały, należy skompilować kod (implementujący endpointa) z opcją -parameters. W przypadku, gdy używamy Mavena wraz z parentem ustawionym na spring-boot-starter-parent, nie powinno być wymagane dodawanie tej opcji, powinno to działać automatycznie. Niemniej mogą nadal wystąpić problemy podczas testów w IDE. W przypadku Eclipse pomaga włączenie opcji kompilatora (w preferencjach wyszukujemy Java Compiler) o nazwie "Store information about method parameters (usable via reflection)". W Intellij w miejscu konfirguracji kompilatora należy wpisać -parameters, w sekcji "Additional command line parameters".

Bezpieczeństwo ponad wszystko

Tak jak w życiu, tak samo w przypadku systemów informatycznych szczególnie ważne jest odpowiednie zabezpieczenie cennych zasobów przed niepowołanym dostępem. W przypadku Actuatora ze Spring Boot-a 2 załatwiamy sprawę w standardowy sposób, to znaczy zgodny z szablonowym modelem bezpieczeństwa aplikacji. Tak więc wystarczy nam stworzenie prostej konfiguracji security, na przykład:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
        .requestMatchers(EndpointRequest.to("health", "info")).permitAll()
        .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ENDPOINT_ADMIN");
    }
}

Oczywiście powyższy przykład jest trywialny, choćby z tego powodu, że zawiera tylko zabezpieczenia dotyczące Actuatora. W rzeczywistości będziemy tutaj mieli wspólny model bezpieczeństwa zarówno dla aplikacji jak i dla Actuatora. Załóżmy jednak dla ułatwienia, że nasze zabezpieczenia wyglądają tak jak w przykładzie. W tym momencie nie dostaniemy się do żadnych endpointów (poza health i info) jeśli nie posiadamy wymaganej roli. Testując taką konfigurację na naszym własnym endpoincie otrzymamy AccessDenied:
Spring Boot Actuator 2 / 3 - Wskaźnik metrics
W ten sposób określamy, które endpointy powinny być widoczne i dla kogo, a które nie. Tym samym nie używamy już konfiguracji znanej z Actuatora 1.x opartej o własność sensitive. Przy próbie użycia własności endpoints.sensitive zostaniemy poinformowani przez nasze IDE (w tym przypadku Eclipse), że własność została zdeprecjonowana:
Spring Boot Actuator 2 / 3 - Wskaźnik metrics
W bieżącym rozdziale przyjrzeliśmy się temu jak działa Actuator w Spring Boot 2. Jeśli dla kogoś z Was zgromadzony tutaj materiał nie jest wystarczający, polecamy zapoznać się z linkami poniżej. Wstawiliśmy tutaj odwołania zarówno do dokumentacji Spring Boota 2 jak również do dokumentacji API Actuatora.

Spring Boot Actuator 3

W poprzednich wersjach Spring Framework automatycznie maskował wartości wrażliwych kluczy w endpointach /env i /configprops, które wyświetlają wrażliwe informacje, takie jak właściwości konfiguracji i zmienne środowiskowe. W tym wydaniu Spring zmienia podejście, aby domyślnie było bezpieczniejsze.

Zamiast maskować tylko niektóre klucze, teraz domyślnie maskuje wartości dla wszystkich kluczy. Możemy zmienić tę konfigurację, ustawiając właściwości management.endpoint.env.show-values (dla punktu końcowego /env ) lub management.endpoint.configprops.show-values (dla punktu końcowego /configprops ) z jedną z tych wartości:
  • NIGDY — nie pokazano żadnych wartości
  • ZAWSZE — wszystkie wyświetlane wartości
  • WHEN_AUTHORIZED — wszystkie wartości są wyświetlane, jeśli użytkownik jest autoryzowany. W przypadku JMX wszyscy użytkownicy są autoryzowani. W przypadku HTTP tylko określona rola może uzyskać dostęp do danych
W Spring Boot 3 pojawiły się też inne aktualizacje w Actuatorze. JMX obsługuje tylko /health endpoint. Możemy je dostosować, konfigurując właściwości management.endpoints.jmx.exposure.include i management.endpoints.jmx.exposure.exclude.

Nastąpiła też zmiana nazwy endpointa /httptrace na /httpexchanges.

Kolejne zmiany dotyczą izolacji ObjectMapper. W nowej wersji instancja mappera odpowiedzialna za serializację odpowiedzi z Actuatora, jest domyślnie izolowana. Oznacza to, że ta instancja ObjectMapper jest oddzielona od innych części aplikacji, co zwiększa bezpieczeństwo i niezawodność przez unikanie potencjalnych konfliktów z innymi elementami aplikacji używającymi mappera. Możemy zmienić tę funkcję, ustawiając właściwość management.endpoints.jackson.isolated-object-mapper na false.
Zdjęcie autora
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java
Topowe Materiały
Spring IO: Spring Boot Actuator Web API Documentation
Baeldung: Spring Boot Actuator
Baeldung: Migrate Application From Spring Boot 2 to Spring Boot 3

Udemy: [NEW] Spring Boot 3, Spring 6 & Hibernate for Beginners  —  polskie napisy

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy: stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .


Pozycjonowanie stron: Grupa TENSE