Suche
Die neue Reaktivitätstheorie

Spring-Boot-Anwendungen überwachen – das Tutorial

Johannes Edmeier

© Shutterstock / Subbotina Anna

Mit Spring Boot ist es ganz einfach und rasend schnell möglich, neue Anwendungen zu erstellen und in Produktion zu bringen. Und dann? Oft werden die Monitoringtools von einem anderen Team betreut, und bis sie richtig konfiguriert sind, vergehen oft Wochen. Hier bietet Spring Boot Admin Abhilfe.

Als Entwickler übernehmen wir nach dem Credo „You build it, you run it!“ immer häufiger die Verantwortung für einen stabilen produktiven Betrieb. Was heißt das für uns: Wir müssen jederzeit auf einen Blick wissen, ob es unseren Anwendungen gut geht. Im Ernstfall brauchen wir schnellen Zugriff auf Detailinformationen und auch die Möglichkeit, das Verhalten der Anwendung zu beeinflussen.

Das Actuator-Modul von Spring Boot stellt HTTP-Endpunkte bereit, die Auskunft über den Zustand der Anwendung geben und es erlauben, die Anwendung zu beeinflussen. Integriert man Spring Boot Actuator in die eigene Anwendung, wird automatisch ein /health-Endpunkt aktiviert, der HealthIndicatoren verwendet, um Auskunft über die aktuelle Lauffähigkeit zu geben. Hier bringt Spring Boot eine Reihe Implementierungen für Datenbanken, JavaMailSender oder LDAP mit, die automatisch konfiguriert werden. Neben dem /health-Endpunkt gibt es noch viele weitere, z. B. für Metriken und Loglevelmanagement.

Was Spring Boot fehlt, ist eine komfortable Oberfläche, um diese HTTP-Endpunkte zu bedienen, aber auch Alarmierungen, wenn die Anwendung klemmt. Mit Spring Boot Admin steht eine Monitoringlösung bereit, die sich ohne aufwendige Konfiguration mit Spring-Boot-Anwendungen versteht und die ohne Anpassungen in der Konfiguration neue Anwendungen in das Monitoring aufnehmen kann.

Bevor wir uns dem Aufsetzen des Monitoringservers widmen, benötigen wir eine Anwendung, die wir überwachen können. Daher stellen wir uns flugs eine Anwendung auf http://start.spring.io zusammen. Spring Boot Admin benötigt Zugriff auf die Spring-Boot-Actuator-Endpunkte per HTTP, also wählen wir Web und Actuator aus. Danach fügen wir einen einfachen RestController hinzu (Listing 1). Und schon haben wir unser ClientApplication, kurz Client.

@RestController
@SpringBootApplication
public class ClientApplication {
 public static void main(String[] args) {
  SpringApplication.run(ClientApplication.class, args);
 }
 @GetMapping("/")
 public String hello() {
   return "Hello World!"
 }
}

Ab Spring Boot Version 1.5 sind die Spring-Boot-Actuator-Endpunkte standardmäßig mit HTTP-Security versehen. Diese werden wir vorerst mit managament.security.enabled=false in der application.properties deaktivieren. Um Sicherheit kümmern wir uns später noch. Alle Anwendungen, die mit Spring Boot Admin Server verwaltet werden sollen, müssen diesem bekannt sein. In unserem Beispiel wird sich der Client selbst registrieren. Dazu nehmen wir de.codecentric:spring-boot-admin-starter-client als Abhängigkeit in unsere pom.xml auf (Listing 2). Wir teilen der Anwendung noch über spring.boot.admin.url mit, bei welchem Admin-Server sie sich registrieren soll (Listing 3).

<dependency>
  <groupId>de.codecentric</groupId>
  <artifactId>spring-boot-admin-starter-client</artifactId>
  <version>1.5.0</version>
</dependency>

managament.security.enabled=false
spring.boot.admin.url=http://localhost:8000

Jetzt setzen wir den Spring Boot Admin Server auf. Bei dem Admin-Server handelt es sich ebenfalls um eine Spring-Boot-Anwendung. Als Basis können wir ebenfalls mit den gleichen Einstellungen ein Projekt auf start.spring.io generieren. Wir müssen die Abhängigkeiten für den Admin-Server aufnehmen (Listing 4) und die dort enthaltene Konfiguration mit @EnableAdminServer aktivieren (Listing 5).

