mirror of https://github.com/sbt/sbt.git
first round of logger cleanup/migration
This commit is contained in:
parent
64618fe56a
commit
0d24118d93
|
|
@ -18,7 +18,7 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
|
|||
val classpathSub = baseProject(utilPath / "classpath", "Classpath")
|
||||
|
||||
val ivySub = project("ivy", "Ivy", new IvyProject(_), interfaceSub, launchInterfaceSub)
|
||||
val logSub = baseProject(utilPath / "log", "Logging", interfaceSub)
|
||||
val logSub = project(utilPath / "log", "Logging", new LogProject(_), interfaceSub)
|
||||
val datatypeSub = baseProject("util" /"datatype", "Datatype Generator", ioSub)
|
||||
|
||||
val testSub = project("scripted", "Test", new TestProject(_), ioSub)
|
||||
|
|
@ -37,7 +37,6 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
|
|||
val sbtSub = project(sbtPath, "Simple Build Tool", new SbtProject(_) {}, compilerSub, launchInterfaceSub)
|
||||
val installerSub = project(sbtPath / "install", "Installer", new InstallerProject(_) {}, sbtSub)
|
||||
|
||||
|
||||
lazy val dist = task { None } dependsOn(launchSub.proguard, sbtSub.publishLocal, installerSub.publishLocal)
|
||||
|
||||
def baseProject(path: Path, name: String, deps: Project*) = project(path, name, new Base(_), deps : _*)
|
||||
|
|
@ -85,13 +84,17 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
|
|||
}
|
||||
trait TestDependencies extends Project
|
||||
{
|
||||
val sc = "org.scala-tools.testing" %% "scalacheck" % "1.6" % "test"
|
||||
val sc = "org.scala-tools.testing" %% "scalacheck" % "1.7" % "test"
|
||||
val sp = "org.scala-tools.testing" % "specs" % "1.6.0" % "test"
|
||||
}
|
||||
class StandardTaskProject(info: ProjectInfo) extends Base(info)
|
||||
{
|
||||
override def testClasspath = super.testClasspath +++ compilerSub.testClasspath --- compilerInterfaceClasspath
|
||||
}
|
||||
class LogProject(info: ProjectInfo) extends Base(info)
|
||||
{
|
||||
val jline = jlineDep
|
||||
}
|
||||
|
||||
class IOProject(info: ProjectInfo) extends Base(info) with TestDependencies
|
||||
class TaskProject(info: ProjectInfo) extends Base(info) with TestDependencies
|
||||
|
|
|
|||
|
|
@ -5,140 +5,8 @@ package sbt
|
|||
|
||||
import scala.collection.mutable.{Buffer, HashMap, ListBuffer}
|
||||
|
||||
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 level: Int) extends LogEvent
|
||||
final class ControlEvent(val event: ControlEvent.Value, val msg: String) extends LogEvent
|
||||
|
||||
object ControlEvent extends Enumeration
|
||||
{
|
||||
val Start, Header, Finish = Value
|
||||
}
|
||||
|
||||
abstract class Logger extends xsbt.CompileLogger with IvyLogger
|
||||
{
|
||||
def getLevel: Level.Value
|
||||
def setLevel(newLevel: Level.Value)
|
||||
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)
|
||||
final def error(message: => String): Unit = log(Level.Error, message)
|
||||
def success(message: => String): Unit
|
||||
def log(level: Level.Value, message: => String): Unit
|
||||
def control(event: ControlEvent.Value, message: => String): Unit
|
||||
|
||||
def logAll(events: Seq[LogEvent]): Unit
|
||||
/** Defined in terms of other methods in Logger and should not be called from them. */
|
||||
final def log(event: LogEvent)
|
||||
{
|
||||
event match
|
||||
{
|
||||
case s: Success => success(s.msg)
|
||||
case l: Log => log(l.level, l.msg)
|
||||
case t: Trace => trace(t.exception)
|
||||
case setL: SetLevel => setLevel(setL.newLevel)
|
||||
case setT: SetTrace => setTrace(setT.level)
|
||||
case c: ControlEvent => control(c.event, c.msg)
|
||||
}
|
||||
}
|
||||
|
||||
import xsbti.F0
|
||||
def debug(msg: F0[String]): Unit = log(Level.Debug, msg)
|
||||
def warn(msg: F0[String]): Unit = log(Level.Warn, msg)
|
||||
def info(msg: F0[String]): Unit = log(Level.Info, msg)
|
||||
def error(msg: F0[String]): Unit = log(Level.Error, msg)
|
||||
def trace(msg: F0[Throwable]) = trace(msg.apply)
|
||||
def log(level: Level.Value, msg: F0[String]): Unit = log(level, msg.apply)
|
||||
}
|
||||
|
||||
/** Implements the level-setting methods of Logger.*/
|
||||
abstract class BasicLogger extends Logger
|
||||
{
|
||||
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 setTrace(level: Int) { traceEnabledVar = level }
|
||||
def getTrace = traceEnabledVar
|
||||
}
|
||||
|
||||
final class SynchronizedLogger(delegate: Logger) extends Logger
|
||||
{
|
||||
override lazy val ansiCodesSupported = delegate.ansiCodesSupported
|
||||
def getLevel = { synchronized { delegate.getLevel } }
|
||||
def setLevel(newLevel: Level.Value) { synchronized { delegate.setLevel(newLevel) } }
|
||||
def setTrace(level: Int) { synchronized { delegate.setTrace(level) } }
|
||||
def getTrace: Int = { synchronized { delegate.getTrace } }
|
||||
|
||||
def trace(t: => Throwable) { synchronized { delegate.trace(t) } }
|
||||
def log(level: Level.Value, message: => String) { synchronized { delegate.log(level, message) } }
|
||||
def success(message: => String) { synchronized { delegate.success(message) } }
|
||||
def control(event: ControlEvent.Value, message: => String) { synchronized { delegate.control(event, message) } }
|
||||
def logAll(events: Seq[LogEvent]) { synchronized { delegate.logAll(events) } }
|
||||
}
|
||||
|
||||
final class MultiLogger(delegates: List[Logger]) 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)) }
|
||||
}
|
||||
|
||||
/** 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.
|
||||
* */
|
||||
final class FilterLogger(delegate: Logger) 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)
|
||||
}
|
||||
trait Logger extends AbstractLogger with xsbt.CompileLogger with IvyLogger
|
||||
|
||||
/** A logger that can buffer the logging done on it by currently executing Thread and
|
||||
* then can flush the buffer to the delegate logger provided in the constructor. Use
|
||||
|
|
@ -151,7 +19,7 @@ final class FilterLogger(delegate: Logger) extends BasicLogger
|
|||
*
|
||||
* This logger is thread-safe.
|
||||
* */
|
||||
final class BufferedLogger(delegate: Logger) extends Logger
|
||||
final class BufferedLogger(delegate: AbstractLogger) extends Logger
|
||||
{
|
||||
override lazy val ansiCodesSupported = delegate.ansiCodesSupported
|
||||
private[this] val buffers = wrap.Wrappers.weakMap[Thread, Buffer[LogEvent]]
|
||||
|
|
@ -244,9 +112,9 @@ final class BufferedLogger(delegate: Logger) extends Logger
|
|||
}
|
||||
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 =
|
||||
synchronized
|
||||
{
|
||||
if(condition)
|
||||
|
|
@ -259,134 +127,3 @@ final class BufferedLogger(delegate: Logger) extends Logger
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ConsoleLogger
|
||||
{
|
||||
private val formatEnabled = ansiSupported && !formatExplicitlyDisabled
|
||||
|
||||
private[this] def formatExplicitlyDisabled = java.lang.Boolean.getBoolean("sbt.log.noformat")
|
||||
private[this] def ansiSupported =
|
||||
try { jline.Terminal.getTerminal.isANSISupported }
|
||||
catch { case e: Exception => !isWindows }
|
||||
|
||||
private[this] def os = System.getProperty("os.name")
|
||||
private[this] def isWindows = os.toLowerCase.indexOf("windows") >= 0
|
||||
}
|
||||
|
||||
/** A logger that logs to the console. On supported systems, the level labels are
|
||||
* colored.
|
||||
*
|
||||
* This logger is not thread-safe.*/
|
||||
class ConsoleLogger extends BasicLogger
|
||||
{
|
||||
override def ansiCodesSupported = ConsoleLogger.formatEnabled
|
||||
def messageColor(level: Level.Value) = Console.RESET
|
||||
def labelColor(level: Level.Value) =
|
||||
level match
|
||||
{
|
||||
case Level.Error => Console.RED
|
||||
case Level.Warn => Console.YELLOW
|
||||
case _ => Console.RESET
|
||||
}
|
||||
def successLabelColor = Console.GREEN
|
||||
def successMessageColor = Console.RESET
|
||||
override def success(message: => String)
|
||||
{
|
||||
if(atLevel(Level.Info))
|
||||
log(successLabelColor, Level.SuccessLabel, successMessageColor, message)
|
||||
}
|
||||
def trace(t: => Throwable): Unit =
|
||||
System.out.synchronized
|
||||
{
|
||||
val traceLevel = getTrace
|
||||
if(traceLevel >= 0)
|
||||
System.out.synchronized { System.out.print(StackTrace.trimmed(t, traceLevel)) }
|
||||
}
|
||||
def log(level: Level.Value, message: => String)
|
||||
{
|
||||
if(atLevel(level))
|
||||
log(labelColor(level), level.toString, messageColor(level), message)
|
||||
}
|
||||
private def setColor(color: String)
|
||||
{
|
||||
if(ansiCodesSupported)
|
||||
System.out.synchronized { System.out.print(color) }
|
||||
}
|
||||
private def log(labelColor: String, label: String, messageColor: String, message: String): Unit =
|
||||
System.out.synchronized
|
||||
{
|
||||
for(line <- message.split("""\n"""))
|
||||
{
|
||||
setColor(Console.RESET)
|
||||
System.out.print('[')
|
||||
setColor(labelColor)
|
||||
System.out.print(label)
|
||||
setColor(Console.RESET)
|
||||
System.out.print("] ")
|
||||
setColor(messageColor)
|
||||
System.out.print(line)
|
||||
setColor(Console.RESET)
|
||||
System.out.println()
|
||||
}
|
||||
}
|
||||
|
||||
def logAll(events: Seq[LogEvent]) = System.out.synchronized { events.foreach(log) }
|
||||
def control(event: ControlEvent.Value, message: => String)
|
||||
{ log(labelColor(Level.Info), Level.Info.toString, Console.BLUE, message) }
|
||||
}
|
||||
|
||||
/** 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
|
||||
{
|
||||
val Debug = Value(1, "debug")
|
||||
val Info = Value(2, "info")
|
||||
val Warn = Value(3, "warn")
|
||||
val Error = Value(4, "error")
|
||||
/** Defines the label to use for success messages. A success message is logged at the info level but
|
||||
* uses this label. Because the label for levels is defined in this module, the success
|
||||
* 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)
|
||||
/** Same as apply, defined for use in pattern matching. */
|
||||
private[sbt] def unapply(s: String) = apply(s)
|
||||
}
|
||||
/** 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.*/
|
||||
final class LoggerWriter(delegate: Logger, level: Level.Value, nl: String) extends java.io.Writer
|
||||
{
|
||||
def this(delegate: Logger, level: Level.Value) = this(delegate, level, FileUtilities.Newline)
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -416,7 +416,7 @@ class xMain extends xsbti.AppMain
|
|||
val ContinuousCompilePollDelaySeconds = 1
|
||||
|
||||
/** The list of logging levels.*/
|
||||
private def logLevels: Iterable[String] = TreeSet.empty[String] ++ Level.levels.map(_.toString)
|
||||
private def logLevels: Iterable[String] = TreeSet.empty[String] ++ Level.values.map(_.toString)
|
||||
/** The list of all interactive commands other than logging level.*/
|
||||
private def basicCommands: Iterable[String] = TreeSet(ShowProjectsAction, ShowActions, ShowCurrent, HelpAction,
|
||||
RebootCommand, TraceCommand, ContinuousCompileCommand, ProjectConsoleAction, BuilderCommand) ++
|
||||
|
|
@ -464,7 +464,7 @@ class xMain extends xsbti.AppMain
|
|||
printCmd(RebootCommand, "Reloads sbt, picking up modifications to sbt.version or scala.version and recompiling modified project definitions.")
|
||||
printCmd(HelpAction, "Displays this help message.")
|
||||
printCmd(ShowCurrent, "Shows the current project, Scala version, and logging level.")
|
||||
printCmd(Level.levels.mkString(", "), "Set logging for the current project to the specified level.")
|
||||
printCmd(Level.values.mkString(", "), "Set logging for the current project to the specified level.")
|
||||
printCmd(TraceCommand + " " + validTraceArguments, "Configures stack trace logging. " + traceExplanation)
|
||||
printCmd(ProjectAction + " <project name>", "Sets the currently active project.")
|
||||
printCmd(ShowProjectsAction, "Shows all available projects.")
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ object LogWriterTest extends Properties("Log Writer")
|
|||
for(ls <- arbList[List[ToLog]].arbitrary; lv <- genLevel) yield
|
||||
new Output(ls, lv)
|
||||
|
||||
def levelsGen: Seq[Gen[Level.Value]] = Level.elements.toList.map(x => value(x))
|
||||
def levelsGen: Seq[Gen[Level.Value]] = Level.values.toList.map(x => value(x))
|
||||
|
||||
def removeNewlines(s: String) = s.replaceAll("""[\n\r]+""", "")
|
||||
def addNewline(l: ToLog): ToLog =
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009, 2010 Mark Harrah
|
||||
*/
|
||||
package xsbt.api
|
||||
package xsbt
|
||||
package api
|
||||
|
||||
import java.io.File
|
||||
import xsbt.FileUtilities
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)) }
|
||||
}
|
||||
Loading…
Reference in New Issue