Implement custom trace repository

- Upgrade to boot 2.0.0.RC1
- Copy original boot's tracing features to get used
  as a base impl for statemachine.
- Fix samples, tests.
- Fixes #491
This commit is contained in:
jvalkeal
2018-02-11 09:24:13 +02:00
parent c693e79f12
commit 328a2e9161
12 changed files with 378 additions and 80 deletions

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2018 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.boot.actuate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* In-memory implementation of {@link StateMachineTraceRepository}.
*
* @author Janne Valkealahti
*
*/
public class InMemoryStateMachineTraceRepository implements StateMachineTraceRepository {
private int capacity = 100;
private boolean reverse = true;
private final List<StateMachineTrace> traces = new LinkedList<StateMachineTrace>();
/**
* Flag to say that the repository lists traces in reverse order.
* @param reverse flag value (default true)
*/
public void setReverse(boolean reverse) {
synchronized (this.traces) {
this.reverse = reverse;
}
}
/**
* Set the capacity of the in-memory repository.
* @param capacity the capacity
*/
public void setCapacity(int capacity) {
synchronized (this.traces) {
this.capacity = capacity;
}
}
@Override
public List<StateMachineTrace> findAll() {
synchronized (this.traces) {
return Collections.unmodifiableList(new ArrayList<StateMachineTrace>(this.traces));
}
}
@Override
public void add(Map<String, Object> map) {
StateMachineTrace trace = new StateMachineTrace(new Date(), map);
synchronized (this.traces) {
while (this.traces.size() >= this.capacity) {
this.traces.remove(this.reverse ? this.capacity - 1 : 0);
}
if (this.reverse) {
this.traces.add(0, trace);
}
else {
this.traces.add(trace);
}
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2018 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.boot.actuate;
import java.util.Date;
import java.util.Map;
import org.springframework.util.Assert;
/**
* A value object representing a statemachine trace event: at a particular time
* with a simple (map) information.
*
* @author Janne Valkealahti
*
*/
public final class StateMachineTrace {
private final Date timestamp;
private final Map<String, Object> info;
/**
* Instantiate a new {@code StateMachineTrace}.
*
* @param timestamp the timestamp
* @param info the trace info
*/
public StateMachineTrace(Date timestamp, Map<String, Object> info) {
super();
Assert.notNull(timestamp, "Timestamp must not be null");
Assert.notNull(info, "Info must not be null");
this.timestamp = timestamp;
this.info = info;
}
/**
* Gets a timestamp
*
* @return a trace timestamp
*/
public Date getTimestamp() {
return this.timestamp;
}
/**
* Gets a trace info.
*
* @return a trace info
*/
public Map<String, Object> getInfo() {
return this.info;
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2018 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.boot.actuate;
import java.util.List;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.util.Assert;
/**
* {@code Endpoint} to expose {@link StateMachineTrace} information.
*
* @author Janne Valkealahti
*
*/
@Endpoint(id = "statemachinetrace")
public class StateMachineTraceEndpoint {
private final StateMachineTraceRepository repository;
/**
* Create a new {@link StateMachineTraceEndpoint} instance.
*
* @param repository the trace repository
*/
public StateMachineTraceEndpoint(StateMachineTraceRepository repository) {
Assert.notNull(repository, "Repository must not be null");
this.repository = repository;
}
@ReadOperation
public List<StateMachineTrace> invoke() {
return this.repository.findAll();
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2018 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.boot.actuate;
import java.util.List;
import java.util.Map;
/**
* A repository for {@link StateMachineTrace}s.
*
* @author Janne Valkealahti
*
*/
public interface StateMachineTraceRepository {
/**
* Find all {@link StateMachineTrace} objects contained in the repository.
*
* @return the results
*/
List<StateMachineTrace> findAll();
/**
* Add a new {@link StateMachineTrace} object at the current time.
*
* @param traceInfo trace information
*/
void add(Map<String, Object> traceInfo);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2017 the original author or authors.
* Copyright 2016-2018 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,14 +16,18 @@
package org.springframework.statemachine.boot.autoconfigure;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.boot.StateMachineProperties;
import org.springframework.statemachine.boot.actuate.InMemoryStateMachineTraceRepository;
import org.springframework.statemachine.boot.actuate.StateMachineTraceEndpoint;
import org.springframework.statemachine.boot.actuate.StateMachineTraceRepository;
import org.springframework.statemachine.boot.support.BootStateMachineMonitor;
import io.micrometer.core.instrument.MeterRegistry;
@@ -36,25 +40,44 @@ import io.micrometer.core.instrument.MeterRegistry;
*/
@Configuration
@EnableConfigurationProperties({ StateMachineProperties.class })
@ConditionalOnClass(MeterRegistry.class)
@ConditionalOnProperty(prefix = "spring.statemachine.monitor", name = "enabled", havingValue = "true", matchIfMissing = true)
public class StateMachineAutoConfiguration {
@ManagementContextConfiguration
public static class StateMachineTraceEndpointConfiguration {
@Bean
public StateMachineTraceEndpoint stateMachieTraceEndpoint(StateMachineTraceRepository stateMachineTraceRepository) {
return new StateMachineTraceEndpoint(stateMachineTraceRepository);
}
}
@Configuration
public static class StateMachineTraceRepositoryConfiguration {
@ConditionalOnMissingBean(StateMachineTraceRepository.class)
@Bean
public InMemoryStateMachineTraceRepository stateMachineTraceRepository() {
return new InMemoryStateMachineTraceRepository();
}
}
@Configuration
@ConditionalOnClass(MeterRegistry.class)
@ConditionalOnProperty(prefix = "spring.statemachine.monitor", name = "enabled", havingValue = "true", matchIfMissing = true)
public static class StateMachineMonitoringConfiguration {
private final MeterRegistry meterRegistry;
private final TraceRepository traceRepository;
private final StateMachineTraceRepository stateMachineTraceRepository;
public StateMachineMonitoringConfiguration(ObjectProvider<MeterRegistry> meterRegistryProvider,
ObjectProvider<TraceRepository> traceRepositoryProvider) {
ObjectProvider<StateMachineTraceRepository> traceRepositoryProvider) {
this.meterRegistry = meterRegistryProvider.getIfAvailable();
this.traceRepository = traceRepositoryProvider.getIfAvailable();
this.stateMachineTraceRepository = traceRepositoryProvider.getIfAvailable();
}
@Bean
public BootStateMachineMonitor<?, ?> bootStateMachineMonitor() {
return new BootStateMachineMonitor<>(meterRegistry, traceRepository);
return new BootStateMachineMonitor<>(meterRegistry, stateMachineTraceRepository);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2017 the original author or authors.
* Copyright 2016-2018 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.
@@ -19,9 +19,9 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.boot.actuate.StateMachineTraceRepository;
import org.springframework.statemachine.monitor.AbstractStateMachineMonitor;
import org.springframework.statemachine.monitor.StateMachineMonitor;
import org.springframework.statemachine.state.State;
@@ -44,18 +44,19 @@ import io.micrometer.core.instrument.Timer;
*/
public class BootStateMachineMonitor<S, E> extends AbstractStateMachineMonitor<S, E> {
private final TraceRepository traceRepository;
private final StateMachineTraceRepository traceRepository;
private final MeterRegistry meterRegistry;
/**
* Instantiates a new boot state machine monitor.
*
* @param meterRegistry the meter registry
* @param traceRepository the trace repository
* @param stateMachineTraceRepository the statemachine trace repository
*/
public BootStateMachineMonitor(MeterRegistry meterRegistry, TraceRepository traceRepository) {
public BootStateMachineMonitor(MeterRegistry meterRegistry,
StateMachineTraceRepository stateMachineTraceRepository) {
this.meterRegistry = meterRegistry;
this.traceRepository = traceRepository;
this.traceRepository = stateMachineTraceRepository;
}
@Override