Slide 1

Slide 1 text

Andy Wilkinson @ankinson MASTERING SPRING BOOT’S ACTUATOR

Slide 2

Slide 2 text

@ankinson ACTUATOR?

Slide 3

Slide 3 text

@ankinson actuator noun mechanical device for moving or controlling something Spring Boot Actuator noun module for controlling Spring Boot applications ACTUATOR?

Slide 4

Slide 4 text

WHAT’S NEW?

Slide 5

Slide 5 text

@ankinson WHAT’S NEW? •Endpoints under /actuator •management.endpoints.web.base-path •management.endpoints.web.exposure.include
 management.endpoints.web.exposure.exclude •management.endpoint.shutdown.enabled •EndpointRequest •Jersey, WebFlux, or Spring MVC

Slide 6

Slide 6 text

@ankinson SCHEDULED TASKS { "cron" : [ { "runnable" : { "target" : "com.example.Processor.processOrders" }, "expression" : "0 0 0/3 1/1 * ?" } ], "fixedDelay" : [ { "runnable" : { "target" : "com.example.Processor.purge" }, "initialDelay" : 5000, "interval" : 5000 } ], "fixedRate" : [ { "runnable" : { "target" : "com.example.Processor.retrieveIssues" }, "initialDelay" : 10000, "interval" : 3000 } ] } /actuator/scheduledtasks Inspired by a proposal from Huang YunKun Builds on top of improvements in Spring Framework 5.0 "cron" : [ { "runnable" : { "target" : "com.example.Processor.processOrders" }, "expression" : "0 0 0/3 1/1 * ?" } "fixedDelay" : [ { "runnable" : { "target" : "com.example.Processor.purge" }, "initialDelay" : 5000, "interval" : 5000 }

Slide 7

Slide 7 text

@ankinson SESSIONS { "sessions" : [ { "id" : "d66667e1-bcf1-453a-89f2-1d777439c4de", "attributeNames" : [ ], "creationTime" : "2018-05-09T11:28:40.594Z", "lastAccessedTime" : "2018-05-09T13:28:28.594Z", "maxInactiveInterval" : 1800, "expired" : false }, { "id" : "85af4f77-319f-4912-8e81-f40c9de63735", "attributeNames" : [ ], "creationTime" : "2018-05-09T01:28:40.593Z", "lastAccessedTime" : "2018-05-09T13:27:55.593Z", "maxInactiveInterval" : 1800, "expired" : false }, { "id" : "4db5efcc-99cb-4d05-a52c-b49acfbb7ea9", "attributeNames" : [ ], "creationTime" : "2018-05-09T08:28:40.594Z", "lastAccessedTime" : "2018-05-09T13:28:03.594Z", "maxInactiveInterval" : 1800, "expired" : false } ] } /actuator/sessions Contributed by Vedran Pavic { "id" : "85af4f77-319f-4912-8e81-f40c9de63735", "attributeNames" : [ ], "creationTime" : "2018-05-09T01:28:40.593Z", "lastAccessedTime" : "2018-05-09T13:27:55.593Z", "maxInactiveInterval" : 1800, "expired" : false }

Slide 8

Slide 8 text

WEB API DOCUMENTATION

Slide 9

Slide 9 text

@ankinson METRICS

Slide 10

Slide 10 text

@ankinson MICROMETER

Slide 11

Slide 11 text

@ankinson Auditorium 15:30

Slide 12

Slide 12 text

@ankinson WRITING YOUR OWN ENDPOINTS

Slide 13

Slide 13 text

@ankinson /** * {@link Endpoint} to expose a user's {@link Session}s. * * @author Vedran Pavic * @since 2.0.0 */ @Endpoint(id = "sessions") public class SessionsEndpoint { // … } @Endpoint(id = "sessions") http://example.com/actuator/ sessions

Slide 14

Slide 14 text

@ankinson @ReadOperation public SessionsReport sessionsForUsername(String username) { Map sessions = this.sessionRepository .findByIndexNameAndIndexValue( FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username); return new SessionsReport(sessions); } @ReadOperation (String username) SessionsReport GET http://example.com/actuator/sessions username ? =alice

Slide 15

Slide 15 text

@ankinson @ReadOperation public SessionDescriptor getSession(@Selector String sessionId) { Session session = this.sessionRepository.findById(sessionId); if (session == null) { return null; } return new SessionDescriptor(session); } @ReadOperation (@Selector String sessionId) SessionDescriptor GET http://example.com/actuator/sessions /{ } sessionId

Slide 16

Slide 16 text

@ankinson @DeleteOperation public void deleteSession(@Selector String sessionId) { this.sessionRepository.deleteById(sessionId); } @DeleteOperation @Selector String sessionId DELETE http://example.com/actuator/sessions /{ } sessionId void

Slide 17

Slide 17 text

@ankinson @Endpoint(id = "loggers") public class LoggersEndpoint { @WriteOperation public void configureLogLevel(@Selector String name, @Nullable LogLevel configuredLevel) { Assert.notNull(name, "Name must not be empty"); this.loggingSystem.setLogLevel(name, configuredLevel); } } @Endpoint(id = “loggers") @WriteOperation void @Selector String name @Nullable LogLevel configuredLevel POST http://example.com/actuator/loggers /{ } name { " ": "DEBUG" } configuredLevel

Slide 18

Slide 18 text

@ankinson @EndpointWebExtension(endpoint = HealthEndpoint.class) public class HealthEndpointWebExtension { @ReadOperation public WebEndpointResponse getHealth( SecurityContext securityContext) { return this.responseMapper.map( this.delegate.health(), securityContext); } } @EndpointWebExtension(endpoint = HealthEndpoint.class) WebEndpointResponse SecurityContext securityContext

Slide 19

Slide 19 text

@ankinson @ServletEndpoint @ControllerEndpoint @RestControllerEndpoint

Slide 20

Slide 20 text

THANKS! Andy Wilkinson @ankinson