diff --git a/akka-actor-tests/src/test/scala/akka/actor/FSMActorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/FSMActorSpec.scala index c5ed765aab..67c94d3dd7 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/FSMActorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/FSMActorSpec.scala @@ -218,18 +218,19 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im } }) val name = fsm.path.toString + val fsmClass = fsm.underlyingActor.getClass system.eventStream.subscribe(testActor, classOf[Logging.Debug]) fsm ! "go" expectMsgPF(1 second, hint = "processing Event(go,null)") { - case Logging.Debug(`name`, _, s: String) if s.startsWith("processing Event(go,null) from Actor[") ⇒ true + case Logging.Debug(`name`, `fsmClass`, s: String) if s.startsWith("processing Event(go,null) from Actor[") ⇒ true } - expectMsg(1 second, Logging.Debug(name, fsm.underlyingActor.getClass, "setting timer 't'/1500 milliseconds: Shutdown")) - expectMsg(1 second, Logging.Debug(name, fsm.underlyingActor.getClass, "transition 1 -> 2")) + expectMsg(1 second, Logging.Debug(name, fsmClass, "setting timer 't'/1500 milliseconds: Shutdown")) + expectMsg(1 second, Logging.Debug(name, fsmClass, "transition 1 -> 2")) fsm ! "stop" expectMsgPF(1 second, hint = "processing Event(stop,null)") { - case Logging.Debug(`name`, _, s: String) if s.startsWith("processing Event(stop,null) from Actor[") ⇒ true + case Logging.Debug(`name`, `fsmClass`, s: String) if s.startsWith("processing Event(stop,null) from Actor[") ⇒ true } - expectMsgAllOf(1 second, Logging.Debug(name, fsm.underlyingActor.getClass, "canceling timer 't'"), Normal) + expectMsgAllOf(1 second, Logging.Debug(name, fsmClass, "canceling timer 't'"), Normal) expectNoMsg(1 second) system.eventStream.unsubscribe(testActor) } diff --git a/akka-actor/src/main/scala/akka/actor/Actor.scala b/akka-actor/src/main/scala/akka/actor/Actor.scala index 8713df95b4..4681e88cfa 100644 --- a/akka-actor/src/main/scala/akka/actor/Actor.scala +++ b/akka-actor/src/main/scala/akka/actor/Actor.scala @@ -112,7 +112,7 @@ object Status { } trait ActorLogging { this: Actor ⇒ - val log = akka.event.Logging(context.system.eventStream, context.self) + val log = akka.event.Logging(context.system, context.self) } object Actor { diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index d940aa2c20..67a1603105 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -296,7 +296,7 @@ class LocalActorRefProvider( val nodename: String = "local" val clustername: String = "local" - val log = Logging(eventStream, "LocalActorRefProvider") + val log = Logging(eventStream, "LocalActorRefProvider(" + rootPath.address + ")") /* * generate name for temporary actor refs diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index a4f1c2c37c..e24a3a29f2 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -330,7 +330,11 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor // this provides basic logging (to stdout) until .start() is called below val eventStream = new EventStream(DebugEventStream) eventStream.startStdoutLogger(settings) - val log = new BusLogging(eventStream, "ActorSystem", this.getClass) + + // unfortunately we need logging before we know the rootpath address, which wants to be inserted here + @volatile + private var _log = new BusLogging(eventStream, "ActorSystem(" + name + ")", this.getClass) + def log = _log val scheduler = createScheduler() @@ -383,6 +387,7 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor private lazy val _start: this.type = { // the provider is expected to start default loggers, LocalActorRefProvider does this provider.init(this) + _log = new BusLogging(eventStream, "ActorSystem(" + lookupRoot.path.address + ")", this.getClass) deadLetters.init(dispatcher, lookupRoot.path / "deadLetters") // this starts the reaper actor and the user-configured logging subscribers, which are also actors registerOnTermination(stopScheduler()) @@ -498,4 +503,6 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor } } + + override def toString = lookupRoot.path.root.address.toString } diff --git a/akka-actor/src/main/scala/akka/actor/FSM.scala b/akka-actor/src/main/scala/akka/actor/FSM.scala index b49be8c0b5..eb573df767 100644 --- a/akka-actor/src/main/scala/akka/actor/FSM.scala +++ b/akka-actor/src/main/scala/akka/actor/FSM.scala @@ -190,7 +190,7 @@ trait FSM[S, D] extends Listeners { type Timeout = Option[Duration] type TransitionHandler = PartialFunction[(S, S), Unit] - val log = Logging(context.system, context.self) + val log = Logging(context.system, this) /** * **************************************** diff --git a/akka-actor/src/main/scala/akka/event/Logging.scala b/akka-actor/src/main/scala/akka/event/Logging.scala index 83bff79617..33c4b1339e 100644 --- a/akka-actor/src/main/scala/akka/event/Logging.scala +++ b/akka-actor/src/main/scala/akka/event/Logging.scala @@ -86,8 +86,9 @@ trait LoggingBus extends ActorEventBus { * Internal Akka use only */ private[akka] def startDefaultLoggers(system: ActorSystemImpl) { + val logName = simpleName(this) + "(" + system + ")" val level = levelFor(system.settings.LogLevel) getOrElse { - StandardOutLogger.print(Error(new EventHandlerException, simpleName(this), this.getClass, "unknown akka.stdout-loglevel " + system.settings.LogLevel)) + StandardOutLogger.print(Error(new EventHandlerException, logName, this.getClass, "unknown akka.stdout-loglevel " + system.settings.LogLevel)) ErrorLevel } try { @@ -101,7 +102,7 @@ trait LoggingBus extends ActorEventBus { } yield { try { ReflectiveAccess.getClassFor[Actor](loggerName) match { - case Right(actorClass) ⇒ addLogger(system, actorClass, level) + case Right(actorClass) ⇒ addLogger(system, actorClass, level, logName) case Left(exception) ⇒ throw exception } } catch { @@ -115,7 +116,7 @@ trait LoggingBus extends ActorEventBus { loggers = myloggers _logLevel = level } - publish(Debug(simpleName(this), this.getClass, "Default Loggers started")) + publish(Debug(logName, this.getClass, "Default Loggers started")) if (!(defaultLoggers contains StandardOutLoggerName)) { unsubscribe(StandardOutLogger) } @@ -150,18 +151,18 @@ trait LoggingBus extends ActorEventBus { publish(Debug(simpleName(this), this.getClass, "all default loggers stopped")) } - private def addLogger(system: ActorSystemImpl, clazz: Class[_ <: Actor], level: LogLevel): ActorRef = { + private def addLogger(system: ActorSystemImpl, clazz: Class[_ <: Actor], level: LogLevel, logName: String): ActorRef = { val name = "log" + Extension(system).id() + "-" + simpleName(clazz) val actor = system.systemActorOf(Props(clazz), name) implicit val timeout = Timeout(3 seconds) val response = try Await.result(actor ? InitializeLogger(this), timeout.duration) catch { case _: TimeoutException ⇒ - publish(Warning(simpleName(this), this.getClass, "Logger " + name + " did not respond within " + timeout + " to InitializeLogger(bus)")) + publish(Warning(logName, this.getClass, "Logger " + name + " did not respond within " + timeout + " to InitializeLogger(bus)")) } if (response != LoggerInitialized) throw new LoggerInitializationException("Logger " + name + " did not respond with LoggerInitialized, sent instead " + response) AllLogLevels filter (level >= _) foreach (l ⇒ subscribe(actor, classFor(l))) - publish(Debug(simpleName(this), this.getClass, "logger " + name + " started")) + publish(Debug(logName, this.getClass, "logger " + name + " started")) actor } @@ -169,11 +170,13 @@ trait LoggingBus extends ActorEventBus { trait LogSource[-T] { def genString(t: T): String + def genString(t: T, system: ActorSystem): String = genString(t) } object LogSource { implicit val fromString: LogSource[String] = new LogSource[String] { def genString(s: String) = s + override def genString(s: String, system: ActorSystem) = s + "(" + system + ")" } implicit val fromActor: LogSource[Actor] = new LogSource[Actor] { @@ -187,10 +190,13 @@ object LogSource { // this one unfortunately does not work as implicit, because existential types have some weird behavior val fromClass: LogSource[Class[_]] = new LogSource[Class[_]] { def genString(c: Class[_]) = simpleName(c) + override def genString(c: Class[_], system: ActorSystem) = simpleName(c) + "(" + system + ")" } implicit def fromAnyClass[T]: LogSource[Class[T]] = fromClass.asInstanceOf[LogSource[Class[T]]] - def apply[T: LogSource](o: T) = implicitly[LogSource[T]].genString(o) + def apply[T: LogSource](o: T): String = implicitly[LogSource[T]].genString(o) + + def apply[T: LogSource](o: T, system: ActorSystem): String = implicitly[LogSource[T]].genString(o, system) def fromAnyRef(o: AnyRef): String = o match { @@ -200,6 +206,15 @@ object LogSource { case s: String ⇒ s case x ⇒ simpleName(x) } + + def fromAnyRef(o: AnyRef, system: ActorSystem): String = + o match { + case c: Class[_] ⇒ fromClass.genString(c, system) + case a: Actor ⇒ fromActor.genString(a, system) + case a: ActorRef ⇒ fromActorRef.genString(a, system) + case s: String ⇒ fromString.genString(s, system) + case x ⇒ simpleName(x) + "(" + system + ")" + } } /** @@ -213,8 +228,8 @@ object LogSource { * ... * log.info("hello world!") * - * - * The source object is used in two fashions: its `Class[_]` will be part of + * + * The source object is used in two fashions: its `Class[_]` will be part of * all log events produced by this logger, plus a string representation is * generated which may contain per-instance information, see `apply` or `create` * below. @@ -305,6 +320,41 @@ object Logging { val infoFormat = "[INFO] [%s] [%s] [%s] %s".intern val debugFormat = "[DEBUG] [%s] [%s] [%s] %s".intern + /** + * Obtain LoggingAdapter for the given actor system and source object. This + * will use the system’s event stream. + * + * The source is used to identify the source of this logging channel and must have + * a corresponding implicit LogSource[T] instance in scope; by default these are + * provided for Class[_], Actor, ActorRef and String types. By these, the source + * object is translated to a String according to the following rules: + * + * + * You can add your own rules quite easily: + * + * {{{ + * trait MyType { // as an example + * def name: String + * } + * + * implicit val myLogSourceType: LogSource[MyType] = new LogSource { + * def genString(a: MyType) = a.name + * } + * + * class MyClass extends MyType { + * val log = Logging(eventStream, this) // will use "hallo" as logSource + * def name = "hallo" + * } + * }}} + */ + def apply[T: LogSource](system: ActorSystem, logSource: T): LoggingAdapter = + new BusLogging(system.eventStream, LogSource(logSource, system), logSource.getClass) + /** * Obtain LoggingAdapter for the given logging bus and source object. * @@ -318,18 +368,18 @@ object Logging { *
  • in case of a class an approximation of its simpleName *
  • and in all other cases the simpleName of its class
  • * - * + * * You can add your own rules quite easily: - * + * * {{{ * trait MyType { // as an example * def name: String * } - * + * * implicit val myLogSourceType: LogSource[MyType] = new LogSource { * def genString(a: MyType) = a.name * } - * + * * class MyClass extends MyType { * val log = Logging(eventStream, this) // will use "hallo" as logSource * def name = "hallo" @@ -353,60 +403,25 @@ object Logging { *
  • in case of a class an approximation of its simpleName *
  • and in all other cases the simpleName of its class
  • * - * - * You can add your own rules quite easily: - * - * {{{ - * trait MyType { // as an example - * def name: String - * } - * - * implicit val myLogSourceType: LogSource[MyType] = new LogSource { - * def genString(a: MyType) = a.name - * } - * - * class MyClass extends MyType { - * val log = Logging(eventStream, this) // will use "hallo" as logSource - * def name = "hallo" - * } - * }}} - */ - def apply[T: LogSource](system: ActorSystem, logSource: T): LoggingAdapter = - new BusLogging(system.eventStream, implicitly[LogSource[T]].genString(logSource), logSource.getClass) - - /** - * Obtain LoggingAdapter for the given actor system and source object. This - * will use the system’s event stream. * - * The source is used to identify the source of this logging channel and must have - * a corresponding implicit LogSource[T] instance in scope; by default these are - * provided for Class[_], Actor, ActorRef and String types. By these, the source - * object is translated to a String according to the following rules: - * - * * You can add your own rules quite easily: - * + * * {{{ * trait MyType { // as an example * def name: String * } - * + * * implicit val myLogSourceType: LogSource[MyType] = new LogSource { * def genString(a: MyType) = a.name * } - * + * * class MyClass extends MyType { * val log = Logging(eventStream, this) // will use "hallo" as logSource * def name = "hallo" * } * }}} */ - def getLogger(system: ActorSystem, logSource: AnyRef): LoggingAdapter = apply(system, LogSource.fromAnyRef(logSource)) + def getLogger(system: ActorSystem, logSource: AnyRef): LoggingAdapter = apply(system, LogSource.fromAnyRef(logSource, system)) /** * Obtain LoggingAdapter for the given logging bus and source object. This @@ -422,25 +437,25 @@ object Logging { *
  • in case of a class an approximation of its simpleName *
  • and in all other cases the simpleName of its class
  • * - * + * * You can add your own rules quite easily: - * + * * {{{ * trait MyType { // as an example * def name: String * } - * + * * implicit val myLogSourceType: LogSource[MyType] = new LogSource { * def genString(a: MyType) = a.name * } - * + * * class MyClass extends MyType { * val log = Logging(eventStream, this) // will use "hallo" as logSource * def name = "hallo" * } * }}} */ - def getLogger(bus: LoggingBus, logSource: AnyRef): LoggingAdapter = apply(bus, LogSource.fromAnyRef(logSource)) + //def getLogger(bus: LoggingBus, logSource: AnyRef): LoggingAdapter = apply(bus, LogSource.fromAnyRef(logSource)) /** * Artificial exception injected into Error events if no Throwable is diff --git a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala index 5b748098ac..037f9d594a 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala @@ -27,8 +27,6 @@ class RemoteActorRefProvider( val scheduler: Scheduler, _deadLetters: InternalActorRef) extends ActorRefProvider { - val log = Logging(eventStream, "RemoteActorRefProvider") - val remoteSettings = new RemoteSettings(settings.config, systemName) def rootGuardian = local.rootGuardian @@ -44,6 +42,8 @@ class RemoteActorRefProvider( val remote = new Remote(settings, remoteSettings) implicit val transports = remote.transports + val log = Logging(eventStream, "RemoteActorRefProvider(" + remote.remoteAddress + ")") + val rootPath: ActorPath = RootActorPath(remote.remoteAddress) private val local = new LocalActorRefProvider(systemName, settings, eventStream, scheduler, _deadLetters, rootPath, deployer)