diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/LocalActorRefProviderLogMessagesSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/LocalActorRefProviderLogMessagesSpec.scala new file mode 100644 index 0000000000..48baf19193 --- /dev/null +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/LocalActorRefProviderLogMessagesSpec.scala @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2020 Lightbend Inc. + */ + +package akka.actor.typed + +import akka.actor.testkit.typed.scaladsl.{ ActorTestKit, LogCapturing, LoggingTestKit, ScalaTestWithActorTestKit } +import akka.actor.typed.internal.adapter.ActorSystemAdapter +import org.scalatest.wordspec.AnyWordSpecLike + +object LocalActorRefProviderLogMessagesSpec { + val config = """ + akka { + loglevel = DEBUG # test verifies debug + log-dead-letters = on + actor { + debug.unhandled = on + } + } + """ +} + +class LocalActorRefProviderLogMessagesSpec + extends ScalaTestWithActorTestKit(LocalActorRefProviderLogMessagesSpec.config) + with AnyWordSpecLike + with LogCapturing { + + "An LocalActorRefProvider" must { + + "logs on dedicated 'serialization' logger of unknown path" in { + val provider = system.asInstanceOf[ActorSystemAdapter[_]].provider + + LoggingTestKit + .debug("of unknown (invalid) path [dummy/path]") + .withLoggerName("akka.actor.LocalActorRefProvider.Deserialization") + .expect { + provider.resolveActorRef("dummy/path") + } + } + + "logs on dedicated 'serialization' logger when path doesn't match existing actor" in { + val provider = system.asInstanceOf[ActorSystemAdapter[_]].provider + val invalidPath = provider.rootPath / "user" / "invalid" + + LoggingTestKit + .debug("Resolve (deserialization) of path [user/invalid] doesn't match an active actor.") + .withLoggerName("akka.actor.LocalActorRefProvider.Deserialization") + .expect { + provider.resolveActorRef(invalidPath) + } + } + + "logs on dedicated 'serialization' logger when of foreign path" in { + + val otherSystem = ActorTestKit("otherSystem").system.asInstanceOf[ActorSystemAdapter[_]] + val invalidPath = otherSystem.provider.rootPath / "user" / "foo" + + val provider = system.asInstanceOf[ActorSystemAdapter[_]].provider + try { + LoggingTestKit + .debug("Resolve (deserialization) of foreign path [akka://otherSystem/user/foo]") + .withLoggerName("akka.actor.LocalActorRefProvider.Deserialization") + .expect { + provider.resolveActorRef(invalidPath) + } + } finally { + ActorTestKit.shutdown(otherSystem) + } + } + } +} diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index fcc0c3a850..3eaf85f406 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -387,7 +387,14 @@ private[akka] class LocalActorRefProvider private[akka] ( override val rootPath: ActorPath = RootActorPath(Address("akka", _systemName)) private[akka] val log: MarkerLoggingAdapter = - Logging.withMarker(eventStream, getClass.getName + "(" + rootPath.address + ")") + Logging.withMarker(eventStream, getClass) + + /* + * This dedicated logger is used whenever a deserialization failure occurs + * and can therefore be disabled/enabled independently + */ + private[akka] val logDeser: MarkerLoggingAdapter = + Logging.withMarker(eventStream, getClass.getName + ".Deserialization") override val deadLetters: InternalActorRef = _deadLetters @@ -587,14 +594,14 @@ private[akka] class LocalActorRefProvider private[akka] ( def resolveActorRef(path: String): ActorRef = path match { case ActorPathExtractor(address, elems) if address == rootPath.address => resolveActorRef(rootGuardian, elems) case _ => - log.debug("Resolve (deserialization) of unknown (invalid) path [{}], using deadLetters.", path) + logDeser.debug("Resolve (deserialization) of unknown (invalid) path [{}], using deadLetters.", path) deadLetters } def resolveActorRef(path: ActorPath): ActorRef = { if (path.root == rootPath) resolveActorRef(rootGuardian, path.elements) else { - log.debug( + logDeser.debug( "Resolve (deserialization) of foreign path [{}] doesn't match root path [{}], using deadLetters.", path, rootPath) @@ -607,13 +614,13 @@ private[akka] class LocalActorRefProvider private[akka] ( */ private[akka] def resolveActorRef(ref: InternalActorRef, pathElements: Iterable[String]): InternalActorRef = if (pathElements.isEmpty) { - log.debug("Resolve (deserialization) of empty path doesn't match an active actor, using deadLetters.") + logDeser.debug("Resolve (deserialization) of empty path doesn't match an active actor, using deadLetters.") deadLetters } else ref.getChild(pathElements.iterator) match { case Nobody => if (log.isDebugEnabled) - log.debug( + logDeser.debug( "Resolve (deserialization) of path [{}] doesn't match an active actor. " + "It has probably been stopped, using deadLetters.", pathElements.mkString("/"))