From 32d6bf38cf78e08316442159900d6135b8f417db Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 26 Jun 2017 23:43:21 -0400 Subject: [PATCH] send TraceEvent on crash Fixes sbt/sbt#3234 --- build.sbt | 15 +++++- .../sbt/internal/util/AbstractEntry.scala | 2 +- .../sbt/internal/util/StringEvent.scala | 2 +- .../sbt/internal/util/TraceEvent.scala | 51 +++++++++++++++++++ .../util/codec/AbstractEntryFormats.scala | 7 +-- .../internal/util/codec/JsonProtocol.scala | 1 + .../util/codec/StringEventFormats.scala | 2 +- .../util/codec/TraceEventFormats.scala | 33 ++++++++++++ .../src/main/contraband/logging.contra | 7 +++ .../sbt/internal/util/ManagedLogger.scala | 10 +++- .../internal/util/codec/JValueFormats.scala | 8 +-- .../util/codec/ThrowableShowLines.scala | 25 +++++++++ project/Dependencies.scala | 2 +- project/plugins.sbt | 2 +- .../src/main/scala/sbt/util/FileInfo.scala | 4 +- 15 files changed, 153 insertions(+), 18 deletions(-) create mode 100644 internal/util-logging/src/main/contraband-scala/sbt/internal/util/TraceEvent.scala create mode 100644 internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/TraceEventFormats.scala create mode 100644 internal/util-logging/src/main/scala/sbt/internal/util/codec/ThrowableShowLines.scala diff --git a/build.sbt b/build.sbt index 36db22d09..1b77cc349 100644 --- a/build.sbt +++ b/build.sbt @@ -2,7 +2,7 @@ import Dependencies._ import Util._ // import com.typesafe.tools.mima.core._, ProblemFilters._ -def baseVersion: String = "1.0.0-M24" +def baseVersion = "1.0.0-SNAPSHOT" def internalPath = file("internal") def commonSettings: Seq[Setting[_]] = Seq( @@ -39,6 +39,11 @@ lazy val utilRoot: Project = (project in file(".")). settings( inThisBuild(Seq( git.baseVersion := baseVersion, + version := { + val v = version.value + if (v contains "SNAPSHOT") git.baseVersion.value + else v + }, bintrayPackage := "util", homepage := Some(url("https://github.com/sbt/util")), description := "Util module for sbt", @@ -108,7 +113,13 @@ lazy val utilLogging = (project in internalPath / "util-logging"). crossScalaVersions := Seq(scala210, scala211, scala212), name := "Util Logging", libraryDependencies ++= Seq(jline, log4jApi, log4jCore, disruptor, sjsonnewScalaJson, scalaReflect.value), - sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-scala" + sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-scala", + contrabandFormatsForType in generateContrabands in Compile := { tpe => + val old = (contrabandFormatsForType in generateContrabands in Compile).value + val name = tpe.removeTypeParameters.name + if (name == "Throwable") Nil + else old(tpe) + }, ) // Relation diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/AbstractEntry.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/AbstractEntry.scala index c20b78e1b..5f8b37c07 100644 --- a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/AbstractEntry.scala +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/AbstractEntry.scala @@ -16,7 +16,7 @@ abstract class AbstractEntry( case _ => false } override def hashCode: Int = { - 37 * (37 * (17 + channelName.##) + execId.##) + 37 * (37 * (37 * (17 + "AbstractEntry".##) + channelName.##) + execId.##) } override def toString: String = { "AbstractEntry(" + channelName + ", " + execId + ")" diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/StringEvent.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/StringEvent.scala index 4ac959836..71763458c 100644 --- a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/StringEvent.scala +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/StringEvent.scala @@ -17,7 +17,7 @@ final class StringEvent private ( case _ => false } override def hashCode: Int = { - 37 * (37 * (37 * (37 * (17 + level.##) + message.##) + channelName.##) + execId.##) + 37 * (37 * (37 * (37 * (37 * (17 + "StringEvent".##) + level.##) + message.##) + channelName.##) + execId.##) } override def toString: String = { "StringEvent(" + level + ", " + message + ", " + channelName + ", " + execId + ")" diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/TraceEvent.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/TraceEvent.scala new file mode 100644 index 000000000..85312aff4 --- /dev/null +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/TraceEvent.scala @@ -0,0 +1,51 @@ +/** + * This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.util +final class TraceEvent private ( + val level: String, + val message: Throwable, + channelName: Option[String], + execId: Option[String]) extends sbt.internal.util.AbstractEntry(channelName, execId) with Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: TraceEvent => (this.level == x.level) && (this.message == x.message) && (this.channelName == x.channelName) && (this.execId == x.execId) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (37 * (37 * (17 + "TraceEvent".##) + level.##) + message.##) + channelName.##) + execId.##) + } + override def toString: String = { + "TraceEvent(" + level + ", " + message + ", " + channelName + ", " + execId + ")" + } + protected[this] def copy(level: String = level, message: Throwable = message, channelName: Option[String] = channelName, execId: Option[String] = execId): TraceEvent = { + new TraceEvent(level, message, channelName, execId) + } + def withLevel(level: String): TraceEvent = { + copy(level = level) + } + def withMessage(message: Throwable): TraceEvent = { + copy(message = message) + } + def withChannelName(channelName: Option[String]): TraceEvent = { + copy(channelName = channelName) + } + def withChannelName(channelName: String): TraceEvent = { + copy(channelName = Option(channelName)) + } + def withExecId(execId: Option[String]): TraceEvent = { + copy(execId = execId) + } + def withExecId(execId: String): TraceEvent = { + copy(execId = Option(execId)) + } +} +object TraceEvent { + + def apply(level: String, message: Throwable, channelName: Option[String], execId: Option[String]): TraceEvent = new TraceEvent(level, message, channelName, execId) + def apply(level: String, message: Throwable, channelName: String, execId: String): TraceEvent = new TraceEvent(level, message, Option(channelName), Option(execId)) +} diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/AbstractEntryFormats.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/AbstractEntryFormats.scala index 4eed06c7b..55784f9ac 100644 --- a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/AbstractEntryFormats.scala +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/AbstractEntryFormats.scala @@ -4,7 +4,8 @@ // DO NOT EDIT MANUALLY package sbt.internal.util.codec -import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder } -trait AbstractEntryFormats { self: sjsonnew.BasicJsonProtocol with sbt.internal.util.codec.StringEventFormats => -implicit lazy val AbstractEntryFormat: JsonFormat[sbt.internal.util.AbstractEntry] = flatUnionFormat1[sbt.internal.util.AbstractEntry, sbt.internal.util.StringEvent]("type") + +import _root_.sjsonnew.JsonFormat +trait AbstractEntryFormats { self: sjsonnew.BasicJsonProtocol with sbt.internal.util.codec.StringEventFormats with sbt.internal.util.codec.TraceEventFormats => +implicit lazy val AbstractEntryFormat: JsonFormat[sbt.internal.util.AbstractEntry] = flatUnionFormat2[sbt.internal.util.AbstractEntry, sbt.internal.util.StringEvent, sbt.internal.util.TraceEvent]("type") } diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/JsonProtocol.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/JsonProtocol.scala index 39484f2e0..4696c9612 100644 --- a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/JsonProtocol.scala +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/JsonProtocol.scala @@ -6,5 +6,6 @@ package sbt.internal.util.codec trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.internal.util.codec.StringEventFormats + with sbt.internal.util.codec.TraceEventFormats with sbt.internal.util.codec.AbstractEntryFormats object JsonProtocol extends JsonProtocol \ No newline at end of file diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/StringEventFormats.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/StringEventFormats.scala index c005071e7..2d142f6ec 100644 --- a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/StringEventFormats.scala +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/StringEventFormats.scala @@ -4,7 +4,7 @@ // DO NOT EDIT MANUALLY package sbt.internal.util.codec -import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder } +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } trait StringEventFormats { self: sjsonnew.BasicJsonProtocol => implicit lazy val StringEventFormat: JsonFormat[sbt.internal.util.StringEvent] = new JsonFormat[sbt.internal.util.StringEvent] { override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.util.StringEvent = { diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/TraceEventFormats.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/TraceEventFormats.scala new file mode 100644 index 000000000..379196a9b --- /dev/null +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/TraceEventFormats.scala @@ -0,0 +1,33 @@ +/** + * This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.util.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait TraceEventFormats { self: sjsonnew.BasicJsonProtocol => +implicit lazy val TraceEventFormat: JsonFormat[sbt.internal.util.TraceEvent] = new JsonFormat[sbt.internal.util.TraceEvent] { + override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.util.TraceEvent = { + jsOpt match { + case Some(js) => + unbuilder.beginObject(js) + val level = unbuilder.readField[String]("level") + val message = unbuilder.readField[Throwable]("message") + val channelName = unbuilder.readField[Option[String]]("channelName") + val execId = unbuilder.readField[Option[String]]("execId") + unbuilder.endObject() + sbt.internal.util.TraceEvent(level, message, channelName, execId) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.util.TraceEvent, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("level", obj.level) + builder.addField("message", obj.message) + builder.addField("channelName", obj.channelName) + builder.addField("execId", obj.execId) + builder.endObject() + } +} +} diff --git a/internal/util-logging/src/main/contraband/logging.contra b/internal/util-logging/src/main/contraband/logging.contra index 67a4b3a04..5cd31c230 100644 --- a/internal/util-logging/src/main/contraband/logging.contra +++ b/internal/util-logging/src/main/contraband/logging.contra @@ -14,3 +14,10 @@ type StringEvent implements sbt.internal.util.AbstractEntry { channelName: String execId: String } + +type TraceEvent implements sbt.internal.util.AbstractEntry { + level: String! + message: Throwable! + channelName: String + execId: String +} diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala index 24b9a8e02..c66ceb4d2 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala @@ -1,10 +1,13 @@ package sbt.internal.util import sbt.util._ -import org.apache.logging.log4j.{ Logger => XLogger } +import org.apache.logging.log4j.{ Logger => XLogger, Level => XLevel } import org.apache.logging.log4j.message.ObjectMessage import sjsonnew.JsonFormat import scala.reflect.runtime.universe.TypeTag +import sbt.internal.util.codec.ThrowableShowLines._ +import sbt.internal.util.codec.TraceEventShowLines._ +import sbt.internal.util.codec.JsonProtocol._ /** * Delegates log events to the associated LogExchange. @@ -15,7 +18,8 @@ class ManagedLogger( val execId: Option[String], xlogger: XLogger ) extends Logger { - override def trace(t: => Throwable): Unit = () // exchange.appendLog(new Trace(t)) + override def trace(t: => Throwable): Unit = + logEvent(Level.Error, TraceEvent("Error", t, channelName, execId)) override def log(level: Level.Value, message: => String): Unit = { xlogger.log( @@ -32,6 +36,8 @@ class ManagedLogger( // println(s"registerStringCodec ${tag.key}") val _ = LogExchange.getOrElseUpdateStringCodec(tag.key, ev) } + registerStringCodec[Throwable] + registerStringCodec[TraceEvent] final def debugEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Debug, event) final def infoEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Info, event) final def warnEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Warn, event) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/codec/JValueFormats.scala b/internal/util-logging/src/main/scala/sbt/internal/util/codec/JValueFormats.scala index 2ff681825..c3ce6299b 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/codec/JValueFormats.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/codec/JValueFormats.scala @@ -15,10 +15,10 @@ trait JValueFormats { self: sjsonnew.BasicJsonProtocol => def read[J](j: Option[J], u: Unbuilder[J]) = JNull } - implicit val JBooleanFormat: JF[JBoolean] = project(_.get, (x: Boolean) => JBoolean(x)) - implicit val JStringFormat: JF[JString] = project(_.value, (x: String) => JString(x)) - implicit val JNumberFormat: JF[JNumber] = project(x => BigDecimal(x.value), (x: BigDecimal) => JNumber(x.toString)) - implicit val JArrayFormat: JF[JArray] = project[JArray, Array[JValue]](_.value, JArray(_)) + implicit val JBooleanFormat: JF[JBoolean] = projectFormat(_.get, (x: Boolean) => JBoolean(x)) + implicit val JStringFormat: JF[JString] = projectFormat(_.value, (x: String) => JString(x)) + implicit val JNumberFormat: JF[JNumber] = projectFormat(x => BigDecimal(x.value), (x: BigDecimal) => JNumber(x.toString)) + implicit val JArrayFormat: JF[JArray] = projectFormat[JArray, Array[JValue]](_.value, JArray(_)) implicit lazy val JObjectJsonWriter: JW[JObject] = new JW[JObject] { def write[J](x: JObject, b: Builder[J]) = { diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/codec/ThrowableShowLines.scala b/internal/util-logging/src/main/scala/sbt/internal/util/codec/ThrowableShowLines.scala new file mode 100644 index 000000000..13abbdf8a --- /dev/null +++ b/internal/util-logging/src/main/scala/sbt/internal/util/codec/ThrowableShowLines.scala @@ -0,0 +1,25 @@ +package sbt +package internal.util.codec + +import sbt.util.ShowLines +import sbt.internal.util.{ StackTrace, TraceEvent } + +trait ThrowableShowLines { + implicit val sbtThrowableShowLines: ShowLines[Throwable] = + ShowLines[Throwable]( (t: Throwable) => { + // 0 means enabled with default behavior. See StackTrace.scala. + val traceLevel = 0 + List(StackTrace.trimmed(t, traceLevel)) + }) +} + +object ThrowableShowLines extends ThrowableShowLines + +trait TraceEventShowLines { + implicit val sbtTraceEventShowLines: ShowLines[TraceEvent] = + ShowLines[TraceEvent]( (t: TraceEvent) => { + ThrowableShowLines.sbtThrowableShowLines.showLines(t.message) + }) +} + +object TraceEventShowLines extends TraceEventShowLines diff --git a/project/Dependencies.scala b/project/Dependencies.scala index aba5a8317..8f380f99c 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -43,7 +43,7 @@ object Dependencies { val scalatest = "org.scalatest" %% "scalatest" % "3.0.1" val parserCombinator211 = "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.4" - val sjsonnewVersion = "0.7.0" + val sjsonnewVersion = "0.8.0-M1" val sjsonnew = "com.eed3si9n" %% "sjson-new-core" % sjsonnewVersion val sjsonnewScalaJson = "com.eed3si9n" %% "sjson-new-scalajson" % sjsonnewVersion diff --git a/project/plugins.sbt b/project/plugins.sbt index c22194daf..1af048fe4 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.4.0") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0-M1") addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.3") -addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0-M5") +addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0-M6") diff --git a/util-cache/src/main/scala/sbt/util/FileInfo.scala b/util-cache/src/main/scala/sbt/util/FileInfo.scala index 6c42422d0..9c675e652 100644 --- a/util-cache/src/main/scala/sbt/util/FileInfo.scala +++ b/util-cache/src/main/scala/sbt/util/FileInfo.scala @@ -39,7 +39,7 @@ object FilesInfo { def empty[F <: FileInfo]: FilesInfo[F] = FilesInfo(Set.empty[F]) implicit def format[F <: FileInfo: JsonFormat]: JsonFormat[FilesInfo[F]] = - project(_.files, (fs: Set[F]) => FilesInfo(fs)) + projectFormat(_.files, (fs: Set[F]) => FilesInfo(fs)) def full: FileInfo.Style = FileInfo.full def hash: FileInfo.Style = FileInfo.hash @@ -52,7 +52,7 @@ object FileInfo { type F <: FileInfo implicit def format: JsonFormat[F] - implicit def formats: JsonFormat[FilesInfo[F]] = project(_.files, (fs: Set[F]) => FilesInfo(fs)) + implicit def formats: JsonFormat[FilesInfo[F]] = projectFormat(_.files, (fs: Set[F]) => FilesInfo(fs)) def apply(file: File): F def apply(files: Set[File]): FilesInfo[F] = FilesInfo(files map apply)