CodeGym /Java Blog /Random /Pag-log: ano, paano, saan, at ano?
John Squirrels
Antas
San Francisco

Pag-log: ano, paano, saan, at ano?

Nai-publish sa grupo
Kumusta sa lahat sa komunidad ng CodeGym! Pag-log: ano, paano, saan, at ano?  - 1 Ngayon ay pag-usapan natin ang tungkol sa pag-log:
  1. Ano ito, bakit ito umiiral, kailan mo dapat gamitin, kailan mo dapat iwasan.
  2. Anong mga pagpapatupad ng pag-log ang magagamit sa Java, at kung ano ang dapat mong gawin sa lahat ng mga opsyon sa pag-log na ito.
  3. At mga antas ng log. Tatalakayin natin kung ano ang appender at kung paano ito i-configure nang tama.
  4. Pag-log node at kung paano i-configure ang mga ito nang tama upang ang lahat ay gumana sa paraang gusto namin.
Ang materyal na ito ay inilaan para sa isang malawak na madla. Magiging malinaw sa sinumang kakakilala pa lang ng Java, pati na rin sa mga taong nagtatrabaho na ngunit nag-explore pa lang ng logger.info("log something"); Let's go!

Bakit kailangan mong mag-log?

Tingnan natin ang ilang totoong mga kaso kung saan ang pag-log ay maaaring malutas ang isang problema. Narito ang isang halimbawa mula sa aking trabaho. May mga punto kung saan isinasama ang isang application sa iba pang mga serbisyo. Gumagamit ako ng pag-log sa mga puntong ito upang magtatag ng isang uri ng "alibi" : kung ang pagsasama ay hindi gumagana, kung gayon nagiging madaling malaman kung aling panig ang may problema. Ito rin ay kanais-nais na mag-log ng mahalagang impormasyon na nakaimbak sa isang database. Halimbawa, ang paglikha ng isang admin user. Ito ang tiyak na uri ng bagay na magandang i-log.

Mga tool para sa pag-log in sa Java

Kabilang sa mga kilalang solusyon sa pag-log sa Java, maaari naming i-highlight ang mga sumusunod:
  • Log4j
  • JUL — java.util.logging
  • JCL — Jakarta Commons Pag-log
  • Logback
  • SLF4J — Simple Logging Facade para sa Java
Magbibigay kami ng pangkalahatang-ideya ng bawat isa sa kanila. Pagkatapos ay kukuha tayo ng slf4j - log4j binding bilang batayan ng isang praktikal na talakayan. Ito ay maaaring mukhang kakaiba ngayon, ngunit huwag mag-alala: sa pagtatapos ng artikulo, ang lahat ay magiging malinaw.

System.err.println

Sa simula, mayroong System.err.println (nagpapakita ng mga entry sa log sa console). Kahit ngayon, ang pamamaraan na ito ay ginagamit upang mabilis na mag-log kapag nagde-debug. Siyempre, walang mga setting na tatalakayin dito, kaya tandaan lamang ang pamamaraang ito at magpapatuloy tayo.

Log4j

Ito ay isang kumpletong solusyon na nilikha ng mga developer dahil sa pangangailangan. Ang resulta ay isang talagang kawili-wiling tool na magagamit mo. Dahil sa iba't ibang mga pangyayari, ang solusyong ito ay hindi napunta sa JDK, isang katotohanang labis na ikinagagalit ng buong komunidad. Ang Log4j ay may mga pagpipilian sa pagsasaayos na nagbibigay-daan sa iyong paganahin ang pag-log in sa com.example.typepackage at i-off ito sa com.example.type.genericsubpackage. Ginagawa nitong posible na mabilis na ibukod ang code na hindi kailangang i-log. Mahalagang tandaan dito na mayroong dalawang bersyon ng Log4j: 1.2.x at 2.xx, at hindi sila tugma sa isa't isa . Idinagdag ni Log4j ang mga konsepto ng appender(isang tool na ginagamit sa pagsulat ng mga log) at layout (pag-format ng log). Hinahayaan ka nitong mag-log lamang kung ano ang kailangan mo at i-log ito kung paano mo ito kailangan. Pag-uusapan natin ang higit pa tungkol sa appender sa ibang pagkakataon.

JUL — java.util.logging

Isa sa mga pangunahing benepisyo ng solusyon na ito ay ang JUL ay kasama sa JDK (Java Development Kit). Sa kasamaang palad, noong ito ay binuo, ang mga tagalikha nito ay hindi nakabatay sa sikat na Log4j utility, ngunit isang solusyon mula sa IBM. Ang desisyon na iyon ay may mga kahihinatnan. Ang katotohanan ay walang gumagamit ng JUL ngayon. Ang mga antas ng log sa JUL ay naiiba sa kung ano ang mayroon sa Logback, Log4j, at Slf4j. Ginagawa nitong mas mahirap para sa kanila na maunawaan ang isa't isa. Ang paggawa ng isang logger ay halos magkapareho. Upang gawin ito, kailangan mong mag-import:

java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
Ang pangalan ng klase ay naipasa, kaya alam natin kung saan magmumula ang ating pag-log. Simula sa Java 8, maaari mong ipasa ang Supplier<String>. Nakakatulong ito sa amin na magbasa at lumikha ng isang linya kapag talagang kailangan namin ito, sa halip na sa bawat oras, tulad ng dati. Sa paglabas lamang ng Java 8, nalutas ng mga developer ang mahahalagang problema at ginawang tunay na magagamit ang JUL. Ibig sabihin, mga pamamaraan na may isang Supplier<String> msgSupplierparameter, tulad ng ipinapakita sa ibaba:

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

JCL — Jakarta Commons Pag-log

Dahil walang pamantayan sa industriya tungkol sa pag-log sa loob ng mahabang panahon at maraming tao ang lumikha ng sarili nilang mga custom na logger, ginawa ang desisyon na ilabas ang JCL, isang pangkalahatang wrapper na maaaring gamitin sa ibabaw ng iba. Bakit? Minsan ang mga dependency na idinagdag sa proyekto ay gumagamit ng ibang logger kaysa sa isa sa proyekto. Dahil dito, idinagdag sila sa proyekto bilang mga transitive dependencies, at lumikha ito ng mga tunay na problema kapag sinusubukang pagsamahin ang lahat. Sa kasamaang palad, ang wrapper ay hindi masyadong gumagana at hindi nagdagdag ng anuman. Malamang na maginhawa kung lahat ay gumamit ng JCL. Ngunit hindi iyon ang nangyari, kaya ang paggamit ng JCL ay hindi ang pinakamahusay na ideya sa ngayon.

Logback

Ang open-source na landas ay mahirap... Ang parehong developer na sumulat ng Log4j ay sumulat din ng Logback bilang isang kahalili na balangkas ng pag-log. Ito ay batay sa parehong ideya bilang Log4j. Ang mga pagkakaiba sa Logback ay:
  • pinahusay na pagganap
  • nagdagdag ng katutubong suporta para sa Slf4j
  • pinalawak na mga opsyon sa pag-filter
Bilang default, ang Logback ay hindi nangangailangan ng anumang configuration, at itinatala ang lahat ng mga kaganapan sa antas ng DEBUG at mas mataas. Kung kailangan mo ng ilang pagpapasadya, maaari mong makuha ito sa pamamagitan ng isang XML configuration:

<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 — Simple Logging Facade para sa Java

Noong 2006, isa sa mga founding father ng Log4j ang umalis sa proyekto at lumikha ng Slf4j (Simple Logging Facade para sa Java), isang wrapper para sa Log4j, JUL, common-logging, at Logback. Gaya ng nakikita mo, sumulong kami sa punto ng paggawa ng wrapper sa ibabaw ng wrapper... Sa kasong ito, nahahati ito sa dalawang bahagi: Isang API na ginagamit sa application, at isang pagpapatupad na idinagdag na may hiwalay na dependencies para sa bawat uri ng pag-log. Halimbawa, slf4j-log4j12.jarat slf4j-jdk14.jar. Kailangan mong i-hook up ang tamang pagpapatupad at iyon lang: gagamitin ito ng iyong buong proyekto. Sinusuportahan ng Slf4j ang lahat ng pinakabagong feature, gaya ng pag-format ng mga string para sa pag-log. Dati, may ganyang problema. Sabihin nating lumikha tayo ng log entry na tulad nito:

log.debug("User " + user + " connected from " + request.getRemoteAddr());
Dahil sa concatenation operator, usertahimik na nagiging string ang object salamat sa user.toString(). Ito ay tumatagal ng oras at nagpapabagal sa sistema. At maaaring maging OK iyon kung ide-debug namin ang application. Nagsisimula kaming makatagpo ng mga problema kung ang antas ng log para sa klase na ito ay INFO o mas mataas. Sa madaling salita, hindi natin dapat isulat ang log entry na ito (para sa INFO o mas mataas), at hindi tayo dapat gumamit ng string concatenation. Sa teorya, ang logging library mismo ay dapat tugunan ito. Habang nangyayari ito, ito ang naging pinakamalaking problema sa unang bersyon ng Log4j. Hindi ito naghatid ng isang disenteng solusyon, ngunit sa halip ay iminungkahi na gawin ang isang bagay tulad nito:

if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
Iyon ay, sa halip na isang linya ng code para sa pag-log, iminungkahi nila ang pagsulat ng 3! Ang pag-log ay dapat mabawasan ang mga pagbabago sa code, at ang tatlong linya ay malinaw na lumalabag sa pangkalahatang diskarte. Walang mga isyu sa compatibility ang Slf4j sa JDK at API, kaya agad na lumitaw ang magandang solusyon:

log.debug("User {} connected from {}", user, request.getRemoteAddr());
kung saan {}nagsasaad ng mga placeholder para sa mga argumentong ipinasa sa pamamaraan. Iyon ay, ang una {}ay tumutugma sa user, at ang pangalawa {}ay tumutugma sa request.getRemoteAddr(). Sa paggawa nito sa ganitong paraan, magsasagawa lamang kami ng string concatenation kung ang antas ng log ay nangangailangan sa amin na isulat ang log entry. Pagkatapos nito, nagsimulang mabilis na lumaki ang Sjf4j sa katanyagan. Sa kasalukuyan, ito ang pinakamahusay na solusyon. Alinsunod dito, tingnan natin ang pag-log gamit ang isang slf4j-log4j12binding.

Ano ang kailangang i-log

Siyempre, hindi mo dapat i-log ang lahat. Ito ay madalas na hindi kinakailangan at kung minsan ay mapanganib pa. Halimbawa, kung nag-log ka ng personal na data ng isang tao at kahit papaano ay na-leak ito, magkakaroon ng mga tunay na problema, lalo na sa mga proyektong nakatuon sa mga pamilihan sa Kanluran. Ngunit mayroon ding mga bagay na talagang dapat mong i-log :
  1. Pagsisimula/pagtatapos ng aplikasyon. Kailangan nating malaman kung talagang nagsimula at natapos ang aplikasyon gaya ng inaasahan.
  2. Mga isyu sa seguridad. Dito, mainam na mag-log ng mga pagtatangka sa paghula ng password ng isang tao, mga pagkakataon kapag nag-sign in ang mga admin, atbp.
  3. Ilang mga estado ng aplikasyon . Halimbawa, ang paglipat mula sa isang estado patungo sa isa pa sa isang proseso ng negosyo.
  4. Ilang impormasyon sa pag-debug kasama ang kaukulang antas ng log.
  5. Ilang mga script ng SQL. May mga real-world na kaso kapag ito ay kinakailangan. Ngunit muli, sa pamamagitan ng mahusay na pagsasaayos ng mga antas ng log, makakamit mo ang mahusay na mga resulta.
  6. Maaaring mai-log ang mga tumatakbong thread kapag bini-verify na gumagana nang tama ang mga bagay.

Mga sikat na error sa pag-log

Mayroong maraming mga nuances dito, ngunit gagawa kami ng espesyal na pagbanggit ng ilang mga karaniwang pagkakamali:
  1. Labis na pag-log. Hindi mo dapat i-log ang bawat hakbang na maaaring maging mahalaga sa teorya. Narito ang isang mahusay na tuntunin ng thumb: Ang mga log ay hindi dapat lumampas sa 10% ng pagkarga. Kung hindi, magkakaroon ng mga problema sa pagganap.
  2. Pag-log sa lahat ng data sa isang file. Sa ilang mga punto, ito ay magiging napakahirap na basahin/isulat ang log, hindi banggitin ang katotohanan na ang ilang mga sistema ay may mga limitasyon sa laki ng file.
  3. Paggamit ng mga maling antas ng log. Ang bawat antas ng log ay may malinaw na mga hangganan, at dapat silang igalang. Kung ang isang hangganan ay hindi malinaw, maaari kang magkaroon ng isang kasunduan tungkol sa kung aling antas ang gagamitin.

Mga antas ng log

x: Nakikita
FATAL ERROR BALAAN IMPORMASYON DEBUG TRACE LAHAT
NAKA-OFF
FATAL x
ERROR x x
BALAAN x x x
IMPORMASYON x x x x
DEBUG x x x x x
TRACE x x x x x x
LAHAT x x x x x x x
Ano ang mga antas ng log? Upang kahit papaano ay makalikha ng hierarchy ng mga log entries, ilang mga convention at delimitasyon ay kinakailangan. Ito ang dahilan kung bakit ipinakilala ang mga antas ng log. Ang antas ay nakatakda sa application. Kung ang isang entry ay mas mababa sa isang tinukoy na antas, hindi ito naka-log. Halimbawa, mayroon kaming mga log na ginagamit namin kapag nagde-debug ng application. Sa panahon ng normal na operasyon (kapag ang application ay ginagamit para sa layunin nito), ang mga naturang log ay hindi kailangan. Samakatuwid, ang antas ng log ay mas mataas kaysa sa pag-debug. Tingnan natin ang mga antas ng log gamit ang Log4j. Bukod sa JUL, ang ibang mga solusyon ay gumagamit ng parehong mga antas ng log. Narito ang mga ito sa bumababa na pagkakasunud-sunod:
  • NAKA-OFF: Walang naitala na mga entry sa log; lahat ay binabalewala.
  • FATAL: Isang error na pumipigil sa application na magpatuloy sa pagtakbo. Halimbawa, "JVM out of memory error".
  • ERROR: Ang mga error sa antas na ito ay nagpapahiwatig ng mga problemang kailangang lutasin. Ang error ay hindi huminto sa application sa kabuuan. Maaaring gumana nang tama ang ibang mga kahilingan.
  • BABALA: Mga log entry na kumakatawan sa isang babala. May nangyaring hindi inaasahan, ngunit nakayanan ng sistema at natupad ang kahilingan
  • INFO: Mga entry sa log na nagpapahiwatig ng mahahalagang aksyon sa application. Hindi ito mga pagkakamali o babala. Ang mga ito ay inaasahang mga kaganapan sa system.
  • DEBUG: Kailangang i-debug ng mga log entry ang application. Para sa pagtiyak na ginagawa ng application ang eksaktong inaasahan, o para sa paglalarawan ng mga aksyon na ginawa ng application, ibig sabihin, "Pumasok na pamamaraan1".
  • TRACE: Lower-priority log entry para sa pag-debug. Ang pinakamababang antas ng log.
  • LAHAT: Isang antas ng log para sa pagsulat ng lahat ng mga entry ng log ng application.
Sa antas ng log ng INFO ay pinagana sa isang lugar sa application, pagkatapos ay mai-log ang mga entry para sa bawat antas, mula INFO hanggang FATAL. Kung nakatakda ang FATAL log level, ang mga log entry lang na may ganoong level ang isusulat.

Pag-log at pagpapadala ng mga log: Appender

Isaalang-alang natin kung paano gumagana ang lahat ng ito kapag gumagamit tayo ng Log4j, na nagbibigay ng sapat na pagkakataon para sa pagsulat/pagpapadala ng mga log:
  • upang magsulat sa isang file -DailyRollingFileAppender
  • upang magsulat ng impormasyon sa console -ConsoleAppender
  • upang magsulat ng mga log sa isang database -JDBCAppender
  • upang pamahalaan ang pagpapadala ng mga log sa TCP/IP —TelnetAppender
  • para sa pagtiyak na ang pag-log ay hindi negatibong nakakaapekto sa pagganap -AsyncAppender
Mayroong ilang higit pang mga pagpapatupad: isang kumpletong listahan ay magagamit dito . Siyanga pala, kung wala ang appender na kailangan mo, walang problema iyon. Maaari mong isulat ang iyong sariling appender sa pamamagitan ng pagpapatupad ng Appender interface, na sinusuportahan ng Log4j.

Pag-log node

Para sa mga layunin ng pagpapakita, gagamit kami ng interface ng Slf4j, na may pagpapatupad mula sa Log4j. Ang paglikha ng isang logger ay napaka-simple: sa isang klase na pinangalanang MainDemo, na gagawa ng ilang pag-log, kailangan nating idagdag ang sumusunod:

org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MainDemo.class);
Ito ay lilikha ng isang logger para sa amin. Upang gumawa ng log entry, mayroong ilang magagamit na mga pamamaraan na ang mga pangalan ay nagpapakita kung aling antas ng log ang gagamitin. Halimbawa:

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);
Bagama't pumasa kami sa klase, ang huling pangalan ay ang buong pangalan ng klase, kasama ang mga pakete. Ginagawa ito upang sa ibang pagkakataon maaari mong hatiin ang pag-log in sa mga node at i-configure ang antas ng pag-log at appender para sa bawat node. Halimbawa, ang logger ay nilikha sa com.github.romankh3.logginglecture.MainDemoklase. Ang pangalan ay nagbibigay ng batayan para sa paglikha ng isang hierarchy ng mga logging node. Ang pangunahing node ay top-level RootLogger . Ito ang node na tumatanggap ng lahat ng log entries para sa buong application. Ang natitirang mga node ay maaaring ilarawan tulad ng ipinapakita sa ibaba: Pag-log: ano, paano, saan, at ano?  - 3Ang mga appenders ay na-configure para sa mga partikular na logging node. Ngayon ay titingnan natin ang log4j.properties file upang makakita ng halimbawa kung paano i-configure ang mga ito.

Isang step-by-step na gabay sa log4j.properties file

Ise-set up namin ang lahat nang paisa-isa at tingnan kung ano ang posible:

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
Sinasabi ng linyang ito na nirerehistro namin ang CONSOLE appender, na gumagamit ng org.apache.log4j.ConsoleAppender na pagpapatupad. Ang appender na ito ay nagsusulat ng impormasyon sa console. Susunod, nagrehistro kami ng isa pang appender. Ang isang ito ay magsusulat sa isang file:

log4j.appender.FILE=org.apache.log4j.RollingFileAppender
Mahalagang tandaan na ang mga appenders mismo ay kailangan pa ring i-configure. Kapag nairehistro na namin ang aming mga appender, matutukoy namin kung aling mga antas ng log at kung aling mga appender ang gagamitin sa mga node.

log4j.rootLogger=DEBUG, CONSOLE, FILE

  • Ang ibig sabihin ng log4j.rootLogger ay kino-configure namin ang root node, na naglalaman ng lahat ng log entries
  • Ang unang salita pagkatapos ng katumbas na tanda ay nagpapahiwatig ng pinakamababang antas ng log na isusulat (sa aming kaso, ito ay DEBUG)
  • Kasunod ng kuwit, ipinapahiwatig namin ang lahat ng mga appenders na gagamitin.
Upang i-configure ang isang mas tiyak na logging node, gagamit ka ng isang entry na tulad nito:

log4j.logger.com.github.romankh3.logginglecture=TRACE, OWN, CONSOLE
kung saan log4j.logger.ginagamit upang sumangguni sa isang tiyak na node. Sa aming kaso, com.github.romankh3.logginglecture. Ngayon ay pag-usapan natin ang tungkol sa pag-configure ng 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
Dito makikita natin na posibleng itakda ang partikular na antas kung saan magsisimulang magtrabaho ang appender. Narito ang isang halimbawa ng kung ano talaga ang nangyayari: ipagpalagay na ang isang mensahe na may antas ng INFO ay natanggap ng logging node at ipinasa sa appender na nakatalaga dito. Kung nakatakda ang threshold ng appender sa WARN, matatanggap nito ang log entry ngunit wala itong ginagawa. Susunod, kailangan nating magpasya kung aling layout ang gagamitin ng mensahe. Gumagamit ako ng PatternLayout sa halimbawa, ngunit maraming iba pang mga pagpipilian. Hindi namin sila tatalakayin sa artikulong ito. Halimbawa ng pag-configure ng 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
Maaari mong i-configure ang partikular na file kung saan isusulat ang mga entry sa log, tulad ng makikita mula sa linyang ito:

log4j.appender.FILE.File=./target/logging/logging.log
Ang entry ay nakasulat sa logging.logfile. Upang maiwasan ang mga problema sa laki ng file, maaari mong i-configure ang maximum, na sa kasong ito ay 1MB. MaxBackupIndexay nagpapahiwatig kung gaano karaming mga naturang log file ang magkakaroon. Kung kailangan naming lumikha ng higit pang mga file kaysa dito, ang unang file ay tatanggalin. Upang tingnan ang isang tunay na halimbawa kung saan naka-configure ang pag-log, maaari kang pumunta sa pampublikong repositoryo sa GitHub.

Patibayin ang ating napag-usapan

Subukan sa iyong sarili na gawin ang lahat ng aming inilarawan:
  • Lumikha ng iyong sariling proyekto katulad ng aming halimbawa sa itaas.
  • Kung alam mo kung paano gamitin ang Maven, gamitin ito. Kung hindi, basahin ang tutorial na ito , na naglalarawan kung paano ikonekta ang library.

Sa buod

  1. Napag-usapan namin ang tungkol sa mga solusyon sa pag-log na umiiral sa Java.
  2. Halos lahat ng kilalang logging library ay isinulat ng isang tao :D
  3. Natutunan namin kung ano ang dapat at hindi dapat i-log.
  4. Nalaman namin ang mga antas ng log.
  5. Ipinakilala kami sa mga logging node.
  6. Tiningnan namin kung para saan ang appender at para saan ito.
  7. Gumawa kami ng log4j.proteties file nang sunud-sunod.

Mga karagdagang materyales

  1. CodeGym: Aralin sa Logger
  2. Lingguhang Geekly: Java logging. Hello mundo
  3. Coding Horror: Ang Problema Sa Pag-log
  4. YouTube: Pag-unawa sa Java Logging Hell - Ang Mga Pangunahing Kaalaman. Java Logging Hell at Paano maiiwasan ito
  5. Log4j: Appender
  6. Log4j: Layout
Tingnan din ang aking iba pang artikulo:
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION