Git Product home page Git Product logo

logula's Introduction

Logula

Bwah ah ah ah.

Logula is a Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

It's a thin front-end for log4j 1.2 because java.util.logging was a pain in the neck to deal with.

Requirements

  • Java SE 6
  • Scala 2.8.1 or 2.9.0-1
  • log4j 1.2

How To Use

First, specify Logula as a dependency:

<repositories>
  <repository>
    <id>repo.codahale.com</id>
    <url>http://repo.codahale.com</url>
  </repository>
</repositories>

<dependencies>
  <dependency>
    <groupId>com.codahale</groupId>
    <artifactId>logula_${scala.version}</artifactId>
    <version>2.1.3</version>
  </dependency>
</dependencies>

Second, configure the logging system:

import com.codahale.logula.Logging
import org.apache.log4j.Level

Logging.configure { log =>
  log.registerWithJMX = true

  log.level = Level.INFO
  log.loggers("com.myproject.weebits") = Level.OFF

  log.console.enabled = true
  log.console.threshold = Level.WARN

  log.file.enabled = true
  log.file.filename = "/var/log/myapp/myapp.log"
  log.file.maxSize = 10 * 1024 // KB
  log.file.retainedFiles = 5 // keep five old logs around

  // syslog integration is always via a network socket
  log.syslog.enabled = true
  log.syslog.host = "syslog-001.internal.example.com"
  log.syslog.facility = "local3"
}

Third, add some logging to your classes:

class MyThing extends Logging {
  def complicatedManoeuvre() {
    try {
      log.warn("This is about to get complicated...")
      log.info("Trying to do %d backflips", backflipsToAttempt)
      // complicated bit elided
    } catch {
      case e: Exception => log.error(e, "Horrible things have happened.")
    }
  }
}

Notice that the logging statements use Scala's formatting syntax, and that logged exceptions are passed as the first argument.

Statement Arguments

Unlike a lot of Scala logging libraries, Logula doesn't use pass-by-name semantics (e.g., f: => A) for its logging statements, which means two things:

  1. The Scala compiler doesn't have to create one-off closure objects for each logging statement. This should reduce the amount of garbage collection pressure.
  2. If your logging arguments are complex to create, that price will be paid regardless of whether or not the statement is logged.

For example:

log.debug("A huge collection: %s", things.mkString(", "))

The mkString call will happen every time. To prevent this, either keep your arguments simple:

log.debug("A huge collection: %s", things)

or only conditionally log them:

if (log.isDebugEnabled) {
  log.debug("A huge collection: %s", things.mkString(", "))
}

In most cases, it's simple enough to just log basic values.

The Log Format

Logula's log format has a few specific goals.

  • Be roughly human readable. You shouldn't need another program to make sense of your program.
  • Be machine parsable. You shouldn't need another human to make sense of your program. (Shush.)
  • Make it easy for sleepy ops folks to figure out why things are pear-shaped at o'dark-thirty using standard UNIXy tools like tail, grep, and fortune.

An example of logging output looks like this:

TRACE [2010-04-06 06:42:35,271] com.codahale.logula.examples.ThingDoer: Contemplating doing a thing.
DEBUG [2010-04-06 06:42:35,274] com.codahale.logula.examples.ThingDoer: About to do a thing.
INFO  [2010-04-06 06:42:35,274] com.codahale.logula.examples.ThingDoer: Doing a thing
WARN  [2010-04-06 06:42:35,275] com.codahale.logula.examples.ThingDoer: Doing a thing
ERROR [2010-04-06 06:42:35,275] com.codahale.logula.examples.ThingDoer: This may get ugly.
FATAL [2010-04-06 06:42:35,275] com.codahale.logula.examples.ThingDoer: The thing has gone horribly wrong.
! java.lang.RuntimeException: oh noes!
! 	at scala.Predef$.error(Predef.scala:74)
! 	at com.codahale.logula.examples.ThingDoer.run(ExampleLoggingRun.scala:16)
! 	at com.codahale.logula.examples.ExampleLoggingRun$.main(ExampleLoggingRun.scala:40)
! 	at com.codahale.logula.examples.ExampleLoggingRun.main(ExampleLoggingRun.scala)
! 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
! 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
! 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
! 	at java.lang.reflect.Method.invoke(Method.java:597)
! 	at sbt.Run.run0(Run.scala:60)
! 	at sbt.Run.execute$1(Run.scala:47)
! 	at sbt.Run$$anonfun$run$2.apply(Run.scala:50)
! 	at sbt.Run$$anonfun$run$2.apply(Run.scala:50)
! 	at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
! 	at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)
! 

A few items of note:

  • All timestamps are in UTC and ISO 8601 format. This really should be OK with you.
  • You can grep for messages of a specific level really easily: tail -f logula.log | grep '^WARN'
  • You can grep for messages from a specific class or package really easily: tail -f logula.log | grep 'ThingDoer'
  • You can even pull out full exception stack traces, plus the accompanying log message: tail -f logula.log | grep -B 1 '^\!'
  • If you squint, you can still make out the actual log messages.

License

Copyright (c) 2010-2011 Coda Hale

Published under The MIT License, see LICENSE

logula's People

Contributors

codahale avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

logula's Issues

Please publish to oss.sonatype.org

Logula is diffcult to use for maven users who use a repo manager like Nexus:
http://groups.google.com/group/scalaxb/browse_thread/thread/2cd59743c6e4b1fe

It involves adding a repo to Nexus; configuring any groups that should include the new repo; and setting up routing to ensure that dependencies aren't pulled from a repository that shouldn't be provided a given groupId.

Please deploy to oss.sonatype.org or central, which users are more likely to have set up in their repo manager already.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.