/README.md

http://github.com/codahale/logula · Markdown · 181 lines · 137 code · 44 blank · 0 comment · 0 complexity · 61fcf4636a172cd6df0db90711a3a401 MD5 · raw file

  1. Logula
  2. ======
  3. *Bwah ah ah ah.*
  4. [Logula](http://github.com/codahale/logula) is a Scala library which provides a
  5. sane log output format and an easy-to-use mixin for adding logging to your code.
  6. It's a thin front-end for [log4j 1.2](http://logging.apache.org/log4j/1.2/)
  7. because `java.util.logging` was a pain in the neck to deal with.
  8. Requirements
  9. ------------
  10. * Java SE 6
  11. * Scala 2.8.1 or 2.9.0-1
  12. * log4j 1.2
  13. How To Use
  14. ----------
  15. **First**, specify Logula as a dependency:
  16. ```xml
  17. <repositories>
  18. <repository>
  19. <id>repo.codahale.com</id>
  20. <url>http://repo.codahale.com</url>
  21. </repository>
  22. </repositories>
  23. <dependencies>
  24. <dependency>
  25. <groupId>com.codahale</groupId>
  26. <artifactId>logula_${scala.version}</artifactId>
  27. <version>2.1.3</version>
  28. </dependency>
  29. </dependencies>
  30. ```
  31. **Second**, configure the logging system:
  32. ```scala
  33. import com.codahale.logula.Logging
  34. import org.apache.log4j.Level
  35. Logging.configure { log =>
  36. log.registerWithJMX = true
  37. log.level = Level.INFO
  38. log.loggers("com.myproject.weebits") = Level.OFF
  39. log.console.enabled = true
  40. log.console.threshold = Level.WARN
  41. log.file.enabled = true
  42. log.file.filename = "/var/log/myapp/myapp.log"
  43. log.file.maxSize = 10 * 1024 // KB
  44. log.file.retainedFiles = 5 // keep five old logs around
  45. // syslog integration is always via a network socket
  46. log.syslog.enabled = true
  47. log.syslog.host = "syslog-001.internal.example.com"
  48. log.syslog.facility = "local3"
  49. }
  50. ```
  51. **Third**, add some logging to your classes:
  52. ```scala
  53. class MyThing extends Logging {
  54. def complicatedManoeuvre() {
  55. try {
  56. log.warn("This is about to get complicated...")
  57. log.info("Trying to do %d backflips", backflipsToAttempt)
  58. // complicated bit elided
  59. } catch {
  60. case e: Exception => log.error(e, "Horrible things have happened.")
  61. }
  62. }
  63. }
  64. ```
  65. Notice that the logging statements use Scala's formatting syntax, and that
  66. logged exceptions are passed as the first argument.
  67. Statement Arguments
  68. -------------------
  69. Unlike a lot of Scala logging libraries, Logula doesn't use pass-by-name
  70. semantics (e.g., `f: => A`) for its logging statements, which means two things:
  71. 1. The Scala compiler doesn't have to create one-off closure objects for each
  72. logging statement. This should reduce the amount of garbage collection
  73. pressure.
  74. 2. If your logging arguments are complex to create, that price will be paid
  75. regardless of whether or not the statement is logged.
  76. For example:
  77. ```scala
  78. log.debug("A huge collection: %s", things.mkString(", "))
  79. ```
  80. The `mkString` call will happen every time. To prevent this, either keep your
  81. arguments simple:
  82. ```scala
  83. log.debug("A huge collection: %s", things)
  84. ```
  85. or only conditionally log them:
  86. ```scala
  87. if (log.isDebugEnabled) {
  88. log.debug("A huge collection: %s", things.mkString(", "))
  89. }
  90. ```
  91. In most cases, it's simple enough to just log basic values.
  92. The Log Format
  93. --------------
  94. Logula's log format has a few specific goals.
  95. * Be roughly human readable. You shouldn't need another program to make sense of
  96. your program.
  97. * Be machine parsable. You shouldn't need another human to make sense of your
  98. program. (Shush.)
  99. * Make it easy for sleepy ops folks to figure out why things are pear-shaped at
  100. o'dark-thirty using standard UNIXy tools like `tail`, `grep`, and `fortune`.
  101. An example of logging output looks like this:
  102. TRACE [2010-04-06 06:42:35,271] com.codahale.logula.examples.ThingDoer: Contemplating doing a thing.
  103. DEBUG [2010-04-06 06:42:35,274] com.codahale.logula.examples.ThingDoer: About to do a thing.
  104. INFO [2010-04-06 06:42:35,274] com.codahale.logula.examples.ThingDoer: Doing a thing
  105. WARN [2010-04-06 06:42:35,275] com.codahale.logula.examples.ThingDoer: Doing a thing
  106. ERROR [2010-04-06 06:42:35,275] com.codahale.logula.examples.ThingDoer: This may get ugly.
  107. FATAL [2010-04-06 06:42:35,275] com.codahale.logula.examples.ThingDoer: The thing has gone horribly wrong.
  108. ! java.lang.RuntimeException: oh noes!
  109. ! at scala.Predef$.error(Predef.scala:74)
  110. ! at com.codahale.logula.examples.ThingDoer.run(ExampleLoggingRun.scala:16)
  111. ! at com.codahale.logula.examples.ExampleLoggingRun$.main(ExampleLoggingRun.scala:40)
  112. ! at com.codahale.logula.examples.ExampleLoggingRun.main(ExampleLoggingRun.scala)
  113. ! at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  114. ! at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  115. ! at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  116. ! at java.lang.reflect.Method.invoke(Method.java:597)
  117. ! at sbt.Run.run0(Run.scala:60)
  118. ! at sbt.Run.execute$1(Run.scala:47)
  119. ! at sbt.Run$$anonfun$run$2.apply(Run.scala:50)
  120. ! at sbt.Run$$anonfun$run$2.apply(Run.scala:50)
  121. ! at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
  122. ! at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)
  123. !
  124. A few items of note:
  125. * All timestamps are in UTC and ISO 8601 format. This really should be OK with
  126. you.
  127. * You can grep for messages of a specific level really easily:
  128. `tail -f logula.log | grep '^WARN'`
  129. * You can grep for messages from a specific class or package really easily:
  130. `tail -f logula.log | grep 'ThingDoer'`
  131. * You can even pull out full exception stack traces, plus the accompanying
  132. log message: `tail -f logula.log | grep -B 1 '^\!'`
  133. * If you squint, you can still make out the actual log messages.
  134. License
  135. -------
  136. Copyright (c) 2010-2011 Coda Hale
  137. Published under The MIT License, see LICENSE