Skip to content

BootStateMachineMonitor loses traces for transitions to "end" state #1159

Open
@matteo4diani

Description

@matteo4diani

Hi!

In this project https://github.com/matteo4diani/spring-statemachine-deployment-demo I am using Spring Statemachine 4.0.0 to model a simple sequential SM (the configuration class is attached below):

initial:READY --event:DEPLOY--> state:DEPLOYING --event:NAMESPACE_STATUS_CHANGE--> state:DEPLOYED --event:DELETE--> state:DELETING --event:NAMESPACE_STATUS_CHANGE--> end:DELETED

I am using the provided BootStateMachineMonitor to monitor transitions, but I noticed that the external transition to the "end" state DELETED is not shown in the traces. If instead the state is not marked as "end", the trace is present as expected.

Moreover I noticed that if I mark a state SF as "end", and trigger a local transition TL to SF (from an intermediate state SI) after an external transition TE to the intermediate state SI, the trace for the preceding external transition TE is lost as well (if needed i can provide an example for this behavior but I didn't want to overcomplicate things).

Is this intended behavior? Am I doing anything wrong? By comparing my code to your samples and docs I cannot see any difference/mistake so I'm inclined to think this could be a bug.

Thanks for this project btw, we're enjoying it a lot! :)

Here is the actual response from localhost:8080/actuator/statemachinetrace after the state machine has gone from READY to DELETED:

[
    {
        "timestamp": "2024-07-18T14:33:50.356+00:00",
        "info": {
            "duration": 1,
            "machine": "machine-id",
            "transition": "EXTERNAL_DEPLOYED_DELETING"
        }
    },
    {
        "timestamp": "2024-07-18T14:33:41.821+00:00",
        "info": {
            "duration": 1,
            "machine": "machine-id",
            "transition": "EXTERNAL_DEPLOYING_DEPLOYED"
        }
    },
    {
        "timestamp": "2024-07-18T14:33:21.879+00:00",
        "info": {
            "duration": 1,
            "machine": "machine-id",
            "transition": "EXTERNAL_READY_DEPLOYING"
        }
    },
    {
        "timestamp": "2024-07-18T14:33:21.877+00:00",
        "info": {
            "duration": 2,
            "machine": "machine-id",
            "transition": "INITIAL_READY"
        }
    }
]

I would expect to find a similar element in the traces array (which is present if DELETED is not marked as an "end" state):

{
        "timestamp": "2024-07-18T14:33:50.356+00:00",
        "info": {
            "duration": 1,
            "machine": "machine-id",
            "transition": "EXTERNAL_DELETING_DELETED"
        }
}

This is the configuration class I'm using:

@Configuration
@EnableStateMachineFactory
@Slf4j
public class ApplicationStateMachineConfiguration
  extends StateMachineConfigurerAdapter<ApplicationStates, ApplicationEvents> {

  private final BootStateMachineMonitor<ApplicationStates, ApplicationEvents> stateMachineMonitor;

  public ApplicationStateMachineConfiguration(
    BootStateMachineMonitor<ApplicationStates, ApplicationEvents> stateMachineMonitor
  ) {
    this.stateMachineMonitor = stateMachineMonitor;
  }

  @Bean
  public CustomStateMachineService stateMachineService(
    StateMachineFactory<ApplicationStates, ApplicationEvents> stateMachineFactory
  ) {
    return new ApplicationStateMachineService(stateMachineFactory);
  }

  @Override
  public void configure(
    StateMachineConfigurationConfigurer<ApplicationStates, ApplicationEvents> config
  ) throws Exception {
    config.withMonitoring().monitor(stateMachineMonitor);

    config.withConfiguration().autoStartup(false);
  }

  @Override
  public void configure(
    StateMachineStateConfigurer<ApplicationStates, ApplicationEvents> states
  ) throws Exception {
    states
      .withStates()
      .initial(ApplicationStates.READY)
      .end(ApplicationStates.DELETED)
      .states(
        Set.of(
          ApplicationStates.DEPLOYING,
          ApplicationStates.DEPLOYED,
          ApplicationStates.DELETING
        )
      );
  }

  @Override
  public void configure(
    StateMachineTransitionConfigurer<ApplicationStates, ApplicationEvents> transitions
  ) throws Exception {
    transitions
      .withExternal()
      .source(ApplicationStates.READY)
      .target(ApplicationStates.DEPLOYING)
      .event(ApplicationEvents.DEPLOY)
      .guard(context -> true)
      .and()
      .withExternal()
      .source(ApplicationStates.DEPLOYING)
      .target(ApplicationStates.DEPLOYED)
      .event(ApplicationEvents.NAMESPACE_STATUS_CHANGE)
      .guard(context -> true)
      .and()
      .withExternal()
      .source(ApplicationStates.DEPLOYED)
      .target(ApplicationStates.DELETING)
      .event(ApplicationEvents.DELETE)
      .and()
      .withExternal()
      .source(ApplicationStates.DELETING)
      .target(ApplicationStates.DELETED)
      .event(ApplicationEvents.NAMESPACE_STATUS_CHANGE)
      .guard(context -> true);
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    status/need-triageTeam needs to triage and take a first look

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions