|
| 1 | +package dotty.tools.pc |
| 2 | + |
| 3 | +import java.util.logging.Logger |
| 4 | +import scala.jdk.CollectionConverters.* |
| 5 | +import java.nio.file.Files |
| 6 | +import java.nio.file.Path |
| 7 | +import com.google.gson.Gson |
| 8 | +import dotty.tools.pc.util.TraceEvent |
| 9 | + |
| 10 | +trait Profiler: |
| 11 | + def reportEvent(event: util.TraceEvent): Unit |
| 12 | + def reportEvent( |
| 13 | + name: TraceName, |
| 14 | + cat: String, |
| 15 | + eventPhase: EventPhases, |
| 16 | + ts: Long, |
| 17 | + dur: Long, |
| 18 | + pid: Int, |
| 19 | + tid: Int = Thread.currentThread().nn.getId().toInt, |
| 20 | + args: Seq[String] = Nil |
| 21 | + ): Unit = |
| 22 | + reportEvent(util.TraceEvent(name.toString, cat, eventPhase.ph, ts / 1000, dur / 1000, 1, 1, args.asJava)) |
| 23 | + |
| 24 | + def traced[T](origin: String, id: Int, name: TraceName)(f: => T): T = |
| 25 | + val start = System.nanoTime() |
| 26 | + try f |
| 27 | + finally |
| 28 | + val end = System.nanoTime() |
| 29 | + reportEvent(name, origin, EventPhases.Duration, start, end - start, id) |
| 30 | + |
| 31 | +enum EventPhases(val ph: String): |
| 32 | + case Begin extends EventPhases("B") |
| 33 | + case End extends EventPhases("E") |
| 34 | + case Duration extends EventPhases("X") |
| 35 | + case Instant extends EventPhases("i") |
| 36 | + |
| 37 | +enum TraceName: |
| 38 | + case CancellableTask |
| 39 | + case UncancellableTask |
| 40 | + case Started |
| 41 | + case Timeout |
| 42 | + case Completed |
| 43 | + case CancelRequested |
| 44 | + case CacheHit |
| 45 | + case CacheMiss |
| 46 | + case GracefulCancelTriggered |
| 47 | + case ClientCancelled |
| 48 | + case ServerCancelled |
| 49 | + case CompletedExceptionally |
| 50 | + case Compilation |
| 51 | + case TaskInterruptionRequested |
| 52 | + case TaskInterrupted |
| 53 | + case InterruptCancelTriggered |
| 54 | + case ClientCancelTriggered |
| 55 | + |
| 56 | +case class JsonWritingProfiler(outputFolder: Option[Path]) extends Profiler: |
| 57 | + private val logger: Logger = Logger.getLogger(getClass.getName).nn |
| 58 | + |
| 59 | + private val outputFolder0 = outputFolder.map(_.resolve(".metals").nn).getOrElse(Files.createTempDirectory("metals-trace").nn) |
| 60 | + private val gson = new Gson() |
| 61 | + private val outputDir = Files.createDirectories(outputFolder0) |
| 62 | + private val outputFile = outputFolder0.resolve("traces.json") |
| 63 | + |
| 64 | + Files.deleteIfExists(outputFile) |
| 65 | + Files.createFile(outputFile) |
| 66 | + logger.info(s"Writing traces to $outputFile") |
| 67 | + |
| 68 | + def reportEvent(event: util.TraceEvent): Unit = write(event) |
| 69 | + |
| 70 | + |
| 71 | + private def write(event: util.TraceEvent): Unit = |
| 72 | + val json = gson.toJson(event).nn + ",\n" |
| 73 | + Files.write(outputFile, json.getBytes(), java.nio.file.StandardOpenOption.APPEND) |
| 74 | + |
| 75 | +object Profiler: |
| 76 | + def empty: Profiler = new Profiler: |
| 77 | + override def reportEvent(event: TraceEvent): Unit = () |
0 commit comments