Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации

Краткий обзор Журналирования Java™

Последнее обновление 26 ноября 2001

1.0 Краткий обзор Журналирования Java
    1.1 Краткий обзор Потока управления
    1.2 Уровни журнала
    1.3 Регистраторы
    1.4 Журналирование Методов
    1.5 Обработчики
    1.6 Средства форматирования
    1.7 LogManager
    1.8 Конфигурационный файл
    1.9 Конфигурация по умолчанию
    1.10 Динамических Обновления Конфигурации
    1.11 Собственных Метода
    1.12 DTD XML
    1.13 Уникальных ID сообщения
    1.14 Безопасности
    1.15 управления конфигурацией
    1.16 Упаковки
    1.17 Локализации
    1.18 Удаленных доступа и Сериализация
2.0 Примеры
    2.1 Простое Использование
    2.2 Изменение Конфигурации
    2.3 Простое Использование, Игнорируя Глобальную Конфигурацию
    2.4 Демонстрационный XML Вывод
3.0 Приложение A: DTD для Вывода XMLFormatter

1.0 Краткий обзор Журналирования Java

API журналирования описываются подробно в Java Спецификация API SE. Цель этого документа состоит в том, чтобы обеспечить краткий обзор основных элементов.

1.1 Краткий обзор Потока управления

Приложения делают запросы журналирования к объектам Регистратора. Регистраторы организуются в иерархическом пространстве имен, и дочерние Регистраторы могут наследовать некоторые свойства журналирования от своих родителей в пространстве имен.

Приложения делают запросы журналирования к объектам Регистратора. Эти объекты Регистратора выделяют объекты LogRecord, которые передают к Объектам-обработчикам для публикации. И Регистраторы и Обработчики могут использовать Уровни журналирования и (дополнительно) Фильтры, чтобы решить, интересуются ли они определенным LogRecord. Когда необходимо опубликовать LogRecord внешне, Обработчик может (дополнительно) использовать Средство форматирования, чтобы локализовать и отформатировать сообщение прежде, чем опубликовать это к потоку ввода-вывода.

Предыдущий контекст описывает эту графику

Каждый Регистратор отслеживает ряд выходных Обработчиков. По умолчанию все Регистраторы также отправляют свой вывод их родительскому Регистратору. Но Регистраторы могут также быть сконфигурированы, чтобы проигнорировать Обработчики выше дерево.

Некоторые Обработчики могут направить вывод к другим Обработчикам. Например, MemoryHandler поддерживает внутренний кольцевой буфер LogRecords, и на триггерных событиях это публикует свой LogRecords через целевой Обработчик. В таких случаях любое форматирование делается последним Обработчиком в цепочке.

Предыдущий контекст описывает эту графику

API структурируются так, чтобы запросы к API Регистратора могли быть дешевыми, когда журналирование отключается. Если журналирование отключается для данного уровня журнала, то Регистратор может сделать дешевый тест сравнения и возврат. Если журналирование включается для данного уровня журнала, Регистратор все еще делает все возможное минимизировать затраты прежде, чем передать LogRecord в Обработчики. В частности локализация и форматирующий (которые относительно дороги) задерживается, пока Обработчик не запрашивает их. Например, MemoryHandler может поддержать круговой буфер LogRecords, не имея необходимость платить затраты форматирования.

1.2 Уровни журнала

У каждого сообщения журнала есть связанный Уровень журнала. Уровень дает грубое руководство по важности и безотлагательности сообщения журнала. Объекты уровня журнала инкапсулируют целочисленное значение с более высокими значениями, указывающими на более высокие приоритеты.

Класс Level определяет семь стандартных уровней журнала, в пределах от САМОГО ПРЕКРАСНОГО (самый низкий приоритет, с самым низким значением) к СЕРЬЕЗНОМУ (самый высокий приоритет, с самым высоким значением).

1.3 Регистраторы

Как утверждено ранее, клиентский код отправляет запросы журнала объектам Регистратора. Каждый регистратор отслеживает уровень журнала, что он интересуется, и отбрасывает запросы журнала, которые являются ниже этого уровня.

Регистраторы обычно являются именованными сущностями, используя разделенные от точки имена, такие как "java.awt". Пространство имен является иерархическим и управляется LogManager. Пространство имен должно обычно быть выровненное пространства имен упаковки Java, но не обязано следовать за ним по-рабски. Например, Регистратор, названный "java.awt", мог бы обработать запросы журналирования на классы в java.awt пакете, но это могло бы также обработать журналирование для классов в sun.awt, которые поддерживают видимые клиентом абстракции, определенные в java.awt пакете.

В дополнение к именованным Регистраторам также возможно создать анонимные Регистраторы, которые не появляются в совместно используемом пространстве имен. См. раздел 1.14.

Регистраторы отслеживают свои родительские регистраторы в пространстве имен журналирования. Родитель регистратора является своим самым близким существующим предком в пространстве имен журналирования. У корневого Регистратора (названный"") нет никакого родителя. Анонимным регистраторам все дают корневой регистратор как их родитель. Регистраторы могут наследовать различные атрибуты от своих родителей в пространстве имен регистратора. В частности регистратор может наследоваться:

1.4 Журналирование Методов

Класс Регистратора обеспечивает большой набор методов удобства для того, чтобы генерировать сообщения журнала. Для удобства есть методы для каждого уровня журналирования, названного в честь имени уровня журналирования. Таким образом вместо того, чтобы вызвать "logger.log (Уровень. ПРЕДУПРЕЖДАЯ..." разработчик может просто вызвать метод удобства "logger.warning (..."

Есть два различных стиля журналирования методов, чтобы удовлетворить потребности различных сообществ пользователей.

Во-первых, есть методы, которые берут явное исходное имя класса и исходное имя метода. Эти методы предназначаются для разработчиков, которые хотят быть в состоянии быстро определить местоположение источника любого данного журналирования сообщения. Пример этого стиля:

void warning(String sourceClass, String sourceMethod, String msg);

Во-вторых, есть ряд методов, которые не берут явный исходный класс или исходные имена методов. Они предназначаются для разработчиков, которые хотят удобное в работе журналирование и не запрашивают детализированную исходную информацию.

void warning(String msg);

Для этого второго набора методов платформа Журналирования сделает "максимальные усилия", чтобы определить, какой класс и метод, вызванный в платформу журналирования и, добавит эту информацию в LogRecord. Однако, важно понять, что эта автоматически выведенная информация может только быть приблизительной. Последняя генерация виртуальных машин выполняет обширную оптимизацию, когда JITing и может полностью удалить стековые фреймы, лишая возможности достоверно определять местоположение класса вызова и метода.

1.5 Обработчики

Java SE обеспечивает следующие Обработчики:

Это довольно прямо, чтобы разработать новые Обработчики. Разработчики, требующие определенной функциональности, могут или разработать Обработчик с нуля или разделить один на подклассы из обеспеченных Обработчиков.

1.6 Средства форматирования

Java SE также включает два стандартных Средства форматирования:

Как с Обработчиками, это довольно прямо, чтобы разработать новые Средства форматирования.

1.7 LogManager

Есть глобальный объект LogManager, который отслеживает глобальную информацию о журналировании. Это включает:

Есть единственный объект LogManager, который может быть получен, используя статический метод LogManager.getLogManager. Это создается во время инициализации LogManager, основанной на системном свойстве. Это свойство позволяет приложениям-контейнерам (таким как контейнеры EJB) заменять своим собственным подклассом LogManager вместо класса по умолчанию.

1.8 Конфигурационный файл

Конфигурация журналирования может быть инициализирована, используя конфигурационный файл журналирования, который будет считан при запуске. Этот конфигурационный файл журналирования находится в стандарте java.util. Формат свойств.

Альтернативно, конфигурация журналирования может быть инициализирована, определяя класс, который может использоваться для того, чтобы считать свойства инициализации. Этот механизм позволяет данным конфигурации быть считанными из произвольных источников, таких как LDAP, JDBC, и т.д. См. Спецификацию API LogManager для деталей.

Есть маленький набор глобальной конфигурационной информации. Это определяется в описании класса LogManager и включает список Обработчиков на корневом уровне, чтобы установить во время запуска.

Начальная конфигурация может определить уровни для определенных регистраторов. Эти уровни применяются к именованному регистратору и любым регистраторам ниже его в иерархии именования. Уровни применяются в порядке, они определяются в конфигурационном файле.

Начальная конфигурация может содержать произвольные свойства для использования Обработчиками или подсистемами, делающими журналирование. Условно эти свойства должны использовать имена, запускающиеся с имени класса обработчика или имени основного Регистратора для подсистемы.

Например, MemoryHandler использует свойство "java.util.logging. MemoryHandler.size", чтобы определить размер по умолчанию для его кольцевого буфера.

1.9 Конфигурация по умолчанию

Конфигурация журналирования значения по умолчанию, которая поставляет с JRE, является только значением по умолчанию, и может быть переопределена ISV, системными администраторами, и конечными пользователями.

Конфигурация по умолчанию делает только ограниченное использование дискового пространства. Это не лавинно рассылает пользователя с информацией, но действительно удостоверяется, что всегда получило ключевую информацию об отказе.

Конфигурация по умолчанию устанавливает единственный обработчик на корневом регистраторе для того, чтобы отправить вывод консоли.

1.10 Динамических Обновления Конфигурации

Программисты могут обновить конфигурацию журналирования во время выполнения во множестве путей:

1.11 Собственных Метода

Нет никаких встроенных API для того, чтобы зарегистрировать.

Собственный код, который хочет использовать механизмы Журналирования Java, должен выполнить нормальные вызовы JNI в API Журналирования Java.

1.12 DTD XML

DTD XML, используемый XMLFormatter, определяется в Приложении A.

DTD разрабатывается с" <журнал>" элемент как высокоуровневый документ. Отдельные записи журнала тогда пишутся как" <запись>" элементы.

Отметьте, что в случае катастрофических отказов JVM, возможно, не возможно чисто завершить поток XMLFormatter с соответствующим закрытием </журнал>. Поэтому инструменты, которые анализируют записи журнала, должны быть подготовлены справиться с незавершенными потоками.

1.13 Уникальных ID сообщения

API Журналирования Java не оказывают прямой поддержки для уникальных ID сообщения. Те приложения или подсистемы, требующие уникальных ID сообщения, должны определить свои собственные соглашения и включать уникальные ID в строки сообщения как соответствующие.

1.14 Безопасности

Основное требование к защите состоит в том, что недоверяемый код не должен быть в состоянии изменить конфигурацию журналирования. Определенно, если конфигурация журналирования была установлена, чтобы зарегистрировать определенную категорию информации к определенному Обработчику, то недоверяемый код не должен быть в состоянии предотвратить или разрушить то журналирование.

Новое право доступа LoggingPermission определяется, чтобы управлять обновлениями к конфигурации журналирования.

Доверяемым приложениям дают соответствующий LoggingPermission, таким образом, они могут вызвать любой из API конфигурации журналирования. Недоверяемые апплеты являются другой историей. Недоверяемые апплеты могут создать и использовать названные Регистраторы нормальным способом, но им не позволяют изменить настройки управления журналированием, такие как добавление или удаление обработчиков, или изменение уровней журнала. Однако, недоверяемые апплеты в состоянии создать и использовать их собственные "анонимные" регистраторы, используя Logger.getAnonymousLogger. Эти анонимные Регистраторы не регистрируются в глобальном пространстве имен, и их методы не проверяются в доступе, позволяя даже недоверяемый код изменить их настройки управления журналированием.

Платформа журналирования не пытается предотвратить спуфинг. Источники журналирования вызовов не могут быть определены достоверно, так, когда LogRecord публикуется, что требования быть от определенного исходного класса и исходного метода, это может быть производство. Точно так же средства форматирования, такие как XMLFormatter не пытаются защитить себя от вложенных сообщений журнала в строках сообщения. Таким образом, имитация, LogRecord мог бы содержать набор имитации XML в его строке сообщения, чтобы заставить это смотреть, как будто была дополнительная запись XML в выводе.

Кроме того, платформа журналирования не пытается защитить себя от атак "отказ в обслуживании". Любое данное журналирование клиента может лавинно разослать платформу журналирования с бессмысленными сообщениями в попытке скрыть некоторое важное сообщение журнала.

1.15 управления конфигурацией

API структурируются так, чтобы начальный набор конфигурационной информации был считан как свойства из конфигурационного файла. Конфигурационная информация может тогда быть изменена programatically запросами к различным классам журналирования и объектам.

Кроме того, есть методы на LogManager, которые позволяют конфигурационному файлу быть перечитанным. Когда это произойдет, значения конфигурационного файла переопределят любые изменения, которые были произведены programatically.

1.16 Упаковки

Весь класс журналирования находится в части Java * пространства имен в java.util.logging пакете.

1.17 Локализации

Сообщения журнала, возможно, должны быть локализованы.

У каждого Регистратора может быть имя Пакета Ресурса, связанное с этим. Соответствующий Пакет Ресурса может использоваться, чтобы отобразиться между необработанными строками сообщения и локализованными строками сообщения.

Обычно локализация будет выполняться Средствами форматирования. Как удобство, класс средства форматирования обеспечивает formatMessage метод, который обеспечивает некоторую основную локализацию и форматирующий поддержку.

1.18 Удаленных доступа и Сериализация

Как с большинством API платформы Java, API журналирования разрабатываются для использования в единственном адресном пространстве. Все вызовы предназначаются, чтобы быть локальными. Однако, ожидается, что некоторые Обработчики будут хотеть направить свои выходные данные к другим системам. Есть множество способов сделать это:

Некоторые Обработчики (такие как SocketHandler) могут записать данные в другие системы, используя XMLFormatter. Это обеспечивает простой, стандартный, формат обмена, который может быть проанализирован и обработан на множестве систем.

Некоторые Обработчики могут хотеть передать объекты LogRecord по RMI. Класс LogRecord поэтому сериализуем. Однако есть проблема в том, как иметь дело с параметрами LogRecord. Некоторые параметры, возможно, не сериализуемы, и другие параметры, возможно, были разработаны, чтобы сериализировать намного больше состояния, чем требуется для того, чтобы зарегистрировать. Чтобы избежать этих проблем, у класса LogRecord есть пользовательский writeObject метод, который преобразовывает параметры в строки (использующий Object.toString ()) перед выписыванием их. См. Спецификацию API LogRecord для деталей.

Большинство классов журналирования не предназначается, чтобы быть сериализуемым. И Регистраторы и Обработчики являются stateful классами, которые связываются в определенную виртуальную машину. В этом отношении они походят на java.io классы, которые также не сериализуемы.

2.0 Примеры

2.1 Простое Использование

Следующее является маленькой программой, которая выполняет журналирование, используя конфигурацию по умолчанию.

Эта программа полагается на корневые обработчики, которые были установлены LogManager, основанным на конфигурационном файле. Это создает свой собственный объект Регистратора и затем делает звонки в тот объект Регистратора сообщить о различных событиях.

package com.wombat;
import java.util.logging.*;

public class Nose{
    // Obtain a suitable logger.
    private static Logger logger = Logger.getLogger("com.wombat.nose");
    public static void main(String argv[]) {
        // Log a FINE tracing message
        logger.fine("doing stuff");
        try{
            Wombat.sneeze();
        } catch (Exception ex) {
            // Log the exception
            logger.log(Level.WARNING, "trouble sneezing", ex);
        }
        logger.fine("done");
    }
}

2.2 Изменение Конфигурации

Вот маленькая программа, которая динамически корректирует конфигурацию журналирования, чтобы отправить вывод определенному файлу и получить большую информацию о вомбатах. Образец "%t" означает систему временный каталог.

