diff --git a/build.gradle b/build.gradle index 464a9b05..57a2e6fb 100644 --- a/build.gradle +++ b/build.gradle @@ -421,6 +421,7 @@ configure(rootProject) { from 'spring-statemachine-samples/eventservice/src/main/java/' from 'spring-statemachine-samples/datajpa/src/main/java/' from 'spring-statemachine-samples/datajpa/src/main/resources/' + from 'spring-statemachine-samples/monitoring/src/main/java/' include '**/*.java' include '**/*.uml' include '**/*.json' diff --git a/docs/src/reference/asciidoc/getting-started.adoc b/docs/src/reference/asciidoc/getting-started.adoc index 96bdfc96..fa0e2cdb 100644 --- a/docs/src/reference/asciidoc/getting-started.adoc +++ b/docs/src/reference/asciidoc/getting-started.adoc @@ -58,6 +58,9 @@ framework. |spring-statemachine-uml |Support module for UI uml modeling with Eclipse Papyrus. + +|spring-statemachine-boot +|Support module for `Spring Boot`. |=== == Using Gradle diff --git a/docs/src/reference/asciidoc/images/sm-datajpa-3.png b/docs/src/reference/asciidoc/images/sm-datajpa-3.png index 11e1f308..bbc1fd95 100644 Binary files a/docs/src/reference/asciidoc/images/sm-datajpa-3.png and b/docs/src/reference/asciidoc/images/sm-datajpa-3.png differ diff --git a/docs/src/reference/asciidoc/images/sm-monitoring-1.png b/docs/src/reference/asciidoc/images/sm-monitoring-1.png new file mode 100644 index 00000000..384dd397 Binary files /dev/null and b/docs/src/reference/asciidoc/images/sm-monitoring-1.png differ diff --git a/docs/src/reference/asciidoc/images/sm-monitoring-2.png b/docs/src/reference/asciidoc/images/sm-monitoring-2.png new file mode 100644 index 00000000..03164e6a Binary files /dev/null and b/docs/src/reference/asciidoc/images/sm-monitoring-2.png differ diff --git a/docs/src/reference/asciidoc/sm-examples.adoc b/docs/src/reference/asciidoc/sm-examples.adoc index 465968b0..17fb4f30 100644 --- a/docs/src/reference/asciidoc/sm-examples.adoc +++ b/docs/src/reference/asciidoc/sm-examples.adoc @@ -38,6 +38,8 @@ normal build cycle. Samples in this chapter are: <> JPA Config. +<> Monitoring. + [source,text] ---- @@ -1493,3 +1495,98 @@ Actual source for populator data is shown below. include::samples/data.json[] ---- +[[statemachine-examples-monitoring]] +== Monitoring +Monitoring is an example how state machine concepts can be used to +monitor machine transitions and actions. + +[source,java,indent=0] +---- +include::samples/demo/monitoring/StateMachineConfig.java[tags=snippetA] +---- + +Lets get into actual demo. Run the boot based sample application: + +[source,text,subs="attributes"] +---- +# java -jar spring-statemachine-samples-monitoring-{revnumber}.jar +---- + +image::images/sm-monitoring-1.png[width=1000] + +Execute some transitions. + +image::images/sm-monitoring-2.png[width=1000] + +Metrics can be viewed from Boot. + +[source,json] +---- +# curl http://localhost:8080/metrics + +{ +"gauge.ssm.transition.INITIAL_S1.duration":0.0, +"gauge.ssm.transition.EXTERNAL_S2_S3.duration":0.0, +"gauge.ssm.action.demo.monitoring.StateMachineConfig$Config$$Lambda$8/12546741@a522d0.duration":0.0, +"gauge.ssm.transition.EXTERNAL_S1_S2.duration":1.0, +"gauge.ssm.action.demo.monitoring.StateMachineConfig$Config$$Lambda$7/25284245@1c21333.duration":0.0, +"gauge.ssm.action.demo.monitoring.StateMachineConfig$Config$$Lambda$9/28306193@10069f9.duration":0.0, +"counter.ssm.action.demo.monitoring.StateMachineConfig$Config$$Lambda$8/12546741@a522d0.execute":1, +"counter.ssm.action.demo.monitoring.StateMachineConfig$Config$$Lambda$9/28306193@10069f9.execute":1, +"counter.ssm.transition.EXTERNAL_S2_S3.transit":1, +"counter.ssm.action.demo.monitoring.StateMachineConfig$Config$$Lambda$7/25284245@1c21333.execute":1, +"counter.ssm.transition.EXTERNAL_S1_S2.transit":1, +"counter.ssm.transition.INITIAL_S1.transit":2, +} +---- + +Tracing can be viewed from Boot. + +[source,json] +---- +# curl http://localhost:8080/trace + +[{ + "timestamp":1478419121956, + "info":{ + "duration":0, + "machine":null, + "transition": + "EXTERNAL_S2_S3" + } + }, + { + "timestamp":1478419121956, + "info":{ + "duration":0, + "machine":null, + "action":"demo.monitoring.StateMachineConfig$Config$$Lambda$9/28306193@10069f9" + } + }, + { + "timestamp":1478419121956, + "info":{ + "duration":0, + "machine":null, + "action":"demo.monitoring.StateMachineConfig$Config$$Lambda$8/12546741@a522d0" + } + }, + { + "timestamp":1478419121956, + "info":{ + "duration":1, + "machine":null, + "transition":"EXTERNAL_S1_S2" + } + }, + { + "timestamp":1478419121955, + "info":{ + "duration":0, + "machine":null, + "action":"demo.monitoring.StateMachineConfig$Config$$Lambda$7/25284245@1c21333" + } + } +] + +---- diff --git a/docs/src/reference/asciidoc/sm.adoc b/docs/src/reference/asciidoc/sm.adoc index 192d323d..4cb47985 100644 --- a/docs/src/reference/asciidoc/sm.adoc +++ b/docs/src/reference/asciidoc/sm.adoc @@ -1722,6 +1722,41 @@ Check sample <> for detailed usage. `RedisConnectionFactory` for it to work and we recommend a `JedisConnectionFactory` for it as seeing from above example. +[[sm-boot]] +== Spring Boot Support +Currently support for Boot auto-configuration exists only for monitoring +and tracing. If _spring-statemachine-boot_ is in a classpath, +`BootStateMachineMonitor` is created automatically and associated with +a state machine. This `BootStateMachineMonitor` will hook into Boot's +`CounterService`, `GaugeService` and `TraceRepository` if available. +Optionally this auto-configuration can be disabled by setting key +`spring.statemachine.monitor.enabled` to `false`. Use of this +auto-config is shown in sample <>. + +[[sm-monitoring]] +== Monitoring State Machine +`StateMachineMonitor` can be used to get more information about +durations of how long transitions and actions takes to execute. Below +you can see how this interface is implemented. + +[source,java,indent=0] +---- +include::samples/DocsConfigurationSampleTests9.java[tags=snippetB] +---- + +Once you have `StateMachineMonitor` implementation it can be added to +a state machine via configuration as shown below. + +[source,java,indent=0] +---- +include::samples/DocsConfigurationSampleTests9.java[tags=snippetA] +---- + +[TIP] +==== +Check sample <> for detailed usage. +==== + [[sm-distributed]] == Using Distributed States Distributed state is probably one of a most compicated concepts of a diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/monitor/AbstractStateMachineMonitor.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/monitor/AbstractStateMachineMonitor.java index ef912e0e..22152c01 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/monitor/AbstractStateMachineMonitor.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/monitor/AbstractStateMachineMonitor.java @@ -16,6 +16,7 @@ package org.springframework.statemachine.monitor; import org.springframework.statemachine.StateMachine; +import org.springframework.statemachine.action.Action; import org.springframework.statemachine.transition.Transition; /** @@ -31,4 +32,8 @@ public abstract class AbstractStateMachineMonitor implements StateMachineM @Override public void transition(StateMachine stateMachine, Transition transition, long duration) { } + + @Override + public void action(StateMachine stateMachine, Action action, long duration) { + } } diff --git a/spring-statemachine-core/src/test/java/org/springframework/statemachine/docs/DocsConfigurationSampleTests9.java b/spring-statemachine-core/src/test/java/org/springframework/statemachine/docs/DocsConfigurationSampleTests9.java new file mode 100644 index 00000000..eb860d33 --- /dev/null +++ b/spring-statemachine-core/src/test/java/org/springframework/statemachine/docs/DocsConfigurationSampleTests9.java @@ -0,0 +1,83 @@ +/* + * Copyright 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.statemachine.docs; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.StateMachine; +import org.springframework.statemachine.action.Action; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.monitor.AbstractStateMachineMonitor; +import org.springframework.statemachine.monitor.StateMachineMonitor; +import org.springframework.statemachine.transition.Transition; + +public class DocsConfigurationSampleTests9 { + +// tag::snippetA[] + @Configuration + @EnableStateMachine + public class Config1 extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withMonitoring() + .monitor(stateMachineMonitor()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("S1") + .state("S2"); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .source("S1") + .target("S2") + .event("E1"); + } + + @Bean + public StateMachineMonitor stateMachineMonitor() { + return new TestStateMachineMonitor(); + } + } +// end::snippetA[] + +// tag::snippetB[] + public class TestStateMachineMonitor extends AbstractStateMachineMonitor { + + @Override + public void transition(StateMachine stateMachine, Transition transition, long duration) { + } + + @Override + public void action(StateMachine stateMachine, Action action, long duration) { + } + } +// end::snippetB[] + +}