From f4b61e2a28a6eb537dda1136859e7a51429e8adf Mon Sep 17 00:00:00 2001 From: Ilya Murzinov Date: Mon, 11 Dec 2017 18:54:26 +0300 Subject: [issue-39] add logging output to file (#53) --- core/src/main/scala/mill/Main.scala | 2 +- core/src/main/scala/mill/eval/Evaluator.scala | 39 ++++++++++++++++----- core/src/main/scala/mill/util/Logger.scala | 50 +++++++++++++++++++++------ 3 files changed, 72 insertions(+), 19 deletions(-) (limited to 'core') diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala index df9e0dc6..afc59e33 100644 --- a/core/src/main/scala/mill/Main.scala +++ b/core/src/main/scala/mill/Main.scala @@ -93,7 +93,7 @@ object Main { case _ => Nil } target <- mill.main.Resolve.resolve(sel, disc.mirror, obj, rest, crossSelectors, Nil) - evaluator = new Evaluator(pwd / 'out, Discovered.mapping(obj)(disc), log) + evaluator = new Evaluator(pwd / 'out, Discovered.mapping(obj)(disc), log, sel) _ <- evaluate(evaluator, target, watch).toLeft(()) } yield () diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala index 96c868e9..b4f4413f 100644 --- a/core/src/main/scala/mill/eval/Evaluator.scala +++ b/core/src/main/scala/mill/eval/Evaluator.scala @@ -1,12 +1,11 @@ package mill.eval -import java.io.PrintStream - import ammonite.ops._ import ammonite.runtime.SpecialClassLoader import mill.define.{Graph, Target, Task} import mill.discover.Mirror import mill.discover.Mirror.LabelledTarget +import mill.discover.Mirror.Segment.{Cross, Label} import mill.util import mill.util._ @@ -14,7 +13,8 @@ import scala.collection.mutable class Evaluator(workspacePath: Path, labeling: Map[Target[_], LabelledTarget[_]], - log: Logger){ + log: Logger, + sel: List[Mirror.Segment] = List()){ def evaluate(goals: OSet[Task[_]]): Evaluator.Results = { mkdir(workspacePath) @@ -155,6 +155,8 @@ class Evaluator(workspacePath: Path, if(logRun) { log.info("Running " + targetLabel) } } + val multiLogger = resolveLogger(targetDestPath) + for (target <- nonEvaluatedTargets) { newEvaluated.append(target) @@ -168,15 +170,16 @@ class Evaluator(workspacePath: Path, val args = new Ctx( targetInputValues.toArray[Any], targetDestPath.orNull, - log + multiLogger ) + val out = System.out val err = System.err try{ - System.setErr(log.outputStream) - System.setOut(log.outputStream) - Console.withOut(log.outputStream){ - Console.withErr(log.outputStream){ + System.setErr(multiLogger.outputStream) + System.setOut(multiLogger.outputStream) + Console.withOut(multiLogger.outputStream){ + Console.withErr(multiLogger.outputStream){ target.evaluate(args) } } @@ -189,9 +192,29 @@ class Evaluator(workspacePath: Path, newResults(target) = res } + multiLogger.close() + (newResults, newEvaluated) } + def resolveLogger(targetDestPath: Option[Path]): Logger = { + if (targetDestPath.isEmpty && sel.isEmpty) + log + else { + val path = targetDestPath.getOrElse( + sel.foldLeft[Path](pwd / 'out) { + case (d, Label(s)) => d / s + case (d, Cross(args)) => d / args.map(_.toString) + } + ) + val dir = path / up + mkdir(dir) + val file = dir / (path.last + ".log") + rm(file) + MultiLogger(log, FileLogger(file)) + } + } + } diff --git a/core/src/main/scala/mill/util/Logger.scala b/core/src/main/scala/mill/util/Logger.scala index ba8aa95f..d988c1fc 100644 --- a/core/src/main/scala/mill/util/Logger.scala +++ b/core/src/main/scala/mill/util/Logger.scala @@ -1,29 +1,59 @@ package mill.util -import java.io.{OutputStream, PrintStream} +import java.io.{FileOutputStream, PrintStream} +import ammonite.ops.Path import ammonite.util.Colors -trait Logger{ +trait Logger { val outputStream: PrintStream def info(s: String): Unit def error(s: String): Unit + def close(): Unit = () } -object DummyLogger extends Logger{ - object outputStream extends PrintStream(new OutputStream { - def write(b: Int) = () - }) +object DummyLogger extends Logger { + object outputStream extends PrintStream(_ => ()) def info(s: String) = () def error(s: String) = () } -class PrintLogger(coloredOutput: Boolean) extends Logger{ - val outputStream = System.err + +case class PrintLogger(coloredOutput: Boolean) extends Logger { + val outputStream: PrintStream = System.err + val colors = if(coloredOutput) Colors.Default else Colors.BlackWhite - def info(s: String) = System.err.println(colors.info()(s)) - def error(s: String) = System.err.println(colors.error()(s)) + def info(s: String) = outputStream.println(colors.info()(s)) + def error(s: String) = outputStream.println(colors.error()(s)) +} + +case class FileLogger(file: Path) extends Logger { + private[this] var outputStreamUsed: Boolean = false + + lazy val outputStream = { + outputStreamUsed = true + new PrintStream(new FileOutputStream(file.toIO.getAbsolutePath)) + } + + def info(s: String) = outputStream.println(s) + def error(s: String) = outputStream.println(s) + override def close() = { + if (outputStreamUsed) + outputStream.close() + } +} + +case class MultiLogger(streams: Logger*) extends Logger { + lazy val outputStream: PrintStream = + new PrintStream(b => streams.foreach(_.outputStream.write(b))) { + override def flush() = streams.foreach(_.outputStream.flush()) + override def close() = streams.foreach(_.outputStream.close()) + } + + def info(s: String) = streams.foreach(_.info(s)) + def error(s: String) = streams.foreach(_.error(s)) + override def close() = streams.foreach(_.close()) } \ No newline at end of file -- cgit v1.2.3