<dependency>
  <groupId>de.codecentric</groupId>
  <artifactId>spring-boot-admin-server</artifactId>
  <version>1.5.0</version>
</dependency>
<dependency>
  <groupId>de.codecentric</groupId>
  <artifactId>spring-boot-admin-server-ui</artifactId>
  <version>1.5.0</version>
</dependency>
@Configuration
@EnableAutoConfiguration
@EnableAdminServer
 public class SpringBootAdminApplication {
  public static void main(String[] args) {
   SpringApplication.run(SpringBootAdminApplication.class, args);
  }
}

Den Adminserver konfigurieren wir mit server.port=8000 mit dem Port, den wir beim Client angegeben haben. Nun können wir beide Anwendungen einfach starten (z. B. mit mvn spring-boot:run) und haben sofort einige Funktionalitäten für die Verwaltung unserer Anwendung. Desktopbenachrichtigungen und ein Journal über Statusänderungen sowie eine detaillierte Übersicht über den Status der Anwendungen sind zu sehen (Abb. 1). Auch Informationen über das konfigurierte Spring Environment und einfache Änderungsmöglichkeit der Loglevel (Abb. 2) werden uns angeboten. Außerdem gibt es eine Ansicht für Thread-Dumps, Heap-Dump-Download, HTTP Request Traces und eine Übersicht über Audit-Events.

Nachdem die Clientanwendung gestartet ist, sorgt die Autokonfiguration des spring-boot-admin-starter-client hinter der Bühne dafür, dass diese sich per HTTP POST beim Admin-Server registriert. Der Request enthält Informationen darüber, wie die Clientanwendung zu erreichen ist. Dabei wird der URL basierend auf den Hostnamen server.port, server.context-path, management.context-path automatisch berechnet.

Stimmen die Werte nicht, z. B. weil ein Reverse-Proxy davor geschaltet ist oder das Ganze in einem Docker-Container läuft, stehen unter spring.boot.admin.client.* einige Konfigurationsoptionen zur Verfügung, mit denen man das Verhalten beeinflussen kann. Wenn auch das nicht ausreicht, kann man im Client eine eigene ApplicationFactory implementieren, die für die Ermittlung des URL verantwortlich ist. Wie bei Spring Boot selbst werden möglichst sinnvolle Defaults verwendet. Es ist aber jederzeit möglich, die Defaults zu überschreiben oder Teile der Implementierung auszutauschen.

DevOps Docker Camp

Teilnehmer lernen die Konzepte von Docker und die darauf aufbauenden Infrastrukturen umfassend kennen. Schritt für Schritt bauen sie eine eigene Infrastruktur für und mit Docker auf.

Alle Termine des DevOps Docker Camps 2018 in der Übersicht

München: 19. – 21. Februar 2018
Berlin: 14. – 16. März 2018

Nachdem sich ein Client beim Admin registriert hat, fragt dieser periodisch den /health-Endpunkt des Clients ab, um den Status zu ermitteln. Für die Anzeige der restlichen Informationen im UI enthält der Spring Boot Admin Server einen Reverse-Proxy auf Basis von Neflix Zuul. So muss vom Browser aus nur der Admin-Server erreichbar sein, aber nicht alle registrierten Clients. Es ist möglich, mehrere Instanzen der Clientanwendung mit dem gleichen Namen zu registrieren. Spring Boot Admin bildet für jede Instanz eine eindeutige ID auf Basis des URL des /health-Endpunkts und gruppiert diese in der Übersicht. Es ist aber nicht möglich, bestimmte Aktionen (z. B. Logleveländerung) für eine ganze Gruppe auszuführen. Denn die Aktionen erfolgen auf Instanzebene.

Lesen Sie auch: Eine frühlingshafte Lösung für Microservices: Spring Boot

Wer ohnehin einen von Spring Cloud unterstützen Discovery-Mechanismus verwendet, kann auf den spring-boot-admin-starter-client verzichten. Stattdessen fügt man dem Admin-Server eine DiscoveryClient-Implementierung hinzu und konfiguriert sie wie bei den anderen Clientanwendungen. Dadurch werden dem Admin-Server die zu überwachenden Anwendungen bekannt gemacht. Eine zusätzliche Registrierung ist nicht nötig. Hier zeigt sich der Vorteil, dass Spring Boot Admin als Bibliothek und nicht als fertiger Server konzipiert ist. So kann man sich seine benötigte Konfiguration selbst zusammenstellen und einen maßgeschneiderten Monitoringserver erstellen. Wenn die vorgefertigten Komponenten nicht passen, kann man ganz einfach eigene hinzufügen.

Abb. 1: Anwendungsdetails- und metriken

Abb. 2: Loglevelmanagement

Mehr auf der Oberfläche anzeigen

Für die Anzeige der Versionsnummer unserer Applikation reicht es aus, das build-info goal des spring-boot-maven-plugins in der Client-pom.xml zu aktivieren. Diese erzeugt beim Build der Anwendung eine build.properties, die Informationen wie Version, Build-Zeitstempel und Commit-ID enthält. Die enthaltenen Informationen werden über den /info-Endpunkt ausgeliefert und im Spring Boot Admin in der Übersicht angezeigt. Wir können diesem Endpunkt weitere Informationen hinzufügen, indem wir entsprechende info.* Properties setzen. Werden hier Webadressen angegeben, werden diese als Links in der Oberfläche dargestellt. Dies ist nützlich, um z. B. einen direkten Link zur Dokumentation, dem Code-Repository oder dem Issue Tracker aufzunehmen.

Wer den spring-boot-admin-starter-client verwendet, nimmt org.jolokia:jolokia-core als transitive Abhängigkeit in den Klassenpfad mit auf. Dadurch konfiguriert Spring Boot Actuator automatisch einen Endpunkt, über den man Zugriff auf alle JMX Beans in der Clientanwendung hat. So kann man diese komfortabel über die Admin-Oberfläche bedienen. Wird ein DiscoveryClient verwendet, muss die Jolokia-Bibliothek manuell hinzugefügt werden.

Für einen schnellen Blick in die Logdatei (mit Verfolgung) über das UI, muss im Client die logging.file Property von Spring Boot gesetzt sein. Damit wird der /logfile-Endpunkt aktiviert und der Admin Server kann auf die Logdatei per HTTP zugreifen.

Die Bereiche in der Oberfläche, die nicht für jede Clientanwendung relevant sind, werden je nach Verfügbarkeit ein oder ausgeblendet. So gibt es standardmäßig in der Oberfläche eine Übersicht für die DB-Migrationstools Flyway und Liquibase. Dafür ist keine weitere Konfiguration im Admin-Server notwendig. Die Seiten werden angezeigt, wenn die Clientanwendung die notwendigen Actuator-Endpunkte bereitstellt.

Will man Properties im Spring Environment zur Laufzeit verändern, kann man den spring-cloud-starter im Client verwenden. Dieser bringt zwei Dinge mit: den EnvironmentManager und den RefreshScope. Der EnvironmentManager erlaubt es, mit dem zugehörigen Actuator-Endpunkt eine hoch priorisierte PropertySource per HTTP-Interface zu manipulieren. Ändert man Property-Werte im ApplicationContext, hat dies in der Regel zunächst keine Auswirkung auf die bestehenden Beans, da diese bereits instanziiert und verdrahtet sind. Werden diese Beans mittels @RefreshScope in diesen Scope aufgenommen, lassen sie sich neu erzeugen und verdrahten. Dies geschieht, wenn ein Refresh über den Actuator-Endpunkt ausgelöst wird. Das Manipulieren des Environments und der Refresh sind einfach über die Admin-Server-Oberfläche zu bedienen. Man muss sich keine Reihe komplizierter curl-Kommandos merken. Aber Obacht: Die Änderungen sind nicht persistent und gehen nach einem Neustart der Anwendung verloren.

Zu guter Letzt sei noch erwähnt, dass das Spring-Boot-Admin-Projekt noch UI-Module für Hystrix/Turbine und Activiti anbietet. Diese müssen dem Admin-Server explizit über UI-Module hinzugefügt werden und erfordern zusätzliche Konfiguration für die Weiterleitung der Endpunkte über den Zuul-Proxy im Admin-Server. Ich möchte an dieser Stelle auf die Dokumentation des GitHub-Projekts verweisen.

Mehr als Desktopbenachrichtigungen

Im Alltag reichen die Desktopbenachrichtigungen nicht aus, da für diese der Browser ständig geöffnet sein muss. Für Mailbenachrichtigungen reicht es aus, spring-boot-starter-mail im Admin-Server aufzunehmen und mit smtp.host einen SMTP-Server zu spezifizieren, über den die E-Mails versendet werden. Mit spring.boot.admin.notify.mail.to muss eine Liste von Adressaten für die E-Mail angegeben werden. Danach erhält man eine E-Mail, wenn eine Anwendung nicht mehr korrekt läuft. Es gibt diverse Konfigurationsmöglichkeiten um Text, Betreff etc. zu ändern. Spring Boot Admin bietet verschiedene Notifier-Implementierungen an, mit denen man Benachrichtigungen per Slack oder HipChat versenden kann. Ist das gewünschte Tool nicht dabei, kann man natürlich einfach ein eigenes hinzufügen. Unter den vorgefertigten Implementierungen möchte ich noch zwei besonders erwähnen: Erstens der FilteringNotifier, für den man per HTTP Filter einstellen kann, um Benachrichtigungen für eine bestimmte Zeit auszusetzen, z. B. vor einem Deployment. Und zweitens den RemindingNotifier, der eine Benachrichtigung wiederholt, bis der Zustand der Anwendung wieder UP ist. Die Notifier sind bewusst klein und modular gehalten, sodass sich mit den Design Patterns Composite und Decorator mächtige Konfigurationen erstellen lassen.

Prinzipiell ist es möglich den Admin-Server in die Clientanwendung zu integrieren und mit spring.boot.admin.context-path den Pfad für das Admin-UI explizit zu setzen. Allerdings rate ich davon aus mehreren Gründen ab. Allen voran ergibt es keinen Sinn, dass sich eine Anwendung selbst überwacht. Stirbt die Anwendung, kann sie, falls sie es überhaupt noch mitbekommt, niemanden mehr davon in Kenntnis setzen. Zudem zieht der Admin-Server eigene Abhängigkeiten in die Anwendung und löst eventuell Versionskonflikte aus. Die Spring Beans des Admin-Server würden dem ApplicationContext der Geschäftslogik hinzugefügt. Dadurch können ungewollte Seiteneffekte entstehen.

In der Standardkonfiguration werden die Daten des Spring Boot Admins weder persistiert noch über mehrere Knoten repliziert. Die Daten werden nur im Arbeitsspeicher gehalten. Es existiert die Möglichkeit, die Daten per Hazelcast zu persistieren und im Cluster zu replizieren. Wie das genau funktioniert, ist ebenfalls in der Dokumentation des Projekts beschrieben. Wem Hazelcast hier nicht zusagt, kann eine eigene Persistenzschicht (z. B. auf Basis von JPA) entwickeln, indem er das ApplicationStore-Interface selbst implementiert.

Eigene Healthchecks definieren

Dank Spring Boot Actuator ist es einfach, für die Anwendungen eigene Healthchecks zu definieren. Man muss nur eine Bean hinzufügen, die das HealthIndicator-Interface implementiert. Listing 6 enthält ein Beispiel, wie man die Verfügbarkeit eines anderen Systems, das für den Betrieb der eigenen Anwendung benötigt wird, per simplen Connect prüft. Schlägt der Healthcheck fehl, geht der Status der eigenen Anwendung auf DOWN und es wird eine Benachrichtigung ausgelöst.

public class SocketHealthIndicator extends AbstractHealthIndicator {
 private String host;
 private int port;
 private int timeout = 5000;
 @Override
 protected void doHealthCheck(Health.Builder health) throws Exception {
  Socket socket = new Socket();
  try {
   socket.connect(new InetSocketAddress(host, port), timeout);
   health.up();
  } finally {
   socket.close();
  }
 }
// ... Getter + Setter
}

Die Healthchecks werden jedesmal ausgeführt, wenn der /health-Endpunkt aufgerufen wird, aber in der Standardeinstellung maximal einmal pro Sekunde. Das bedeutet, dass die Checks möglichst schnell und effizient sein sollten. Kommt man um eine teure Überprüfung nicht herum, sollte man sich Gedanken über ein Caching des Ergebnisses machen. Dadurch, dass der Check Teil der Clientanwendung ist, muss man für neue Prüfungen an dem Admin-Server keine Konfiguration ändern.

Absichern des Admin-Servers und der Clients

Wie versprochen, kümmern wir uns nun um die Sicherheit. Da es sich bei dem Admin-Server nur um eine gewöhnliche Spring-MVC-Webanwendung handelt, lässt sich diese mit den gewohnten Mitteln absichern. Hier bringt Spring Boot Admin Server keine fertige Konfiguration mit. Die eigene Konfiguration ist aber nicht viel Arbeit. Das Beispiel zeigt, wie der Admin-Server mit einem Form-Log-in versehen und das API mittels HTTP Basic Authentication abgesichert wird. Zunächst fügen wir spring-boot-starter-security unsere Abhängigkeiten hinzu.

Zusätzlich nehmen wir de.codedentric:spring-boot-admin-ui-login auf. Dieses UI-Modul enthält eine Seite mit Log-in-Formular und stellt einen Abmeldebutton zur Verfügung, enthält aber keine Konfiguration für Spring Security. Diese müssen wir mit WebSecurityConfigurerAdapters selbst beisteuern. Dabei müssen zwei Dinge beachtet werden: Damit sich die Clients registrieren können, muss HTTP Basic aktiviert werden, und die CSRF Protection muss deaktiviert werden, da die AngularJS-Oberfläche dies nicht unterstützt. Eine Konfiguration könnte dann wie in Listing 7 aussehen.

 
@Configuration
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
 @Override
  protected void configure(HttpSecurity http) throws Exception {
  // Form-Login Seite konfigurieren, die einen POST an /login sendet
  http.formLogin().loginPage("/login.html").loginProcessingUrl("/login").permitAll();
  // Der Abmeldebutton sendet den POST and /logout
  http.logout().logoutUrl("/logout");
  // CSRF Protection deaktivieren
  http.csrf().disable();

  // Die statischen Assets nicht schützen
  http.authorizeRequests()
   .antMatchers("/login.html", "/**/*.css", "/img/**", "/third-party/**")
   .permitAll();
  // Alle anderen Requests müssen authorisiert sein
  http.authorizeRequests().antMatchers("/**").authenticated();
  // HTTP Basic Authentication aktivieren.
  http.httpBasic();
 }
}

Wir nutzen der Einfachheit halber die Möglichkeit, von Spring Boot ein statisches Passwort per security.user.name und security.user.password zu setzen. Im realen Leben würden wir hier einen eigenen AuthenticationManager konfigurieren, der beispielsweise einen LDAP-Server zur Authentifizierung verwendet. Wird ein DiscoveryClient verwendet, muss an den Clients nichts geändert werden, da diese selbst keinen Kontakt zum Admin-Server aufnehmen. Wird hingegen der spring-boot-admin-starter-client verwendet, teilen wir diesem mit den Properties spring.boot.admin.username und spring.boot.admin.password die nötigen Credentials mit. Damit erhalten diese per HTTP Basic Zugriff auf den Admin-Server. Aber Achtung: Mit dieser Konfiguration werden Passwörter im Klartext übertragen, es ist also unerlässlich, den Netzwerkverkehr mit HTTPS abzusichern oder wenigstens in ein geschütztes Netzwerksegment zu verlagern.

Wenn man die Clientanwendungen absichert, gibt es ein Detail zu beachten. Die Actuator-Endpunkte müssen für den Admin-Server mittels HTTP Basic Authentication verfügbar sein. Dazu muss dem Admin-Server während der Registrierung des Clients Benutzername und Passwort mitgeteilt werden. Dafür nutzen wir die Metadaten, die während der Registrierung übertragen werden. Die Properties liegen unter spring.boot.admin.client.metadata.* für den spring-boot-admin-starter-client. Für den gegebenenfalls verwendeten DiscoveryClient bitte die jeweilige Dokumentation konsultieren. Für beide Varianten wird Benutzername/Password über user.name und user.password in den Metadaten übertragen.

