2011-12-13 14:46:15 +01:00
|
|
|
|
.. _logging-scala:
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
2011-12-13 14:46:15 +01:00
|
|
|
|
#################
|
|
|
|
|
|
Logging (Scala)
|
|
|
|
|
|
#################
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
|
|
|
|
|
.. sidebar:: Contents
|
|
|
|
|
|
|
|
|
|
|
|
.. contents:: :local:
|
|
|
|
|
|
|
|
|
|
|
|
How to Log
|
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
|
|
Create a ``LoggingAdapter`` and use the ``error``, ``warning``, ``info``, or ``debug`` methods,
|
2011-12-13 14:46:15 +01:00
|
|
|
|
as illustrated in this example:
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
|
|
|
|
|
.. includecode:: code/akka/docs/event/LoggingDocSpec.scala
|
|
|
|
|
|
:include: my-actor
|
|
|
|
|
|
|
2011-12-13 13:32:58 +01:00
|
|
|
|
For convenience you can mixin the ``log`` member into actors, instead of defining it as above.
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: scala
|
|
|
|
|
|
|
2011-12-14 15:12:40 +01:00
|
|
|
|
class MyActor extends Actor with akka.actor.ActorLogging {
|
2012-01-13 13:50:42 +01:00
|
|
|
|
...
|
|
|
|
|
|
}
|
2011-12-13 13:32:58 +01:00
|
|
|
|
|
2011-12-13 14:46:15 +01:00
|
|
|
|
The second parameter to the ``Logging`` is the source of this logging channel.
|
2011-12-13 12:33:29 +01:00
|
|
|
|
The source object is translated to a String according to the following rules:
|
|
|
|
|
|
|
|
|
|
|
|
* if it is an Actor or ActorRef, its path is used
|
|
|
|
|
|
* in case of a String it is used as is
|
|
|
|
|
|
* in case of a class an approximation of its simpleName
|
2012-01-13 13:50:42 +01:00
|
|
|
|
* and in all other cases a compile error occurs unless and implicit
|
|
|
|
|
|
:class:`LogSource[T]` is in scope for the type in question.
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
2011-12-14 15:12:40 +01:00
|
|
|
|
The log message may contain argument placeholders ``{}``, which will be substituted if the log level
|
2011-12-13 12:33:29 +01:00
|
|
|
|
is enabled.
|
|
|
|
|
|
|
2012-01-13 13:50:42 +01:00
|
|
|
|
Translating Log Source to String and Class
|
|
|
|
|
|
------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
The rules for translating the source object to the source string and class
|
|
|
|
|
|
which are inserted into the :class:`LogEvent` during runtime are implemented
|
|
|
|
|
|
using implicit parameters and thus fully customizable: simply create your own
|
|
|
|
|
|
instance of :class:`LogSource[T]` and have it in scope when creating the
|
|
|
|
|
|
logger.
|
|
|
|
|
|
|
|
|
|
|
|
.. includecode:: code/akka/docs/event/LoggingDocSpec.scala#my-source
|
|
|
|
|
|
|
|
|
|
|
|
This example creates a log source which mimics traditional usage of Java
|
|
|
|
|
|
loggers, which are based upon the originating object’s class name as log
|
|
|
|
|
|
category. The override of :meth:`getClazz` is only included for demonstration
|
|
|
|
|
|
purposes as it contains exactly the default behavior.
|
|
|
|
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
|
|
You may also create the string representation up front and pass that in as
|
|
|
|
|
|
the log source, but be aware that then the :class:`Class[_]` which will be
|
|
|
|
|
|
put in the :class:`LogEvent` is
|
|
|
|
|
|
:class:`akka.event.DummyClassForStringSources`.
|
|
|
|
|
|
|
|
|
|
|
|
The SLF4J event listener treats this case specially (using the actual string
|
|
|
|
|
|
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 loggin adapter.
|
|
|
|
|
|
|
2011-12-13 12:33:29 +01:00
|
|
|
|
Event Handler
|
|
|
|
|
|
=============
|
|
|
|
|
|
|
2012-01-13 13:50:42 +01:00
|
|
|
|
Logging is performed asynchronously through an event bus. You can configure
|
|
|
|
|
|
which event handlers that should subscribe to the logging events. That is done
|
|
|
|
|
|
using the ``event-handlers`` element in the :ref:`configuration`. Here you can
|
|
|
|
|
|
also define the log level.
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
|
|
|
|
|
.. code-block:: ruby
|
|
|
|
|
|
|
|
|
|
|
|
akka {
|
|
|
|
|
|
# Event handlers to register at boot time (Logging$DefaultLogger logs to STDOUT)
|
|
|
|
|
|
event-handlers = ["akka.event.Logging$DefaultLogger"]
|
2011-12-14 15:12:40 +01:00
|
|
|
|
# Options: ERROR, WARNING, INFO, DEBUG
|
|
|
|
|
|
loglevel = "DEBUG"
|
2011-12-13 12:33:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-01-13 13:50:42 +01:00
|
|
|
|
The default one logs to STDOUT and is registered by default. It is not intended
|
|
|
|
|
|
to be used for production. There is also an :ref:`slf4j-scala`
|
2011-12-13 12:33:29 +01:00
|
|
|
|
event handler available in the 'akka-slf4j' module.
|
|
|
|
|
|
|
2011-12-13 14:46:15 +01:00
|
|
|
|
Example of creating a listener:
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
|
|
|
|
|
.. includecode:: code/akka/docs/event/LoggingDocSpec.scala
|
|
|
|
|
|
:include: my-event-listener
|
|
|
|
|
|
|
2011-12-13 14:46:15 +01:00
|
|
|
|
.. _slf4j-scala:
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
|
|
|
|
|
SLF4J
|
|
|
|
|
|
=====
|
|
|
|
|
|
|
2011-12-14 15:12:40 +01:00
|
|
|
|
Akka provides an event handler for `SL4FJ <http://www.slf4j.org/>`_. This module is available in the 'akka-slf4j.jar'.
|
2011-12-13 12:33:29 +01:00
|
|
|
|
It has one single dependency; the slf4j-api jar. In runtime you also need a SLF4J backend, we recommend `Logback <http://logback.qos.ch/>`_:
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: scala
|
|
|
|
|
|
|
|
|
|
|
|
lazy val logback = "ch.qos.logback" % "logback-classic" % "1.0.0" % "runtime"
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-14 15:12:40 +01:00
|
|
|
|
You need to enable the Slf4jEventHandler in the 'event-handlers' element in
|
|
|
|
|
|
the :ref:`configuration`. Here you can also define the log level of the event bus.
|
2011-12-13 12:33:29 +01:00
|
|
|
|
More fine grained log levels can be defined in the configuration of the SLF4J backend
|
2011-12-14 15:12:40 +01:00
|
|
|
|
(e.g. logback.xml). The String representation of the source object that is used when
|
2011-12-13 12:33:29 +01:00
|
|
|
|
creating the ``LoggingAdapter`` correspond to the name of the SL4FJ logger.
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: ruby
|
|
|
|
|
|
|
|
|
|
|
|
akka {
|
|
|
|
|
|
event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
|
|
|
|
|
|
loglevel = "DEBUG"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-01-11 14:14:08 +01:00
|
|
|
|
Logging Thread and Akka Source in MDC
|
|
|
|
|
|
-------------------------------------
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
|
|
|
|
|
Since the logging is done asynchronously the thread in which the logging was performed is captured in
|
|
|
|
|
|
Mapped Diagnostic Context (MDC) with attribute name ``sourceThread``.
|
|
|
|
|
|
With Logback the thread name is available with ``%X{sourceThread}`` specifier within the pattern layout configuration::
|
|
|
|
|
|
|
2011-12-14 15:12:40 +01:00
|
|
|
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
|
|
|
|
|
<layout>
|
|
|
|
|
|
<pattern>%date{ISO8601} %-5level %logger{36} %X{sourceThread} - %msg%n</pattern>
|
|
|
|
|
|
</layout>
|
|
|
|
|
|
</appender>
|
2011-12-13 12:33:29 +01:00
|
|
|
|
|
2012-01-13 13:50:42 +01:00
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
|
|
It will probably be a good idea to use the ``sourceThread`` MDC value also in
|
|
|
|
|
|
non-Akka parts of the application in order to have this property consistently
|
|
|
|
|
|
available in the logs.
|
|
|
|
|
|
|
2012-01-11 14:14:08 +01:00
|
|
|
|
Another helpful facility is that Akka captures the actor’s address when
|
|
|
|
|
|
instantiating a logger within it, meaning that the full instance identification
|
|
|
|
|
|
is available for associating log messages e.g. with members of a router. This
|
|
|
|
|
|
information is available in the MDC with attribute name ``akkaSource``::
|
|
|
|
|
|
|
|
|
|
|
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
|
|
|
|
|
<layout>
|
|
|
|
|
|
<pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} - %msg%n</pattern>
|
|
|
|
|
|
</layout>
|
|
|
|
|
|
</appender>
|
|
|
|
|
|
|
|
|
|
|
|
For more details on what this attribute contains—also for non-actors—please see
|
|
|
|
|
|
`How to Log`_.
|