В прошлом выпуске мы поделились обработкой логов в Java (Часть 1): связанные знания о логах в Java, принцип работы Slf4j и анализ исходного кода
В этом выпуске мы поделимся обработкой логов в Java (ниже)
Во-первых, давайте взглянем на остальную часть протокола журнала в Руководстве по разработке Ali Java и проведем анализ:
- 2. [Обязательно] Рекомендуется сохранять лог-файлы не менее 15 дней, т.к. некоторые исключения имеют характеристики "недельной" периодичности.
анализировать:
- При использовании
Log4j
, И использованиеRollingFileAppender
образом, установивmaxBackupIndex
Атрибут, указывающий максимальное количество файлов журнала, которое необходимо сохранить для косвенного удаления файлов журнала старше N дней.- При использовании
Log4j
, и используяDailyRollingFileAppender
метод, так как этот метод не поддерживаетmaxBackupIndex
, нужно переделатьDailyRollingFileAppender
, поддерживатьmaxBackupIndex
параметр- При использовании
Logback
, можно установитьmaxHistory
Реализовать удаление журналов старше N дней
-
3. [Обязательно] Способ именования расширенных журналов (таких как управление, временный мониторинг, журналы доступа и т.д.) в приложении: appName_logType_logName.log. logType: тип журнала, рекомендуемые категории: статистика/описание/монитор/посещение и т. д.; logName: описание журнала. Преимущество этого именования: вы можете узнать, к какому приложению, какому типу и какой цели принадлежит файл журнала, по имени файла, что также полезно для классификации и поиска. Положительный пример: отслеживайте исключения преобразования часовых поясов отдельно в приложении mppserver, например: mppserver_monitor_timeZoneConvert.log Примечание. Рекомендуется классифицировать журналы, например хранить журналы ошибок и бизнес-журналы отдельно, что удобно разработчикам для своевременного просмотра и мониторинга системы через журналы.
-
4. [Обязательно] Для вывода журнала уровня трассировки/отладки/информации необходимо использовать условный вывод или заполнители. Описание: logger.debug("Обработка сделки с id: " + id + " и symbol: " + symbol); Если уровень лога warn, лог не будет распечатан, но будет выполнена операция конкатенации строк. Если символ является объектом, будет выполнен метод toString(), который тратит ресурсы системы.Вышеуказанные операции выполняются, но окончательный журнал не печатается.
Положительный пример: (условие)
if (logger.isDebugEnabled()) {
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}
Положительный пример: (заполнитель)
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
анализировать:
- Как проанализировано в предыдущей статье, всем рекомендуется использовать
Slf4j
, журнал печати используется единообразно占位符
, и не нужно интерпретировать isxxxEnabled()
- 5. [Обязательно] Во избежание повторной печати журналов и траты места на диске обязательно установите additivity=false в файле log4j.xml. Положительный пример:
<logger name="com.taobao.dubbo.config" additivity="false">
- 6. [Обязательно] Информация об исключении должна включать два типа информации: информацию о месте преступления и информацию о стеке исключений. Если он не обработан, он будет переброшен вверх через ключевое слово throws. Положительный пример:
logger.error(各类参数或者对象 toString + "_" + e.getMessage(), e);
- 7. [Рекомендуется] Внимательно ведите журнал. Запрещено выводить отладочные журналы в производственной среде; выборочно выводить информационные журналы; если вы используете предупреждение для записи информации о бизнес-поведении, когда вы просто выходите в интернет, вы должны обратить внимание на проблему вывода журнала, чтобы избежать разрыва диска сервера, и не забудьте вовремя удалить эти журналы наблюдений. Примечание. Выводится большое количество недействительных журналов, что не способствует повышению производительности системы и не способствует быстрому обнаружению точек ошибок. При записи журналов подумайте: действительно ли эти журналы читаются? Что вы можете сделать, увидев этот журнал? Может ли он быть полезен для устранения неполадок?
- 8. [Ссылка] Вы можете использовать уровень журнала предупреждений для записи ошибок пользовательских входных параметров, чтобы пользователи не терялись, когда они жалуются. Обратите внимание на уровень вывода журнала.На уровне ошибок записывается только важная информация об ошибках, такая как системные логические ошибки и исключения. Пожалуйста, не вводите уровень ошибки в этой сцене без необходимости.
Пополнить
- 1. Когда используется многопоточность, лучше всего печатать идентификатор потока в журнале, чтобы различать разные потоки.
public final class LogIdThreadLocal {
private static ThreadLocal<String> logIdThreadLocal = new ThreadLocal<String>();
...
}
public class MyPatternLayout extends PatternLayout {
private static final String SPLIT_STRING = "|";
@Override
public String format(LoggingEvent event) {
String log = super.format(event);
String threadLocalId = LogIdThreadLocal.getLogId();
if (StringUtils.isEmpty(threadLocalId)) {
threadLocalId = LogIdThreadLocal.create();
}
return log + threadLocalId + SPLIT_STRING + event.getMessage() + Layout.LINE_SEP;
}
}
log4j.appender.output.layout=com.test.log.MyPatternLayout
log4j.appender.output.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss:SSS}|%t|%-5p|%C{1}.%M:%L|
- 2. Предоставьте интерфейс для динамического изменения уровня журнала или используйте Log4j Web Tracker.
Для рабочей среды уровень журнала по умолчанию может быть error/warning/info, а журнал отладки не печатается. изменить После этого нам нужно перезапустить tomcat, Мы знаем, что невозможно случайно перезапустить производственную среду, так что есть ли другой способ? Ответ: да. Log4j предоставляет нам такой API.Вызывая API Log4j, он предоставляет интерфейс отдыха, чтобы клиент мог динамически изменять уровень журнала:
private String changeLoggerLevel(String loggerName, String level) {
Logger logger = LogManager.exists(loggerName);
String result = null;
if (logger != null) {
logger.setLevel(Level.toLevel(level));
result = logger.getName() + "|" + logger.getLevel();
} else {
result = "logger not exist.";
}
return result;
}
Кроме того, рекомендуется сторонний компонент с открытым исходным кодом:Log4j Web Track(Ссылка — это адрес Github), как показано ниже:
Связанная конфигурация:
<servlet>
<servlet-name>TrackerServlet</servlet-name>
<servlet-class>log4jwebtracker.servlet.TrackerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TrackerServlet</servlet-name>
<url-pattern>/tracker/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Log4jInitServlet</servlet-name>
<servlet-class>log4jwebtracker.servlet.init.Log4jInitServlet</servlet-class>
<init-param>
<param-name>log4jConfigLocation</param-name>
<param-value>WEB-INF/classes/log4j.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Читая исходный код, он также вызывает API Log4j для демонстрации:
public abstract class LoggingUtils {
static synchronized public List getFileAppenders() {
List list = new ArrayList();
Enumeration e = LogManager.getRootLogger().getAllAppenders();
while(e.hasMoreElements()) {
Appender a = (Appender) e.nextElement();
if(a instanceof FileAppender) {
list.add(a);
}
}
return list;
}
static synchronized public FileAppender getFileAppender(String appenderName) {
Enumeration e = LogManager.getRootLogger().getAllAppenders();
while(e.hasMoreElements()) {
Appender a = (Appender) e.nextElement();
if(a instanceof FileAppender && a.getName().equals(appenderName)) {
return (FileAppender) a;
}
}
return null;
}
static public boolean contains(List loggers, String loggerName) {
int i=0;
while(i<loggers.size()) {
if(((Logger)loggers.get(i)).getName().equals(loggerName)) {
return true;
}
i++;
}
return false;
}
static public List getLoggers() {
Enumeration e = LogManager.getCurrentLoggers();
List loggersList = new LinkedList();
while(e.hasMoreElements()) {
loggersList.add(e.nextElement());
}
Collections.sort(loggersList, new Comparator() {
public int compare(Object arg0, Object arg1) {
Logger log0 = (Logger) arg0;
Logger log1 = (Logger) arg1;
return log0.getName().compareTo(log1.getName());
}
});
loggersList.add(0, LogManager.getRootLogger());
return loggersList;
}
}
Публичный аккаунт WeChat:На мечеПожалуйста, обратите внимание на мою личную технологию общедоступного аккаунта WeChat, подпишитесь на дополнительный контентЕсли интересно, можем реализовать фасад Web Tracker, аналогичный Slf4j, тогда можно визуализировать логи Log4j1/2, LogBack, Juc, Commons Logging и реализовать функцию динамического изменения уровня логов