Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion backend/src/main/scala/bloop/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ case class CompileInputs(
ioExecutor: Executor,
invalidatedClassFilesInDependentProjects: Set[File],
generatedClassFilePathsInDependentProjects: Map[String, File],
resources: List[AbsolutePath]
resources: List[AbsolutePath],
resourceMappings: List[(AbsolutePath, String)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a change from a different PR

)

case class CompileOutPaths(
Expand Down
112 changes: 110 additions & 2 deletions backend/src/main/scala/bloop/tracing/BraveTracer.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package bloop.tracing

import java.util.concurrent.ConcurrentHashMap
import java.nio.file.{Paths => NioPaths, Files}
import java.net.URI

import scala.util.control.NonFatal

import bloop.task.Task
import bloop.io.AbsolutePath

import brave.Span
import brave.Tracer
Expand All @@ -21,6 +24,8 @@ sealed trait BraveTracer {
thunk: BraveTracer => T
): T

def tag(key: String, value: String): Unit

def traceVerbose[T](name: String, tags: (String, String)*)(
thunk: BraveTracer => T
): T
Expand Down Expand Up @@ -49,6 +54,8 @@ object NoopTracer extends BraveTracer {

override def startNewChildTracer(name: String, tags: (String, String)*): BraveTracer = this

override def tag(key: String, value: String): Unit = ()

override def trace[T](name: String, tags: (String, String)*)(thunk: BraveTracer => T): T = thunk(
this
)
Expand Down Expand Up @@ -91,9 +98,22 @@ object BraveTracer {
if (properties.enabled) {
BraveTracerInternal(name, properties, ctx, tags: _*)
} else {
NoopTracer
val buildUri = tags.collectFirst { case ("workspace.dir", value) => value }
buildUri match {
case Some(uri) =>
val workspaceDir = AbsolutePath(NioPaths.get(uri))
val traceFile = workspaceDir.resolve("compilation-trace.json")
if (traceFile.exists) {
val projectName = tags
.collectFirst { case ("compile.target", value) => value }
.getOrElse(name)
new CompilationTraceTracer(projectName, traceFile, System.currentTimeMillis())
} else {
NoopTracer
}
case None => NoopTracer
}
}

}
}

Expand All @@ -104,6 +124,11 @@ final class BraveTracerInternal private (
properties: TraceProperties
) extends BraveTracer {

override def tag(key: String, value: String): Unit = {
_currentSpan.tag(key, value)
()
}

def currentSpan = Some(_currentSpan)

def startNewChildTracer(name: String, tags: (String, String)*): BraveTracer = {
Expand Down Expand Up @@ -263,3 +288,86 @@ object BraveTracerInternal {
new BraveTracerInternal(tracer, rootSpan, closeEverything, properties)
}
}

final class CompilationTraceTracer(
project: String,
traceFile: bloop.io.AbsolutePath,
startTime: Long
) extends BraveTracer {
import bloop.tracing.CompilationTrace
import bloop.tracing.TraceArtifacts
import com.github.plokhotnyuk.jsoniter_scala.core.writeToArray
import com.github.plokhotnyuk.jsoniter_scala.core.WriterConfig

private val tags = new ConcurrentHashMap[String, String]()

override def startNewChildTracer(name: String, tags: (String, String)*): BraveTracer = this
override def tag(key: String, value: String): Unit = {
this.tags.put(key, value)
()
}

override def trace[T](name: String, tags: (String, String)*)(thunk: BraveTracer => T): T =
thunk(this)
override def traceVerbose[T](name: String, tags: (String, String)*)(
thunk: BraveTracer => T
): T = thunk(this)
override def traceTask[T](name: String, tags: (String, String)*)(
thunk: BraveTracer => Task[T]
): Task[T] = thunk(this)
override def traceTaskVerbose[T](name: String, tags: (String, String)*)(
thunk: BraveTracer => Task[T]
): Task[T] = thunk(this)

override def terminate(): Unit = {
val durationMs = System.currentTimeMillis() - startTime
val isNoOp = tags.getOrDefault("isNoOp", "false").toBoolean
val analysisOut = tags.getOrDefault("analysis", "")
val classesDir = tags.getOrDefault("classesDir", "")
val artifacts = TraceArtifacts(classesDir, analysisOut)
val fileCount = tags.getOrDefault("fileCount", "0").toInt
val files = (0 until fileCount).map(i => tags.get(s"file.$i")).filter(_ != null)

import com.github.plokhotnyuk.jsoniter_scala.core.readFromString
val diagnosticCount = tags.getOrDefault("diagnostics.count", "0").toInt
val diagnostics = (0 until diagnosticCount).flatMap { i =>
val json = tags.get(s"diagnostic.$i")
if (json != null) {
try {
Some(readFromString[TraceDiagnostic](json)(CompilationTrace.diagnosticCodec))
} catch { case NonFatal(_) => None }
} else None
}

val trace = CompilationTrace(
project,
files,
diagnostics,
artifacts,
isNoOp,
durationMs
)

try {
if (!java.nio.file.Files.exists(traceFile.getParent.underlying)) {
java.nio.file.Files.createDirectories(traceFile.getParent.underlying)
}
traceFile.getParent.underlying.synchronized {
val projectTraceFile = traceFile.getParent.resolve(s"compilation-trace-${project}.json")
val bytes = writeToArray(trace, WriterConfig.withIndentionStep(4))(CompilationTrace.codec)
java.nio.file.Files.write(projectTraceFile.underlying, bytes)
()
}
} catch {
case NonFatal(e) => e.printStackTrace()
}
}

override def currentSpan: Option[Span] = None
override def toIndependentTracer(
name: String,
traceProperties: TraceProperties,
tags: (String, String)*
): BraveTracer =
this
}
42 changes: 42 additions & 0 deletions backend/src/main/scala/bloop/tracing/CompilationTrace.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package bloop.tracing

import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker

case class CompilationTrace(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example of how the trace file looks like?

project: String,
files: Seq[String],
diagnostics: Seq[TraceDiagnostic],
artifacts: TraceArtifacts,
isNoOp: Boolean,
durationMs: Long
)

object CompilationTrace {
implicit val codec: JsonValueCodec[CompilationTrace] =
JsonCodecMaker.make[CompilationTrace]
implicit val listCodec: JsonValueCodec[List[CompilationTrace]] =
JsonCodecMaker.make[List[CompilationTrace]]
implicit val diagnosticCodec: JsonValueCodec[TraceDiagnostic] =
JsonCodecMaker.make[TraceDiagnostic]
}

case class TraceDiagnostic(
severity: String,
message: String,
range: Option[TraceRange],
code: Option[String],
source: Option[String]
)

case class TraceRange(
startLine: Int,
startCharacter: Int,
endLine: Int,
endCharacter: Int
)

case class TraceArtifacts(
classesDir: String,
analysisFile: String
)
7 changes: 5 additions & 2 deletions backend/src/main/scala/bloop/tracing/TraceProperties.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ case class TraceProperties(
localServiceName: String,
traceStartAnnotation: Option[String],
traceEndAnnotation: Option[String],
enabled: Boolean
enabled: Boolean,
compilationTrace: Boolean
)

object TraceProperties {
Expand All @@ -20,6 +21,7 @@ object TraceProperties {
val localServiceName = Properties.propOrElse("bloop.tracing.localServiceName", "bloop")
val traceStartAnnotation = Properties.propOrNone("bloop.tracing.traceStartAnnotation")
val traceEndAnnotation = Properties.propOrNone("bloop.tracing.traceEndAnnotation")
val compilationTrace = Properties.propOrFalse("bloop.tracing.compilationTrace")

val traceServerUrl = Properties.propOrElse(
"zipkin.server.url",
Expand All @@ -33,7 +35,8 @@ object TraceProperties {
localServiceName,
traceStartAnnotation,
traceEndAnnotation,
enabled
enabled,
compilationTrace
)
}
}
1 change: 1 addition & 0 deletions frontend/src/it/scala/bloop/CommunityBuild.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ abstract class CommunityBuild(val buildpressHomeDir: AbsolutePath) {
scalaInstance = allProjectsInBuild.head.project.scalaInstance,
rawClasspath = Nil,
resources = Nil,
resourceMappings = Nil,
compileSetup = Config.CompileSetup.empty,
genericClassesDir = dummyClassesDir,
isBestEffort = false,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/main/scala/bloop/data/Project.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ final case class Project(
scalaInstance: Option[ScalaInstance],
rawClasspath: List[AbsolutePath],
resources: List[AbsolutePath],
resourceMappings: List[(AbsolutePath, String)],
compileSetup: Config.CompileSetup,
genericClassesDir: AbsolutePath,
isBestEffort: Boolean,
Expand Down Expand Up @@ -347,6 +348,8 @@ object Project {
val tags = project.tags.getOrElse(Nil)
val projectDirectory = AbsolutePath(project.directory)

val resourceMappings = List.empty[(AbsolutePath, String)]

Project(
project.name,
projectDirectory,
Expand All @@ -355,6 +358,7 @@ object Project {
instance,
compileClasspath,
compileResources,
resourceMappings,
setup,
AbsolutePath(project.classesDir),
isBestEffort = false,
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/main/scala/bloop/data/TraceSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ case class TraceSettings(
localServiceName: Option[String],
traceStartAnnotation: Option[String],
traceEndAnnotation: Option[String],
enabled: Option[Boolean]
enabled: Option[Boolean],
compilationTrace: Option[Boolean]
)

object TraceSettings {
Expand All @@ -22,7 +23,8 @@ object TraceSettings {
settings.localServiceName.getOrElse(default.localServiceName),
settings.traceStartAnnotation.orElse(default.traceStartAnnotation),
settings.traceEndAnnotation.orElse(default.traceEndAnnotation),
settings.enabled.getOrElse(default.enabled)
settings.enabled.getOrElse(default.enabled),
settings.compilationTrace.getOrElse(default.compilationTrace)
)
}

Expand All @@ -34,7 +36,8 @@ object TraceSettings {
localServiceName = Some(properties.localServiceName),
traceStartAnnotation = properties.traceStartAnnotation,
traceEndAnnotation = properties.traceEndAnnotation,
enabled = Some(properties.enabled)
enabled = Some(properties.enabled),
compilationTrace = Some(properties.compilationTrace)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ final case class ResultsCache private (

def addFinalResults(ps: List[FinalCompileResult]): ResultsCache = {
ps.foldLeft(this) {
case (rs, FinalNormalCompileResult(p, r)) => rs.addResult(p, r)
case (rs, FinalNormalCompileResult(p, r, _)) => rs.addResult(p, r)
case (rs, FinalEmptyResult) => rs
}
}
Expand Down
Loading