Merge pull request #1173 from akka/wip-2965-show-how-to-stop-stdout-logging-master-ban
Add new log level OFF. See #2965
This commit is contained in:
commit
e09f0ac3ff
10 changed files with 177 additions and 35 deletions
96
akka-actor-tests/src/test/scala/akka/event/LoggerSpec.scala
Normal file
96
akka-actor-tests/src/test/scala/akka/event/LoggerSpec.scala
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||||
|
*/
|
||||||
|
package akka.event
|
||||||
|
|
||||||
|
import akka.testkit._
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
import com.typesafe.config.{ Config, ConfigFactory }
|
||||||
|
import akka.actor.{ ActorRef, Actor, ActorSystem }
|
||||||
|
import org.scalatest.WordSpec
|
||||||
|
import org.scalatest.matchers.MustMatchers
|
||||||
|
import akka.event.Logging.{ LogEvent, LoggerInitialized, InitializeLogger }
|
||||||
|
|
||||||
|
object LoggerSpec {
|
||||||
|
|
||||||
|
val defaultConfig = ConfigFactory.parseString("""
|
||||||
|
akka {
|
||||||
|
stdout-loglevel = "WARNING"
|
||||||
|
loglevel = "DEBUG"
|
||||||
|
loggers = ["akka.event.LoggerSpec$TestLogger"]
|
||||||
|
}
|
||||||
|
""").withFallback(AkkaSpec.testConf)
|
||||||
|
|
||||||
|
val noLoggingConfig = ConfigFactory.parseString("""
|
||||||
|
akka {
|
||||||
|
stdout-loglevel = "OFF"
|
||||||
|
loglevel = "OFF"
|
||||||
|
loggers = ["akka.event.LoggerSpec$TestLogger"]
|
||||||
|
}
|
||||||
|
""").withFallback(AkkaSpec.testConf)
|
||||||
|
|
||||||
|
case class SetTarget(ref: ActorRef)
|
||||||
|
|
||||||
|
class TestLogger extends Actor with Logging.StdOutLogger {
|
||||||
|
var target: Option[ActorRef] = None
|
||||||
|
override def receive: Receive = {
|
||||||
|
case InitializeLogger(bus) ⇒
|
||||||
|
bus.subscribe(context.self, classOf[SetTarget])
|
||||||
|
sender ! LoggerInitialized
|
||||||
|
case SetTarget(ref) ⇒
|
||||||
|
target = Some(ref)
|
||||||
|
ref ! ("OK")
|
||||||
|
case event: LogEvent ⇒
|
||||||
|
print(event)
|
||||||
|
target foreach { _ ! event.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
|
||||||
|
class LoggerSpec extends WordSpec with MustMatchers {
|
||||||
|
|
||||||
|
import LoggerSpec._
|
||||||
|
|
||||||
|
private def createSystemAndLogToBuffer(name: String, config: Config, shouldLog: Boolean) = {
|
||||||
|
val out = new java.io.ByteArrayOutputStream()
|
||||||
|
Console.withOut(out) {
|
||||||
|
implicit val system = ActorSystem(name, config)
|
||||||
|
try {
|
||||||
|
val probe = TestProbe()
|
||||||
|
system.eventStream.publish(SetTarget(probe.ref))
|
||||||
|
probe.expectMsg("OK")
|
||||||
|
system.log.error("Danger! Danger!")
|
||||||
|
// since logging is asynchronous ensure that it propagates
|
||||||
|
if (shouldLog) {
|
||||||
|
probe.fishForMessage(0.5.seconds.dilated) {
|
||||||
|
case "Danger! Danger!" ⇒ true
|
||||||
|
case _ ⇒ false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
probe.expectNoMsg(0.5.seconds.dilated)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
system.shutdown()
|
||||||
|
system.awaitTermination(5.seconds.dilated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
"A normally configured actor system" must {
|
||||||
|
|
||||||
|
"log messages to standard output" in {
|
||||||
|
val out = createSystemAndLogToBuffer("defaultLogger", defaultConfig, true)
|
||||||
|
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, false)
|
||||||
|
out.size must be(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,11 +29,11 @@ akka {
|
||||||
|
|
||||||
# Log level used by the configured loggers (see "loggers") as soon
|
# Log level used by the configured loggers (see "loggers") as soon
|
||||||
# as they have been started; before that, see "stdout-loglevel"
|
# as they have been started; before that, see "stdout-loglevel"
|
||||||
# Options: ERROR, WARNING, INFO, DEBUG
|
# Options: OFF, ERROR, WARNING, INFO, DEBUG
|
||||||
loglevel = "INFO"
|
loglevel = "INFO"
|
||||||
|
|
||||||
# Log level for the very basic logger activated during AkkaApplication startup
|
# 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"
|
stdout-loglevel = "WARNING"
|
||||||
|
|
||||||
# Log the complete configuration at INFO level when the actor system is started.
|
# Log the complete configuration at INFO level when the actor system is started.
|
||||||
|
|
|
||||||
|
|
@ -456,7 +456,7 @@ class LocalActorRefProvider private[akka] (
|
||||||
|
|
||||||
def stopWhenAllTerminationHooksDone(): Unit =
|
def stopWhenAllTerminationHooksDone(): Unit =
|
||||||
if (terminationHooks.isEmpty) {
|
if (terminationHooks.isEmpty) {
|
||||||
eventStream.stopDefaultLoggers()
|
eventStream.stopDefaultLoggers(system)
|
||||||
context.stop(self)
|
context.stop(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,19 +67,24 @@ trait LoggingBus extends ActorEventBus {
|
||||||
_logLevel = level
|
_logLevel = level
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private def setUpStdoutLogger(config: Settings) {
|
||||||
* Internal Akka use only
|
|
||||||
*/
|
|
||||||
private[akka] def startStdoutLogger(config: Settings) {
|
|
||||||
val level = levelFor(config.StdoutLogLevel) getOrElse {
|
val level = levelFor(config.StdoutLogLevel) getOrElse {
|
||||||
|
// only log initialization errors directly with StandardOutLogger.print
|
||||||
StandardOutLogger.print(Error(new LoggerException, simpleName(this), this.getClass, "unknown akka.stdout-loglevel " + config.StdoutLogLevel))
|
StandardOutLogger.print(Error(new LoggerException, simpleName(this), this.getClass, "unknown akka.stdout-loglevel " + config.StdoutLogLevel))
|
||||||
ErrorLevel
|
ErrorLevel
|
||||||
}
|
}
|
||||||
AllLogLevels filter (level >= _) foreach (l ⇒ subscribe(StandardOutLogger, classFor(l)))
|
AllLogLevels filter (level >= _) foreach (l ⇒ subscribe(StandardOutLogger, classFor(l)))
|
||||||
guard.withGuard {
|
guard.withGuard {
|
||||||
loggers = Seq(StandardOutLogger)
|
loggers :+= StandardOutLogger
|
||||||
_logLevel = level
|
_logLevel = level
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal Akka use only
|
||||||
|
*/
|
||||||
|
private[akka] def startStdoutLogger(config: Settings) {
|
||||||
|
setUpStdoutLogger(config)
|
||||||
publish(Debug(simpleName(this), this.getClass, "StandardOutLogger started"))
|
publish(Debug(simpleName(this), this.getClass, "StandardOutLogger started"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,7 +94,8 @@ trait LoggingBus extends ActorEventBus {
|
||||||
private[akka] def startDefaultLoggers(system: ActorSystemImpl) {
|
private[akka] def startDefaultLoggers(system: ActorSystemImpl) {
|
||||||
val logName = simpleName(this) + "(" + system + ")"
|
val logName = simpleName(this) + "(" + system + ")"
|
||||||
val level = levelFor(system.settings.LogLevel) getOrElse {
|
val level = levelFor(system.settings.LogLevel) getOrElse {
|
||||||
StandardOutLogger.print(Error(new LoggerException, logName, this.getClass, "unknown akka.stdout-loglevel " + system.settings.LogLevel))
|
// only log initialization errors directly with StandardOutLogger.print
|
||||||
|
StandardOutLogger.print(Error(new LoggerException, logName, this.getClass, "unknown akka.loglevel " + system.settings.LogLevel))
|
||||||
ErrorLevel
|
ErrorLevel
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
@ -99,7 +105,7 @@ trait LoggingBus extends ActorEventBus {
|
||||||
case loggers ⇒ loggers
|
case loggers ⇒ loggers
|
||||||
}
|
}
|
||||||
case loggers ⇒
|
case loggers ⇒
|
||||||
StandardOutLogger.print(Warning(logName, this.getClass, "[akka.event-handlers] config is deprecated, use [akka.loggers]"))
|
publish(Warning(logName, this.getClass, "[akka.event-handlers] config is deprecated, use [akka.loggers]"))
|
||||||
loggers
|
loggers
|
||||||
}
|
}
|
||||||
val myloggers =
|
val myloggers =
|
||||||
|
|
@ -145,10 +151,10 @@ trait LoggingBus extends ActorEventBus {
|
||||||
/**
|
/**
|
||||||
* Internal Akka use only
|
* Internal Akka use only
|
||||||
*/
|
*/
|
||||||
private[akka] def stopDefaultLoggers() {
|
private[akka] def stopDefaultLoggers(system: ActorSystem) {
|
||||||
val level = _logLevel // volatile access before reading loggers
|
val level = _logLevel // volatile access before reading loggers
|
||||||
if (!(loggers contains StandardOutLogger)) {
|
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"))
|
publish(Debug(simpleName(this), this.getClass, "shutting down: StandardOutLogger started"))
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
|
|
@ -173,7 +179,7 @@ trait LoggingBus extends ActorEventBus {
|
||||||
val actor = system.systemActorOf(Props(clazz), name)
|
val actor = system.systemActorOf(Props(clazz), name)
|
||||||
implicit def timeout =
|
implicit def timeout =
|
||||||
if (system.settings.EventHandlerStartTimeout.duration >= Duration.Zero) {
|
if (system.settings.EventHandlerStartTimeout.duration >= Duration.Zero) {
|
||||||
StandardOutLogger.print(Warning(logName, this.getClass,
|
publish(Warning(logName, this.getClass,
|
||||||
"[akka.event-handler-startup-timeout] config is deprecated, use [akka.logger-startup-timeout]"))
|
"[akka.event-handler-startup-timeout] config is deprecated, use [akka.logger-startup-timeout]"))
|
||||||
system.settings.EventHandlerStartTimeout
|
system.settings.EventHandlerStartTimeout
|
||||||
} else system.settings.LoggerStartTimeout
|
} else system.settings.LoggerStartTimeout
|
||||||
|
|
@ -424,16 +430,25 @@ object Logging {
|
||||||
final val InfoLevel = LogLevel(3)
|
final val InfoLevel = LogLevel(3)
|
||||||
final val DebugLevel = LogLevel(4)
|
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,
|
* Returns the LogLevel associated with the given string,
|
||||||
* valid inputs are upper or lowercase (not mixed) versions of:
|
* valid inputs are upper or lowercase (not mixed) versions of:
|
||||||
* "error", "warning", "info" and "debug"
|
* "error", "warning", "info" and "debug"
|
||||||
*/
|
*/
|
||||||
def levelFor(s: String): Option[LogLevel] = s match {
|
def levelFor(s: String): Option[LogLevel] = s.toLowerCase match {
|
||||||
case "ERROR" | "error" ⇒ Some(ErrorLevel)
|
case "off" ⇒ Some(OffLevel)
|
||||||
case "WARNING" | "warning" ⇒ Some(WarningLevel)
|
case "error" ⇒ Some(ErrorLevel)
|
||||||
case "INFO" | "info" ⇒ Some(InfoLevel)
|
case "warning" ⇒ Some(WarningLevel)
|
||||||
case "DEBUG" | "debug" ⇒ Some(DebugLevel)
|
case "info" ⇒ Some(InfoLevel)
|
||||||
|
case "debug" ⇒ Some(DebugLevel)
|
||||||
case unknown ⇒ None
|
case unknown ⇒ None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,12 +95,12 @@ A custom ``application.conf`` might look like this::
|
||||||
|
|
||||||
# Log level used by the configured loggers (see "loggers") as soon
|
# Log level used by the configured loggers (see "loggers") as soon
|
||||||
# as they have been started; before that, see "stdout-loglevel"
|
# as they have been started; before that, see "stdout-loglevel"
|
||||||
# Options: ERROR, WARNING, INFO, DEBUG
|
# Options: OFF, ERROR, WARNING, INFO, DEBUG
|
||||||
loglevel = DEBUG
|
loglevel = "DEBUG"
|
||||||
|
|
||||||
# Log level for the very basic logger activated during AkkaApplication startup
|
# 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
|
stdout-loglevel = "DEBUG"
|
||||||
|
|
||||||
actor {
|
actor {
|
||||||
default-dispatcher {
|
default-dispatcher {
|
||||||
|
|
@ -222,11 +222,11 @@ from the whole class path, it is easiest to utilize that functionality and
|
||||||
differentiate actor systems within the hierarchy of the configuration::
|
differentiate actor systems within the hierarchy of the configuration::
|
||||||
|
|
||||||
myapp1 {
|
myapp1 {
|
||||||
akka.loglevel = WARNING
|
akka.loglevel = "WARNING"
|
||||||
my.own.setting = 43
|
my.own.setting = 43
|
||||||
}
|
}
|
||||||
myapp2 {
|
myapp2 {
|
||||||
akka.loglevel = ERROR
|
akka.loglevel = "ERROR"
|
||||||
app2.setting = "appname"
|
app2.setting = "appname"
|
||||||
}
|
}
|
||||||
my.own.setting = 42
|
my.own.setting = 42
|
||||||
|
|
@ -245,15 +245,17 @@ system is this
|
||||||
|
|
||||||
.. code-block:: ruby
|
.. code-block:: ruby
|
||||||
|
|
||||||
akka.loglevel = WARNING
|
akka.loglevel = "WARNING"
|
||||||
my.own.setting = 43
|
my.own.setting = 43
|
||||||
my.other.setting = "hello"
|
my.other.setting = "hello"
|
||||||
// plus myapp1 and myapp2 subtrees
|
// plus myapp1 and myapp2 subtrees
|
||||||
|
|
||||||
while in the second one, only the “akka” subtree is lifted, with the following
|
while in the second one, only the “akka” subtree is lifted, with the following
|
||||||
result::
|
result
|
||||||
|
|
||||||
akka.loglevel = ERROR
|
.. code-block:: ruby
|
||||||
|
|
||||||
|
akka.loglevel = "ERROR"
|
||||||
my.own.setting = 42
|
my.own.setting = 42
|
||||||
my.other.setting = "hello"
|
my.other.setting = "hello"
|
||||||
// plus myapp1 and myapp2 subtrees
|
// plus myapp1 and myapp2 subtrees
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ You almost definitely need to have logging set to DEBUG to use any of the option
|
||||||
.. code-block:: ruby
|
.. code-block:: ruby
|
||||||
|
|
||||||
akka {
|
akka {
|
||||||
loglevel = DEBUG
|
loglevel = "DEBUG"
|
||||||
}
|
}
|
||||||
|
|
||||||
This config option is very good if you want to know what config settings are loaded by Akka:
|
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`.
|
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
|
Loggers
|
||||||
=======
|
=======
|
||||||
|
|
@ -167,7 +181,7 @@ Here you can also define the log level.
|
||||||
# Loggers to register at boot time (akka.event.Logging$DefaultLogger logs
|
# Loggers to register at boot time (akka.event.Logging$DefaultLogger logs
|
||||||
# to STDOUT)
|
# to STDOUT)
|
||||||
loggers = ["akka.event.Logging$DefaultLogger"]
|
loggers = ["akka.event.Logging$DefaultLogger"]
|
||||||
# Options: ERROR, WARNING, INFO, DEBUG
|
# Options: OFF, ERROR, WARNING, INFO, DEBUG
|
||||||
loglevel = "DEBUG"
|
loglevel = "DEBUG"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -618,7 +618,7 @@ All these messages are logged at ``DEBUG`` level. To summarize, you can enable
|
||||||
full logging of actor activities using this configuration fragment::
|
full logging of actor activities using this configuration fragment::
|
||||||
|
|
||||||
akka {
|
akka {
|
||||||
loglevel = DEBUG
|
loglevel = "DEBUG"
|
||||||
actor {
|
actor {
|
||||||
debug {
|
debug {
|
||||||
autoreceive = on
|
autoreceive = on
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ object FaultHandlingDocSample extends App {
|
||||||
import Worker._
|
import Worker._
|
||||||
|
|
||||||
val config = ConfigFactory.parseString("""
|
val config = ConfigFactory.parseString("""
|
||||||
akka.loglevel = DEBUG
|
akka.loglevel = "DEBUG"
|
||||||
akka.actor.debug {
|
akka.actor.debug {
|
||||||
receive = on
|
receive = on
|
||||||
lifecycle = on
|
lifecycle = on
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ You almost definitely need to have logging set to DEBUG to use any of the option
|
||||||
.. code-block:: ruby
|
.. code-block:: ruby
|
||||||
|
|
||||||
akka {
|
akka {
|
||||||
loglevel = DEBUG
|
loglevel = "DEBUG"
|
||||||
}
|
}
|
||||||
|
|
||||||
This config option is very good if you want to know what config settings are loaded by Akka:
|
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
|
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.
|
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
|
Loggers
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
|
@ -210,7 +225,7 @@ also define the log level.
|
||||||
# Loggers to register at boot time (akka.event.Logging$DefaultLogger logs
|
# Loggers to register at boot time (akka.event.Logging$DefaultLogger logs
|
||||||
# to STDOUT)
|
# to STDOUT)
|
||||||
loggers = ["akka.event.Logging$DefaultLogger"]
|
loggers = ["akka.event.Logging$DefaultLogger"]
|
||||||
# Options: ERROR, WARNING, INFO, DEBUG
|
# Options: OFF, ERROR, WARNING, INFO, DEBUG
|
||||||
loglevel = "DEBUG"
|
loglevel = "DEBUG"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -698,7 +698,7 @@ All these messages are logged at ``DEBUG`` level. To summarize, you can enable
|
||||||
full logging of actor activities using this configuration fragment::
|
full logging of actor activities using this configuration fragment::
|
||||||
|
|
||||||
akka {
|
akka {
|
||||||
loglevel = DEBUG
|
loglevel = "DEBUG"
|
||||||
actor {
|
actor {
|
||||||
debug {
|
debug {
|
||||||
receive = on
|
receive = on
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue