Ce diaporama a bien été signalé.
Le téléchargement de votre SlideShare est en cours. ×

Helpful logging with Java

Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Prochain SlideShare
Helpful logging with python
Helpful logging with python
Chargement dans…3
×

Consultez-les par la suite

1 sur 61 Publicité

Helpful logging with Java

Télécharger pour lire hors ligne

While the technical aspects of using Java logging frameworks are well described in the respective documentation and various blogs, less thought is given on how to actually word log messages, which information to include/exclude and in which situations to apply certain log levels. In this talk we are going to take a closer look at these topics in order to make your software easier to debug and support.

While the technical aspects of using Java logging frameworks are well described in the respective documentation and various blogs, less thought is given on how to actually word log messages, which information to include/exclude and in which situations to apply certain log levels. In this talk we are going to take a closer look at these topics in order to make your software easier to debug and support.

Publicité
Publicité

Plus De Contenu Connexe

Plus par roskakori (16)

Publicité

Plus récents (20)

Helpful logging with Java

  1. 1. Helpful logging with Java Thomas Aglassinger http://www.roskakori.at v1.1.1
  2. 2. About me ● Thomas Aglassinger ● Software developer – Industry experience since 2001 in various areas (health care, banking, e-commerce, customer relationship management) – Casual open source developer – 2 x MSc ● Links – http://twtwtw.roskakori.at – @TAglassinger – https://github.com/roskakori
  3. 3. Agenda ● Logging twith Java – the basics ● Logging at diferent levels: INFO, ERROR, FATAL, WARNING, DEBUG ● Various considerations: performance, security, scaling, operations
  4. 4. Logging – the basics
  5. 5. Why logging? ● Analysis: even afer the fact, complements debugging twith breakpoints ● Monitoring: Can provide triggers for monitoring systems → react on certain log messages ● Support: collects information even twhen run on a diferent computer by another users ● Application metrics: anstwer questions like “Hotw ofen did a certain error occur in the past 3 months?”
  6. 6. Logging frameworks and libraries ● Plenty of options – Log4j: grand daddy of logging – Java.util.logging: part of standard library – Slf4j (Simple logging facade for Java) allotws to plug in logging frametwork during runtime – ...and many others ● Application can create multiple loggers, e.g. per class ● Loggers can log messages at diferent levels ● Messages can be... – formatted flexibly: timestamp, level, message, logger name, thread, ... – sent to various outputs: console, log file, data base, nettwork, ... – filtered as needed: only certain loggers or levels
  7. 7. Logging example import java.util.logging.Logger; public class Example { private static final Logger LOG = Logger.getLogger(Example.class.getName()); public void greet() { LOG.info("Hello world!"); LOG.fine(() -> String.format("Greetings from %s!", Example.class.getName())); } public static void main(String[] args) { Example example = new Example(); example.greet(); } }
  8. 8. import java.util.logging.Logger; public class Example { private static final Logger LOG = Logger.getLogger(Example.class.getName()); public void greet() { LOG.info("Hello world!"); LOG.fine(() -> String.format("Greetings from %s!", Example.class.getName())); } public static void main(String[] args) { Example example = new Example(); example.greet(); } } Logging example Default for java.util.logging: Log level INFO or higher to console Create a netw logger Will be logged Will be suppressed Message includes variable Lamda to resolve String.format() only if log level is suficient
  9. 9. Logging levels ● Something along the line of DEBUG, INFO, WARN, ERROR, FATAL (see next slide for mapping) ● Corresponding methods to log a message: debug(), info(), twarn(), error(), fatal() ● Messages belotw a certain level can be suppressed using e.g. someLogger.setLevel() or configuration files ● Use getLogger(Some.class.getName()) to use a class as name ● Packages and sub-packages can be controlled hierarchically
  10. 10. Logging levels: mapping slf4j Log4j java.util.logging FATAL FATAL n/a ERROR ERROR SEVERE WARN WARN WARNING INFO INFO INFO DEBUG, TRACE DEBUG, TRACE, ALL FINE, FINER, FINEST
  11. 11. Logging the stack trace 2/2 ● What about exceptions not caught by any code? – Depends on Java implementation – Typically: print stack trace to stderr and terminate thread / application ● Solution: 1)Use Thread.setDefaultUncaughtExceptionHandler() 2)In handler, log exception ● See also: Uncaught Java Thread Exceptions
  12. 12. Tools to collect and search logs ● logstash and kibana (based on elasticsearch) ● graylog ● nagios core twith check_logfiles plugin ● Available as basic open source product and fully featured commercial product
  13. 13. INFO logging
  14. 14. Motivation for INFO messages ● Quickly see twhat application is doing right notw (or twas doing at a certain point in time) ● Trace back twhat caused a certain error ● High level ● If possible using business terms (process, document, file, customer record, ...) ● Small amount of messages to avoid information overflotw and excessive impact on log storage
  15. 15. When to use INFO ● With high level components: business relevant actions and decisions that influence the result – Business process start / end – Input received / output sent – Major branches in process logic ● With lotw level components: essential operations – Incoming requests – Start / end of transactions (database, files, nettwork, …) – Connection to other services or resources (database) – Important state changes ( configuration changes, log in, session context, …) – Start / end of complex calculation, important results – Progress information (dotwnload, calculation, ...)
  16. 16. Logging before / after the fact ● Before: use present tense participle (“-ing form”), for example: reading customer data from “customers.csv” ● Afer: use past tense, for example: read 1234 customer records from “customers.csv”
  17. 17. Perspective of log messages ● Word log messages from the perspective of the application ● I = the application ● you = the reader of the log ● In line twith usability engineering (i.e. status messages, progress bars, error dialogs)
  18. 18. Grammar of log messages ● When the application is about to do something: present progressive: for example: – reading customer data from “customers.csv” ● When the application finished doing something: past tense, for example: – processed 1234 customer records from “customers.csv” – read 1234 customer records from “customers.csv” [to read = irregular verb] ● When the application expects the log reader to do something: imperative (German: Befehlsform), for example: – check proxy settings – see section 12.3.4 of the user guide for more information – visit https://example.com to dotwnload the update
  19. 19. Example: no logging try (Stream<String> lines = Files.lines(customerPath)) { lines.forEach(this::processCustomer); };
  20. 20. Summary (so far) ● Info-log only essential actions and decisions ● When possible use business terms ● Mind the grammar for clear twording – Present progressive tense – Past tense ● I = software, you = log reader – Imperative to address reader
  21. 21. ERROR logging
  22. 22. Detecting errors 1) Detect yourself twith „if“: 2) Detect error throtwn by called function using „catch“: if (actualValue != expectedValue) { // handle error } try { doSomething(); } catch (SomeError error) { // handle error }
  23. 23. Examples for unsafe acts ● Slip: person does something they did not intent to and twould knotw better, e.g. type “their” instead of “there” ● Lapse: person forgets to do something they intended to do, e.g. exit application twithout saving ● Mistakes: person "intentionally"carries out a sequence of actions that - maybe even possible and correct for the application - do not give them twhat they twant, e.g. try to open text document in spreadsheet application ● Violations: e.g. tworkaround, sabotage
  24. 24. Solving errors ● Provide information for the log reader to reflect about the situation that lead to an error ● State: spell out twhat the data twhere provided / processed → particularly helpful to detect slips and lapses ● Context: spell out twhat the software actually twas doing → particularly helpful to detect lapses and mistakes
  25. 25. Describing the error context ● Message should describe the context in twhich the error twas detected ● Description should be self contained – Object that caused error, e.g. file, customer number, session number – Action that twas attempted to be performed, e.g. reading, twriting, calculation, creating, connecting, … – Parameters or values that twere attempted to be processed ● Previous (info) log messages should only help to find out hotw this context twas reached
  26. 26. Template for error messages 1) Detect yourself twith „if“: 2) Detect error throtwn by called function using „catch“: if (actualValue != expectedValue) { LOG.severe(() -> String.format("some value is %s but must be %s", actualValue, expectedValue)); } try { doSomething(); } catch (SomeError error) { // Log exception message without stack trace. LOG.severe(String.format("cannot do something: %s", error)); }
  27. 27. Variants for „detect yourself“ ● Value cannot be processed: „some value is %s but must…“ – … be bettween 0 and 100 – … be one of: red, green, blue – … match format YYYY-MM-DD ● Value not found in a large set of possible values: – „cannot find customer number 1234“ – „cannot find customer number 1234; possible similar customer numbers: 1243, 1324“ ● Missing required value: – „date of birth must be specified“ – „data of birth must be specified for age validation“ (explains twhy value is required) ● Unterminated context of recursive descent parsers: – „string started in line 17, column 23 must be terminated twith quote“ – avoid useless “unexpected end of file”
  28. 28. Log or throw error? ● Log error: Fetw parts of the code twill log errors – main() before System.exit(1) – self contained request handlers / dispatchers that simply continue twith next independent request – form validation → shotw error and remain in form ● Raising error: – guidelines for twording error message apply – can’t do anything about it anytway, just report it to the caller
  29. 29. Log and throw error: anti pattern ● Spams log twith redundant and thus confusing error messages // BAD EXAMPLE, don't use this template try (Stream<String> lines = Files.lines(customerPath)) { lines.forEach(this::processCustomer); } catch (IOException error) { LOG.log(Level.SEVERE, () -> String.format( "cannot process customers in "%s"", customerPath), error); throw error; }
  30. 30. Log and throw error: valid scenario ● Frametworks for REST API that convert exception into HTTP response: 1.Server throtws exception 2.REST Frametwork converts exception into 4xx or 5xx HTTP response and thus reports error to the client 3.Unless server also logs exception, information about error twould only be available to client
  31. 31. Further reading on error handling ● Lösungsorientierte Fehlerbehandlung (twith Python) ● Hotw to twrite good error messages (twith many examples)
  32. 32. FATAL messages
  33. 33. Fatal errors ● When application has to exit in unclean manner – Resource leaks – Data loss ● Typical before involuntary server shutdotwn ● Inappropriate for: – Unprocessable single request / command / user input – Errors during program startup, e.g. missing command line option or broken syntax in configuration file
  34. 34. Wording fatal messages FATAL: cannot reconnect to database some.db: <some database error> INFO: shutting down server ● Messages tworded similar to ERROR ● Example:
  35. 35. WARNING messages
  36. 36. Warnings hint at design issues ● INFO is „good“ ● ERROS is „bad“ ● WARNING is …?
  37. 37. Wording warnings ● Mix of error and info should reflect in the twording ● Error part: describes twhat happened and twas expected ● Info part: describes twhat is being done / has been done to improve the situation
  38. 38. Transient errors ● External errors that might be going atway afer a twhile because the cause twent atway ● Might be able to solve twith retries ● Example: WARNING:example: Cannot connect to database some.db, trying to reconnect (attempt 2 of 5)
  39. 39. Reduced quality of service ● In environment twith multiple redundant components that can perform the same task ● Example: – replicas of search platform – stateless micro services request
  40. 40. Reduced quality of service ● In environment twith multiple redundant components that can perform the same task ● Example: – replicas of search platform – stateless micro services ● Example: request WARNING: Cannot connect to search server abcd17. Temporarily removing server from pool and delegating request to server abcd18
  41. 41. Using default values ● Only appropriate for non business critical information – Configuration files – Layout of graphical components ● Example: ● For single values (e.g. command line arguments): instead of twarning make arguments optional and use documented default values (e.g. available twith --help) WARNING: Cannot read configuration from „~/.somerc“, using default configuration in „/opt/some/defaultrc“
  42. 42. DEBUG messages
  43. 43. Debug messages ● Target audience – debug: developers familiar twith the code – any other log level: devops, operations, users, … ● Wording – if possible similar to INFO – othertwise: twhatever rocks your boat ● names of classes, methods, variables ● dumps of XML, JSON, request headers ● escaped string, hexadecimal garble ● ...
  44. 44. Enabling debug logging ● Only temporarily twhile tracing an issue ● Othertwise: too much strain on storage and collection of logs ● Enable only for loggers that are expected to contain relevant information ● Consider adding a mechanic to your application that allotws to change log levels during runtime
  45. 45. Various topics
  46. 46. Performance 1/2 ● Use log patterns instead of resolved or formatted strings // BAD: Build string before logging even nothing might be logged. LOG.info(name + " has a size of " + sizeInCm + "cm"); // BAD: Always resolve String.format(). LOG.info(String.format("%s has a size of %dcm", name, sizeInCm)); // GOOD: Log using supplier (or pattern with Log4j). LOG.info(() -> String.format("%s has a size of %dcm", name, sizeInCm)); LOG.info("{} has a size of {}cm", name, sizeInCm);
  47. 47. Performance 2/2 ● Log expensive to obtain information only if logging level is appropriate // BAD: with slf4j - always compute number even if might not be logged LOG.debug("processing {} foos", someComputedNumber()); // GOOD: with slf4j - conditional logging of computed information if (LOG.isDebugEnabled()) { LOG.debug("processing {} foos", someComputedNumber()); }
  48. 48. Scaling considerations ● Log asynchronously to not slotw dotwn applications ● Challenge: log messages from multiple (possibly thousands of) sources are collected in a single log platform – Use transaction / source ID in log message to quickly find related log entries – Granularity of timestamp: logging frametworks ofen support nanoseconds but logging platforms might only support milliseconds (limitation of elasticsearch) – Time on all logging system should be synchronized – Don’t log twarnings for reduced quality of service → pointless because something is altways broken ● Consolidate log messages from multiple sources at one place – Kafka and Zookeeper scale twell but are comparably dificult to configure and maintain – Simpler solutions might already sufice, e.g. copy cronjob, S3 and Airflotw ● Be atware that some logging platforms sort by time received instead of time logged (e.g. graylog) ● Further reading: „30 best practices for logging at scale“
  49. 49. Security: what not to log ● Sensitive business data – Passtwords – Credit card numbers – Session identifiers – Account numbers ● Personally identifiable information – Social security numbers (mostly USA problem though) – Birth dates – Full names – Email addresses – Driver’s license numbers ● Source: Get Started Quickly With Python Logging ● Discussion: IP addresses? GDPR?
  50. 50. Operations ● Logging to text file – Messy regular expressions to split log line into timestamp, level, message etc – Possible injections issues twith line breaks ● Logging to structured format (e.g. JSON) – Log entry is already separated into timestamp, level, message etc – Messages can have line breaks
  51. 51. Conclusion
  52. 52. Summary ● INFO: – doing vs done – Focus on business logic – Keep amount of messages lotw ● ERROR: – “cannot do something: something must be something else“ – Log vs throtw, avoid log and throtw ● FATAL: like error but only if the application cannot recover ● WARNING – Might hint at design issues – Fetw valid situations – Combines error and info message ● DEBUG – For developers – Log twhatever is necessary
  53. 53. Questions and answers Thomas Aglassinger http://www.roskakori.at @TAglassinger

×