Quantcast
Channel: Baeldung
Viewing all articles
Browse latest Browse all 3541

Spring Boot Actuator

$
0
0

1. Overview

In this article, we’re going to introduce Spring Boot Actuators and talk about some simple ways to work with them in production.

2. What Is An Actuator?

Actuators enable production-ready features to a Spring Boot application – without having to actually implement these things yourself.

They’re mainly used to expose different types of information about the running application – health, metrics, info, dump, env etc. And while these are no replacement for a production-grade monitoring solution – they’re a very good starting point.

2.1. How to Enable an Actuator

To start using the existing actuators in Boot – we’ll just need to add the spring-boot-actuator dependency to the pom:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <version>1.2.3.RELEASE</version>
</dependency>

3. Endpoints

Endpoints allow you to monitor the application and, in some cases – interact with it as well. Boot comes with many built-in endpoints and, like with pretty much anything in Spring – you can also roll your own.

Most endpoints are sensitive – meaning they’re not fully public – while a handful are not: /health and /info.

Here’s some of the most common endpoints Boot provides out of the box:

  • /health – Shows application health information (a simple ‘status’ when accessed over an unauthenticated connection or full message details when authenticated). It is sensitive by default.
  • /info – Displays arbitrary application info. Not sensitive by default.
  • /metrics – Shows ‘metrics’ information for the current application. It is also sensitive by default.
  • /trace – Displays trace information (by default the last few HTTP requests).

You can find the full list of existing endpoints over on the official docs.

4. Customizing Existing Endpoints

Each endpoint can be customized with properties using the following format: endpoints.[endpoint name].[property to customize]

Three properties are available:

  • id – by which this endpoint will be accessed over HTTP
  • enabled – if true then it can be accessed otherwise not
  • sensitive – if true then need authorization to show crucial information over HTTP

For example, add the following properties will customize the /beans endpoint:

endpoints.beans.id=springbeans
endpoints.beans.sensitive=false
endpoints.beans.enabled=true

4.1. /health Endpoint

The /health endpoint is used to check the health / status of the running application. It’s usually used by basic monitoring software to alert you if the production goes down.

By default only health information is shown to unauthorized access over HTTP:

{
    "status" : "UP"
}

This health information is collected from all the beans implementing HealthIndicator interface configured in your application context.

Some information returned by HealthIndicator is sensitive in nature – but you can configure endpoints.health.sensitive=false to expose the other information like diskspace, datasource etc.

4.2. A Custom HealthIndicator

You can also roll your own custom health indicator – which can collect any type of custom health data specific to the application and provide it to the /health endpoint:

@Component
public class HealthCheck implements HealthIndicator {
    @Override
    public Health health() {
        int errorCode = check(); // perform some specific health check
        if (errorCode != 0) {
            return Health.down().withDetail("Error Code", errorCode).build();
        }
        return Health.up().build();
    }
    
    public int check() {
    	// Your logic to check health
    	return 0;
    }
}

Here’s how the output would look like:

{
    "status" : "DOWN",
    "myHealthCheck" : {
        "status" : "DOWN",
        "Error Code" : 1,
        "Description" : "You custom MyHealthCheck endpoint is down"
     },
     "diskSpace" : {
         "status" : "UP",
         "free" : 209047318528,
         "threshold" : 10485760
     }
}

4.3. /info Endpoint

You can also customize the data shown by /info endpoint – for example:

info.app.name=Spring Sample Application
info.app.description=This is my first spring boot application
info.app.version=1.0.0

And the sample output:

{
    "app" : {
        "version" : "1.0.0",
        "description" : "This is my first spring boot application",
        "name" : "Spring Sample Application"
    }
}

4.4. /metrics Endpoint

The metrics endpoint is one of the more important endpoints as it gathers and publishes information about OS, JVM and Application level metrics; out of the box, we get things like memory, heap, processors, threads, classes loaded, classes unloaded, thread pools along with some HTTP metrics as well.

Here’s what the output of this endpoint looks like out of the box:

{
    "mem" : 193024,
    "mem.free" : 87693,
    "processors" : 4,
    "instance.uptime" : 305027,
    "uptime" : 307077,
    "systemload.average" : 0.11,
    "heap.committed" : 193024,
    "heap.init" : 124928,
    "heap.used" : 105330,
    "heap" : 1764352,
    "threads.peak" : 22,
    "threads.daemon" : 19,
    "threads" : 22,
    "classes" : 5819,
    "classes.loaded" : 5819,
    "classes.unloaded" : 0,
    "gc.ps_scavenge.count" : 7,
    "gc.ps_scavenge.time" : 54,
    "gc.ps_marksweep.count" : 1,
    "gc.ps_marksweep.time" : 44,
    "httpsessions.max" : -1,
    "httpsessions.active" : 0,
    "counter.status.200.root" : 1,
    "gauge.response.root" : 37.0
}

4.5. Custom Metric Data

There is actually support here for ‘gauge’ – single value data, and ‘counter’ – incrementing/decrementing data types of metrics. Let’s make use of some of this support to implement our own custom data into the /metrics endpoint.

For example – we’ll customize the login flow to record a successful and failed login attempt:

public interface LoginService {
    public boolean login(String userName, char[] password);
}

And the actual implementation, where we increase the relevant counters:

@Service
public class LoginServiceImpl implements LoginService {

    private CounterService counterService;
    
    @Autowired
    public LoginServiceImpl(CounterService counterService) {
        this.counterService = counterService;
    }
	
    public boolean login(String userName, char[] password) {
        boolean success;
        if (userName.equals("admin") && "secret".toCharArray().equals(password)) {
            counterService.increment("counter.login.success");
            success = true;
        }
        else {
            counterService.increment("counter.login.failure");
            success = false;
        }
        return success;
    }
}

Here’s what the output might look like:

{
    ...
    "counter.login.success" : 105,
    "counter.login.failure" : 12,
    ...
}

5. Create A New Endpoint

Besides using the existing endpoints provided by Spring Boot – you can also create an entirely new endpoint.

First – you’ll need to have the new endpoint implementation implement the Endpoint<T> interface:

@Component
public class CustomEndpoint implements Endpoint<List<String>> {
    
    public String getId() {
        return "customEndpoint";
    }

    public boolean isEnabled() {
        return true;
    }

    public boolean isSensitive() {
        return true;
    }

    public List<String> invoke() {
        // Custom logic to build the output
        List<String> messages = new ArrayList<String>();
        messages.add("This is message 1");
        messages.add("This is message 2");
        return messages;
    }
}

Output:

[ "This is message 1", "This is message 2" ]

6. A New Endpoint To List All Endpoints

Another interesting custom endpoint is one that exposes all available endpoints. To implement this one, you’ll need to extend the AbstractEndpoint<T> class:

@Component
public class ListEndpoints extends AbstractEndpoint<List<Endpoint>> {
    private List<Endpoint> endpoints;

    @Autowired
    public ListEndpoints(List<Endpoint> endpoints) {
        super("listEndpoints");
        this.endpoints = endpoints;
    }

    public List<Endpoint> invoke() {
        return this.endpoints;
    }
}

Here’s how the output will look like:

[ 
   {
       "id" : "customEndpoint",
       "enabled" : true,
       "sensitive" : true
    }, {
       "id" : "mappings",
       "sensitive" : true,
       "enabled" : true
    }, {
       "id" : "env",
       "sensitive" : true,
       "enabled" : true
    }, {
       "id" : "myhealth",
       "sensitive" : true,
       "enabled" : true,
       "timeToLive" : 1000
    }, {
       "id" : "beans",
       "sensitive" : true,
       "enabled" : true
    }, {
       "id" : "info",
       "sensitive" : false,
       "enabled" : true
    }, {
       "id" : "metrics",
       "sensitive" : true,
       "enabled" : true
    }, {
       "id" : "trace",
       "sensitive" : true,
       "enabled" : true
    }, {
       "id" : "dump",
       "sensitive" : true,
       "enabled" : true
    }, {
       "id" : "autoconfig",
       "sensitive" : true,
       "enabled" : true
    }, {
       "id" : "shutdown",
       "sensitive" : true,
       "enabled" : true
    }, {
       "id" : "configprops",
       "sensitive" : true,
       "enabled" : true
    } 
]

7. Further Customization

For security purposes, you might choose to expose the actuator endpoints over a non-standard port – the management.port property can easily be used to configure that.

You can also change the management.address property to restrict where the endpoints can be accessed from over the network:

management.port=8081
management.address=127.0.0.1
management.security.enabled=false

All the built-in endpoints except /info are sensitive by default. If the application is using Spring Security – you can secure these endpoints by defining the default security properties – user name, password and role – in application.properties file:

security.user.name=admin
security.user.password=secret
management.security.role=SUPERUSER

8. Conclusion

In this tutorial we had a first look at the interesting Actuator functionality provided by Spring Boot. We went over the existing endpoints available in the framework, augmented some of them with new, custom data and finally rolled our own to expose some entirely new kind of data.


Viewing all articles
Browse latest Browse all 3541

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>