Жодне серйозне додаток не обходиться без логування, будь то сайтик, GUI або навіть що-небудь під Android. У світі Java ситуація з логування на перший погляд дещо заплутана. Є якісь SLF4J, якийсь Logback, для чогось потрібно створювати XML-файли, ось це все. Але, як це часто буває, якщо сісти, і не поспішаючи у всьому розібратися, насправді все виявляється дуже просто і логічно.
У випадку зі Scala є заслуговує на увагу бібліотека scala-logging. є обгорткою над SLF4J. Використовуючи макроси Scala. вона додає перевірку перед записом рядка в лог, чи буде при поточних настройках цей рядок насправді кудись записана.
Тобто, ви пишете:
log. debug # 40; s "Test $ msg" # 41;
... а після розгортання макросу це перетворюється в:
if # 40; log. isDebugEnabled # 41; log. debug # 40; s "Test $ msg" # 41;
В результаті, якщо налагоджувальні логи відключені, не буде виділятися і звільнятися пам'ять під рядок, не буде виконуватися інтерполяція, і так далі. Таким чином отримуємо істотно бо більшу продуктивність.
Давайте спробуємо прикрутити логирование до нашого REST-сервісу на базі Finagle. У build.sbt дописуємо залежності:
"Ch.qos.logback"% "logback-classic"% "1.1.3",
"Com.typesafe.scala-logging" %% "scala-logging"% "3.1.0"
У конструкторі класу FinagleServiceExample створюємо логер:
import com. typesafe. scalalogging. _
import org. slf4j. LoggerFactory
private val logger = Logger # 40; LoggerFactory. getLogger # 40; this. getClass # 41; # 41;
Після чого беремо і просто пишемо логи:
logger. info # 40; s "service started" # 41;
logger. debug # 40; s "reading $ key" # 41;
logger. error # 40; s "bad request: $ req" # 41;
Існують такі рівні логування, від меншого до більшого: TRACE, DEBUG, INFO, WARN, ERROR. В налаштуваннях, мова про які піде нижче, вибирається ефективний рівень. При виборі певного ефективного рівня в лог потрапляють усі повідомлення даного рівня і вище. Наприклад, якщо обраний ефективний рівень INFO, в логах ви побачите все INFO, WARN і ERROR повідомлення. Крім того, є особливий ефективний рівень OFF, який відключає всі логирование.
Logback шукає файл з настройками за такими правилами:
- Якщо в classpath є logback.groovy, використовується він;
- Інакше в classpath шукається файл logback-test.xml;
- Якщо немає і його, пробуємо знайти logback.xml;
- Якщо і він не знайдений, використовуємо стандартні параметри, тобто, пишемо просто в консоль;
Давайте покладемо в src / test / resources файл logback-test.xml такого змісту:
. % -5level [% thread]% logger -% msg% n
Як нескладно здогадатися, тут ми говоримо Logback писати всі повідомлення рівня DEBUG і вище в STDOUT, використовуючи заданий формат. Якщо тепер запустити тести, у висновку ви дійсно побачите все DEBUG, INFO і ERROR логи. Можете замінити рівень в рядку
В каталозі src / main / resources створимо logback.xml трохи іншого змісту:
.ate% -5level [% thread]% logger -% msg% n
.ate% -5level [% thread]% logger -% msg% n
Ці настройки теж в особливих пояснень не потребують. Ми говоримо писати як в консоль, так і в файл, використовуючи трохи інший формат логів. Можна зібрати standalone jar, використовуючи команду:
... потім запустити його, сказавши:
java -jar. / Target / scala- 2.11 / finagle-example-assembly- 0.1 .jar
... і перевірити, що Logback успішно підхоплює налаштування.
Можна перевизначити налаштування без пересборки jar, сказавши:
java -Dlogback.configurationFile = path / to / logback.xml \
-jar. / Target / scala- 2.11 / finagle-example-assembly- 0.1 .jar
Можна змусити Logback автоматично перечитувати документацію, змінивши перший рядок в logback.xml приблизно так:
Можна фільтрувати логи по класах і пакетам, при цьому щодо ієрархій працює інтуїтивна семантика:
У appender-секціях можна вказувати мінімальний рівень повідомлень:
Список конкретних пакетів і класів можна направляти в задані аппендери:
Можна налаштувати ротацію і архівацію логів:
/path/to/application-..log.gz
Як бачите, все дуже гнучко, дуже потужно і не сказати, щоб супер складно.
А чим ви пишете логи?