среда, 1 августа 2012 г.

module: log4j

    В мире Java популярны такие системы логирования:
    - Log4J
    - java.util.Logging
    - Apache Commons Logging
    - SLF4J
    - Logback

    Процесс логгирования административно разделен на два независимых модуля:
    - инструментирование кода вызовами логгера
        - выбрать с какими именами получать логгеры
        - выбрать с какими уровнями логгирования генерировать событие
        - выбрать какое сообщение генерировать
    - внешняя настройка логгирования
        - выбрать appenders, layouts для сбора и переработки LogEvents-ов

    После курса должны уметь
    Понимать роль логгирования в корпоративных проектах.
    Уметь сравнить java.util.logging и Log4J.
    Подключать Log4J к проекту.
    Получать instance логгера для конкретного класса.
package a.b.c;

public class Foo {
    private final static Logger logger = Logger.getLogger(Foo.class);
    Понимать концепцию named logger hierarchy.
    Понимать концепцию root logger.    
    Оптимизировать отключенный вывод.
if(logger.isDebugEnabled()) {
    logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
    Понимать иерархию уровней логгирования (trace, debug, info, warn, error, fatal) и как в нее можно вклиниться - Logger.log(Level l, Object msg). TRACE < DEBUG < INFO < WARN < ERROR < FATAL.
    Уметь настроить PatternMatcher.
    Уметь настроить DailyRollingAppender.
    Уметь конфигурировать Log4J из property-файла и из xml-файла. Понимать отличия.
    Понимать, что именование логгеров полными именами классов - это договоренность, а не обязательство.
    Должны понимать, что значит "Log4j uses JavaBeans style configuration".
    Вы умеете настраивать PatternLayout в объеме - имя класса, имя метода, имя логгера, время события, Level события, текст сообщения.

    После курса должны уметь (advanced)
    Уметь сравнить и понимать разницу между Apache Commons Logging, java.util.logging, Log4J 1.x, Log4J 2, Logback и SLF4J.
    Понимать и к месту использовать концепцию nested diagnostic context (NDC).
    Понимать концепцию inherited level.

    Шаблоны в Log4J


    From "Short introduction to Log4J":

    Log4j has three main components: loggers, appenders and layouts. These three types of components work together to enable developers to log messages according to message type and level, and to control at runtime how these messages are formatted and where they are reported.

    Logger named hierarchy
    The first and foremost advantage of any logging API over plain System.out.println resides in its ability to disable certain log statements while allowing others to print unhindered. This capability assumes that the logging space, that is, the space of all possible logging statements, is categorized according to some developer-chosen criteria.
    A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.
    For example, the logger named "com.foo" is a parent of the logger named "com.foo.Bar". Similarly, "java" is a parent of "java.util" and an ancestor of "java.util.Vector".
    The root logger resides at the top of the logger hierarchy. It is exceptional in two ways:
    - it always exists,
    - it cannot be retrieved by name.

    Invoking the class static Logger.getRootLogger() method retrieves it. All other loggers are instantiated and retrieved with the class static Logger.getLogger(...) method. This method takes the name of the desired logger as a parameter.

    Level Inheritance
    If a given logger is not assigned a level, then it inherits one from its closest ancestor with an assigned level. More formally:
    The inherited level for a given logger C, is equal to the first non-null level in the logger hierarchy, starting at C and proceeding upwards in the hierarchy towards the root logger.

    Basic Selection Rule
    A logging request is said to be enabled if its level is higher than or equal to the level of its logger. Otherwise, the request is said to be disabled. A logger without an assigned level will inherit one from the hierarchy. This rule is summarized below.
    A log request of level p in a logger with (either assigned or inherited, whichever is appropriate) level q, is enabled if p >= q.

    Layout / formatters
    Pattern Converter
hierarchical loggers == named logger hierarchy

    From Log4J 1.2 FAQ:

    Is log4j a reliable logging system?
    No. log4j is not reliable. It is a best-effort fail-stop logging system.
    By fail-stop, we mean that log4j will not throw unexpected exceptions at run-time potentially causing your application to crash. 
    Moreover, log4j will not revert to System.out or System.err when its designated output stream is not opened, is not writable or becomes full. This avoids corrupting an otherwise working program by flooding the user's terminal because logging fails. However, log4j will output a single message to System.err indicating that logging can not be performed.

    What are the features of log4j?
    Log4j is optimized for speed.
    Log4j is based on a named logger hierarchy.
    Log4j is fail-stop. However, altough it certainly strives to ensure delivery, log4j does not guarantee that each log statement will be delivered to its destination.
    Log4j is thread-safe.
    Log4j is not restricted to a predefined set of facilities.
    Logging behavior can be set at runtime using a configuration file. Configuration files can be property files or in XML format.
    Log4j is designed to handle Java Exceptions from the start.
    Log4j can direct its output to a file, the console, an java.io.OutputStream, java.io.Writer, a remote server using TCP, a remote Unix Syslog daemon, to a remote listener using JMS, to the NT EventLog or even send e-mail.
    Log4j uses 6 levels, namely TRACE, DEBUG, INFO, WARN, ERROR and FATAL.
    The format of the log output can be easily changed by extending the Layout class.
    The target of the log output as well as the writing strategy can be altered by implementations of the Appender interface.
    Log4j supports multiple output appenders per logger.
    Log4j supports internationalization.

    Are there any suggested ways for naming loggers?
    Yes, there are.
    You can name loggers by locality. It turns out that instantiating a logger in each class, with the logger name equal to the fully-qualified name of the class, is a useful and straightforward approach of defining loggers. This approach has many benefits:
    - It is very simple to implement.
    - It is very simple to explain to new developers.
    - It automatically mirrors your application's own modular design.
    - It can be further refined at will.
    - Printing the logger automatically gives information on the locality of the log statement.
    However, this is not the only way for naming loggers. A common alternative is to name loggers by functional areas. For example, the "database" logger, "RMI" logger, "security" logger, or the "XML" logger.
    You may choose to name loggers by functionality and subcategorize by locality, as in "DATABASE.com.foo.some.package.someClass" or "DATABASE.com.foo.some.other.package.someOtherClass".
    You are totally free in choosing the names of your loggers. The log4j package merely allows you to manage your names in a hierarchy. However, it is your responsibility to define this hierarchy.
    Note by naming loggers by locality one tends to name things by functionality, since in most cases the locality relates closely to functionality.

    What are the configurable options for FooBarAppender?
    Log4j uses JavaBeans style configuration.
    Thus, any setter method in FooBarAppender corresponds to a configurable option. For example, in RollingFileAppender the setMaxBackupIndex(int maxBackups) method corresponds to the maxBackupIndex option. The first letter of the option can be upper case, i.e. MaxBackupIndex and maxBackupIndex are equivalent but not MAXBACKUPIndex nor mAXBackupIndex.
    Layouts options are also defined by their setter methods. The same goes for most other log4j components.


    Напишите код, логгирующий в файл при помощи простого FileAppender. Замерьте время на вызов 10.000 Logger.log(...). Поставьте перед FileLogger асинхронный логгер AsyncLogger. Замерьте время теперь.

    Напишите код использующий SMTPAppender. Пусть все сообщения уровня WARN и выше приходят на ваш e-mail с темой "С проектом проблемы: " + errorMsg. Пусть все сообщения уровня FATAL и выше приходят на ваш e-mail с темой "СРОЧНО!!! FATAL!!! С проектом проблемы: " + errorMsg. В качестве "базового" SMTP сервера возьмите gmail.com

    Настройте DaylyRollingAppander (или допишите) на создание нового файла каждый час или если более 1Кб.

    Исследуйте и попробуйте какой-нибудь инструмент для поиска по логам Log4j.

    Напишите код использующий:
    1) NDC
    2) MDC

    Какой аппендер пишет в 2 аппендера? Вначале в первый, при сбое первого - во второй.