This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Repository files navigation

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:

importcom.codahale.logula.Loggingimportorg.apache.log4j.LevelLogging.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:

classMyThingextendsLogging {
defcomplicatedManoeuvre() {
try {
log.warn("This is about to get complicated...")
log.info("Trying to do %d backflips", backflipsToAttempt)
// complicated bit elided
} catch {
casee: 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

About

[ABANDONED] A Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Repository files navigation

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:

importcom.codahale.logula.Loggingimportorg.apache.log4j.LevelLogging.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:

classMyThingextendsLogging {
defcomplicatedManoeuvre() {
try {
log.warn("This is about to get complicated...")
log.info("Trying to do %d backflips", backflipsToAttempt)
// complicated bit elided
} catch {
casee: 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

About

[ABANDONED] A Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Repository files navigation

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:

importcom.codahale.logula.Loggingimportorg.apache.log4j.LevelLogging.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:

classMyThingextendsLogging {
defcomplicatedManoeuvre() {
try {
log.warn("This is about to get complicated...")
log.info("Trying to do %d backflips", backflipsToAttempt)
// complicated bit elided
} catch {
casee: 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

About

[ABANDONED] A Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Repository files navigation

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:

importcom.codahale.logula.Loggingimportorg.apache.log4j.LevelLogging.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:

classMyThingextendsLogging {
defcomplicatedManoeuvre() {
try {
log.warn("This is about to get complicated...")
log.info("Trying to do %d backflips", backflipsToAttempt)
// complicated bit elided
} catch {
casee: 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

About

[ABANDONED] A Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Repository files navigation

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:

importcom.codahale.logula.Loggingimportorg.apache.log4j.LevelLogging.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:

classMyThingextendsLogging {
defcomplicatedManoeuvre() {
try {
log.warn("This is about to get complicated...")
log.info("Trying to do %d backflips", backflipsToAttempt)
// complicated bit elided
} catch {
casee: 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

About

[ABANDONED] A Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Repository files navigation

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:

importcom.codahale.logula.Loggingimportorg.apache.log4j.LevelLogging.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:

classMyThingextendsLogging {
defcomplicatedManoeuvre() {
try {
log.warn("This is about to get complicated...")
log.info("Trying to do %d backflips", backflipsToAttempt)
// complicated bit elided
} catch {
casee: 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

About

[ABANDONED] A Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Repository files navigation

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:

importcom.codahale.logula.Loggingimportorg.apache.log4j.LevelLogging.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:

classMyThingextendsLogging {
defcomplicatedManoeuvre() {
try {
log.warn("This is about to get complicated...")
log.info("Trying to do %d backflips", backflipsToAttempt)
// complicated bit elided
} catch {
casee: 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

About

[ABANDONED] A Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Repository files navigation

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:

importcom.codahale.logula.Loggingimportorg.apache.log4j.LevelLogging.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:

classMyThingextendsLogging {
defcomplicatedManoeuvre() {
try {
log.warn("This is about to get complicated...")
log.info("Trying to do %d backflips", backflipsToAttempt)
// complicated bit elided
} catch {
casee: 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

About

[ABANDONED] A Scala library which provides a sane log output format and an easy-to-use mixin for adding logging to your code.

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages