Логгирование в Java с помощью java.util.logging
Простой пример записи лога с использованием java.util.logging
Запись лога в формате HTML. Пишем свой java.util.logging.Formatter
Простой пример записи лога с использованием java.util.logging
С помощью классов расположенных в java.util.logging вы легко можете добавить протоколирование (запись логов/логгирование) в Java. Причём вы можете управлять форматом вывода (XML/HTML/сокеты и т. д.).
Посмотрите на пример простой программы с записью лога:
package temp;
import java.io.IOException;
import java.util.logging.*;
/**
* Пример программы с использованием java.util.logging.
* @author Урванов Ф. В.
*
*/
public class LogApp {
/**
* Старт программы
* @param args не используется
*/
public static void main(String[] args)
{
// Получаем экземпляр класса, который будем использовать для записи логов.
// Передаваемый параметр LogApp - имя логера.
// В документации сказано, что имя логгера должно совпадать с именем
// класса или пакета ().
Logger logger = Logger.getLogger(LogApp.class.getName());
// Создаём handler, который будет записывать лог
// в файл "LogApp". Символ "%t" указывает на то, что файл
// будет располагаться в папке с системными временными файлами.
try {
FileHandler fh = new FileHandler("%tLogApp");
logger.addHandler(fh);
} catch (SecurityException e) {
logger.log(Level.SEVERE,
"Не удалось создать файл лога из-за политики безопасности.",
e);
} catch (IOException e) {
logger.log(Level.SEVERE,
"Не удалось создать файл лога из-за ошибки ввода-вывода.",
e);
}
logger.log(Level.INFO, "Запись лога с уровнем INFO (информационная)");
logger.log(Level.WARNING,"Запись лога с уровнем WARNING (Предупреждение)");
logger.log(Level.SEVERE, "Запись лога с уровнем SEVERE (серъёзная ошибка)");
}
}
Как видите ничего сложного тут нет. Вы просто создаёте (или получаете, если он уже создан) экземпляр класса java.util.logging.Logger. Потом пишите лог с его помощью.
Приведённый выше пример пишет лог в файл LogApp. Если вы его откроете (В Linux он будет располагаться где-то в /tmp/LogApp), то увидите следущий текст:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE log SYSTEM "logger.dtd"> <log> <record> <date>2011-06-27T18:48:52</date> <millis>1309186132015</millis> <sequence>0</sequence> <logger>temp.LogApp</logger> <level>INFO</level> <class>temp.LogApp</class> <method>main</method> <thread>10</thread> <message>Запись лога с уровнем INFO (информационная)</message> </record> <record> <date>2011-06-27T18:48:52</date> <millis>1309186132111</millis> <sequence>1</sequence> <logger>temp.LogApp</logger> <level>WARNING</level> <class>temp.LogApp</class> <method>main</method> <thread>10</thread> <message>Запись лога с уровнем WARNING (Предупреждение)</message> </record> <record> <date>2011-06-27T18:48:52</date> <millis>1309186132111</millis> <sequence>2</sequence> <logger>temp.LogApp</logger> <level>SEVERE</level> <class>temp.LogApp</class> <method>main</method> <thread>10</thread> <message>Запись лога с уровнем SEVERE (серъёзная ошибка)</message> </record> </log>
По крайней мере у меня получился именно такой файл.
Запись лога в формате HTML. Пишем свой java.util.logging.Formatter
А что делать, если хочется лог в формате HTML? Всё очень просто. Вам нужно написать ещё один небольшой класс, отнаследовав его от java.util.logging.Formatter и переопределить в нём методы getHead, getTail и format:
package temp;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
/**
* @author Урванов Ф. В.
* Класс, преобразующий лог в формат HTML.
*
*/
public class HtmlFormatter extends Formatter {
public HtmlFormatter()
{
}
/**
* Возвращаем заголовочную часть HTML файла.
*/
@Override
public String getHead(Handler h)
{
/**
* Записываем заголовок HTML файла, мета информацию и начало таблицы.
*/
return "<html><head><title>AppLog</title>" +
"<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">" +
"</head><body>" +
"<table border=1>" +
"<tr bgcolor=CYAN><td>date</td><td>level</td><td>class</td><td>method</td>" +
"<td>message</td><td>thrown message</td><td>stacktrace</td></tr>";
}
/**
* Возвращаем хвост (конец) HTML файла.
*/
@Override
public String getTail(Handler h)
{
/**
* Записываем окончание таблицы и конец HTML файла.
*/
return "</table></body></html>";
}
/**
* Форматируем одно сообщение в строку таблицы.
*/
@Override
public String format(LogRecord record)
{
StringBuilder result=new StringBuilder();
Date d = new Date();
Level level = record.getLevel();
/**
* Ошибки будут выделены красным цветом,
* предупреждения - серым,
* информационные сообщения - белым.
*/
if (level==Level.SEVERE)
{
result.append("<tr bgColor=Tomato><td>");
}
else if (level==Level.WARNING)
{
result.append("<tr bgColor=GRAY><td>");
}
else
{
result.append("<tr bgColor=WHITE><td>");
}
result.append("\n");
result.append(d);
result.append("</td><td>");
result.append(record.getLevel().toString());
result.append("</td><td>");
result.append(record.getSourceClassName());
result.append("</td><td>");
result.append(record.getSourceMethodName());
result.append("</td><td>");
result.append(record.getMessage());
result.append("</td><td>");
Throwable thrown = record.getThrown();
if (thrown!=null)
{
// Если было передано исключение, то выводим полный
// стек вызовов.
result.append(record.getThrown().getMessage());
result.append("</td><td>");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
record.getThrown().printStackTrace(pw);
String stackTrace=sw.toString();
result.append(stackTrace);
result.append("</td>");
}
else
{
// Просто пустые ячейки.
result.append("</td><td>null");
result.append("</td>");
}
// Конец строки
result.append("</tr>\n");
return result.toString();
}
}
Теперь нужно указать логгеру в какой файл выводить информацию с помощью этого HtmlFormatter. Наш класс LogApp станет выглядеть следующим образом (изменённая часть выделена красным цветом):
package temp;
import java.io.IOException;
import java.util.logging.*;
/**
* Пример программы с использованием java.util.logging.
* @author Урванов Ф. В.
*
*/
public class LogApp {
/**
* Старт программы
* @param args не используется
*/
public static void main(String[] args)
{
// Получаем экземпляр класса, который будем использовать для записи логов.
// Передаваемый параметр LogApp - имя логера.
// В документации сказано, что имя логгера должно совпадать с именем
// класса или пакета ().
Logger logger = Logger.getLogger(LogApp.class.getName());
// Создаём handler, который будет записывать лог
// в файл "LogApp". Символ "%t" указывает на то, что файл
// будет располагаться в папке с системными временными файлами.
try {
// Оставляем предыдущий handler (будет создаваться файл "LogApp")
FileHandler fh = new FileHandler("%tLogApp");
logger.addHandler(fh);
// Добавляем ещё файл "LogApp.htm".
HtmlFormatter htmlformatter = new HtmlFormatter();
FileHandler htmlfile = new FileHandler("%tLogApp.htm");
// Устанавливаем html форматирование с помощью класса HtmlFormatter.
htmlfile.setFormatter(htmlformatter);
logger.addHandler(htmlfile);
} catch (SecurityException e) {
logger.log(Level.SEVERE,
"Не удалось создать файл лога из-за политики безопасности.",
e);
} catch (IOException e) {
logger.log(Level.SEVERE,
"Не удалось создать файл лога из-за ошибки ввода-вывода.",
e);
}
logger.log(Level.INFO, "Запись лога с уровнем INFO (информационная)");
logger.log(Level.WARNING,"Запись лога с уровнем WARNING (Предупреждение)");
logger.log(Level.SEVERE, "Запись лога с уровнем SEVERE (серъёзная ошибка)",
new Exception("Проверочное сообщение об ошибке"));
}
}
В результате в папке с временными файлами будет файл "LogApp.htm". Его содержимое будет таким (откроется в новом окне).