Auch interessant: Wie man architektonische Komplexität mit Spring Boot und Spring Cloud lösen kann

Der Admin-Server maskiert in seinem API sensitive Informationen in den Metadaten. Wenn eine der Spring-Cloud-Discovery-Varianten verwendet wird, gilt es zu beachten, dass die Metadaten für jeden sichtbar sind, der Zugriff auf die Service-Registry erhält. Im Admin-Server ist der BasicAuthHttpHeaderProvider dafür verantwortlich, die Metadaten in entsprechende HTTP-Header für die Authentifizierung umzuwandeln. Wer Bedarf hat, das Passwort verschlüsselt in der Service-Registry zu speichern, kann hier die Implementierung gegen eine eigene austauschen, die mit verschlüsselten Passwörtern arbeitet. Bei dieser Variante, die Anwendungen abzusichern, entscheidet der Spring Boot Admin Server darüber, welche seiner angemeldeten Benutzer Zugriff auf die Clientanwendung erhalten, und nicht die jeweilige Anwendung selbst. Als Alternative kann die Absicherung z. B. mit OAuth 2 erfolgen. Das Set-up wird dadurch komplexer, aber die Clientanwendungen können selbstständig entscheiden, ob der jeweilige Benutzer Zugriff auf die eigenen Endpunkte erhält. Für weitere Informationen über diese Variante möchte ich hier auf mein GitHub Repository verweisen, das zu OAuth 2 ein Beispiel enthält.

Die Oberfläche erweitern

Die Oberfläche von Spring Boot Admin ist in Angular (1.x) implementiert und lässt sich nur eingeschränkt modifizieren. Für die vorhandenen HTML-Seiten oder das CSS gibt es aktuell keine vorgesehene Anpassungsmöglichkeit. Man kann hier ein wenig tricksen und die Ressourcen im Klassenpfad unter META-INF/spring-boot-admin-ui/** austauschen. Anstelle dieser Fummelei empfehle ich die Source des spring-boot-admin-server-ui-Projekts zu kopieren, anzupassen und das Ergebnis des Node.js Builds statt des mitgelieferten UI zu verwenden.

Wer hingegen eine neue Seite z. B. für eigene Actuator-Endpunkte hinzufügen will, kann dies ohne Anpassungen am Spring-Boot-Admin-Quellcode machen. Diese Erweiterungsmöglichkeit ist aber bisher nicht dokumentiert und wird sich eventuell in einer Version 2.0 ändern. Im folgenden Beispiel werde ich zeigen, wie man einen eigenen Endpunkt der Clientanwendung hinzufügt und eine Anzeige im Admin-Server realisiert. Für diesen Abschnitt ist es von Vorteil, wenn man schon Erfahrung mit Angular (1.x) hat.

Der einfachste Part ist es, den eigenen Endpoint zu erstellen. Dafür schreiben wir eine neue Klasse, die von AbstractEndpoint erbt (Listing 8) und fügen eine Bean von diesem Typ unserem ApplicationContext hinzu. Der neue Endpunkt wird automatisch unter seiner ID, die wir dem Superkonstruktor mitgeben, als HTTP-Endpunkt verfügbar. Zusätzlich wird er als JMX Bean registriert.

 
public class CurrentTimeEndpoint extends AbstractEndpoint<Map<String, String>> {
  public CurrentTimeEndpoint() {
    super("currentTime");
  }

  @Override
  public Map<String, String> invoke() {
    return Collections.singletonMap("currentTime", ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
  }
}

Der Admin-Server lädt alle UI-Module vom Klassenpfad, die dem Pattern /META-INF/spring-boot-admin-server-ui/*/module.js entsprechen. Diese Datei ist unser Einstiegspunkt. Hier erzeugen wir ein eigenes Angular-Modul und fügen es der globalen Liste der Module hinzu, damit das UI es lädt. Beim Start des Angular-Moduls registrieren wir eine neue ApplicationView. Hier geben wir den Titel, die Reihenfolge und den State für den Angular-Router mit (Listing 9). Für anwendungsbezogene Ansichten ist es wichtig, dass der neue State unterhalb von applications eingeordnet wird. So können wir uns später die ausgewählte Anwendung in den Controller injizieren lassen.

 
//Neues modul instanziieren und registrieren
var module = angular.module('sba-applications-currentTime', ['sba-applications']);
sbaModules.push(module.name);

//Die neue Seite registrieren
module.run(['ApplicationViews', '$http', function (ApplicationViews, $http) {
 ApplicationViews.register({
  order: 50,
  title: 'Current Time',
  state: 'applications.currentTime'
 });
}]);

Wie für Angular-Anwendungen typisch, müssen wir für den State einen URL, ein Template und den zugehörigen Controller angeben und implementieren. Im Controller fragen wir per HTTP GET den neuen Endpunkt ab (Listing 10). In unserem Template für die Seite geben wir einfach den abgefragten Wert aus (Listing 11).

 
//Den Router-State beschreiben
module.config(['$stateProvider', function ($stateProvider) {
 $stateProvider.state('applications.currentTime', {
  url: '/currentTime',
  templateUrl: 'applications-currentTime/currentTime.html',
  controller: 'currentTimeCtrl'
 });
}]);

//Den Controller für die Seite anlegen
module.controller('currentTimeCtrl', ['$scope', '$http', 'application', functi-on ($scope, $http, application) {
  //Den Endpoint auslesen
  $http.get('api/applications/' + application.id + '/currentTime').then(function (response) {
   $scope.currentTime = response.data.currentTime;
  })
 }]);
  
<div>
  {{ currentTime }}
</div>

Für das Pattern /META-INF/spring-boot-admin-server-ui/*/module.css können wir noch eine CSS-Datei ablegen. Diese wird dann mit den anderen CSS-Dateien vom Browser geladen. Als Letztes müssen wir dafür sorgen, dass der neue Actuator-Endpunkt über den integrierten Zuul-Proxy im Admin-Server verfügbar wird. Dazu fügen wir den neuen Endpunkt der Liste in spring.boot.admin.routes.endpoints hinzu, und schon können wir die Ansicht für den neuen Endpunkt in der Oberfläche aufrufen. Zugegebenermaßen ist das Ergebnis weder sehr schön noch in irgendeiner Form sinnvoll, zeigt aber kurz und knapp, wie man die Oberfläche erweitern kann. Neben diesen anwendungsbezogenen Ansichten kann man auch MainViews, wie die About-Seite, auf ähnliche Weise hinzufügen. Hierfür wirft man am einfachsten einen Blick in den Quellcode des spring-boot-admin-server-ui-login-Moduls.

Fazit

Der Betrieb von Spring Boot Admin ist wie der Betrieb der eigenen Spring-Boot-Anwendung kinderleicht. Daher gelingt die Installation ohne Enterprise-Zertifizierung durch den Hersteller oder tagelangem Handbuchwälzen. Für Spring-Boot-Anwendungen wird eine Reihe nützlicher Funktionen out of the box unterstützt, die man bei anderen Monitoringlösungen vermisst. Dadurch, dass der Spring Boot Admin für viele Java-Entwickler vertraute Dinge verwendet, lässt sich die Monitoringlösung ganz leicht auf die eigenen Bedürfnisse anpassen. Wenn es dann doch mal hier oder da klemmt, lade ich jeden dazu ein, sich an dem Open-Source-Projekt auf GitHub zu beteiligen. Der vollständige Quellcode der Beispiele ist in meinem GitHub Repository zu finden.

Mehr zum Thema:

Spring Boot – was ist das, was kann das?

Verwandte Themen:

Geschrieben von
Johannes Edmeier
Johannes Edmeier
Johannes Edmeier ist Software Engineer bei der codecentric AG und Maintainer des Spring-Boot-Admin-Projekts.
Kommentare
  1. Michael2017-08-05 19:49:29

    Es hat sich ein kleiner Fehler eingeschlichen. Für die Loginmaske benötigt man statt de.codedentric:spring-boot-admin-ui-login folgendes dependency:

    de.codecentric
    spring-boot-admin-server-ui
    1.5.3

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.