From c92254f908c0d030967b48dbfb31126be1d709e3 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Wed, 11 Dec 2013 10:41:12 +0100 Subject: [PATCH] +act #3609 Include host and port in log source --- .../src/main/scala/akka/actor/Actor.scala | 11 +++- .../src/main/scala/akka/event/Logging.scala | 21 ++++--- .../scala/akka/remote/LogSourceSpec.scala | 56 +++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 akka-remote/src/test/scala/akka/remote/LogSourceSpec.scala diff --git a/akka-actor/src/main/scala/akka/actor/Actor.scala b/akka-actor/src/main/scala/akka/actor/Actor.scala index 1bfa971285..af7d340ace 100644 --- a/akka-actor/src/main/scala/akka/actor/Actor.scala +++ b/akka-actor/src/main/scala/akka/actor/Actor.scala @@ -10,6 +10,7 @@ import scala.annotation.tailrec import scala.reflect.BeanProperty import scala.util.control.NoStackTrace import java.util.regex.Pattern +import akka.event.LoggingAdapter /** * INTERNAL API @@ -279,7 +280,15 @@ object Status { * }}} */ trait ActorLogging { this: Actor ⇒ - val log = akka.event.Logging(context.system, this) + private var _log: LoggingAdapter = _ + + def log: LoggingAdapter = { + // only used in Actor, i.e. thread safe + if (_log eq null) + _log = akka.event.Logging(context.system, this) + _log + } + } /** diff --git a/akka-actor/src/main/scala/akka/event/Logging.scala b/akka-actor/src/main/scala/akka/event/Logging.scala index eef6d5288a..4a68f77620 100644 --- a/akka-actor/src/main/scala/akka/event/Logging.scala +++ b/akka-actor/src/main/scala/akka/event/Logging.scala @@ -4,7 +4,6 @@ package akka.event import language.existentials - import akka.actor._ import akka.{ ConfigurationException, AkkaException } import akka.actor.ActorSystem.Settings @@ -16,6 +15,7 @@ import scala.collection.immutable import scala.concurrent.duration._ import scala.concurrent.Await import scala.util.control.NoStackTrace +import scala.util.control.NonFatal /** * This trait brings log level handling to the EventStream: it reads the log @@ -281,11 +281,18 @@ object LogSource { } implicit val fromActor: LogSource[Actor] = new LogSource[Actor] { - def genString(a: Actor) = a.self.path.toString + def genString(a: Actor) = fromActorRef.genString(a.self) + override def genString(a: Actor, system: ActorSystem) = fromActorRef.genString(a.self, system) } implicit val fromActorRef: LogSource[ActorRef] = new LogSource[ActorRef] { def genString(a: ActorRef) = a.path.toString + override def genString(a: ActorRef, system: ActorSystem) = try { + a.path.toStringWithAddress(system.asInstanceOf[ExtendedActorSystem].provider.getDefaultAddress) + } catch { + // it can fail if the ActorSystem (remoting) is not completely started yet + case NonFatal(_) ⇒ a.path.toString + } } // this one unfortunately does not work as implicit, because existential types have some weird behavior @@ -721,11 +728,11 @@ object Logging { private val date = new Date() private val dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS") - private val errorFormat = "[ERROR] [%s] [%s] [%s] %s%s".intern - private val errorFormatWithoutCause = "[ERROR] [%s] [%s] [%s] %s".intern - private val warningFormat = "[WARN] [%s] [%s] [%s] %s".intern - private val infoFormat = "[INFO] [%s] [%s] [%s] %s".intern - private val debugFormat = "[DEBUG] [%s] [%s] [%s] %s".intern + private val errorFormat = "[ERROR] [%s] [%s] [%s] %s%s" + private val errorFormatWithoutCause = "[ERROR] [%s] [%s] [%s] %s" + private val warningFormat = "[WARN] [%s] [%s] [%s] %s" + private val infoFormat = "[INFO] [%s] [%s] [%s] %s" + private val debugFormat = "[DEBUG] [%s] [%s] [%s] %s" def timestamp(event: LogEvent): String = synchronized { date.setTime(event.timestamp) diff --git a/akka-remote/src/test/scala/akka/remote/LogSourceSpec.scala b/akka-remote/src/test/scala/akka/remote/LogSourceSpec.scala new file mode 100644 index 0000000000..fa4b8f6be4 --- /dev/null +++ b/akka-remote/src/test/scala/akka/remote/LogSourceSpec.scala @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2009-2013 Typesafe Inc. + */ +package akka.remote + +import scala.concurrent.duration._ +import akka.testkit.AkkaSpec +import akka.actor.Actor +import akka.actor.ActorLogging +import akka.actor.Props +import akka.event.Logging +import akka.testkit.ImplicitSender +import akka.testkit.TestProbe +import akka.actor.Deploy +import akka.event.Logging.Info +import akka.actor.ExtendedActorSystem + +object LogSourceSpec { + class Reporter extends Actor with ActorLogging { + def receive = { + case s: String ⇒ + log.info(s) + } + } +} + +@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) +class LogSourceSpec extends AkkaSpec( + """ + akka.loglevel = INFO + akka.actor.provider = "akka.remote.RemoteActorRefProvider" + akka.remote.netty.tcp.port = 0 + """) { + + import LogSourceSpec._ + + val reporter = system.actorOf(Props[Reporter], "reporter") + val logProbe = TestProbe() + system.eventStream.subscribe(system.actorOf(Props(new Actor { + def receive = { + case i @ Info(_, _, msg: String) if msg contains "hello" ⇒ logProbe.ref ! i + case _ ⇒ + } + }).withDeploy(Deploy.local), "logSniffer"), classOf[Logging.Info]) + + "Log events" must { + + "must include host and port for local LogSource" in { + reporter ! "hello" + val info = logProbe.expectMsgType[Info] + info.message must be("hello") + val defaultAddress = system.asInstanceOf[ExtendedActorSystem].provider.getDefaultAddress + info.logSource must include(defaultAddress.toString) + } + } +}