Skip to content

Commit

Permalink
[split] util-logging: Gets correct method and class name in c.t.u.Log…
Browse files Browse the repository at this point in the history
…Record

RB_ID=248087
  • Loading branch information
mosesn authored and CI committed Jan 4, 2014
1 parent eb65af3 commit ff61ba5
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 7 deletions.
6 changes: 6 additions & 0 deletions util-logging/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
<version>1.6.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_2.9.2</artifactId>
<version>1.9.1</version>
<scope>test</scope>
</dependency>
<!-- project dependencies -->
<dependency>
<groupId>com.twitter</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ package com.twitter.logging

import java.util.{logging => javalog}

class LazyLogRecord(level: javalog.Level, messageGenerator: => AnyRef) extends LogRecord(level, "") {
class LazyLogRecord(
level: javalog.Level,
messageGenerator: => AnyRef
) extends LogRecord(level, "") {
// for each logged line, generate this string only once, regardless of how many handlers there are:
override lazy val getMessage = messageGenerator.toString
}
Expand All @@ -30,4 +33,4 @@ class LazyLogRecordUnformatted(level: javalog.Level, message: String, items: Any
extends LazyLogRecord(level, { message.format(items: _*) }) {
require(items.size > 0)
val preformatted = message
}
}
62 changes: 57 additions & 5 deletions util-logging/src/main/scala/com/twitter/logging/LogRecord.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,62 @@ package com.twitter.logging
import java.util.{logging => javalog}

/**
* Wrapper around {@link java.util.logging.LogRecord}.
* Wrapper around {@link java.util.logging.LogRecord}. Should only be accessed from a single thread.
*
* The only difference is around log time where messages by Java are formatted using
* {@link java.text.MessageFormat}, whereas this class formats using a regular
* {@link java.text.StringFormat}.
* Messages are formatted by Java's LogRecord using {@link java.text.MessageFormat} whereas
* this class uses a regular {@link java.text.StringFormat}
*
* This class takes {@link com.twitter.logging.Logger} into account when inferring the
* `sourceMethod` and `sourceClass` names.
*/
class LogRecord(level: javalog.Level, msg: String) extends javalog.LogRecord(level, msg)
class LogRecord(level: javalog.Level, msg: String) extends javalog.LogRecord(level, msg) {
private[this] var inferred = false
private[this] var sourceClassName: String = null
private[this] var sourceMethodName: String = null

// May be incorrect if called lazily
override def getSourceClassName(): String = {
if (!inferred)
infer()
sourceClassName
}

// May be incorrect if called lazily
override def getSourceMethodName(): String = {
if (!inferred)
infer()
sourceMethodName
}

override def setSourceClassName(name: String) {
inferred = true
sourceClassName = name
}

override def setSourceMethodName(name: String) {
inferred = true
sourceMethodName = name
}

private[this] def infer() {
// TODO: there is a small optimization we can do in jdk7 with new JavaLangAccess
val stack = Thread.currentThread.getStackTrace()

def notTwitterString(elt: StackTraceElement): Boolean =
elt.getClassName != LogRecord.twitterString

// Find the first non-Logger StackTraceElement after the first occurrence of Logger.
val elt = stack dropWhile notTwitterString find notTwitterString

val (cName, mName) = elt match {
case Some(element) => (element.getClassName, element.getMethodName)
case None => (super.getSourceClassName, super.getSourceMethodName)
}
setSourceMethodName(mName)
setSourceClassName(cName)
}
}

object LogRecord {
private[logging] val twitterString = "com.twitter.logging.Logger"
}
1 change: 1 addition & 0 deletions util-logging/src/test/scala/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ junit_tests(name='scala',
pants('3rdparty:junit'),
pants('3rdparty:mockito-all'),
pants('3rdparty:specs'),
pants('3rdparty:scalatest'),
pants('util/util-core/src/main/scala'),
pants('util/util-logging/src/main/scala'),
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.twitter.logging

import java.util.logging.{Level => JLevel, LogRecord => JRecord}
import org.junit.runner.RunWith
import org.scalatest.FunSuite
import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner])
class LogRecordTest extends FunSuite {
test("LogRecord should getMethod properly") {
Logger.withLoggers(Nil) {
new LogRecordTestHelper({ r: JRecord => r.getSourceMethodName() }) {
def makingLogRecord() {
logger.log(Level.INFO, "OK")
assert(handler.get === "makingLogRecord")
}
makingLogRecord()
}
}
}

test("LogRecord should getClass properly") {
Logger.withLoggers(Nil) {
new Foo {
assert(handler.get === "com.twitter.logging.Foo")
}
}
}
}

abstract class LogRecordTestHelper(formats: JRecord => String) {
val formatter = new Formatter {
override def format(r: JRecord): String = formats(r)
}
val handler = new StringHandler(formatter)
val logger = Logger.get("")
logger.addHandler(handler)
}

class Foo extends LogRecordTestHelper({ r: JRecord => r.getSourceClassName() }) {
def makingLogRecord() {
logger.log(Level.INFO, "OK")
}

makingLogRecord()
}

0 comments on commit ff61ba5

Please sign in to comment.