Оглавление

Логгирование в 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". Его содержимое будет таким (откроется в новом окне).