Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
package sbt // package privateなclassを参照したいので
import java.nio.file.Files
import sbt.internal.AbstractTaskExecuteProgress
import sbt.internal.ShutdownHooks
import scala.concurrent.duration._
import sjsonnew.shaded.scalajson.ast.unsafe.JString
import sjsonnew.support.scalajson.unsafe.CompactPrinter
/**
* 本来sbtの起動時の引数に `-Dsbt.traces=true` だけ指定すれば、大体同等のことが可能だが、
* デフォルトだと全てのtaskが記録されて大きなファイルになるので、多少改変したもの
* [[https://github.com/sbt/sbt/blob/eec3c32cc841365799eaa5460272e8287b975f10/main/src/main/scala/sbt/internal/TaskTraceEvent.scala]]
* [[https://github.com/sbt/sbt/pull/4576]]
*/
class ChromeTraceEventReporter extends AbstractTaskExecuteProgress with ExecuteProgress[Task] {
import AbstractTaskExecuteProgress.Timer
private[this] val start = System.nanoTime
override def initial(): Unit = ()
override def afterReady(task: Task[_]): Unit = ()
override def afterCompleted[T](task: Task[T], result: Result[T]): Unit = ()
override def afterAllCompleted(results: RMap[Task, Result]): Unit = ()
override def stop(): Unit = ()
ShutdownHooks.add(() => report())
private[this] def report() = {
if (anyTimings) {
writeTraceEvent()
}
}
def taskFilter(name: String, durationMicros: Long): Boolean = {
// 一定以上時間がかかったものだけを記録
durationMicros > 1.seconds.toMicros
}
private[this] def writeTraceEvent(): Unit = {
val fileName = "trace.json"
val tracesDirectory = (new File("target").getAbsoluteFile) / "traces"
if (!tracesDirectory.exists) IO.createDirectory(tracesDirectory)
else ()
val outFile = tracesDirectory / fileName
val trace = Files.newBufferedWriter(outFile.toPath)
try {
trace.append("""{"traceEvents":[""")
trace.append("\n")
def durationEvent(name: String, t: Timer): String = {
val sb = new java.lang.StringBuilder(name.length + 2)
CompactPrinter.print(new JString(name), sb)
s"""{"name":${sb.toString},"cat":"","ph":"X","ts":${(t.startMicros)},"dur":${(t.durationMicros)},"pid":0,"tid":${t.threadId}}"""
}
val entryIterator = currentTimings
var first = true
while (entryIterator.hasNext) {
val (key, value) = entryIterator.next()
val n = taskName(key)
if (taskFilter(n, value.durationMicros)) {
if (first) {
first = false
} else {
trace.append(",\n")
}
trace.append(durationEvent(n, value))
}
}
trace.append("\n]}\n")
()
} finally {
trace.close()
try println(s"wrote $outFile")
catch { case _: java.nio.channels.ClosedChannelException => }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment