diff --git a/akka-actor-tests/src/test/scala/akka/event/LoggerSpec.scala b/akka-actor-tests/src/test/scala/akka/event/LoggerSpec.scala new file mode 100644 index 0000000000..2f97668b4c --- /dev/null +++ b/akka-actor-tests/src/test/scala/akka/event/LoggerSpec.scala @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2009-2013 Typesafe Inc. + */ +package akka.event + +import akka.testkit.AkkaSpec +import com.typesafe.config.{ Config, ConfigFactory } +import org.scalatest.WordSpec +import akka.actor.ActorSystem +import org.scalatest.matchers.MustMatchers + +object LoggerSpec { + + val defaultConfig = ConfigFactory.parseString(""" + akka { + stdout-loglevel = WARNING + loglevel = DEBUG + } + """).withFallback(AkkaSpec.testConf) + + val noLoggingConfig = ConfigFactory.parseString(""" + akka { + stdout-loglevel = OFF + loglevel = OFF + } + """).withFallback(AkkaSpec.testConf) +} + +@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) +class LoggerSpec extends WordSpec with MustMatchers { + + import LoggerSpec._ + + private def createSystemAndLogToBuffer(name: String, config: Config) = { + val out = new java.io.ByteArrayOutputStream() + Console.withOut(out) { + val system = ActorSystem(name, config) + try { + system.log.error("Danger! Danger!") + } finally { + system.shutdown() + } + } + out + } + + "A normally configured actor system" must { + + "log messages to standard output" in { + val out = createSystemAndLogToBuffer("defaultLogger", defaultConfig) + out.size must be > (0) + } + } + + "An actor system configured with the logging turned off" must { + + "not log messages to standard output" in { + val out = createSystemAndLogToBuffer("noLogging", noLoggingConfig) + out.size must be(0) + } + } +} diff --git a/akka-actor/src/main/resources/reference.conf b/akka-actor/src/main/resources/reference.conf index 1eed4db675..bff860665e 100644 --- a/akka-actor/src/main/resources/reference.conf +++ b/akka-actor/src/main/resources/reference.conf @@ -29,11 +29,11 @@ akka { # Log level used by the configured loggers (see "loggers") as soon # as they have been started; before that, see "stdout-loglevel" - # Options: ERROR, WARNING, INFO, DEBUG + # Options: OFF, ERROR, WARNING, INFO, DEBUG loglevel = "INFO" # Log level for the very basic logger activated during AkkaApplication startup - # Options: ERROR, WARNING, INFO, DEBUG + # Options: OFF, ERROR, WARNING, INFO, DEBUG stdout-loglevel = "WARNING" # Log the complete configuration at INFO level when the actor system is started. diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index 7853832b87..5a9d7f65ba 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -455,7 +455,7 @@ class LocalActorRefProvider private[akka] ( def stopWhenAllTerminationHooksDone(): Unit = if (terminationHooks.isEmpty) { - eventStream.stopDefaultLoggers() + eventStream.stopDefaultLoggers(system) context.stop(self) } diff --git a/akka-actor/src/main/scala/akka/event/Logging.scala b/akka-actor/src/main/scala/akka/event/Logging.scala index 851c6cf1f3..9dd1dfd2c9 100644 --- a/akka-actor/src/main/scala/akka/event/Logging.scala +++ b/akka-actor/src/main/scala/akka/event/Logging.scala @@ -67,19 +67,23 @@ trait LoggingBus extends ActorEventBus { _logLevel = level } - /** - * Internal Akka use only - */ - private[akka] def startStdoutLogger(config: Settings) { + private def setUpStdoutLogger(config: Settings) { val level = levelFor(config.StdoutLogLevel) getOrElse { StandardOutLogger.print(Error(new LoggerException, simpleName(this), this.getClass, "unknown akka.stdout-loglevel " + config.StdoutLogLevel)) ErrorLevel } AllLogLevels filter (level >= _) foreach (l ⇒ subscribe(StandardOutLogger, classFor(l))) guard.withGuard { - loggers = Seq(StandardOutLogger) + loggers :+= StandardOutLogger _logLevel = level } + } + + /** + * Internal Akka use only + */ + private[akka] def startStdoutLogger(config: Settings) { + setUpStdoutLogger(config) publish(Debug(simpleName(this), this.getClass, "StandardOutLogger started")) } @@ -145,10 +149,10 @@ trait LoggingBus extends ActorEventBus { /** * Internal Akka use only */ - private[akka] def stopDefaultLoggers() { + private[akka] def stopDefaultLoggers(system: ActorSystem) { val level = _logLevel // volatile access before reading loggers if (!(loggers contains StandardOutLogger)) { - AllLogLevels filter (level >= _) foreach (l ⇒ subscribe(StandardOutLogger, classFor(l))) + setUpStdoutLogger(system.settings) publish(Debug(simpleName(this), this.getClass, "shutting down: StandardOutLogger started")) } for { @@ -424,17 +428,26 @@ object Logging { final val InfoLevel = LogLevel(3) final val DebugLevel = LogLevel(4) + /** + * Internal Akka use only + * + * Don't include the OffLevel in the AllLogLevels since we should never subscribe + * to some kind of OffEvent. + */ + private final val OffLevel = LogLevel(Int.MinValue) + /** * Returns the LogLevel associated with the given string, * valid inputs are upper or lowercase (not mixed) versions of: * "error", "warning", "info" and "debug" */ - def levelFor(s: String): Option[LogLevel] = s match { - case "ERROR" | "error" ⇒ Some(ErrorLevel) - case "WARNING" | "warning" ⇒ Some(WarningLevel) - case "INFO" | "info" ⇒ Some(InfoLevel) - case "DEBUG" | "debug" ⇒ Some(DebugLevel) - case unknown ⇒ None + def levelFor(s: String): Option[LogLevel] = s.toLowerCase match { + case "off" ⇒ Some(OffLevel) + case "error" ⇒ Some(ErrorLevel) + case "warning" ⇒ Some(WarningLevel) + case "info" ⇒ Some(InfoLevel) + case "debug" ⇒ Some(DebugLevel) + case unknown ⇒ None } /** diff --git a/akka-docs/rst/general/configuration.rst b/akka-docs/rst/general/configuration.rst index 94054ac007..e55c9add85 100644 --- a/akka-docs/rst/general/configuration.rst +++ b/akka-docs/rst/general/configuration.rst @@ -95,11 +95,11 @@ A custom ``application.conf`` might look like this:: # Log level used by the configured loggers (see "loggers") as soon # as they have been started; before that, see "stdout-loglevel" - # Options: ERROR, WARNING, INFO, DEBUG + # Options: OFF, ERROR, WARNING, INFO, DEBUG loglevel = DEBUG # Log level for the very basic logger activated during AkkaApplication startup - # Options: ERROR, WARNING, INFO, DEBUG + # Options: OFF, ERROR, WARNING, INFO, DEBUG stdout-loglevel = DEBUG actor { diff --git a/akka-docs/rst/java/logging.rst b/akka-docs/rst/java/logging.rst index e75aff0e55..73bd2825eb 100644 --- a/akka-docs/rst/java/logging.rst +++ b/akka-docs/rst/java/logging.rst @@ -56,7 +56,7 @@ You almost definitely need to have logging set to DEBUG to use any of the option .. code-block:: ruby akka { - loglevel = DEBUG + loglevel = "DEBUG" } This config option is very good if you want to know what config settings are loaded by Akka: @@ -153,6 +153,20 @@ If you want to see all messages that are received through remoting at DEBUG log Also see the logging options for TestKit: :ref:`actor.logging-java`. +Turn Off Logging +---------------- + +To turn off logging you can configure the log levels to be ``OFF`` like this. + +.. code-block:: ruby + + akka { + stdout-loglevel = "OFF" + loglevel = "OFF" + } + +The ``stdout-loglevel`` is only in effect during system startup and shutdown, and setting +it to ``OFF`` as well, ensures that nothing gets logged during system startup or shutdown. Loggers ======= @@ -167,7 +181,7 @@ Here you can also define the log level. # Loggers to register at boot time (akka.event.Logging$DefaultLogger logs # to STDOUT) loggers = ["akka.event.Logging$DefaultLogger"] - # Options: ERROR, WARNING, INFO, DEBUG + # Options: OFF, ERROR, WARNING, INFO, DEBUG loglevel = "DEBUG" } diff --git a/akka-docs/rst/scala/logging.rst b/akka-docs/rst/scala/logging.rst index 130569aa4c..f004770f5c 100644 --- a/akka-docs/rst/scala/logging.rst +++ b/akka-docs/rst/scala/logging.rst @@ -57,7 +57,7 @@ You almost definitely need to have logging set to DEBUG to use any of the option .. code-block:: ruby akka { - loglevel = DEBUG + loglevel = "DEBUG" } This config option is very good if you want to know what config settings are loaded by Akka: @@ -196,6 +196,21 @@ purposes as it contains exactly the default behavior. to look up the logger instance to use instead of the class’ name), and you might want to do this also in case you implement your own logging adapter. +Turn Off Logging +---------------- + +To turn off logging you can configure the log levels to be ``OFF`` like this. + +.. code-block:: ruby + + akka { + stdout-loglevel = "OFF" + loglevel = "OFF" + } + +The ``stdout-loglevel`` is only in effect during system startup and shutdown, and setting +it to ``OFF`` as well, ensures that nothing gets logged during system startup or shutdown. + Loggers ======= @@ -210,7 +225,7 @@ also define the log level. # Loggers to register at boot time (akka.event.Logging$DefaultLogger logs # to STDOUT) loggers = ["akka.event.Logging$DefaultLogger"] - # Options: ERROR, WARNING, INFO, DEBUG + # Options: OFF, ERROR, WARNING, INFO, DEBUG loglevel = "DEBUG" }