first round of logger cleanup/migration

This commit is contained in:
Mark Harrah 2010-06-10 21:26:27 -04:00
parent 1584f01de8
commit e02adb0694
9 changed files with 142 additions and 34 deletions

View File

@ -1,15 +1,15 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
* Copyright 2008, 2009, 2010 Mark Harrah
*/
package xsbt
package sbt
/** Implements the level-setting methods of Logger.*/
abstract class BasicLogger extends Logger
abstract class BasicLogger extends AbstractLogger
{
private var traceEnabledVar = true
private var traceEnabledVar = java.lang.Integer.MAX_VALUE
private var level: Level.Value = Level.Info
def getLevel = level
def setLevel(newLevel: Level.Value) { level = newLevel }
def enableTrace(flag: Boolean) { traceEnabledVar = flag }
def traceEnabled = traceEnabledVar
}
def setTrace(level: Int) { traceEnabledVar = level }
def getTrace = traceEnabledVar
}

View File

@ -1,8 +1,9 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
* Copyright 2008, 2009, 2010 Mark Harrah
*/
package xsbt
import sbt.{AbstractLogger, ControlEvent, Level, Log, LogEvent, SetLevel, SetTrace, Success, Trace}
import scala.collection.mutable.ListBuffer
/** A logger that can buffer the logging done on it and then can flush the buffer
@ -13,7 +14,7 @@
*
* This class assumes that it is the only client of the delegate logger.
* */
class BufferedLogger(delegate: Logger) extends Logger
class BufferedLogger(delegate: AbstractLogger) extends AbstractLogger
{
private[this] val buffer = new ListBuffer[LogEvent]
private[this] var recording = false
@ -54,10 +55,10 @@ class BufferedLogger(delegate: Logger) extends Logger
}
def getLevel = delegate.getLevel
def traceEnabled = delegate.traceEnabled
def enableTrace(flag: Boolean)
def setTrace(level: Int)
{
buffer += new SetTrace(flag)
delegate.enableTrace(flag)
buffer += new SetTrace(level)
delegate.setTrace(level)
}
def trace(t: => Throwable): Unit =
@ -73,9 +74,9 @@ class BufferedLogger(delegate: Logger) extends Logger
delegate.logAll(events)
def control(event: ControlEvent.Value, message: => String): Unit =
doBufferable(Level.Info, new ControlEvent(event, message), _.control(event, message))
private def doBufferable(level: Level.Value, appendIfBuffered: => LogEvent, doUnbuffered: Logger => Unit): Unit =
private def doBufferable(level: Level.Value, appendIfBuffered: => LogEvent, doUnbuffered: AbstractLogger => Unit): Unit =
doBufferableIf(atLevel(level), appendIfBuffered, doUnbuffered)
private def doBufferableIf(condition: => Boolean, appendIfBuffered: => LogEvent, doUnbuffered: Logger => Unit): Unit =
private def doBufferableIf(condition: => Boolean, appendIfBuffered: => LogEvent, doUnbuffered: AbstractLogger => Unit): Unit =
if(condition)
{
if(recording)

View File

@ -1,7 +1,7 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
* Copyright 2008, 2009, 2010 Mark Harrah
*/
package xsbt
package sbt
object ConsoleLogger
{
@ -17,10 +17,12 @@ object ConsoleLogger
}
/** A logger that logs to the console. On supported systems, the level labels are
* colored. */
* colored.
*
* This logger is not thread-safe.*/
class ConsoleLogger extends BasicLogger
{
import ConsoleLogger.formatEnabled
override def ansiCodesSupported = ConsoleLogger.formatEnabled
def messageColor(level: Level.Value) = Console.RESET
def labelColor(level: Level.Value) =
level match
@ -39,8 +41,9 @@ class ConsoleLogger extends BasicLogger
def trace(t: => Throwable): Unit =
System.out.synchronized
{
if(traceEnabled)
t.printStackTrace
val traceLevel = getTrace
if(traceLevel >= 0)
System.out.synchronized { System.out.print(StackTrace.trimmed(t, traceLevel)) }
}
def log(level: Level.Value, message: => String)
{
@ -49,7 +52,7 @@ class ConsoleLogger extends BasicLogger
}
private def setColor(color: String)
{
if(formatEnabled)
if(ansiCodesSupported)
System.out.synchronized { System.out.print(color) }
}
private def log(labelColor: String, label: String, messageColor: String, message: String): Unit =

View File

@ -0,0 +1,35 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009, 2010 Mark Harrah
*/
package sbt
/** A filter logger is used to delegate messages but not the logging level to another logger. This means
* that messages are logged at the higher of the two levels set by this logger and its delegate.
* */
class FilterLogger(delegate: AbstractLogger) extends BasicLogger
{
override lazy val ansiCodesSupported = delegate.ansiCodesSupported
def trace(t: => Throwable)
{
if(traceEnabled)
delegate.trace(t)
}
override def setTrace(level: Int) { delegate.setTrace(level) }
override def getTrace = delegate.getTrace
def log(level: Level.Value, message: => String)
{
if(atLevel(level))
delegate.log(level, message)
}
def success(message: => String)
{
if(atLevel(Level.Info))
delegate.success(message)
}
def control(event: ControlEvent.Value, message: => String)
{
if(atLevel(Level.Info))
delegate.control(event, message)
}
def logAll(events: Seq[LogEvent]): Unit = delegate.logAll(events)
}

View File

@ -1,11 +1,11 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
*/
package xsbt
package sbt
/** An enumeration defining the levels available for logging. A level includes all of the levels
* with id larger than its own id. For example, Warn (id=3) includes Error (id=4).*/
object Level extends Enumeration with NotNull
object Level extends Enumeration
{
val Debug = Value(1, "debug")
val Info = Value(2, "info")
@ -16,10 +16,8 @@ object Level extends Enumeration with NotNull
* label is also defined here. */
val SuccessLabel = "success"
// added because elements was renamed to iterator in 2.8.0 nightly
def levels = Debug :: Info :: Warn :: Error :: Nil
/** Returns the level with the given name wrapped in Some, or None if no level exists for that name. */
def apply(s: String) = levels.find(s == _.toString)
def apply(s: String) = values.find(s == _.toString)
/** Same as apply, defined for use in pattern matching. */
private[xsbt] def unapply(s: String) = apply(s)
private[sbt] def unapply(s: String) = apply(s)
}

View File

@ -1,14 +1,14 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
*/
package xsbt
package sbt
sealed trait LogEvent extends NotNull
final class Success(val msg: String) extends LogEvent
final class Log(val level: Level.Value, val msg: String) extends LogEvent
final class Trace(val exception: Throwable) extends LogEvent
final class SetLevel(val newLevel: Level.Value) extends LogEvent
final class SetTrace(val enabled: Boolean) extends LogEvent
final class SetTrace(val level: Int) extends LogEvent
final class ControlEvent(val event: ControlEvent.Value, val msg: String) extends LogEvent
object ControlEvent extends Enumeration

View File

@ -1,18 +1,22 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
*/
package xsbt
package sbt
import xsbti.{Logger => xLogger, F0}
abstract class Logger extends xLogger with NotNull
abstract class AbstractLogger extends xLogger with NotNull
{
def getLevel: Level.Value
def setLevel(newLevel: Level.Value)
def enableTrace(flag: Boolean)
def traceEnabled: Boolean
def setTrace(flag: Int)
def getTrace: Int
final def traceEnabled = getTrace >= 0
def ansiCodesSupported = false
def atLevel(level: Level.Value) = level.id >= getLevel.id
def trace(t: => Throwable): Unit
final def verbose(message: => String): Unit = debug(message)
final def debug(message: => String): Unit = log(Level.Debug, message)
final def info(message: => String): Unit = log(Level.Info, message)
final def warn(message: => String): Unit = log(Level.Warn, message)
@ -31,7 +35,7 @@ abstract class Logger extends xLogger with NotNull
case l: Log => log(l.level, l.msg)
case t: Trace => trace(t.exception)
case setL: SetLevel => setLevel(setL.newLevel)
case setT: SetTrace => enableTrace(setT.enabled)
case setT: SetTrace => setTrace(setT.level)
case c: ControlEvent => control(c.event, c.msg)
}
}

View File

@ -0,0 +1,40 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009, 2010 Mark Harrah
*/
package sbt
/** Provides a `java.io.Writer` interface to a `Logger`. Content is line-buffered and logged at `level`.
* A line is delimited by `nl`, which is by default the platform line separator.*/
class LoggerWriter(delegate: AbstractLogger, level: Level.Value, nl: String) extends java.io.Writer
{
def this(delegate: AbstractLogger, level: Level.Value) = this(delegate, level, System.getProperty("line.separator"))
private[this] val buffer = new StringBuilder
override def close() = flush()
override def flush(): Unit =
synchronized {
if(buffer.length > 0)
{
log(buffer.toString)
buffer.clear()
}
}
override def write(content: Array[Char], offset: Int, length: Int): Unit =
synchronized {
buffer.append(content, offset, length)
process()
}
private[this] def process()
{
val i = buffer.indexOf(nl)
if(i >= 0)
{
log(buffer.substring(0, i))
buffer.delete(0, i + nl.length)
process()
}
}
private[this] def log(s: String): Unit = delegate.log(level, s)
}

View File

@ -0,0 +1,27 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009, 2010 Mark Harrah
*/
package sbt
class MultiLogger(delegates: List[AbstractLogger]) extends BasicLogger
{
override lazy val ansiCodesSupported = delegates.forall(_.ansiCodesSupported)
override def setLevel(newLevel: Level.Value)
{
super.setLevel(newLevel)
dispatch(new SetLevel(newLevel))
}
override def setTrace(level: Int)
{
super.setTrace(level)
dispatch(new SetTrace(level))
}
def trace(t: => Throwable) { dispatch(new Trace(t)) }
def log(level: Level.Value, message: => String) { dispatch(new Log(level, message)) }
def success(message: => String) { dispatch(new Success(message)) }
def logAll(events: Seq[LogEvent]) { delegates.foreach(_.logAll(events)) }
def control(event: ControlEvent.Value, message: => String) { delegates.foreach(_.control(event, message)) }
private def dispatch(event: LogEvent) { delegates.foreach(_.log(event)) }
}