From 18c1d023742298afc7cd939530382c84f4c8e6f2 Mon Sep 17 00:00:00 2001 From: SimunKaracic Date: Thu, 12 Nov 2020 13:30:16 +0100 Subject: [PATCH 1/4] Actor tag changes to accomodate typed actors Actor class name tag is removed when the actor is typed. Operation name is now only 'operation(MessageClass)', where before it was 'operation(ActorClass, MessageClass)' --- .../instrumentation/akka/AkkaMetrics.scala | 20 +++++++++++-------- .../akka/instrumentations/ActorCellInfo.scala | 4 ++++ .../akka/instrumentations/ActorMonitor.scala | 19 +++++++++--------- .../akka/instrumentations/RouterMonitor.scala | 2 +- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/AkkaMetrics.scala b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/AkkaMetrics.scala index 48dc907a0..c4e5f404b 100644 --- a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/AkkaMetrics.scala +++ b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/AkkaMetrics.scala @@ -1,6 +1,7 @@ package kamon.instrumentation.akka import kamon.Kamon +import kamon.instrumentation.akka.instrumentations.ActorCellInfo import kamon.metric.InstrumentGroup import kamon.tag.TagSet @@ -35,13 +36,14 @@ object AkkaMetrics { description = "Counts the number of processing errors experienced by an Actor" ) - def forActor(path: String, system: String, dispatcher: String, actorClass: String): ActorInstruments = - new ActorInstruments(TagSet.builder() + def forActor(path: String, system: String, dispatcher: String, actorClass: Class[_]): ActorInstruments = { + val tags = TagSet.builder() .add("path", path) .add("system", system) .add("dispatcher", dispatcher) - .add("class", actorClass) - .build()) + if (!ActorCellInfo.isTyped(actorClass)) tags.add("class", actorClass.getName) + new ActorInstruments(tags.build()) + } class ActorInstruments(tags: TagSet) extends InstrumentGroup(tags) { val timeInMailbox = register(ActorTimeInMailbox) @@ -85,14 +87,16 @@ object AkkaMetrics { description = "Counts the number of processing errors experienced by the routees of a router" ) - def forRouter(path: String, system: String, dispatcher: String, routerClass: String, routeeClass: String): RouterInstruments = - new RouterInstruments(TagSet.builder() + def forRouter(path: String, system: String, dispatcher: String, routerClass: Class[_], routeeClass: String): RouterInstruments = { + val tags = TagSet.builder() .add("path", path) .add("system", system) .add("dispatcher", dispatcher) - .add("routerClass", routerClass) .add("routeeClass", routeeClass) - .build()) + if (!ActorCellInfo.isTyped(routerClass)) tags.add("routerClass", routerClass.getName) + new RouterInstruments(tags.build()) + + } class RouterInstruments(tags: TagSet) extends InstrumentGroup(tags) { val routingTime = register(RouterRoutingTime) diff --git a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorCellInfo.scala b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorCellInfo.scala index 0f8eff4ad..672bfcea7 100644 --- a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorCellInfo.scala +++ b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorCellInfo.scala @@ -84,6 +84,10 @@ object ActorCellInfo { }} } + def isTyped(className: Class[_]): Boolean = { + simpleClassName(className) == "ActorAdapter" + } + private def hasRouterProps(props: Props): Boolean = props.deploy.routerConfig != NoRouter diff --git a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala index daff651d9..84293949f 100644 --- a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala +++ b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala @@ -130,7 +130,7 @@ object ActorMonitor { cellInfo.path, cellInfo.systemName, cellInfo.dispatcherName, - cellInfo.actorOrRouterClass.getName + cellInfo.actorOrRouterClass )) } @@ -149,7 +149,7 @@ object ActorMonitor { cellInfo.path, cellInfo.systemName, cellInfo.dispatcherName, - cellInfo.actorOrRouterClass.getName, + cellInfo.actorOrRouterClass, cellInfo.routeeClass.map(_.getName).getOrElse("Unknown") ) @@ -177,8 +177,6 @@ object ActorMonitor { * Wraps another ActorMonitor implementation and provides tracing capabilities on top of it. */ class TracedMonitor(cellInfo: ActorCellInfo, startsTrace: Boolean, monitor: ActorMonitor) extends ActorMonitor { - private val _actorClassName = cellInfo.actorOrRouterClass.getName - private val _actorSimpleClassName = ActorCellInfo.simpleClassName(cellInfo.actorOrRouterClass) override def captureEnvelopeTimestamp(): Long = monitor.captureEnvelopeTimestamp() @@ -225,23 +223,24 @@ object ActorMonitor { val messageClass = ActorCellInfo.simpleClassName(envelope.message.getClass) val parentSpan = context.get(Span.Key) - Kamon.internalSpanBuilder(operationName(messageClass, envelope.sender), "akka.actor") + val spanBuilder = Kamon.internalSpanBuilder(operationName(messageClass, envelope.sender), "akka.actor") .asChildOf(parentSpan) .doNotTrackMetrics() .tag("akka.system", cellInfo.systemName) .tag("akka.actor.path", cellInfo.path) - .tag("akka.actor.class", _actorClassName) .tag("akka.actor.message-class", messageClass) - .delay(Kamon.clock().toInstant(envelopeTimestamp)) + if (!ActorCellInfo.isTyped(cellInfo.actorOrRouterClass)) { + spanBuilder.tag("akka.actor.class", cellInfo.actorOrRouterClass.getName) + } + spanBuilder.delay(Kamon.clock().toInstant(envelopeTimestamp)) } private def operationName(messageClass: String, sender: ActorRef): String = { - val operationType = if(AkkaPrivateAccess.isPromiseActorRef(sender)) "ask(" else "tell(" + val operationType = if(AkkaPrivateAccess.isPromiseActorRef(sender)) "ask" else "tell" StringBuilder.newBuilder .append(operationType) - .append(_actorSimpleClassName) - .append(", ") + .append("(") .append(messageClass) .append(")") .result() diff --git a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/RouterMonitor.scala b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/RouterMonitor.scala index 68739ee70..8311a5a50 100644 --- a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/RouterMonitor.scala +++ b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/RouterMonitor.scala @@ -54,7 +54,7 @@ object RouterMonitor { cell.path, cell.systemName, cell.dispatcherName, - cell.actorOrRouterClass.getName, + cell.actorOrRouterClass, cell.routeeClass.map(_.getName).getOrElse("Unknown") ) ) From e0956d3ccd8973a5af4cd65128c90e1b383d896f Mon Sep 17 00:00:00 2001 From: SimunKaracic Date: Thu, 12 Nov 2020 13:53:48 +0100 Subject: [PATCH 2/4] Refactor tests to mirror code change --- .../instrumentation/akka/MessageTracingSpec.scala | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/instrumentation/kamon-akka/src/test-common/scala/kamon/instrumentation/akka/MessageTracingSpec.scala b/instrumentation/kamon-akka/src/test-common/scala/kamon/instrumentation/akka/MessageTracingSpec.scala index d822d24a8..3b90e6269 100644 --- a/instrumentation/kamon-akka/src/test-common/scala/kamon/instrumentation/akka/MessageTracingSpec.scala +++ b/instrumentation/kamon-akka/src/test-common/scala/kamon/instrumentation/akka/MessageTracingSpec.scala @@ -34,7 +34,7 @@ class MessageTracingSpec extends TestKit(ActorSystem("MessageTracing")) with Wor val span = testSpanReporter.nextSpan().value val spanTags = stringTag(span) _ spanTags("component") shouldBe "akka.actor" - span.operationName shouldBe("tell(TracingTestActor, String)") + span.operationName shouldBe("tell(String)") spanTags("akka.actor.path") shouldNot include ("filteredout") spanTags("akka.actor.path") should be ("MessageTracing/user/traced-probe-1") } @@ -48,7 +48,7 @@ class MessageTracingSpec extends TestKit(ActorSystem("MessageTracing")) with Wor eventually(timeout(2 seconds)) { val span = testSpanReporter.nextSpan().value val spanTags = stringTag(span) _ - span.operationName shouldBe("tell(TracingTestActor, String)") + span.operationName shouldBe("tell(String)") spanTags("component") shouldBe "akka.actor" spanTags("akka.system") shouldBe "MessageTracing" spanTags("akka.actor.path") shouldBe "MessageTracing/user/traced" @@ -62,7 +62,7 @@ class MessageTracingSpec extends TestKit(ActorSystem("MessageTracing")) with Wor eventually(timeout(2 seconds)) { val span = testSpanReporter.nextSpan().value val spanTags = stringTag(span) _ - span.operationName shouldBe("ask(TracingTestActor, String)") + span.operationName shouldBe("ask(String)") spanTags("component") shouldBe "akka.actor" spanTags("akka.system") shouldBe "MessageTracing" spanTags("akka.actor.path") shouldBe "MessageTracing/user/traced" @@ -83,7 +83,6 @@ class MessageTracingSpec extends TestKit(ActorSystem("MessageTracing")) with Wor val span = testSpanReporter.nextSpan().value val spanTags = stringTag(span) _ - span.operationName should include("tell(TracingTestActor") spanTags("component") shouldBe "akka.actor" spanTags("akka.system") shouldBe "MessageTracing" spanTags("akka.actor.path") shouldBe "MessageTracing/user/traced-first" @@ -97,7 +96,7 @@ class MessageTracingSpec extends TestKit(ActorSystem("MessageTracing")) with Wor val span = testSpanReporter.nextSpan().value val spanTags = stringTag(span) _ span.parentId shouldBe firstSpanID - span.operationName should include("tell(TracingTestActor, String)") + span.operationName should include("tell(String)") spanTags("component") shouldBe "akka.actor" spanTags("akka.system") shouldBe "MessageTracing" spanTags("akka.actor.path") shouldBe "MessageTracing/user/traced-second" @@ -118,7 +117,7 @@ class MessageTracingSpec extends TestKit(ActorSystem("MessageTracing")) with Wor val firstSpanID = eventually(timeout(2 seconds)) { val span = testSpanReporter.nextSpan().value val spanTags = stringTag(span) _ - span.operationName shouldBe("tell(TracingTestActor, Tuple2)") + span.operationName shouldBe("tell(Tuple2)") spanTags("component") shouldBe "akka.actor" spanTags("akka.system") shouldBe "MessageTracing" spanTags("akka.actor.path") shouldBe "MessageTracing/user/traced-chain-first" @@ -133,7 +132,7 @@ class MessageTracingSpec extends TestKit(ActorSystem("MessageTracing")) with Wor val span = testSpanReporter.nextSpan().value val spanTags = stringTag(span) _ span.parentId shouldBe firstSpanID - span.operationName shouldBe("tell(TracingTestActor, String)") + span.operationName shouldBe("tell(String)") spanTags("component") shouldBe "akka.actor" spanTags("akka.system") shouldBe "MessageTracing" spanTags("akka.actor.path") shouldBe "MessageTracing/user/traced-chain-last" @@ -199,4 +198,4 @@ class TracingTestActor extends Actor { Thread.sleep(50) sender ! "pong" } -} \ No newline at end of file +} From 20e20b34cf626fb1a9b31603ea8588d5e5571611 Mon Sep 17 00:00:00 2001 From: SimunKaracic Date: Thu, 12 Nov 2020 14:04:55 +0100 Subject: [PATCH 3/4] Disable auto-grouping for typed actors This must be done becase we can no longer obtain the actor class name consistently, since typed actors are converted to ActorAdapters. If we don't disable autogrouping, all typed actors on the same level are placed in the same group --- .../instrumentation/akka/instrumentations/ActorMonitor.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala index 84293949f..747580cae 100644 --- a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala +++ b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala @@ -96,7 +96,9 @@ object ActorMonitor { val trackingGroups: Seq[ActorGroupInstruments] = if (cell.isRootSupervisor) List() else { val configuredMatchingGroups = AkkaInstrumentation.matchingActorGroups(cell.path) - if (configuredMatchingGroups.isEmpty && !isTracked && settings.autoGrouping && !cell.isRouter && !cell.isRoutee) { + if (configuredMatchingGroups.isEmpty && !isTracked + && settings.autoGrouping && !cell.isRouter + && !cell.isRoutee && !ActorCellInfo.isTyped(cell.actorOrRouterClass)) { if (!trackedFilter.excludes(cell.path) && Kamon.filter(TrackAutoGroupFilterName).accept(autoGroupingPath)) List(AkkaMetrics.forGroup(autoGroupingPath, system.name)) else From e0879d451a6b1baa28cdb5497808c83a514ac6db Mon Sep 17 00:00:00 2001 From: SimunKaracic Date: Mon, 23 Nov 2020 15:37:20 +0100 Subject: [PATCH 4/4] Don't apply routee tags for typed actors --- .../instrumentation/akka/instrumentations/ActorMonitor.scala | 2 +- .../instrumentation/akka/instrumentations/RouterMonitor.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala index 747580cae..100c78249 100644 --- a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala +++ b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/ActorMonitor.scala @@ -152,7 +152,7 @@ object ActorMonitor { cellInfo.systemName, cellInfo.dispatcherName, cellInfo.actorOrRouterClass, - cellInfo.routeeClass.map(_.getName).getOrElse("Unknown") + cellInfo.routeeClass.filterNot(ActorCellInfo.isTyped).map(_.getName).getOrElse("Unknown") ) new TrackedRoutee(routerMetrics, groupMetrics, cellInfo) diff --git a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/RouterMonitor.scala b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/RouterMonitor.scala index 8311a5a50..6876fa284 100644 --- a/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/RouterMonitor.scala +++ b/instrumentation/kamon-akka/src/common/scala/kamon/instrumentation/akka/instrumentations/RouterMonitor.scala @@ -55,7 +55,7 @@ object RouterMonitor { cell.systemName, cell.dispatcherName, cell.actorOrRouterClass, - cell.routeeClass.map(_.getName).getOrElse("Unknown") + cell.routeeClass.filterNot(ActorCellInfo.isTyped).map(_.getName).getOrElse("Unknown") ) ) else NoOpRouterMonitor