public static void main(String[] args) {
    Handler fh = new FileHandler("%t/wombat.log");
    Logger.getLogger("").addHandler(fh);
    Logger.getLogger("com.wombat").setLevel(Level.FINEST);
    ...
}

2.3 Простое Использование, Игнорируя Глобальную Конфигурацию

Вот маленькая программа, которая устанавливает ее собственный Обработчик журналирования и игнорирует глобальную конфигурацию.

package com.wombat;

import java.util.logging.*;

public class Nose {
    private static Logger logger = Logger.getLogger("com.wombat.nose");
    private static FileHandler fh = new FileHandler("mylog.txt");
    public static void main(String argv[]) {
        // Send logger output to our FileHandler.
        logger.addHandler(fh);
        // Request that every detail gets logged.
        logger.setLevel(Level.ALL);
        // Log a simple INFO message.
        logger.info("doing stuff");
        try {
            Wombat.sneeze();
        } catch (Exception ex) {
            logger.log(Level.WARNING, "trouble sneezing", ex);
        }
        logger.fine("done");
    }
}

2.4 Демонстрационный XML Вывод

Вот небольшая выборка того, на что похож некоторый вывод XML XMLFormatter:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2000-08-23 19:21:05</date>
  <millis>967083665789</millis>
  <sequence>1256</sequence>
  <logger>kgh.test.fred</logger>
  <level>INFO</level>
  <class>kgh.test.XMLTest</class>
  <method>writeLog</method>
  <thread>10</thread>
  <message>Hello world!</message>
</record>
</log>

3.0 Приложение A: DTD для Вывода XMLFormatter

<!-- DTD used by the java.util.logging.XMLFormatter -->
<!-- This provides an XML formatted log message. -->

<!-- The document type is "log" which consists of a sequence
of record elements -->
<!ELEMENT log (record*)>

<!-- Each logging call is described by a record element. -->
<!ELEMENT record (date, millis, sequence, logger?, level,
class?, method?, thread?, message, key?, catalog?, param*, exception?)>

<!-- Date and time when LogRecord was created in ISO 8601 format -->
<!ELEMENT date (#PCDATA)>

<!-- Time when LogRecord was created in milliseconds since
midnight January 1st, 1970, UTC. -->
<!ELEMENT millis (#PCDATA)>

<!-- Unique sequence number within source VM. -->
<!ELEMENT sequence (#PCDATA)>

<!-- Name of source Logger object. -->
<!ELEMENT logger (#PCDATA)>

<!-- Logging level, may be either one of the constant
names from java.util.logging.Level (such as "SEVERE"
or "WARNING") or an integer value such as "20". -->
<!ELEMENT level (#PCDATA)>

<!-- Fully qualified name of class that issued
logging call, e.g. "javax.marsupial.Wombat". -->
<!ELEMENT class (#PCDATA)>

<!-- Name of method that issued logging call.
It may be either an unqualified method name such as
"fred" or it may include argument type information
in parenthesis, for example "fred(int,String)". -->
<!ELEMENT method (#PCDATA)>

<!-- Integer thread ID. -->
<!ELEMENT thread (#PCDATA)>

<!-- The message element contains the text string of a log message. -->
<!ELEMENT message (#PCDATA)>

<!-- If the message string was localized, the key element provides
the original localization message key. -->
<!ELEMENT key (#PCDATA)>

<!-- If the message string was localized, the catalog element provides
the logger's localization resource bundle name. -->
<!ELEMENT catalog (#PCDATA)>

<!-- If the message string was localized, each of the param elements
provides the String value (obtained using Object.toString())
of the corresponding LogRecord parameter. -->
<!ELEMENT param (#PCDATA)>

<!-- An exception consists of an optional message string followed
by a series of StackFrames. Exception elements are used
for Java exceptions and other java Throwables. -->
<!ELEMENT exception (message?, frame+)>

<!-- A frame describes one line in a Throwable backtrace. -->
<!ELEMENT frame (class, method, line?)>

<!-- an integer line number within a class's source file. -->
<!ELEMENT line (#PCDATA)>

Oracle и/или его филиалы Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами