Logging

2,027 views

Published on

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,027
On SlideShare
0
From Embeds
0
Number of Embeds
646
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Logging

  1. 1. JAVA logging a confronto Paolo Predonzanipaolo.predonzani@manydesigns.com JUG Genova – 9 Marzo 2011
  2. 2. Logging... alla fine delle finiSi tratta di sostituire questo:System.out.println(“La variabile x vale: ” + x);System.err.println(“Accesso negato: ” + filename);...con questo:Logger logger = LoggerFactory.getLogger(“mylogger”);logger.debug(“La variabile x vale: ” + x);logger.error(“Accesso negato: ” + filename);
  3. 3. Perché System.out e System.err non sono sufficienti?● Solo due stream non bastano per: ● Messaggi UI a carattere ● Messaggi tecnici sul funzionamento interno ● Traccia di sicurezza ● Altri...Spesso si vogliono attivare/disattivare i messaggitecnici in maniera selettiva a seconda dellasituazione. Esempio: i messaggi richiesti insviluppo possono essere molto diversi da quellirichiesti in esercizio.
  4. 4. Il messaggio comunque è... Fate logging (e non fate debugging)“As personal choice, we tend not to use debuggers beyond getting a stack trace or the value of a variable or two. One reason is that it is easy to get lost in details of complicated data structures and control flow; we find stepping through a program less productive than thinking harder and adding output statements and self-checking code at critical places. Clicking over statements takes longer than scanning the output of judiciously-placed displays. It takes less time to decide where to put print statements than to single-step to the critical section of code, even assuming we know where that is. More important, debugging statements stay with the program; debugging sessions are transient.” Brian W. Kernighan and Rob Pike
  5. 5. Output o così:Nov 11, 2009 11:40:06 AM com.manydesigns.portofino.methods.PortofinoServletContextListenercreateDatabaseAbstractionINFO: Database product name: PostgreSQLNov 11, 2009 11:40:06 AM com.manydesigns.portofino.methods.PortofinoServletContextListenercreateDatabaseAbstractionINFO: Database product version: 8.3.5Nov 11, 2009 11:40:06 AM com.manydesigns.portofino.methods.PortofinoServletContextListenercreateDatabaseAbstractionINFO: Database major/minor version: 8.3Nov 11, 2009 11:40:06 AM com.manydesigns.portofino.methods.PortofinoServletContextListenercreateDatabaseAbstractionINFO: Driver name: PostgreSQL Native DriverO così:
  6. 6. Logger (categorie di logging)Un “logger” rappresenta una categoria di messaggicollegati, da controllare in modo unificato.Logger logger = LoggerFactory.getLogger(“security”);Più spesso è semplicemente la categoria dei messaggiprodotti da una certa classe:Logger logger =LoggerFactory.getLogger(“com.example.MyClass”);O più semplicemente:Logger logger =LoggerFactory.getLogger(com.example.MyClass.class);I logger formano una gerarchia: il carattere “.”separa i padri/figli.
  7. 7. Livelli di loggingI livelli di logging indicano la gravità o importanza delmessaggio, es: trace, debug, info, warn, error.logger.setLevel(Level.INFO);logger.info(“Avvio programma”); // sarà stampatoint x = 2;logger.debug(“x vale ” + x); // NON sarà stampatoI livelli di logging per ogni logger sono configurabiliprogrammaticamente (come in esempio) o piùfrequentemente tramite file di configurazione .propertieso .xml
  8. 8. Esempio di configurazione xml<configuration>... <logger name="com.example" level="info"/> <logger name="com.example.MyClass" level="debug"/> <logger name="org.hibernate" level="warn"/> <root level="info"> <appender-ref ref="STDOUT"/> </root></configuration>
  9. 9. Handler e formatter● Uno Handler è un oggetto che si occupa della scrittura fisica dei log su un file, su db, su server di eventi, ecc. ● P.e.: un handler per i messaggi normali e uno per i messaggi di sicurezza ● Più logger insististono su un handler● Un Formatter è un oggetto che formatta in testo una chiamata di logging e i suoi parametri%d{HH:mm:ss.SSS} [userId=%X{userId},userName=%X{userName}]%logger{40} [%F:%L]%n%level: %msg%n13:09:49.026 [userId=1001,userName=predo]c.m.p.database.JdbcConnectionProvider [ConnectionProvider.java:222]WARN: Could not create database abstraction
  10. 10. Mapped Diagnostic Context● Una mappa chiave-valore utile a identificare il contesto di esecuzione, p.e.: lutente, il client, ecc.
  11. 11. Nested Diagnostic Context● Uno stack per identificare il con contesto di esecuzione● Permette di dire “siamo dentro allapplicativo X, modulo Y, sottomodulo Z. Oppure di esprime contesti di algoritmi ricorsivi.
  12. 12. Logging - il rovescio della medaglia: proliferazione delle libreriePerché tante librerie di logging?● Java logging rilasciato tardi (JDK 1.4)● Funzionalità distintive delle singole librerieProblematiche:● Più API da imparare● Versioni diverse della stessa libreria● Conflitti di classloading in ambienti server
  13. 13. Bisogna distinguere● Implementazioni di base: ● Java logging (java.util.logging) ● Log4J ● Logback● API di astrazione: ● Apache commons logging ● SLF4JPerché astrarre?● Per cambiare limplementazione sottostante● Per configurare in un solo punto● Per formattare in modo omogeneo
  14. 14. Astrazione, implementazione e bridging Altra API o framework bridge API di astrazioneAdapter per Adapter per Adapter perJava logging log4j logbackJava logging log4j logback
  15. 15. Java logging – configurazionehandlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler.level = ALLjava.util.logging.ConsoleHandler.level = INFOjava.util.logging.FileHandler.level = ALLjava.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
  16. 16. Log4J esempio di configurazione tramite propetieslog4j.rootLogger=debug, stdout, Rlog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayout# Pattern to output the callers file name and line number.log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%nlog4j.appender.R=org.apache.log4j.RollingFileAppenderlog4j.appender.R.File=example.loglog4j.appender.R.MaxFileSize=100KB# Keep one backup filelog4j.appender.R.MaxBackupIndex=1log4j.appender.R.layout=org.apache.log4j.PatternLayoutlog4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
  17. 17. Logback – configurazione xml<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="STDOUT" /> </root></configuration>
  18. 18. Logback – configurazione groovyimport ch.qos.logback.classic.encoder.PatternLayoutEncoderimport ch.qos.logback.core.ConsoleAppenderimport static ch.qos.logback.classic.Level.DEBUGappender("STDOUT", ConsoleAppender) { encoder(PatternLayoutEncoder) { pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" }}root(DEBUG, ["STDOUT"])
  19. 19. Logback – esempio di output13:09:49.026 [userId=,userName=] c.m.p.database.JdbcConnectionProvider [ConnectionProvider.java:222]WARN: Could not create database abstraction for portofinoorg.postgresql.util.PSQLException: Connection refused. Check that the hostname and port are correct and that thepostmaster is accepting TCP/IP connections. at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:123) ~[postgresql-8.3-606.jdbc3.jar:na] at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66) ~[postgresql-8.3-606.jdbc3.jar:na] at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:124) ~[postgresql-8.3-606.jdbc3.jar:na] at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30) ~[postgresql-8.3-606.jdbc3.jar:na] at org.postgresql.jdbc3.Jdbc3Connection.<init>(Jdbc3Connection.java:24) ~[postgresql-8.3-606.jdbc3.jar:na] at org.postgresql.Driver.makeConnection(Driver.java:386) ~[postgresql-8.3-606.jdbc3.jar:na] at org.postgresql.Driver.connect(Driver.java:260) ~[postgresql-8.3-606.jdbc3.jar:na] at java.sql.DriverManager.getConnection(DriverManager.java:525) ~[na:1.5.0] at java.sql.DriverManager.getConnection(DriverManager.java:171) ~[na:1.5.0] at com.manydesigns.portofino.database.JdbcConnectionProvider.acquireConnection(JdbcConnectionProvider.java:80)~[JdbcConnectionProvider.class:na] at com.manydesigns.portofino.database.ConnectionProvider.init(ConnectionProvider.java:165)~[ConnectionProvider.class:na] atcom.manydesigns.portofino.context.hibernate.HibernateContextImpl.loadConnections(HibernateContextImpl.java:137)[HibernateContextImpl.class:na] at com.manydesigns.portofino.servlets.PortofinoListener.createContext(PortofinoListener.java:328)[PortofinoListener.class:na] at com.manydesigns.portofino.servlets.PortofinoListener.contextInitialized(PortofinoListener.java:153)[PortofinoListener.class:na] at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4135) [catalina.jar:6.0.29] at org.apache.catalina.core.StandardContext.start(StandardContext.java:4630) [catalina.jar:6.0.29] at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791) [catalina.jar:6.0.29] at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771) [catalina.jar:6.0.29]
  20. 20. Confronto implementazioni Java logging Log4j LogbackLicenza JDK Apache EPL/LGPLLayout personalizzabili estensione sì sìNumero di livelli 7 6 5Configurazione properties properties, xml, xml, API, API groovyConfigurazione per test o no no sìcondizionataReload configurazione no Sì tramite thread sì senza threadDiagnostic context no Nested/Mapped MappedJar/versione negli stacktrace no no sìDiffusione scarsa ampia in crescitaStabilità di API/configurazione ferma stabile config cambiataDocumentazione buona ottima ottimaAPI minimale buona molto buonaMessaggi parametrizzati no tramite log4j- sì extras
  21. 21. Confronto API di astrazione Commons logging SLF4JLicenza Apache MITNumero di livelli 6 6Configurazione properties -Configurazione programmatica no noDiffusione ampia ampiaBridging no sìBinding dellimplementazione discovery statica
  22. 22. Problematiche di logging su application server● Presenza/assenza delle librerie di logging nellapplication server: ● Presenza → conflitti con librerie in WEB-INF/lib ● Assenza → assenza della funzionalità● Problemi di class loader● Memory-leak
  23. 23. Presenza delle librerie su vari appserver Java log4j logback JCL SLF4J loggingTomcat 6 JULIJboss 5.1 Sì Sì Sì SìGlassfish 3 Sì
  24. 24. Soluzioni● Usare una libreria di logging inusuale ● Essendo improbabile che lappserver la contenga, includerla nella webapp è sicuro● Usare Java logging standard● Includere la libreria nella webapp sempre ● sperare che non vada in conflitto con lappserver ● va bene con API stabili● Includere o non includere la libreria nella webapp a seconda dellappserver
  25. 25. Riferimenti● http://download.oracle.com/javase/1.4.2/docs/g uide/util/logging/overview.html http://commons.apache.org/logging/● http://logback.qos.ch/● http://logging.apache.org/log4j/● http://www.slf4j.org/● http://logging.apache.org/chainsaw/index.html● http://articles.qos.ch/thinkAgain.html

×