Skip to content

feat: Implement compilation tracing for detailed build diagnostics#2845

Open
krrish175-byte wants to merge 5 commits intoscalacenter:mainfrom
krrish175-byte:feature/compilation-trace
Open

feat: Implement compilation tracing for detailed build diagnostics#2845
krrish175-byte wants to merge 5 commits intoscalacenter:mainfrom
krrish175-byte:feature/compilation-trace

Conversation

@krrish175-byte
Copy link

Description

This PR introduces a new "compilation tracing" feature that records detailed information about every compilation run (successful, failed, or no-op) into a JSON file (.bloop/compilation-trace.json). This allows users and tool authors to inspect exactly what happened during a build.

This feature provides a structured, machine-readable record of these events, enabling better observability into the build process.

Key Changes

1. New Data Structures

  • Added CompilationTrace (and derived types like TraceDiagnostic, TraceArtifacts) to model the structured trace data.
  • Added compilationTrace boolean flag to TraceSettings to enable/disable the feature at the workspace level.

2. Trace Generation Logic

  • Implemented reportCompilationTrace in CompileTask.scala. This method gathers results from FinalCompileResult, structures them, and serializes them to JSON.
  • The compiled trace includes:
    • Project name
    • List of source files compiled (full paths)
    • Full diagnostics (errors/warnings) with line/column positions
    • Output artifacts (classes directory, analysis file path)
    • No-op status
    • Timestamps

3. Improved Failure Handling

  • Problem: Previously, when a compilation failed, the internal PartialFailure type discarded the SuccessfulCompileBundle (which holds the reporter and inputs). This resulted in traces for failed builds missing critical diagnostic information.
  • Fix: Modified PartialFailure in CompileResult.scala to optionally carry the SuccessfulCompileBundle.
  • Updated CompileGraph.scala to properly propagate this bundle when wrapping a failed result.
  • Updated CompileResult.toFinalResult to expose this bundle in FinalNormalCompileResult, ensuring that reportCompilationTrace has access to diagnostics even when compilation fails.

4. Tests

  • Added CompilationTraceSpec.scala with a suite of tests verifying:
    • Success: Trace is created with correct file lists and artifact paths.
    • Failure: Trace is created and correctly contains compiler diagnostics (e.g. type mismatches).
    • No-op: Trace correctly flags the compilation as a no-op.

Verification

Run the new test suite:

sbt "frontend/testOnly bloop.CompilationTraceSpec"

Closing issue:

issue #2697

@tgodzik

cleanUpTasksToSpawnInBackground.toList
}

private def reportCompilationTrace(
Copy link
Contributor

Choose a reason for hiding this comment

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

Coukld we instead reuse the current tracing behaviour? Maybe an implementation of BraveTracer and dump the data there if the json file exists

* Resource mappings allow files to be copied from source locations to custom
* target paths, similar to SBT's "mappings" field.
*/
object ResourceMapper {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not related to this PR

@krrish175-byte
Copy link
Author

@tgodzik: Thanks for the review, I have refactored the implementation to address your points:

  1. Use BraveTracer abstraction: I've moved the tracing logic into a new CompilationTraceTracer implementation within BraveTracer.scala. It now collects compilation data via tag calls and writes the compilation-trace.json file upon termination. This allowed me to remove the explicit reportCompilationTrace calls from CompileTask.
  2. Cleaned up ResourceMapper: I reverted the unrelated changes to ResourceMapper.scala and removed the file and its usages, as they were not relevant to this PR.
  3. Structure: I moved the CompilationTrace data structures to the backend so they are accessible to the new tracer implementation.

The changes are now pushed. Let me know if this aligns better with the design you had in mind!

if (properties.compilationTrace) {
val traceFile = bloop.io.AbsolutePath(
java.nio.file.Paths
.get(name.stripPrefix("compile ").stripSuffix(" (transitively)"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's use some of the directories in 'bloop.io.Paths', we can mention which one user needs to create when bloop about is run

NoopTracer
}

if (properties.compilationTrace) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should instead check if the trace files exists and if does, write to it. It's the same as with lsp.trace.json in metals

val projectName = tags
.collectFirst { case ("compile.target", value) => value }
.getOrElse(name)
CompositeTracer(
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should either allow for the more complex Zipkin tracer or tracing using a file. Would make it a bit less complicated and we wouldn't need to add compositeTracer class

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?

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

@krrish175-byte krrish175-byte force-pushed the feature/compilation-trace branch from 6ed966f to 860919e Compare January 14, 2026 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants