CodeGym /Java блог /Случаен /Сеч: какво, как, къде и с какво?
John Squirrels
Ниво
San Francisco

Сеч: какво, как, къде и с какво?

Публикувано в групата
Здравейте всички в общността на CodeGym! Сеч: Howво, How, къде и с Howво?  - 1 Днес нека поговорим за регистриране:
  1. Какво представлява, защо съществува, кога трябва да го използвате, кога трябва да го избягвате.
  2. Какви реализации на регистриране са налични в Java и Howво трябва да направите с всички тези опции за регистриране.
  3. И регистрационни нива. Ще обсъдим Howво е appender и How да го конфигурирате правилно.
  4. Регистриращи възли и How да ги конфигурираме правилно, така че всичко да работи Howто искаме.
Този материал е предназначен за широка аудитория. Ще бъде ясно за всеки, който тепърва се запознава с Java, Howто и за хора, които вече работят, но само са изследвали logger.info("log something"); Let's go!

Защо се нуждаете от регистриране?

Нека да разгледаме някои реални случаи, при които регистрирането може да реши проблем. Ето един пример от моята работа. Има точки, в които едно приложение се интегрира с други услуги. Използвам регистриране в тези точки, за да установя един вид "алиби" : ако интеграцията не работи, тогава става лесно да се разбере коя страна има проблема. Също така е желателно да регистрирате важна информация, съхранявана в база данни. Например, създаването на администраторски потребител. Това е точно нещо, което би било добре да се регистрира.

Инструменти за влизане в Java

Сред добре познатите решения за регистриране в Java можем да подчертаем следното:
  • Log4j
  • JUL — java.util.logging
  • JCL — Jakarta Commons Logging
  • Регистриране
  • SLF4J — Проста фасада за регистриране за Java
Ще предоставим общ преглед на всеки от тях. След това ще вземем slf4j - log4j свързване като основа на практическа дискусия. Сега това може да изглежда странно, но не се притеснявайте: до края на статията всичко ще стане ясно.

System.err.println

В началото имаше System.err.println (показва записи в журнала на конзолата). Дори днес тази техника се използва за бързо регистриране при отстраняване на грешки. Разбира се, тук няма настройки за обсъждане, така че просто запомнете този метод и ще продължим напред.

Log4j

Това е цялостно решение, създадено от разработчиците поради необходимост. Резултатът е наистина интересен инструмент, който можете да използвате. Поради различни обстоятелства това решение не попадна в JDK, факт, който силно разстрои цялата общност. Log4j има опции за конфигурация, които ви позволяват да активирате регистриране в com.example.typeпакета и да го изключите в com.example.type.genericподпакета. Това дава възможност за бързо изключване на code, който не е необходимо да се регистрира. Тук е важно да се отбележи, че има две версии на Log4j: 1.2.x и 2.xx и те са несъвместими една с друга . Log4j добави концепциите за добавяне(инструмент, използван за писане на регистрационни файлове) и оформление (форматиране на регистрационни файлове). Това ви позволява да регистрирате само това, от което се нуждаете, и да го регистрирате точно Howто ви е необходимо. Ще говорим повече за appender малко по-късно.

JUL — java.util.logging

Едно от основните предимства на това решение е, че JUL е включен в JDK (Java Development Kit). За съжаление, когато е разработен, създателите му не са го базирали на популярната помощна програма Log4j, а по-скоро на решение от IBM. Това решение имаше последствия. Реалността е, че сега никой не използва JUL. Нивата на журнал в JUL се различават от това, което имат Logback, Log4j и Slf4j. Това затруднява разбирането им. Създаването на логер е повече or по-малко подобно. За да направите това, трябва да извършите импортиране:

java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
Името на класа се предава, така че знаем откъде ще дойде нашето регистриране. Започвайки с Java 8, можете да преминете Supplier<String>. Това ни помага да четем и създаваме ред само когато наистина имаме нужда от него, а не всеки път, Howто беше преди. Едва с пускането на Java 8 разработчиците най-накрая решиха важни проблеми и направиха JUL наистина използваем. А именно методи с Supplier<String> msgSupplierпараметър, Howто е показано по-долу:

public void info(Supplier<String> msgSupplier) {
   log(Level.INFO, msgSupplier);
}

JCL — Jakarta Commons Logging

Тъй като дълго време нямаше индустриален стандарт по отношение на регистриране и много хора създадоха свои собствени персонализирани регистратори, беше взето решение да се пусне JCL, обща обвивка, която може да се използва върху други. Защо? Понякога зависимостите, добавени към проекта, използват различен регистратор от този в проекта. Поради това те бяха добавени към проекта като преходни зависимости и това създаде истински проблеми при опитите да се събере всичко заедно. За съжаление обвивката не беше много функционална и не добави нищо. Вероятно би било удобно, ако всички използват JCL. Но това не се случи, така че използването на JCL не е най-добрата идея в момента.

Регистриране

Пътят с отворен code е трънлив... Същият разработчик, който написа Log4j, също написа Logback като приемник на рамка за регистриране. Той се основава на същата идея като Log4j. Разликите в Logback са:
  • подобрена производителност
  • добавена естествена поддръжка за Slf4j
  • разширени опции за филтриране
По подразбиране Logback не изисква ниHowва конфигурация и записва всички събития на ниво DEBUG и по-високо. Ако имате нужда от персонализиране, можете да го постигнете чрез XML конфигурация:

<configuration> 
    <appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
        <file>app.log</file> 
        <encoder> 
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern> 
        </encoder> 
    </appender> 
    <logger name="org.hibernate.SQL" level="DEBUG" /> 
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" /> 
    <root level="info"> 
        <appender-ref ref="FILE" /> 
    </root> 
</configuration>

SLF4J — Проста фасада за регистриране за Java

Някъде през 2006 г. един от основателите на Log4j напусна проекта и създаде Slf4j (Simple Logging Facade for Java), обвивка за Log4j, JUL, common-logging и Logback. Както можете да видите, стигнахме до точката на създаване на обвивка върху обвивка... В този случай тя е разделена на две части: API, който се използва в приложението, и реализация, която се добавя с отделни зависимости за всеки тип регистриране. Например slf4j-log4j12.jarи slf4j-jdk14.jar. Трябва да свържете правилното внедряване и това е всичко: целият ви проект ще го използва. Slf4j поддържа всички най-нови функции, като форматиране на низове за регистриране. Преди това имаше такъв проблем. Да кажем, че създаваме запис в дневник като този:

log.debug("User " + user + " connected from " + request.getRemoteAddr());
Благодарение на оператора за конкатенация, userобектът тихо се превръща в низ благодарение на user.toString(). Това отнема време и забавя системата. И това може да е добре, ако отстраняваме грешки в приложението. Започваме да срещаме проблеми, ако нивото на журнал за този клас е INFO or по-високо. С други думи, не трябва да пишем този запис в журнала (за INFO or по-висок) и не трябва да използваме конкатенация на низове. На теория самата библиотека за регистриране трябва да се справи с това. Както се случва, това се оказа най-големият проблем в първата version на Log4j. Не предостави прorчно решение, а instead of това предложи да се направи нещо подобно:

if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
Тоест, instead of един ред code за регистриране, те предложиха да напише 3! Регистрирането трябва да минимизира промените в codeа и трите реда явно нарушават този общ подход. Slf4j нямаше проблеми със съвместимостта с JDK и API, така че веднага се появи хубаво решение:

log.debug("User {} connected from {}", user, request.getRemoteAddr());
където {}обозначава контейнери за аргументите, предадени на метода. Тоест първото {}съответства на user, а второто {}съответства на request.getRemoteAddr(). Правейки го по този начин, ще извършим конкатенация на низове само ако нивото на журнала изисква да напишем записа в журнала. След това Sjf4j започна бързо да набира популярност. В момента това е най-доброто решение. Съответно, нека да разгледаме регистрирането с помощта на slf4j-log4j12обвързване.

Какво трябва да се регистрира

Разбира се, не трябва да регистрирате всичко. Това често не е необходимо, а понякога дори опасно. Например, ако регистрирате нечии лични данни и те по няHowъв начин изтекат, ще има реални проблеми, особено в проекти, фокусирани върху западните пазари. Но има и неща, които определено трябва да регистрирате :
  1. Начало/край на приложението. Трябва да знаем дали приложението наистина е започнало и завършило според очакванията.
  2. Проблеми със сигурността. Тук би било добре да се регистрират опити за отгатване на нечия парола, случаи на влизане на администратори и т.н.
  3. Определени състояния на приложението . Например преходът от едно състояние в друго в бизнес процес.
  4. Определена информация за отстраняване на грешки заедно със съответното ниво на регистрационен файл.
  5. Определени SQL скриптове. Има реални случаи, когато това е необходимо. Но отново, чрез умело регулиране на нивата на лога, можете да постигнете отлични резултати.
  6. Текущите нишки могат да бъдат регистрирани, когато се проверява дали нещата работят правилно.

Популярни грешки при регистриране

Тук има много нюанси, но ще обърнем специално внимание на няколко често срещани грешки:
  1. Прекомерна сеч. Не трябва да регистрирате всяка стъпка, която теоретично може да бъде важна. Ето едно добро правило: трупите не трябва да надвишават 10% от товара. В противен случай ще има проблеми с производителността.
  2. Регистриране на всички данни в един файл. В един момент това ще направи много трудно четенето/записването на дневника, да не говорим за факта, че някои системи имат ограничения за размера на file.
  3. Използване на неправилни нива на журнал. Всяко ниво на регистрация има ясни граници и те трябва да се спазват. Ако границата е неясна, можете да постигнете споразумение кое ниво да използвате.

Нива на лога

x: Видимо
ФАТАЛНО ГРЕШКА ПРЕДУПРЕЖДЕНИЕ ИНФО ОТСТРАНЯВАНЕ НА ГРЕШКИ СЛЕДИ ВСИЧКО
ИЗКЛ
ФАТАЛНО х
ГРЕШКА х х
ПРЕДУПРЕЖДЕНИЕ х х х
ИНФО х х х х
ОТСТРАНЯВАНЕ НА ГРЕШКИ х х х х х
СЛЕДИ х х х х х х
ВСИЧКО х х х х х х х
Какво представляват нивата на журнал? За да се създаде по няHowъв начин йерархия от записи в журнала, са необходими определени конвенции и разграничения. Ето защо бяха въведени нивата на журнал. Нивото се задава в приложението. Ако даден запис е под определено ниво, той не се регистрира. Например имаме регистрационни файлове, които използваме при отстраняване на грешки в приложението. При нормална работа (когато приложението се използва по преднаmeaning), такива регистрационни файлове не са необходими. Следователно нивото на регистрационния файл е по-високо от това за отстраняване на грешки. Нека да разгледаме нивата на журнал с помощта на Log4j. Освен JUL, други решения използват същите нива на журнал. Ето ги в низходящ ред:
  • ИЗКЛ.: Не се записват записи в журнала; всичко се игнорира.
  • ФАТАЛНО: Грешка, която не позволява на приложението да продължи да работи. Например „Грешка при липса на памет на JVM“.
  • ГРЕШКА: Грешките на това ниво показват проблеми, които трябва да бъдат разрешени. Грешката не спира приложението като цяло. Други заявки може да работят правилно.
  • ПРЕДУПРЕЖДЕНИЕ: Записи в журнала, които представляват предупреждение. Случи се нещо неочаквано, но системата успя да се справи и изпълни заявката
  • ИНФОРМАЦИЯ: Записи в дневника, които показват важни действия в приложението. Това не са грешки or предупреждения. Те са очаквани системни събития.
  • ОТСТРАНЯВАНЕ НА ГРЕШКИ: Записите в регистрационните файлове трябва да отстраняват грешки в приложението. За гарантиране, че приложението прави точно това, което се очаква, or за описание на действията, предприети от приложението, т.е. „Въведен метод1“.
  • TRACE: Записи в регистрационния файл с по-нисък приоритет за отстраняване на грешки. Най-ниското ниво на регистър.
  • ВСИЧКИ: Ниво на регистър за записване на всички записи в журнала на приложението.
В INFO нивото на регистрационни файлове е активирано някъде в приложението, след което записите за всяко ниво ще бъдат регистрирани, от INFO до FATAL. Ако е зададено ниво на журнал FATAL, ще се записват само записи в журнал с това ниво.

Регистриране и изпращане на регистрационни файлове: Appender

Нека разгледаме How работи всичко това, когато използваме Log4j, който предоставя достатъчно възможности за писане/изпращане на регистрационни файлове:
  • да пиша във файл -DailyRollingFileAppender
  • за запис на информация в конзолата —ConsoleAppender
  • за запис на регистрационни файлове в база данни —JDBCAppender
  • за управление на изпращане на регистрационни файлове през TCP/IP —TelnetAppender
  • за гарантиране, че регистрирането няма да повлияе отрицателно на производителността —AsyncAppender
Има още няколко реализации: пълен списък е достъпен тук . Между другото, ако добавката, от която се нуждаете, не съществува, това не е проблем. Можете да напишете свой собствен appender, като имплементирате Appender интерфейса, който Log4j поддържа.

Регистриращи възли

За демонстрационни цели ще използваме Slf4j интерфейс с реализация от Log4j. Създаването на регистратор е много просто: в клас с име MainDemo, който ще извършва известно регистриране, трябва да добавим следното:

org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MainDemo.class);
Това ще създаде регистратор за нас. За да направите запис в журнала, има няколко налични метода, чиито имена отразяват кое ниво на регистър ще се използва. Например:

logger.trace("Method 1 started with argument={}", argument);
logger.debug("Database updated with script = {}", script);
logger.info("Application has started on port = {}", port);
logger.warn("Log4j didn't find the log4j.properties file. Please fix this.");
logger.error("Connection refused to host = {}", host);
Въпреки че предаваме класа, крайното име е пълното име на класа, включително пакетите. Това се прави, за да можете по-късно да разделите регистрирането на възли и да конфигурирате нивото на регистриране и приложението за всеки възел. Например регистраторът е създаден в com.github.romankh3.logginglecture.MainDemoкласа. Името осигурява основата за създаване на йерархия от регистриращи възли. Основният възел е RootLogger от най-високо ниво . Това е възелът, който получава всички записи в журнала за цялото приложение. Останалите възли могат да бъдат изобразени, Howто е показано по-долу: Сеч: Howво, How, къде и с Howво?  - 3Допълнителите са конфигурирани за конкретни възли за регистриране. Сега ще разгледаме file log4j.properties , за да видим пример How да ги конфигурирате.

Ръководство стъпка по стъпка за file log4j.properties

Ще настроим всичко стъпка по стъпка и ще видим Howво е възможно:

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
Този ред казва, че регистрираме CONSOLE appender, който използва изпълнението на org.apache.log4j.ConsoleAppender. Този appender записва информация в конзолата. След това регистрираме друг appender. Този ще пише във файл:

log4j.appender.FILE=org.apache.log4j.RollingFileAppender
Важно е да се отбележи, че самите добавки все още трябва да бъдат конфигурирани. След като регистрираме нашите добавки, можем да определим кои нива на журнал и кои добавки ще се използват в възлите.

log4j.rootLogger=ДЕГРЕШКИ, КОНЗОЛА, ФАЙЛ

  • log4j.rootLogger означава, че конфигурираме основния възел, който съдържа всички записи в журнала
  • Първата дума след знака за equalsство показва минималното ниво на запис за запис (в нашия случай това е DEBUG)
  • След запетаята посочваме всички добавки, които да се използват.
За да конфигурирате по-специфичен възел за регистриране, бихте използвали запис като този:

log4j.logger.com.github.romankh3.logginglecture=TRACE, OWN, CONSOLE
където log4j.logger.се използва за препратка към конкретен възел. В нашия случай, com.github.romankh3.logginglecture. сега нека поговорим за конфигурирането на CONSOLE appender:

# CONSOLE appender customization
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] : %c:%L : %m%n
Тук виждаме, че е възможно да зададете конкретното ниво, на което appender ще започне да работи. Ето пример Howво всъщност се случва: да предположим, че съобщение с ниво INFO е получено от регистриращия възел и предадено на присвоения му appender. Ако прагът на appender е зададен на WARN, тогава той получава записа в журнала, но не прави нищо с него. След това трябва да решим кое оформление ще използва съобщението. Използвам PatternLayout в примера, но има много други опции. Няма да ги разглеждаме в тази статия. Пример за конфигуриране на FILE appender:

# File appender customization
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=./target/logging/logging.log
log4j.appender.FILE.MaxFileSize=1MB
log4j.appender.FILE.threshold=DEBUG
log4j.appender.FILE.MaxBackupIndex=2
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[ %-5p] - %c:%L - %m%n
Можете да конфигурирате конкретния файл, в който ще се записват записи в журнала, Howто се вижда от този ред:

log4j.appender.FILE.File=./target/logging/logging.log
Записът се записва във logging.logfile. За да избегнете проблеми с размера на file, можете да конфигурирате максимума, който в този случай е 1MB. MaxBackupIndexпоказва колко такива регистрационни файлове ще има. Ако трябва да създадем повече файлове от този, тогава първият файл ще бъде изтрит. За да разгледате реален пример, където регистрирането е конфигурирано, можете да отидете в публичното хранorще на GitHub.

Подкрепете това, което обсъдихме

Опитайте сами да направите всичко, което описахме:
  • Създайте свой собствен проект, подобен на нашия пример по-горе.
  • Ако знаете How да използвате Maven, използвайте го. Ако не, тогава прочетете този урок, който описва How да свържете библиотеката.

в обобщение

  1. Говорихме за решенията за регистриране, които съществуват в Java.
  2. Почти всички известни библиотеки за регистриране са написани от един човек :D
  3. Научихме Howво трябва и Howво не трябва да се регистрира.
  4. Разбрахме нивата на регистрационния файл.
  5. Запознахме се с възлите за регистриране.
  6. Разгледахме Howво е appender и за Howво служи.
  7. Създадохме файл log4j.proterties стъпка по стъпка.

Допълнителни материали

  1. CodeGym: Урок по дърводобив
  2. Седмичен Geekly: Регистриране на Java. Здравей свят
  3. Ужас за codeиране: Проблемът с регистрирането
  4. YouTube: Разбиране на Java Logging Hell - Основите. Java Logging Hell & Как да стоите настрана от него
  5. Log4j: Appender
  6. Log4j: Оформление
Вижте и другата ми статия:
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION