diff --git a/build.gradle b/build.gradle index d1e59f73..d610ef5e 100644 --- a/build.gradle +++ b/build.gradle @@ -60,8 +60,8 @@ configure(allprojects) { } compileJava { - sourceCompatibility = 1.7 - targetCompatibility = 1.7 + sourceCompatibility = 1.8 + targetCompatibility = 1.8 } compileTestJava { @@ -195,6 +195,7 @@ project('spring-statemachine-boot') { optional project(":spring-statemachine-data-common:spring-statemachine-data-jpa") optional project(":spring-statemachine-data-common:spring-statemachine-data-redis") optional project(":spring-statemachine-data-common:spring-statemachine-data-mongodb") + optional "io.micrometer:micrometer-core" optional "org.eclipse.persistence:javax.persistence" optional "org.springframework.boot:spring-boot-starter-data-jpa" optional "org.springframework.boot:spring-boot-starter-data-redis" diff --git a/spring-statemachine-boot/src/main/java/org/springframework/statemachine/boot/autoconfigure/StateMachineAutoConfiguration.java b/spring-statemachine-boot/src/main/java/org/springframework/statemachine/boot/autoconfigure/StateMachineAutoConfiguration.java index 123c7783..03b563a6 100644 --- a/spring-statemachine-boot/src/main/java/org/springframework/statemachine/boot/autoconfigure/StateMachineAutoConfiguration.java +++ b/spring-statemachine-boot/src/main/java/org/springframework/statemachine/boot/autoconfigure/StateMachineAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,6 @@ package org.springframework.statemachine.boot.autoconfigure; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -28,6 +26,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.boot.StateMachineProperties; import org.springframework.statemachine.boot.support.BootStateMachineMonitor; +import io.micrometer.core.instrument.MeterRegistry; + /** * {@link EnableAutoConfiguration Auto-configuration} for Spring Statemachine. * @@ -39,25 +39,22 @@ import org.springframework.statemachine.boot.support.BootStateMachineMonitor; public class StateMachineAutoConfiguration { @Configuration - @ConditionalOnClass(CounterService.class) + @ConditionalOnClass(MeterRegistry.class) @ConditionalOnProperty(prefix = "spring.statemachine.monitor", name = "enabled", havingValue = "true", matchIfMissing = true) public static class StateMachineMonitoringConfiguration { - private final CounterService counterService; - private final GaugeService gaugeService; + private final MeterRegistry meterRegistry; private final TraceRepository traceRepository; - public StateMachineMonitoringConfiguration(ObjectProvider counterServiceProvider, - ObjectProvider gaugeServiceProvider, + public StateMachineMonitoringConfiguration(ObjectProvider meterRegistryProvider, ObjectProvider traceRepositoryProvider) { - this.counterService = counterServiceProvider.getIfAvailable(); - this.gaugeService = gaugeServiceProvider.getIfAvailable(); + this.meterRegistry = meterRegistryProvider.getIfAvailable(); this.traceRepository = traceRepositoryProvider.getIfAvailable(); } @Bean public BootStateMachineMonitor bootStateMachineMonitor() { - return new BootStateMachineMonitor<>(counterService, gaugeService, traceRepository); + return new BootStateMachineMonitor<>(meterRegistry, traceRepository); } } } diff --git a/spring-statemachine-boot/src/main/java/org/springframework/statemachine/boot/support/BootStateMachineMonitor.java b/spring-statemachine-boot/src/main/java/org/springframework/statemachine/boot/support/BootStateMachineMonitor.java index 27985ae9..bf9083d5 100644 --- a/spring-statemachine-boot/src/main/java/org/springframework/statemachine/boot/support/BootStateMachineMonitor.java +++ b/spring-statemachine-boot/src/main/java/org/springframework/statemachine/boot/support/BootStateMachineMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,8 @@ package org.springframework.statemachine.boot.support; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.action.Action; @@ -29,6 +28,11 @@ import org.springframework.statemachine.state.State; import org.springframework.statemachine.transition.Transition; import org.springframework.util.ObjectUtils; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.stats.hist.Histogram; + /** * Implementation of a {@link StateMachineMonitor} which converts monitoring * events and bridges those into supported format handled by Spring Boot's @@ -41,31 +45,24 @@ import org.springframework.util.ObjectUtils; */ public class BootStateMachineMonitor extends AbstractStateMachineMonitor { - private final String METRIC_TRANSITION_BASE = "ssm.transition"; - private final String METRIC_ACTION_BASE = "ssm.action"; - private final CounterService counterService; - private final GaugeService gaugeService; private final TraceRepository traceRepository; + private final MeterRegistry meterRegistry; /** * Instantiates a new boot state machine monitor. * - * @param counterService the counter service - * @param gaugeService the gauge service + * @param meterRegistry the meter registry * @param traceRepository the trace repository */ - public BootStateMachineMonitor(CounterService counterService, GaugeService gaugeService, - TraceRepository traceRepository) { - this.counterService = counterService; - this.gaugeService = gaugeService; + public BootStateMachineMonitor(MeterRegistry meterRegistry, TraceRepository traceRepository) { + this.meterRegistry = meterRegistry; this.traceRepository = traceRepository; } @Override public void transition(StateMachine stateMachine, Transition transition, long duration) { - String transitionName = transitionToName(transition); - this.counterService.increment(METRIC_TRANSITION_BASE + "." + transitionName + ".transit"); - this.gaugeService.submit(METRIC_TRANSITION_BASE + "." + transitionName + ".duration", duration); + getTransitionCounterBuilder(transition).register(meterRegistry).increment(); + getTransitionTimerBuilder(transition).register(meterRegistry).record(duration, TimeUnit.MILLISECONDS); Map traceInfo = new HashMap<>(); traceInfo.put("transition", transitionToName(transition)); traceInfo.put("duration", duration); @@ -76,8 +73,8 @@ public class BootStateMachineMonitor extends AbstractStateMachineMonitor stateMachine, Action action, long duration) { String actionName = actionToName(action); - this.counterService.increment(METRIC_ACTION_BASE + "." + actionName + ".execute"); - this.gaugeService.submit(METRIC_ACTION_BASE + "." + actionName + ".duration", duration); + getActionCounterBuilder(action).register(meterRegistry).increment(); + getActionTimerBuilder(action).register(meterRegistry).record(duration, TimeUnit.MILLISECONDS); Map traceInfo = new HashMap<>(); traceInfo.put("action", actionName); traceInfo.put("duration", duration); @@ -85,6 +82,40 @@ public class BootStateMachineMonitor extends AbstractStateMachineMonitor transition) { + String transitionName = transitionToName(transition); + Counter.Builder builder = Counter.builder("ssm.transition.transit") + .tags("transitionName", transitionName) + .description("Counter of Transition"); + return builder; + } + + private Timer.Builder getTransitionTimerBuilder(Transition transition) { + String transitionName = transitionToName(transition); + Timer.Builder builder = Timer.builder("ssm.transition.duration") + .tags("transitionName", transitionName) + .description("Timer of Transition"); + builder.histogram(Histogram.percentilesTime()); + return builder; + } + + private Counter.Builder getActionCounterBuilder(Action action) { + String actionName = actionToName(action); + Counter.Builder builder = Counter.builder("ssm.action.execute") + .tags("actionName", actionName) + .description("Counter of Action"); + return builder; + } + + private Timer.Builder getActionTimerBuilder(Action action) { + String actionName = actionToName(action); + Timer.Builder builder = Timer.builder("ssm.action.duration") + .tags("actionName", actionName) + .description("Timer of Action"); + builder.histogram(Histogram.percentilesTime()); + return builder; + } + private static String transitionToName(Transition transition) { String sourceId = nullStateId(transition.getSource()); String targetId = nullStateId(transition.getTarget()); diff --git a/spring-statemachine-samples/build.gradle b/spring-statemachine-samples/build.gradle index 31f2e0c1..71cc2585 100644 --- a/spring-statemachine-samples/build.gradle +++ b/spring-statemachine-samples/build.gradle @@ -131,9 +131,9 @@ project('spring-statemachine-samples-monitoring') { description = 'Spring State Machine Monitoring Sample' dependencies { compile project(":spring-statemachine-boot") + compile("org.springframework.boot:spring-boot-starter-actuator") compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-thymeleaf") - compile("org.springframework.boot:spring-boot-starter-security") testCompile("com.jayway.jsonpath:json-path") testCompile("com.jayway.jsonpath:json-path-assert") } diff --git a/spring-statemachine-samples/monitoring/src/main/resources/application.yml b/spring-statemachine-samples/monitoring/src/main/resources/application.yml index 7f5d6d93..42c79c3e 100644 --- a/spring-statemachine-samples/monitoring/src/main/resources/application.yml +++ b/spring-statemachine-samples/monitoring/src/main/resources/application.yml @@ -1,12 +1,10 @@ logging: level: root: INFO -management: - security: - enabled: false -security: - basic: - enabled: false +spring: + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration endpoints: default: web: diff --git a/spring-statemachine-samples/monitoring/src/test/java/demo/monitoring/MonitoringTests.java b/spring-statemachine-samples/monitoring/src/test/java/demo/monitoring/MonitoringTests.java index 7ae67968..0cc14206 100644 --- a/spring-statemachine-samples/monitoring/src/test/java/demo/monitoring/MonitoringTests.java +++ b/spring-statemachine-samples/monitoring/src/test/java/demo/monitoring/MonitoringTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,13 @@ */ package demo.monitoring; +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -80,7 +82,11 @@ public class MonitoringTests { andExpect(status().isOk()); mvc. perform(get("/application/metrics")). - andExpect(jsonPath("$.['counter.ssm.transition.INITIAL_S1.transit']", is(1))); + andExpect(jsonPath("$.names", hasItems("ssm.transition.duration", "ssm.transition.transit"))); + mvc. + perform(get("/application/metrics/ssm.transition.duration")). + andDo(print()). + andExpect(jsonPath("$['ssmTransitionDuration.transitionname.INITIAL_S1']", notNullValue())); } @Test diff --git a/spring-statemachine-samples/web/src/main/java/demo/web/WebSocketConfig.java b/spring-statemachine-samples/web/src/main/java/demo/web/WebSocketConfig.java index f7f55e2e..331cc4d7 100644 --- a/spring-statemachine-samples/web/src/main/java/demo/web/WebSocketConfig.java +++ b/spring-statemachine-samples/web/src/main/java/demo/web/WebSocketConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ */ package demo.web; +import java.util.concurrent.ConcurrentHashMap; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; @@ -41,7 +43,7 @@ public class WebSocketConfig extends AbstractSessionWebSocketMessageBrokerConfig @Bean public MapSessionRepository mapSessionRepository() { - return new MapSessionRepository(); + return new MapSessionRepository(new ConcurrentHashMap<>()); } } \ No newline at end of file