Traces and Metrics for Basic Actor Request-Response Scenario
On this page we will take a look at the most simple scenario: two local actors are sending messages to each other.
Code
Here is a code sample we will use:
var pong = Sys.ActorOf<PongActor>("pong");
var ping = Sys.ActorOf(Props.Create(() => new PingActor(pong, TestActor)), "ping");
for (var i = 0; i < 2; ++i)
ping.Tell(Request.Instance);
for (var i = 0; i < 2; ++i)
ExpectMsg<Response>();
private class PingActor : ReceiveActor
{
public PingActor(IActorRef pongActor, IActorRef testActor)
{
Receive<Request>(m => pongActor.Tell(Request.Instance));
Receive<Response>(m => testActor.Tell(Response.Instance));
}
}
private class PongActor : ReceiveActor
{
public PongActor()
{
var counter = Context.GetInstrumentation().Monitor.CreateCounter<long>("requests.count");
Receive<Request>(m =>
{
// increment custom counter
counter.Add(1, new KeyValuePair<string, object>("myTag", "myValue"));
Context.Sender.Tell(Response.Instance);
});
}
}
public class Request
{
public static readonly Request Instance = new Request();
}
public class Response
{
public static readonly Response Instance = new Response();
}
What will Phobos collect for us in this case?
Metrics
Phobos will automatically collect some metrics available in this sample:
akka.actor.created
counter - how many actors of given type were created at that moment?akka.messages.recv
meters - how many messages of given type arrived into actor's mailboxes?
OpenTelemetry exposes its own rich metrics functionality and you can collect your own custom metrics quite easily by creating a new Meter
and subscribing to it through the OpenTelemetry.Extensions.Hosting
NuGet package's extension methods.
Here we are just incrementing custom requests.count
counter.
Context: Akka.NET
Counters
Name | Tags | Value |
---|---|---|
akka.messages.recv | actortype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+PongActor messagetype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request |
4 |
akka.messages.recv | actortype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+PingActor messagetype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request |
4 |
requests.count | myTag: myValue |
4 |
akka.messages.recv | actortype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+PingActor messagetype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Response |
4 |
akka.actor.created | actortype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+PongActor |
2 |
akka.actor.created | actortype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+PingActor |
2 |
Histograms
Name | Tags | Value |
---|---|---|
akka.messages.latency | actortype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+PongActor messagetype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request |
4 |
akka.messages.latency | actortype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+PingActor messagetype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request |
4 |
akka.messages.latency | actortype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+PingActor messagetype: Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Response |
4 |
Traces
Phobos will also keep track of actor's communication, using OpeTelemetry's tracing' to represent message flow.
Here is how one of two collected traces will look like:
ParentIndex: none
Tags:
akka.actor.recv.msgType:
Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request
Logs:
message
content:
Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request
/user/ping->>/user/pong: akka.msg.recv Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request Note over /user/ping,/user/pong: SpanIndex: 1
ParentIndex: 0
Tags:
akka.actor.recv.msgType:
Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request
Logs:
waiting
message
content:
Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Request
/user/pong->>/user/ping: akka.msg.recv Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Response Note over /user/pong,/user/ping: SpanIndex: 2
ParentIndex: 1
Tags:
akka.actor.recv.msgType:
Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Response
Logs:
waiting
message
content:
Phobos.Actor.End2End.Tests.Standalone.RequestResponseSpec+Response
Here we can see that:
- Test actor is sending a message of type
Request
to ourPing
actor Ping
actor is sendingRequest
toPong
. Note that this two spans are connected (child_of
relation), which puts them into single tracePong
actor is replying back withResponse
message
We have all this exported into your favourite tracing / metrics collection system out of the box!