Spring Boot Admin

Spring Boot Admin thumbnail
20K
By Dhiraj 06 July, 2020

This article is in continuation with our last article Spring Boot Actuator. We discussed actuators in great detail for application managing and monitoring with spring security integrated.

In this article, we will discuss Spring Boot Admin that utilizes those Actuator endpoints to provide a clean UI to visualize our application metrics and state. First, we will create a simple client and server app with a monolithic approach that will help to understand the Spring Boot Admin core concepts and then we will extend it to support monitoring of microservices-based architecture apps in cloud.

What is Spring Boot Admin

Spring Boot Admin is a web app developed by codecentric which provides an admin console for the managing and monitoring of spring boot applications by consuming Actuator REST endpoints.

There are mainly 2 starter projects for this - server and client. The server project is the web app itself that provides the admin console whereas client apps are all the microservices running for which we want to set up the monitoring.

We configure the server location in the client app and the client app registers itself to the server app and then the server app utilizes client's Actuator endpoints to fetch all the app metrics.

We can also configure Server app to discover client apps from a discovery server assuming all the client apps register themselves to a central discovery server. This is typically a distributed system setup.

Setting Up Spring Boot Admin Server

Head over to start.spring.io to generate our sample server project with required dependencies including Spring Boot Admin Server artifacts.

spring-boot-admin-server-project-generation

Let us check what are the maven dependencies that we got in our pom.xml.

        <dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>de.codecentric</groupId>
			<artifactId>spring-boot-admin-starter-server</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>de.codecentric</groupId>
				<artifactId>spring-boot-admin-dependencies</artifactId>
				<version>${spring-boot-admin.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

Now, we can import it into our IDE and we can annotate our spring boot main class with @EnableAdminServer to enable the spring boot admin server.

Noe, let us run our SpringBootAdminServerApplication.java to see spring boot admin server in action.

@EnableAdminServer
@SpringBootApplication
public class SpringBootAdminServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootAdminServerApplication.class, args);
	}

}
application.properties
server.port=8085

With this much of configuration, our admin server is now running at port 8085.

spring-boot-admin-console-no-instance

As we can see there are no applications registred as we have not registerd any clients and hence the console is empty. Let us create our client app.

Setting Up Spring Boot Admin Client

Head over to start.spring.io to generate our sample server project with required dependencies including Spring Boot Admin client artifcat and Actuator artifact.

Spring boot actuator will expose more then 16 endpoints to manage and monitor our application and these REST endpoints will be consumed by our admin server to show the different metrics of our client app in the admin console.

spring-boot-admin-client-project

Now, let us checkout our pom.xml in case you only want to add dependencies in your existing project.

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>de.codecentric</groupId>
			<artifactId>spring-boot-admin-starter-client</artifactId>
		</dependency>

	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>de.codecentric</groupId>
				<artifactId>spring-boot-admin-dependencies</artifactId>
				<version>${spring-boot-admin.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

With default condifuration of Actuator, all the endpoints are enabled except /shutdown but only 2 endpoints are exposed and they are /health and /info. To expose all these actuator endpoints we have to add below configuration on our application.properties. The details of it can be found in my last actuator article here.

application.properties
spring.application.name=devglan-demo

spring.boot.admin.client.url=http://localhost:8085

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

info.app.developer=Dhiraj
info.app.java.source=1.8
info.app.java.target=1.8

spring.boot.admin.client.url is the URL of our admin server app which is running at port 8085.

The application name that we configured in our properties file will be shown in our admin console to uniquely identify multiple running applications. By default, the value for show-details is never and we can configure its value as always. We have also added some custom info about our app.

With this much of configuration let us run our client app and restart server app and check the admin console.

@SpringBootApplication
public class SpringBootAdminClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootAdminClientApplication.class, args);
	}

}

Now, we can check out http://localhost:8085/wallboard to see our client application registered in the admin console and we can see different metrics of the client app and manage and monitor it through the admin console.

spring-boot-admin-console-health

Service Discovery of Client Apps

Till this point, we have our spring boot admin server and client are running perfectly fine but we have a manual hardcoded configuration of the admin server URL in our client app. The admin server also provides the service discovery of the client app and let us configure the same in our admin server app which would be essential in a microservice-based architecture application.

You can refer this to discover all the concepts of microservices that we have discussed so far.

We will be using the Netflix Eureka server for our service discovery. We have already discovered the concepts and configuration behind this Spring Boot Eureka Server in my previous article and hence let's directly jump into code implementation.

First, let us run our service discovery instance. Head over to start.spring.io and generate a project for our discovery server and import it into our IDE.

Below are the dependencies included in pom.xml. Here, the spring cloud version is Hoxton.SR6.

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

Below is our configuration parameters for discovery server.

spring:
  application:
    name: discovery-service

eureka:
  client:
    eureka-server-connect-timeout-seconds: 5
    enabled: true
    fetch-registry: false
    register-with-eureka: false
    log-delta-diff: false
  instance:
    prefer-ip-address: true
  server:
    enable-self-preservation: true


server:
  port: 8761

Let us annotate the SpringCloudEurekaServerApplication.java with the annotation @EnableEurekaServer and start it as a Spring Boot app. Our central discovery server is up now at http://localhost:8761. Let us configure the admin server and client app to make use of it.

Enabling Service Discovery in Admin Server App

We need to add below maven dependency in our server app pom.xml file to enable the service discovery.

<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
<dependencies>
	...
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>

<dependencies>

	<dependencyManagement>
		...
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
application.yml
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka
    register-with-eureka: false
    registry-fetch-interval-seconds: 5
  instance:
    preferIpAddress: true
spring:
  application:
    name: admin-server
server:
  port: 8085

Now, let us enable our spring boot admin client to register itself to discovery server. For this purpose, let us add the same dependency that we added for admin server app and below is the yml file. This yml file has register-with-eureka set to true so that the admin client app registers itself to the discovery server.

Once our client app registers itself to the discovery server then the admin server project will pick this server info from the discovery server and start showing its metrics in the admin console.

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka
    register-with-eureka: false
    registry-fetch-interval-seconds: 5
  instance:
    preferIpAddress: true

This is pretty much the configuration of spring Boot Admin in a microservice based apps. Let us start our client app and check the admin console.

spring-boot-admin-service-registry spring-boot-admin-dashboard

Configuring Notifications in Spring Boot Admin

There are various notification options that we can configure in our admin server app. There are some out of the box notifications support provided by the admin server which we can configure in our app whereas we can also create custom notifications as per the requirement.

Below are the notifiers which can be configured in no time with simple application.properties entries.

  • eMail
  • slack
  • pagerduty
  • HipChat
  • OpsGenie
  • LetsChat
  • Microsoft Teams
  • Telegram
  • Discord

We can also add custom notifications apart from these default ones that we will discuss later.

Email Notification Configuration

Email notification can be used to trigger email notifications whenever the state of our application changes such as UP or DOWN. To do so first we need to configure mailing system in our admin server project.

Let us add spring boot starter mail artifact in our pom.xml and configure to use Gmail as our mail client.

pom.xml
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

We need to make below mail related entries in application.properties. This will send email to admin@gmail.com on app status change.

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=username
spring.mail.password=password
spring.boot.admin.notify.mail.to=admin@gmail.com
spring.mail.properties.mail.smtp.starttls.enable=true

Custom Notifications in Spring Boot Admin

Spring boot admin works based on event-sourcing. Hence, whenever any of the state changes, an event is triggered and we can create our custom Notifier Bean to listen to those event and can send our custom notifications.

Below is an example code from the official source of Spring Boot Admin for custom notifications.

The RemindingNotifier sends reminders for down/offline applications and delegates the sending of notifications to another notifier.

@Configuration
public class NotifierConfig {

    private final InstanceRepository repository;

    private final ObjectProvider> otherNotifiers;

    public NotifierConfig(InstanceRepository repository, ObjectProvider> otherNotifiers) {
        this.repository = repository;
        this.otherNotifiers = otherNotifiers;
    }

    @Bean
    public FilteringNotifier filteringNotifier() {
        CompositeNotifier delegate = new CompositeNotifier(this.otherNotifiers.getIfAvailable(Collections::emptyList));
        return new FilteringNotifier(delegate, this.repository);
    }

    @Primary
    @Bean(initMethod = "start", destroyMethod = "stop")
    public RemindingNotifier remindingNotifier() {
        RemindingNotifier notifier = new RemindingNotifier(filteringNotifier(), this.repository);
        notifier.setReminderPeriod(Duration.ofMinutes(10));
        notifier.setCheckReminderInverval(Duration.ofSeconds(10));
        return notifier;
    }
}

Apart from this we can also add our custom notifier by extending AbstractEventNotifier or AbstractStatusChangeNotifier.

public class CustomNotifier extends AbstractEventNotifier {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingNotifier.class);

    public CustomNotifier(InstanceRepository repository) {
        super(repository);
    }

    @Override
    protected Mono doNotify(InstanceEvent event, Instance instance) {
        return Mono.fromRunnable(() -> {
            if (event instanceof InstanceStatusChangedEvent) {
                LOGGER.info("Instance {} ({}) is {}", instance.getRegistration().getName(), event.getInstance(),
                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus());
            }
            else {
                LOGGER.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(),
                        event.getType());
            }
        });
    }
}

Securing Spring Boot Admin with Spring Security

Spring Boot admin provides easy integration with spring security to secure our admin console. Adding a basic authentication to the admin console only requires some properties update but it is not only limited to basic authentication as it provides integration with OAUTH2, JWT or traditional session-based authentication.

We have discussed securing spring boot admin server and client in detail in my next article here.

Conclusion

In this article, we discussed about Spring Boot Admin and created separate projects for sample admin server and client and performed the client discovery through Netflix Eureka.

Share

If You Appreciate This, You Can Consider:

We are thankful for your never ending support.

About The Author

author-image
A technology savvy professional with an exceptional capacity to analyze, solve problems and multi-task. Technical expertise in highly scalable distributed systems, self-healing systems, and service-oriented architecture. Technical Skills: Java/J2EE, Spring, Hibernate, Reactive Programming, Microservices, Hystrix, Rest APIs, Java 8, Kafka, Kibana, Elasticsearch, etc.

Further Reading on Spring Boot