Actoverse API implementation for Akka Actor Framework
This library extends the Akka Actor system to realize captureing causal relationships and reverse debugging. Note that this implmentation is too experimental and there are several limitations for debugging.
Important: After ver 0.2.0, you don't have to rewrite source codes by introducing AspectJ.
Create file project/plugins.sbt
in your project with:
resolvers += Resolver.url("45deg/sbt-plugins", url("https://dl.bintray.com/45deg/sbt-plugins/"))(Resolver.ivyStylePatterns)
addSbtPlugin("com.github.45deg" %% "actoverse-sbt" % "0.2.0")
Then, add the line below to build.sbt
:
enablePlugins(ActoversePlugin)
Add the settings to (src/main/resources/)applications.conf
in your project with:
# ActorPathes of the targets. You can use a regular expression.
actoverse.target-actorpath = "akka://[SYSTEM NAME]/user/.+"
# [Optional] The name of the ActorSystem for this debugger.
actoverse.debugger-system-name = "ActoverseDebuggerSystem"
# [Optional] The name of actors that is introduced into target ActorSystems.
actoverse.debugger-actor-name = "__debugger"
# Address and Port of WebSocket API Endpoint.
actoverse.wshandler.hostname = "localhost"
actoverse.wshandler.port = 3000
See also: An Example Repository.
DebuggingSystem
controls actors. It commits a command fromWebSocketHandler
to actors and reports their states to the handler.WebSocketHandler
performs a mediator between the target system and the debugger UI.- Incoming/outgoing messages are trapped by
DebuggingSupporter
s, which are accessories to actors.
The debugger attaches an additional information (internally, called Envelope
) to all the messages sent by actors with !
. It includes sender and receiver's Actor pathes, Lamport timestamps, and auto-generated UUIDs.
On the other hand, the DebuggingSupporter
of an receiving actor opens an envelope and delivers the original message to the actor. The idea of interception comes from Receive Pipeline Pattern
The figure below provides an overview of processing incoming messages (envelopes).
DebuggingSupporter
stores the state (variables) of the actor itself every time when an actor finishes processing an incoming message, that is, finishes receive
. Currently, all var
s in the classes that extends Actor
are to be captured.
AspectJ (a framework for Aspect-oriented programming) enables the debugger to hook Actors' behaviors such as sending or receiving messages without modifying source codes. In this work, I used akka-viz and kamon-akka as reference and they were very helpful.
This implementation does not cover several functions of Akka or Scala, such as:
- To read/write external files or networks. The debugger cannot capture these modifications and restore a previous state of them.
- To deal with stopping and restarting actors. Because of Akka Actor's lifecycle, it is impossible to regenerate an actor with the same reference as the previous actor, which stopped manually. Therefore, restoring the system to the former condition is difficult.
- To variables which cannot be copied or duplicated. This framework copies and stores variables into a list. For the same reason, inconsistencies may occur when there is a reference variable of another object which can be modified from the outside of the Actor system.