some polishing of new Logging

- add scaladoc
- remove (empty) EventHandler.scala
- make BugLogging more of an implementation detail, i.e. use the
  Logging() factories to get a Logging implementation.
This commit is contained in:
Roland 2011-10-29 19:10:58 +02:00
parent d1e0f411ef
commit 55f896226c
7 changed files with 87 additions and 82 deletions

View file

@ -168,7 +168,7 @@ class AkkaApplication(val name: String, val config: Configuration) extends Actor
// this provides basic logging (to stdout) until .start() is called below
val mainbus = new MainBus(DebugMainBus)
mainbus.startStdoutLogger(AkkaConfig)
val log = new MainBusLogging(mainbus, this)
val log = new BusLogging(mainbus, this)
// TODO correctly pull its config from the config
val dispatcherFactory = new Dispatchers(this)

View file

@ -11,7 +11,7 @@ import akka.AkkaApplication
import java.util.concurrent.ConcurrentHashMap
import com.eaio.uuid.UUID
import akka.AkkaException
import akka.event.{ ActorClassification, DeathWatch, MainBusLogging }
import akka.event.{ ActorClassification, DeathWatch, Logging }
import akka.dispatch._
/**
@ -91,7 +91,7 @@ class ActorRefProviderException(message: String) extends AkkaException(message)
class LocalActorRefProvider(val app: AkkaApplication) extends ActorRefProvider {
val terminationFuture = new DefaultPromise[AkkaApplication.ExitStatus](Timeout.never)(app.dispatcher)
val log = new MainBusLogging(app.mainbus, this)
val log = Logging(app.mainbus, this)
/**
* Top-level anchor for the supervision hierarchy of this actor system. Will

View file

@ -8,7 +8,7 @@ import collection.immutable.Seq
import java.util.concurrent.ConcurrentHashMap
import akka.event.MainBusLogging
import akka.event.Logging
import akka.actor.DeploymentConfig._
import akka.{ AkkaException, AkkaApplication }
import akka.config.{ Configuration, ConfigurationException }
@ -34,7 +34,7 @@ trait ActorDeployer {
class Deployer(val app: AkkaApplication) extends ActorDeployer {
val deploymentConfig = new DeploymentConfig(app)
val log = new MainBusLogging(app.mainbus, this)
val log = Logging(app.mainbus, this)
// val defaultAddress = Node(Config.nodename)

View file

@ -4,7 +4,7 @@
package akka.actor
import akka.util._
import akka.event.MainBusLogging
import akka.event.Logging
import scala.collection.mutable
import java.util.concurrent.ScheduledFuture
@ -190,7 +190,7 @@ trait FSM[S, D] extends ListenerManagement {
type Timeout = Option[Duration]
type TransitionHandler = PartialFunction[(S, S), Unit]
val log = new MainBusLogging(app.mainbus, context.self)
val log = Logging(app.mainbus, context.self)
/**
* ****************************************

View file

@ -1,55 +0,0 @@
/**
* Copyright (C) 2009-2011 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.event
import akka.actor._
import akka.dispatch.Dispatchers
import akka.config.ConfigurationException
import akka.util.{ ListenerManagement, ReflectiveAccess }
import akka.serialization._
import akka.AkkaException
import akka.AkkaApplication
/**
* Event handler.
* <p/>
* Create, add and remove a listener:
* <pre>
* val eventHandlerListener = Actor.actorOf(new Actor {
* self.dispatcher = EventHandler.EventHandlerDispatcher
*
* def receive = {
* case EventHandler.Error(cause, instance, message) ...
* case EventHandler.Warning(instance, message) ...
* case EventHandler.Info(instance, message) ...
* case EventHandler.Debug(instance, message) ...
* case genericEvent ...
* }
* })
*
* EventHandler.addListener(eventHandlerListener)
* ...
* EventHandler.removeListener(eventHandlerListener)
* </pre>
* <p/>
* However best is probably to register the listener in the 'akka.conf'
* configuration file.
* <p/>
* Log an error event:
* <pre>
* EventHandler.notify(EventHandler.Error(exception, this, message))
* </pre>
* Or use the direct methods (better performance):
* <pre>
* EventHandler.error(exception, this, message)
* </pre>
*
* Shut down the EventHandler:
* <pre>
* EventHandler.shutdown()
* </pre>
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/

View file

@ -28,15 +28,24 @@ trait LoggingBus extends ActorEventBus {
@volatile
private var _logLevel: LogLevel = _
/**
* Query currently set log level. See object Logging for more information.
*/
def logLevel = _logLevel
/**
* Change log level: default loggers (i.e. from configuration file) are
* subscribed/unsubscribed as necessary so that they listen to all levels
* which are at least as severe as the given one. See object Logging for
* more information.
*/
def logLevel_=(level: LogLevel) {
for { l AllLogLevels if l > _logLevel && l <= level; log loggers } subscribe(log, classFor(l))
for { l AllLogLevels if l <= _logLevel && l > level; log loggers } unsubscribe(log, classFor(l))
_logLevel = level
}
def startStdoutLogger(config: AkkaConfig) {
private[akka] def startStdoutLogger(config: AkkaConfig) {
val level = levelFor(config.StdoutLogLevel) getOrElse {
StandardOutLogger.print(Error(new EventHandlerException, this, "unknown akka.stdout-loglevel " + config.StdoutLogLevel))
ErrorLevel
@ -47,7 +56,7 @@ trait LoggingBus extends ActorEventBus {
publish(Info(this, "StandardOutLogger started"))
}
def startDefaultLoggers(app: AkkaApplication, config: AkkaConfig) {
private[akka] def startDefaultLoggers(app: AkkaApplication, config: AkkaConfig) {
val level = levelFor(config.LogLevel) getOrElse {
StandardOutLogger.print(Error(new EventHandlerException, this, "unknown akka.stdout-loglevel " + config.LogLevel))
ErrorLevel
@ -59,7 +68,7 @@ trait LoggingBus extends ActorEventBus {
}
loggers = for {
loggerName defaultLoggers
if loggerName != DefaultLoggerName
if loggerName != StandardOutLoggerName
} yield {
try {
ReflectiveAccess.getClassFor[Actor](loggerName) match {
@ -74,7 +83,7 @@ trait LoggingBus extends ActorEventBus {
}
}
publish(Info(this, "Default Loggers started"))
if (defaultLoggers contains DefaultLoggerName) {
if (defaultLoggers contains StandardOutLoggerName) {
loggers :+= StandardOutLogger
} else {
unsubscribe(StandardOutLogger)
@ -88,7 +97,7 @@ trait LoggingBus extends ActorEventBus {
}
}
def stopDefaultLoggers() {
private[akka] def stopDefaultLoggers() {
val level = _logLevel // volatile access before reading loggers
if (!(loggers contains StandardOutLogger)) {
AllLogLevels filter (level >= _) foreach (l subscribe(StandardOutLogger, classFor(l)))
@ -111,6 +120,24 @@ trait LoggingBus extends ActorEventBus {
}
/**
* Main entry point for Akka logging: log levels and message types (aka
* channels) defined for the main transport medium, the main event bus. The
* recommended use is to obtain an implementation of the Logging trait with
* suitable and efficient methods for generating log events:
*
* <pre><code>
* val log = Logging(&lt;bus&gt;, &lt;source object&gt;)
* ...
* log.info("hello world!")
* </code></pre>
*
* Loggers are attached to the level-specific channels <code>Error</code>,
* <code>Warning</code>, <code>Info</code> and <code>Debug</code> as
* appropriate for the configured (or set) log level. If you want to implement
* your own, make sure to handle these four event types plus the <code>InitializeLogger</code>
* message which is sent before actually attaching it to the logging bus.
*/
object Logging {
trait LogLevelType
@ -143,6 +170,7 @@ object Logging {
case DebugLevel classOf[Debug]
}
// these type ascriptions/casts are necessary to avoid CCEs during construction while retaining correct type
val AllLogLevels = Seq(ErrorLevel: AnyRef, WarningLevel, InfoLevel, DebugLevel).asInstanceOf[Seq[LogLevel]]
val errorFormat = "[ERROR] [%s] [%s] [%s] %s\n%s".intern
@ -151,8 +179,8 @@ object Logging {
val debugFormat = "[DEBUG] [%s] [%s] [%s] %s".intern
val genericFormat = "[GENERIC] [%s] [%s]".intern
def apply(app: AkkaApplication, instance: AnyRef): Logging = new MainBusLogging(app.mainbus, instance)
def apply(bus: MainBus, instance: AnyRef): Logging = new MainBusLogging(bus, instance)
def apply(app: AkkaApplication, instance: AnyRef): Logging = new BusLogging(app.mainbus, instance)
def apply(bus: LoggingBus, instance: AnyRef): Logging = new BusLogging(bus, instance)
class EventHandlerException extends AkkaException
@ -181,6 +209,11 @@ object Logging {
def level = DebugLevel
}
/**
* Message which is sent to each default logger (i.e. from configuration file)
* after its creation but before attaching it to the logging bus. The logger
* actor should handle this message, e.g. to register for more channels.
*/
case class InitializeLogger(bus: LoggingBus)
trait StdOutLogger {
@ -240,13 +273,25 @@ object Logging {
}
}
/**
* Actor-less logging implementation for synchronous logging to standard
* output. This logger is always attached first in order to be able to log
* failures during application start-up, even before normal logging is
* started. Its log level can be configured by setting
* <code>akka.stdout-loglevel</code> in <code>akka.conf</code>.
*/
class StandardOutLogger extends MinimalActorRef with StdOutLogger {
override val toString = "StandardOutLogger"
override def postMessageToMailbox(obj: Any, channel: UntypedChannel) { print(obj) }
}
val StandardOutLogger = new StandardOutLogger
val DefaultLoggerName = StandardOutLogger.getClass.getName
val StandardOutLoggerName = StandardOutLogger.getClass.getName
/**
* Actor wrapper around the standard output logger. If
* <code>akka.event-handlers</code> is not set, it defaults to just this
* logger.
*/
class DefaultLogger extends Actor with StdOutLogger {
def receive = {
case InitializeLogger(_)
@ -270,7 +315,22 @@ object Logging {
/**
* Logging wrapper to make nicer and optimize: provide template versions which
* evaluate .toString only if the log level is actually enabled.
* evaluate .toString only if the log level is actually enabled. Typically used
* by obtaining an implementation from the Logging object:
*
* <code><pre>
* val log = Logging(&lt;bus&gt;, &lt;source object&gt;)
* ...
* log.info("hello world!")
* </pre></code>
*
* All log-level methods support simple interpolation templates with up to four
* arguments placed by using <code>{}</code> within the template (first string
* argument):
*
* <code><pre>
* log.error(exception, "Exception while processing {} in state {}", msg, state)
* </pre></code>
*/
trait Logging {
@ -333,21 +393,21 @@ trait Logging {
}
class MainBusLogging(val mainbus: MainBus, val loggingInstance: AnyRef) extends Logging {
class BusLogging(val bus: LoggingBus, val loggingInstance: AnyRef) extends Logging {
import Logging._
def isErrorEnabled = mainbus.logLevel >= ErrorLevel
def isWarningEnabled = mainbus.logLevel >= WarningLevel
def isInfoEnabled = mainbus.logLevel >= InfoLevel
def isDebugEnabled = mainbus.logLevel >= DebugLevel
def isErrorEnabled = bus.logLevel >= ErrorLevel
def isWarningEnabled = bus.logLevel >= WarningLevel
def isInfoEnabled = bus.logLevel >= InfoLevel
def isDebugEnabled = bus.logLevel >= DebugLevel
protected def notifyError(cause: Throwable, message: String) { mainbus.publish(Error(cause, loggingInstance, message)) }
protected def notifyError(cause: Throwable, message: String) { bus.publish(Error(cause, loggingInstance, message)) }
protected def notifyWarning(message: String) { mainbus.publish(Warning(loggingInstance, message)) }
protected def notifyWarning(message: String) { bus.publish(Warning(loggingInstance, message)) }
protected def notifyInfo(message: String) { mainbus.publish(Info(loggingInstance, message)) }
protected def notifyInfo(message: String) { bus.publish(Info(loggingInstance, message)) }
protected def notifyDebug(message: String) { mainbus.publish(Debug(loggingInstance, message)) }
protected def notifyDebug(message: String) { bus.publish(Debug(loggingInstance, message)) }
}

View file

@ -9,14 +9,14 @@ import org.scalatest.matchers.MustMatchers
import akka.AkkaApplication
import akka.actor.{ Actor, ActorRef, Props }
import akka.dispatch.MessageDispatcher
import akka.event.{ Logging, MainBusLogging }
import akka.event.Logging
import akka.util.duration._
import akka.dispatch.FutureTimeoutException
abstract class AkkaSpec(_application: AkkaApplication = AkkaApplication())
extends TestKit(_application) with WordSpec with MustMatchers with BeforeAndAfterAll {
val log: Logging = new MainBusLogging(app.mainbus, this)
val log: Logging = Logging(app.mainbus, this)
final override def beforeAll {
atStartup()