【JAVA】Спецификация печати журнала Java
【JAVA】Спецификация печати журнала Java

Почему нам следует стандартизировать журналы?

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

Функция журнала

  • Поиск проблем онлайн. Основная функция журналов заключается в том, что основные предприятия должны иметь полные журналы для облегчения устранения неполадок.
  • отладка журнала отладки. Журналы отладки можно использовать для отладки во время разработки и тестирования. Добавление журналов отладки к ключевым частям повышает точность тестирования. Разработчики также могут использовать журналы отладки для самотестирования.
  • Поведение журнала пользователя. В основном он используется для записи некоторых конфиденциальных операций пользователя для мониторинга или для того, чтобы операционная группа сообщала о проблемах клиентов. Половина этих действий имеет определенные характеристики продукта.
  • Чушь собачья. В основном при соединении с третьей стороной, если возникает ситуация, когда другая сторона внезапно меняет параметры возврата и отклоняет платеж, вы можете использовать журнал в качестве доказательства. Или операционные ошибки можно объяснить с помощью журналов.

Простой случай

Это хороший способ непосредственно ознакомиться с некоторыми отличными платформами с открытым исходным кодом или прочитать некоторые примеры обработки исключений в исходном коде JDK. Вот несколько примеров:

Журнал печатается на основе собранной конкретной информации об исключении:

Язык кода:java
копировать
try {  
    File defaultAclFile = new File(fileName);  
    if (!defaultAclFile.exists()) {  
        defaultAclFile.createNewFile();  
    }  
} catch (IOException e) { 
	// Собирайте информацию об определенных исключениях и печатайте журналы.
    log.warn("create default acl file has exception when update accessConfig. ", e);  
}

Используйте String.format вместо + сплайсинга, определите и создайте собственные исключения:

Язык кода:java
копировать
try {  
    byte[] signature = sign(data.getBytes(charset), key.getBytes(charset), algorithm);  
    return new String(Base64.encodeBase64(signature), DEFAULT_CHARSET);  
} catch (Exception e) {
	// Используйте String.format заменять + Сращивание
    String message = String.format(CAL_SIGNATURE_FAILED_MSG, CAL_SIGNATURE_FAILED, e.getMessage());  
    log.error(message, e);  
    // Пользовательское исключение
    throw new AclException("CAL_SIGNATURE_FAILED", CAL_SIGNATURE_FAILED, message, e);  
}

Иногда обработка исключений ведет себя неожиданно. Я думаю, что такая обработка выглядит хорошо, но на самом деле ее легко «заложить». Если автор не представит ее в документе, это будет очень опасное поведение.

Язык кода:java
копировать
try {  
  return Long.parseLong(value);  
} catch (NumberFormatException e) {  
	// Я думаю, что такая обработка выглядит хорошо, но на самом деле ее очень легко «закопать мины».
  return new BigDecimal(value).longValue();  
}

История развития

Можно сказать, что структуру журналирования JAVA представляет собой кусок шпагата, и в конечном итоге вся эта куча шпагата сделана одним человеком. Соответственно, если мы воспользуемся инструментом lombok, мы обнаружим, что существуют такие аннотации, как @Log4j, @Slf4j и @Log4j2. Имена этих логов не только трудно запомнить, но и имеют почти одинаковую длину. используя их, мы не знаем, какой из них использовать, или даже не знаем, почему это используется. Вот общий обзор результатов развития всего фреймворка к настоящему моменту:

Давайте начнем разбираться, как получилась эта картинка =-=.

System.outа такжеSystem.err

Это самый старый способ печати журналов в JAVA. Такая печать проста и быстра. Недостаток в том, что ее нельзя настроить в любом формате, и нет проблем с выводом, поэтому эффективность крайне низкая.

Log4j

В 1996 году проект, родившийся на европейском рынке электронной безопасности, решил разработать набор API-интерфейсов для отслеживания журналов. Впоследствии этот набор API стал независимым проектом Log4j.

Ceki GülcüкакLog4jОсновное развитие,Предоставляет множество ссылок на инфраструктуру разработки журналов. Лог4дж Он до сих пор используется большим количеством компаний, и его влияние имеет далеко идущие последствия.

JUL(Java Util Logging)

Sun очень завидует Log4j. Отклонив просьбу об интеграции Log4j в Java, она разработала собственную структуру журналов. Конечно, по сути, это можно рассматривать как копирование. Но поскольку Log4j существует уже много лет, отзывы рынка не идеальны, и все по-прежнему используют Log4j.

JCL(Jakarta Commons Logging)

Вот ключевой момент сравнения,Apach и Sun начинают спорить из-за стандартов ведения журналов,Впоследствии компания Apach разработала JCL.,предназначен для использованияJCLВзлететьSunРазвитый инструмент журналирования。Jakarta Commons LoggingПосле выпуска также предоставляется единый интерфейс журнала.,По сути, это простой уровень абстракции печати журналов.

Но идея очень красивая, но реальность очень уродлива. JCL и JUL тоже постигла похожая судьба. Они не получили хороших отзывов на рынке и позже были скрыты Apach.

Slf4j(Simple Logging Facade for Java)

На этом фоне,Ceki GülcüПо личным причинам отApachПодать в отставку,И попытки самостоятельно сформулировать набор спецификаций для замены JCL.,Наконец назван Sfl4j,Судя по результатам, он действительно гораздо успешнее JCL.,Но мы должны обратить вниманиеSlf4jиJCLПросто набор стандартов,Так что позжеCeki GülcüРазработано сновамостовой пакетсовместимый JCL, Log4j и JUC также интегрированы в него. Он все сделал сам, он действительно как бог.

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

Давайте присоединимся сновамостовой пакет(красный логотипмостовой пакет),Следующие изменения произошли снова,Результаты пакета спецификации + совместимости Slf4j следующие:

Slf4j мост
Slf4j мост

Но иногда возникает другая ситуация при конкретном использовании фреймворка. Хотя все продукты реализованы с использованием Slf4j, фактические детали печати журналов размещаются отдельно, поскольку Slf4j только упрощает унифицированный вход и не выполняет никаких операций по объединению журналов. Например, здесь мы используем среду SpringBoot, предполагая, что она использует log4j, а наш собственный бизнес-код использует slf4j, будет два разных формата журналов.

Поэтому Slf4j впоследствии реализовал обработку совместимости. Целью является не только возможность доступа к различным журналам, но и взять на себя всю работу других фреймворков журналов. Да, мостовое соединение здесь все еще используется. Однако мостовое соединение эквивалентно обеспечению совместимости всей печати журналов с совместимой платформой журналов и управления ею в соответствии с форматом журнала sfl4j.

На данный момент Slf4j стал совместим со всеми другими продуктами, и он действительно достиг эффекта замены одной платформы другими платформами журналирования.

Печать журналов, совместимая с Slf4j
Печать журналов, совместимая с Slf4j

Logback

SLf4j объединяет несколько фреймворков.,Но Sl4j всё-таки стандартизирован,Не конкретный продукт,затемCeki GülcüТрахнул еще одногоLogbackпублично заявить,Этот LogBack можно рассматривать как обновление Log4j.,Не только производительность может быть в десять раз быстрее, чем у Log4j.,Это также идеальная заменаSlf4j。Для простоты памяти вот простое резюме:Журнал регистрации = Slf4j + Log4j (улучшено)

Logback
Logback

Log4j2

Ceki Gülcüиз старого клубаApachВполне естественно не радоваться, когда вы видите, как бывший сотрудник бьет вас по носу или лицу.,для сравнительного анализаLogbackразвитыйLog4j 2. Неудивительно, что он охватывает практически все функции Logback, а также предоставляет отдельные операции. Да, это всего лишь небольшое улучшение на основе Slf4j и использует интерфейсы, совместимые с другими платформами журналов, в виде пакета (Api), самого продукта журнала. формируется в пакет (Core).

Итоговый рисунок немного пугает. Построение можно сохранить и просмотреть несколько раз (для удобства просмотра здесь убраны вспомогательные линии).

Вся платформа ведения журналов Java разработала четыре платформы и три интерфейса.,Основная используемая структура::Log4j2Slf4jLogbackJUL(Sunразвивать),Интерфейсы — это набор вещей мостового пакета.,Используется для объединения всех спецификаций и интерфейсов других платформ в ваши собственные продукты.,

Примечание. На самом деле здесь вы можете увидеть более интересную деталь.,То естьJCL(Jakarta Commons Logging)Тихо уходим со сцены истории,Потому что в прошлом это действительно было мошенничество,Log4j2, разработанный Apach, имеет доступ только к JUL вместо JCL, который он разработал ранее.

Итак, когда система выбирает план ведения журнала, как принять решение?

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

• Добавляйте только одну зависимость продукта журналов. Если вы полагаетесь на несколько продуктов журналов, это только усложнит обработку журналов вашего приложения и не сможет управляться единообразно.

• Установите зависимость продукта журнала наOptionalиruntime scopeвOptionalдляЗависимости не будут переданы,Например, если кто-то другой цитирует вашу банку,Вы будете вынуждены использовать зависимости журналов, которые вы не хотите использовать.

Например, чтобы предотвратить передачу зависимостей, вы можете использовать следующий метод:

Язык кода:html
копировать
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>${log4j.version}</version>
    <optional>true</optional>
</dependency>

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

Язык кода:html
копировать
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>${log4j.version}</version>
    <scope>runtime</scope>
</dependency>

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

Когда войти?

Журналы записи в основном проверяют следующие моменты:

  • Параметры инициализации:Параметры идеиизации Вы можете видеть некоторый контент в различных структурах, а в развитии собственного бизнеса вы используете параметры полиграфического бизнеса для чтения соответствующего контента.
  • Исключение запроса языка программирования:основнойи业务развивать人员对于异常的处理а также异常的容忍度,Здесь соответствующие журналы печатаются в соответствии с различными уровнями журналов.
  • Ожидания от бизнес-процессов не оправдываются:Когда условие ветвления приводит к непредвиденной ситуации, необходимо распечатать соответствующие журналы.。
  • Основные роли системы, ключевые действия компонентов:основной是核心业务的触发动作,Но следует избегать очень высокочастотной печати.,При этом логи уточняются.
  • Удаленный вызов стороннего сервиса:Сторонние компоненты в микросервисах не очень надежны.,Логирование необходимо,Иногда, столкнувшись с неожиданными проблемами, можно узнать более важную информацию.

Журнал практики

Мы можем использовать следующий формат для форматирования вывода журнала:

Язык кода:java
копировать
2019-12-01 00:00:00.000|pid|log-level|[svc-name,trace-id,span-id,user-id,biz-id]|thread-name|package-name.class-name : log message
  • время
  • pid,pid
  • уровень журнала, уровень журнала
  • svc-имя, имя приложения
  • идентификатор трассировки, идентификация цепочки вызовов
  • span-id, идентификатор уровня вызова
  • идентификатор пользователя, идентификатор пользователя
  • biz-id, бизнес-идентификатор
  • имя потока, имя потока
  • имя-пакета.имя-класса, имя регистратора
  • сообщение журнала, тело сообщения журнала

Взяв в качестве примера Logback, мы можем использовать следующий формат для стандартизированной печати:

Язык кода:java
копировать
%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}|${PID:- }|%level|${LOG_LEVEL_PATTERN:-%5p}|%t|%-40.40logger{39}: %msg%n

Настройки logback.xml следующие:

Язык кода:html
копировать
<configuration><property name="LOG_PATH"
          value="${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}"/>


<springProperty scope="context" name="APP_NAME"
                source="spring.application.name" defaultValue="spring-boot-fusion"/>
<!-- Глобальное единство pattern -->
<property name="LOG_PATTERN"
          value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}|${PID:- }|%level|${LOG_LEVEL_PATTERN:-%5p}|%t|%-40.40logger{39}: %msg%n"/>
<!-- Режим вывода файл, файл скользящей записи, сначала назначьте файл журнала файлу, при выполнении определенного условия регистрация в других файлах -->
<appender name="fileInfo" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!--Имя файла пишется,Может быть относительным каталогом,Это также может быть абсолютный каталог,Если каталог верхнего уровня не существует, он будет создан автоматически.,нет значения по умолчанию。-->
    <file>${LOG_PATH}/${APP_NAME}-info.log</file>
    <!--скользящая стратегия  Стратегия субподряда, основанная на времени -->
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <!-- yyyy-MM-dd стратегия времени — один файл в день -->
        <FileNamePattern>${LOG_PATH}/${APP_NAME}-info.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
        <!--Часы хранения файла журнала-->
        <MaxHistory>48</MaxHistory>
        <maxFileSize>1GB</maxFileSize>
        <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <!--  layout Отвечает за преобразование событий в строки и вывод форматированной информации журнала. -->
    <layout class="ch.qos.logback.classic.PatternLayout">
        <pattern>${LOG_PATTERN}</pattern>
    </layout>
    <!--фильтр уровня,Фильтрация по уровню журнала. Если уровень журнала равен уровню конфигурации,Фильтр будет основан на onMath и onMismatchПринять или отклонить журналы-->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <!--Установить уровень фильтрации-->
        <level>INFO</level>
        <!--Используется для настройки действий, соответствующих условиям фильтра.-->
        <onMatch>ACCEPT</onMatch>
        <!--Используется для настройки операций, которые не соответствуют условиям фильтра.-->
        <onMismatch>DENY</onMismatch>
    </filter>
</appender>
</configuration>

Вот несколько ключевых моментов, которые стоит представить:

  1. время Точка, специфичная для миллисекунд, ЧЧ:мм:сс.ССС Точность к конкретному времени более способствует устранению неполадок.
  2. Журналы разных уровней хранятся в категориях.,Можно использоватьadditivity="false"Избегайте повторной печати журналов。
  3. Рекомендуется@lombok.extern.slf4j.Slf4j+logbackплан,сам logback также является автором slft4j,Что-то сделано автором log4j,Это конечный интегрированный продукт.
Язык кода:html
копировать
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
    <scope>provided</scope>
</dependency>
  1. Запрещать System.out.println и System.err.println,В то же время для прямой печати содержимого объекта,Набор для объекта@ToStringаннотацияилииспользоватьIDEМожет генерироваться автоматически。
  2. 打印бревно不建议использовать+而是更建议использовать{}Распечатать как заполнитель:
Язык кода:java
копировать
// Для корректных примеров необходимо использовать параметризованную информацию.
log.debug("order is paying with userId:[{}] and orderId : [{}]",userId, orderId);
// ошибка Пример,Не вводите строку Сращивание, которая сгенерирует много String объект,Занимая место,влияют на производительность. И уровень журнала выше этого уровня также будет выполнять логику строкового Сращивания.
log.debug("order is paying with userId: " + userId + " and orderId: " + orderId);

Рекомендации по использованию

Если разрешено, вы можете использовать lombok для добавления аннотаций для использования экземпляров переменных журнала.

Язык кода:html
копировать
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> 
<dependency> 
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId> 
	<version>1.18.10</version> 
	<scope>provided</scope> 
</dependency>

Используются следующие места:

Язык кода:java
копировать
import lombok.extern.slf4j.Slf4j; 
@Slf4j public class LogTest 
{ 
	public static void main(String[] args) { 
		log.info("this is log test"); 
		} 
}

Выбор уровня журнала

Основные уровни журналов следующие: Уровни журналов от малого к большому:

  • DEBUG:DEBUGбревноосновной是развивать是阶段использовать,Сценарии использования обычно являются результатом того, выполняются ли некоторые ключевые операции на этапах разработки и тестирования.,Разработчики могут подробно записывать различное содержимое в отладочную информацию.,Постарайтесь найти и устранить проблемы на этапе разработки, насколько это возможно.
  • INFO:INFOЖурнал содержит ключевую информацию журнала.,Основная функция – сохранение информации во время работы.,Разработчики могут вести журналы ключей для облегчения эксплуатации и обслуживания, чтобы извлекать информацию из журнала выполнения ключевой логики.,Потому что журнал INFO будет распечатан в режиме реального времени на консоли онлайн-журнала.,Поэтому необходимо сохранить наиболее важную информацию.,После завершения рекомендуется настроить локальную настройку на тестирование уровня INFO.
  • WARN:предупреждающее сообщениеиERRORНе очень легко отличить,Однако на самом деле вам нужно рассматривать уровень журнала WARNиERROR только как предупреждения о поведении, которое оказывает влияние, но не оказывает особенно большого влияния на бизнес-процессы.,Например, есть исключения в параметрах,Требуется последующий анализ журнала.
  • ERROR:Печать требуется при возникновении сценариев, которые серьезно влияют на выполнение бизнеса.Errorбревно,Если влияние не особенно велико,Просто нужно сосредоточиться В случае возникновения проблемы выводится WARN. Журнал уровня.

Выбор ОТЛАДКА/ИНФО

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

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

Выбор ПРЕДУПРЕЖДЕНИЕ/ОШИБКА

Как и в приведенном выше описании, вы можете использовать WARN для предупреждения о конфиденциальных операциях пользователей или неожиданных результатах, но при этом никаких происшествий не происходит. Если у вас есть какие-либо сомнения, вы можете проверить журнал WARN для устранения неполадок позже. ОШИБКА используется в более серьезных ситуациях, требующих технического онлайн-устранения неполадок, поэтому в процессе разработки необходимо тщательно учитывать положение печати ОШИБКИ.

Основные моменты ERROR следующие:

  • Что пошло не так и какие функции были затронуты
  • Получение справочной информации: прямая справочная информация или место хранения справочной информации.
  • Узнайте решение или найдите кого-нибудь, кто сможет решить эту проблему, позвонив в полицию.

Нормативные рекомендации

1. Соответствующий уровень журнала

  • error:Более серьезная проблема,Влияние на нормальную деловую деятельность
  • warn:Небольшое влияние на бизнес,но нужноВнимание развития
  • info:Основная информация для ежедневного устранения неполадок,Входные параметры интерфейса и выходные параметры и т. д.
  • trace:Подробности,Уровень файла журнала
  • debug:仅仅用于развиватьили测试查看重要的内部логика细节,Но деловые отношения в Интернете не особенно близки.

2. В журнале распечатываются входные параметры.

Все логи, относящиеся к интерфейсу,а такжеключевые методыженьшеняи返回值都建议加上бревно。

3. Соответствующий формат формата

Справочный шаблон:

Язык кода:java
копировать
"%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n"

4. Для условий с несколькими филиалами рекомендуется печатать первую строку филиала.

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

Язык кода:java
копировать
String type = ???;
if(log.isDebugEnbale()){
	log.debug("Текущий тип ветки: {}", type);
}
if(type == "xxx"){

}else if(type == "aaa"){

}

// или
switch(type){
	case "xxx":
		// ....
		break;
	case "xxx":
		// ....
		break;
}

5. Оценка на уровне журнала

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

Язык кода:java
копировать
User user = new User(666L, "xxxx", "xxxx");
if (log.isDebugEnabled()) {
    log.debug("userId is: {}", user.getId());
}

6. Используйте API в системе ведения журналов SLF4J.

людиlombokОни все дали один@Slf4j的аннотация,Так что используйте это.

На самом деле, это потому, что slf4j также был написан автором log4j, и его совместимость с фасадами получила широкую оценку. Потом... потом apach научился этому, я тоже могу это сделать! Конечным результатом является то, что компоненты системы журналирования Java с открытым исходным кодом чрезвычайно запутаны и плохи, как кусок дерьма. Из этой ситуации также видно, что установление стандартов очень важно.

7. Заполнитель вместо знака +

При компиляции в класс с помощью Java StringBuffer будет использоваться для выполнения операций сращивания строк. Я обнаружил, что независимо от того, насколько велик или мал проект, даже когда речь идет о фреймворке, мы часто видим сращивание знаков +. Хотя влияние оптимизации компиляции более высоких версий JDK на самом деле очень мало, лично я все еще не замечаю этого. Мне не нравится такое соединение знаков +, оно недостаточно элегантно.

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

Язык кода:txt
копировать
logger.info("Processing trade with id: {} and symbol : {} ", id, symbol);

использовать+Оператор для строки Сращивание,Есть определенная суммаПотеря производительности

Язык кода:txt
копировать
logger.info("Processing trade with id: " + id + " and symbol: " + symbol);

8. Для вывода логов рекомендуется использовать асинхронный метод.

  • В конечном итоге журнал будет выведен в файл или другой поток вывода. Если есть требования к производительности ввода-вывода, рекомендуется использовать асинхронный режим, который может значительно улучшить производительность ввода-вывода.
  • Используйте асинхронный режим для вывода журналов. Взяв в качестве примера журналирование, чтобы настроить асинхронное использование, используйте AsyncAppender
Язык кода:html
копировать
<appender name="FILE_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="ASYNC"/>
</appender>

9. Не используйте e.printStackTrace().

Причины не использовать:

  • e.printStackTrace()打印出的堆栈бревно跟业务代码бревно是交错混合在一起的,Обычно неудобно устранять неполадки в журналах исключений.
  • e.printStackTrace()Строка, сгенерированная оператором, записывает информацию о стеке.,Если сообщение слишком длинное и его слишком много,В блоке памяти, где расположен пул строковых констант, нет места, то есть память заполнена.,Так,Запрос пользователя застрял~

Следует использовать следующее правильное употребление:

Язык кода:java
копировать
try{
  // Обработка бизнес-кода
}catch(Exception e){
  log.error("В вашей программе есть исключение",e);
}

10. Не записывайте только половину журнала исключений

Например, следующий журнал не имеет значения:

Язык кода:java
копировать
try {
    //Обработка бизнес-кода
} catch (Exception e) {
    // ошибка
    LOG.error('В вашей программе есть исключение');
}

На самом деле метод обработки очень прост:

Язык кода:java
копировать
try{
  // Обработка бизнес-кода
}catch(Exception e){
  log.error("В вашей программе есть исключение",e);
}

Также необходимо обратить внимание,e.getMessage()Подробная информация об исключениях стека не будет регистрироваться.,Будет записана только основная информация описания.,Не способствует решению проблем. также,如果использовать Hutool Tools, есть класс инструментов для извлечения информации об исключениях, что более удобно.

11. Не глотайте финики всем сердцем.

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

12. Отключите отладку в онлайн-среде.

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

13. Не вставляйте исключения

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

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

Ниже приводится соответствующий контрпример:

Язык кода:java
копировать
try{
  // Обработка бизнес-кода
  try{
  // Обработка бизнес-кода
	}catch(Exception e){
	  log.error("В вашей программе есть исключение",e);
	}
}catch(Exception e){
  log.error("В вашей программе есть исключение",e);
}

14. Не регистрируйте исключения, а затем выбрасывайте их.

Вызов исключения после записи — очень опасная операция.,Потому что внешний уровень может не обработать исключение снова после того, как внутренний уровень его перехватит.,в случае Пользовательское Примечание Устранить проблему еще сложнее,Кроме того, такой подход приведет кСтековая вторичная печать,Очень расточительно влияет на производительность системы,

Контрпример следующий:

Язык кода:java
копировать
try{
  // Обработка бизнес-кода
	}catch(Exception e){
	 log.error("IO exception", e);
		throw new MyException(e);
	}

15. Разделение файлов журналов

Различные типы журналов могут быть разделены,напримерaccess.log,илиerrorуровеньerror.log,Все можно распечатать отдельно в файл. Разделение по бизнес-модулям – это тоже способ,Таким образом, модули, ответственные за каждый из них, могут четко видеть журналы.

16. Избегайте повторной печати журналов

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

Язык кода:java
копировать
log.info("Этот пользователь является участником,Id:{}",user,getUserId());
  //Избыточно, можно объединить с предыдущим журналом
  log.info("Начать обработку логики членства, идентификатор: {}", user, getUserId());

17. Журнал основного функционального модуля

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

Нормативные рекомендацииссылка

Ниже приводится стандартная печать журнала:

Язык кода:java
копировать
2018-05-22 15:35:53.850 TRACE TDWZLog [0x00001b10] <36> <TDWZProtocol::Init>,TDWZProtocol::Init
2018-05-22 15:35:53.850 TRACE TDWZLog [0x00001b10] <89> <TDWZProtocol::Init>,End in processing TDWZProtocol::Init
2018-05-22 15:35:53.853 TRACE TDWZLog [0x00001b10] <142>    <TDWZProtocol::Connect>,Connect Execute finish
2018-05-22 15:35:53.853 TRACE TDWZLog [0x00002f10] <149>    <GetAlarmEventPro>,Enter GetAlarmEventPro func
2018-05-22 15:39:36.382 WARN TrackLog [0x000029fc] - [ internal WARN htrace_server_convert_msgstring_to_contextintls(493) ] detect input id error, trace_id span_id,this chain may not be tracked.
2018-05-22 15:39:36.383 WARN TrackLog [0x000029fc] - [ internal WARN htrace_server_receive(195) ] can not detect trace_id in context, this chain may not be tracked.
2018-05-22 15:39:36.383 TRACE TDWZLog [0x000029fc] <231>    <TDWZProtocol::DisConnect>,TDWZProtocol::DisConnect
2018-05-22 15:39:37.502 TRACE TDWZLog [0x00002f10] <225>    <GetAlarmEventPro>,End Get AlarmEventPro Func
2018-05-22 15:39:37.503 TRACE TDWZLog [0x000029fc] <241>    <TDWZProtocol::DisConnect>,close socket
2018-05-22 15:39:37.503 TRACE TDWZLog [0x000029fc] <242>    <TDWZProtocol::DisConnect>,Execute DisConnect function succeed.

Пример регистрации TRACE

Язык кода:java
копировать
DRV_LOG_TRACE("Connect Execute start");
DRV_LOG_TRACE("Connect Execute finish");
DRV_LOG_TRACE("DisConnect func");
DRV_LOG_TRACE("Execute DisConnect function succeed.");
DRV_LOG_TRACE("Enter UploadEvent Func");
DRV_LOG_TRACE("extInfo = %s", Extension);
DRV_LOG_TRACE("Send a Msg ");
DRV_LOG_TRACE("- Connect Execute start");
DRV_LOG_TRACE("- Connect Execute finish");
DRV_LOG_TRACE("- Enter GetAlarmEventPro func");
DRV_LOG_TRACE("- Receive an info");
DRV_LOG_TRACE("- End Get AlarmEventPro Func");
DRV_LOG_TRACE("- DisConnect func");
DRV_LOG_TRACE("- Execute DisConnect function succeed.");
DRV_LOG_TRACE("- Enter UploadEvent Func");
DRV_LOG_TRACE("- Leave UploadEvent Func");
DRV_LOG_TRACE("- ============Сработала сигнализация электросети");
DRV_LOG_TRACE("- ============Начать отправку значений тока и напряжения");
DRV_LOG_TRACE("- ============ Отправьте значения тока и напряжения повторно через интервал более минуты");

регистрация информации

Язык кода:java
копировать
DRV_LOG_INFO("- UpdataEvent  nchal= %d,EventID = %d.",iChannelNo,nEventType);
DRV_LOG_INFO("- do not support doControl");
DRV_LOG_INFO("- channelId = %s, nStatusType = %d", channelId.c_str(), nStatusType)

ведение журнала отладки

Язык кода:java
копировать
DRV_LOG_DEBUG("- Ситуация выходного сигнала тревоги: номер сетки: %d, номер сигнала тревоги: %d, содержание сигнала тревоги: %s.", datas.data1.chn, datas.data1.alarm_num, datas.data1.alarms);
DRV_LOG_DEBUG("- Ситуация выходного сигнала тревоги: номер сетки: %d, номер сигнала тревоги: %d, содержание сигнала тревоги: %s.", datas.data2.chn, datas.data2.alarm_num, datas.data2.alarms);
DRV_LOG_DEBUG("- Ситуация выходного сигнала тревоги: номер сетки: %d, номер сигнала тревоги: %d, содержание сигнала тревоги: %s.", datas.data3.chn, datas.data3.alarm_num, datas.data3.alarms);
DRV_LOG_DEBUG("- Ситуация выходного сигнала тревоги: номер сетки: %d, номер сигнала тревоги: %d, содержание сигнала тревоги: %s.",datas.data4.chn,datas.data4.alarm_num,datas.data4.alarms);
DRV_LOG_DEBUG("- ============datas.data1.huab = %d",datas.data1.huab);
DRV_LOG_DEBUG("- ============datas.data1.hiab = %d",datas.data1.hiab);
DRV_LOG_DEBUG("- ============datas.data2.huab = %d",datas.data2.huab);
DRV_LOG_DEBUG("- ============datas.data2.hiab = %d",datas.data2.hiab);
DRV_LOG_DEBUG("- ============datas.data3.huab = %d",datas.data3.huab);
DRV_LOG_DEBUG("- ============datas.data3.hiab = %d",datas.data3.hiab);
DRV_LOG_DEBUG("- ============datas.data4.huab = %d",datas.data4.huab);
DRV_LOG_DEBUG("- ============datas.data4.hiab = %d",datas.data4.hiab);
DRV_LOG_DEBUG("- Alarm is : %s",szEvent.c_str());
DRV_LOG_DEBUG("- GetChannelExtInfo channelId=%s", channelId.c_str());
DRV_LOG_DEBUG("- nChan = %d, szInfo = %s", nChan, szInfo);

ПРЕДУПРЕЖДЕНИЕ

Язык кода:java
копировать
DRV_LOG_WARN("[0x%08x] - invaild event msg,discard it", DRV_INVALID_ARG);
DRV_LOG_WARN("[0x%08x] - Can't find channel by channelId");
DRV_LOG_WARN("[0x%08x] - [DWSdk.errorcode=0x%08x]Connect device failed", DRV_CONNECT_FAILED, sdkErrCode);
DRV_LOG_WARN("[0x%08x] - [DWSdk.errorcode=0x%08x]dw_start_receive failed", DRV_ERROR, sdkErrCode);
DRV_LOG_WARN("[0x%08x] - [DWSdk.errorcode=0x%08x]Communicate failed, socket recv error", DRV_ERROR, DW_SOCKET_RECV_ERROR);
DRV_LOG_WARN("[0x%08x] - [DWSdk.errorcode=0x%08x>other error", DRV_ERROR, iGetResult);
DRV_LOG_WARN("[0x%08x] - [DWSdk.errorcode=0x%08x>other error", DRV_ERROR, iGetResult);
DRV_LOG_WARN("[0x%08x] - SetEventCallBack should be called first", DRV_ERROR);

Регистрация ошибок

Язык кода:java
копировать
DRV_LOG_ERROR("Init DwSDK filded;<errCode=%d>", initRet);  
DRV_LOG_ERROR("Connect device failed");
DRV_LOG_ERROR("Create thread failed");
DRV_LOG_ERROR("dw_start_receive failed");
DRV_LOG_ERROR("Communicate failed, socket recv error");
DRV_LOG_ERROR("other error<errCode=%d>", iGetResult);
DRV_LOG_ERROR("SetEventCallBack should be called first");
DRV_LOG_ERROR("[0x%08x] - [DWSdk.errorcode=0x%08x]Init DwSDK filded", DRV_INIT_FAILED, initRet);
DRV_LOG_ERROR("- [HPR.errorcode=0x%08x]Create thread failed", HPR_GetLastError());

Значение 0x%08x можно объяснить на примере.,printf("0x%08x", 0x1234);,После форматирования он станет0x00001234

boy illustration
Учебное пособие по Jetpack Compose для начинающих, базовые элементы управления и макет
boy illustration
Код js веб-страницы, фон частицы, код спецэффектов
boy illustration
【новый! Суперподробное】Полное руководство по свойствам компонентов Figma.
boy illustration
🎉Обязательно к прочтению новичкам: полное руководство по написанию мини-программ WeChat с использованием программного обеспечения Cursor.
boy illustration
[Забавный проект Docker] VoceChat — еще одно приложение для мгновенного чата (IM)! Может быть встроен в любую веб-страницу!
boy illustration
Как реализовать переход по странице в HTML (html переходит на указанную страницу)
boy illustration
Как решить проблему зависания и низкой скорости при установке зависимостей с помощью npm. Существуют ли доступные источники npm, которые могут решить эту проблему?
boy illustration
Серия From Zero to Fun: Uni-App WeChat Payment Practice WeChat авторизует вход в систему и украшает страницу заказа, создает интерфейс заказа и инициирует запрос заказа
boy illustration
Серия uni-app: uni.navigateЧтобы передать скачок значения
boy illustration
Апплет WeChat настраивает верхнюю панель навигации и адаптируется к различным моделям.
boy illustration
JS-время конвертации
boy illustration
Обеспечьте бесперебойную работу ChromeDriver 125: советы по решению проблемы chromedriver.exe не найдены
boy illustration
Поле комментария, щелчок мышью, специальные эффекты, js-код
boy illustration
Объект массива перемещения объекта JS
boy illustration
Как открыть разрешение на позиционирование апплета WeChat_Как использовать WeChat для определения местонахождения друзей
boy illustration
Я даю вам два набора из 18 простых в использовании фонов холста Power BI, так что вам больше не придется возиться с цветами!
boy illustration
Получить текущее время в js_Как динамически отображать дату и время в js
boy illustration
Вам необходимо изучить сочетания клавиш vsCode для форматирования и организации кода, чтобы вам больше не приходилось настраивать формат вручную.
boy illustration
У ChatGPT большое обновление. Всего за 45 минут пресс-конференция показывает, что OpenAI сделал еще один шаг вперед.
boy illustration
Copilot облачной разработки — упрощение разработки
boy illustration
Микросборка xChatGPT с низким кодом, создание апплета чат-бота с искусственным интеллектом за пять шагов
boy illustration
CUDA Out of Memory: идеальное решение проблемы нехватки памяти CUDA
boy illustration
Анализ кластеризации отдельных ячеек, который должен освоить каждый&MarkerгенетическийВизуализация
boy illustration
vLLM: мощный инструмент для ускорения вывода ИИ
boy illustration
CodeGeeX: мощный инструмент генерации кода искусственного интеллекта, который можно использовать бесплатно в дополнение к второму пилоту.
boy illustration
Машинное обучение Реальный бой LightGBM + настройка параметров случайного поиска: точность 96,67%
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция без кодирования и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
LM Studio для создания локальных больших моделей
boy illustration
Как определить количество слоев и нейронов скрытых слоев нейронной сети?
boy illustration
[Отслеживание целей] Подробное объяснение ByteTrack и детали кода