Stackable Trait Patterns – Part II

This post is the second of a two-part series of articles on Stackable Traits, click here to view Part I.

Gathering metrics with stackable actors

We like to gather the following metrics:

  • time-in-mailbox:
    The time from the moment a message was enqueued into an actor’s mailbox until the moment it was dequeued for processing.
  • processing-time:
    How long did it take for the actor to process a message?

And to log when an actor starts handling a message and before it finishes.

Stackable actor-based implementation

Say we have the following actor that we like to monitor:

Let’s start with the ‘time-in-mailbox’ metric. The simplest way to implement it is to take the time before the message was sent and calculate the time in the mailbox when the actor starting processing it.

For the sake of example, we’ll assume that a message was created just before it was sent.

The message class that should be monitored is:

We initialized the time before the message was sent, and gave it a name, to be used as a tag for the metric.

Next, create the stackable trait for monitoring the actor on RecordableMessage:

You might notice that:

  1. As discussed in Part I, the modifier of the ‘receive’ method should be “abstract override”
  2. We gather the metrics only on the ‘RecordableMessage’ message
  3. For calculating ‘time-in-mailbox’, ‘dispatchTime’ is used
  4. For calculating ‘processing-time’, we take time before invoking the action, then invoking the action, and record the ‘processing-time’ when it finished.

The LoggerActor is the following:

Lastly, mix these traits to a concrete MyActor class

class MyMonitoredActor extends MyActor with LatencyRecorderActor with LoggerActor

And we ended up with:

Try it out

Create a concrete RecordableMessage:

And send it to a MonitoredActor instance

Results with the following printed to the log:

Wrapping up

Stackable trait patterns are a good choice when you need to ‘pipe’ actions or modify and redirect data for an action.

Mix and stack traits to describe the state of the class and execute the actions are clean and flexible, and generally the Scala-functional way to do it.

Read these next