1515
1616import static com .google .common .base .Preconditions .checkNotNull ;
1717
18+ import com .google .common .eventbus .Subscribe ;
1819import com .google .common .primitives .Booleans ;
1920import com .google .devtools .build .lib .buildtool .BuildRequest ;
21+ import com .google .devtools .build .lib .buildtool .buildevent .BuildCompleteEvent ;
2022import com .google .devtools .build .lib .events .Event ;
2123import com .google .devtools .build .lib .exec .CompactSpawnLogContext ;
2224import com .google .devtools .build .lib .exec .ExecutionOptions ;
4042
4143/** Module providing on-demand spawn logging. */
4244public final class SpawnLogModule extends BlazeModule {
45+
4346 @ Nullable private SpawnLogContext spawnLogContext ;
47+ @ Nullable private Path outputPath ;
48+
49+ @ Nullable private AbruptExitException abruptExit = null ;
4450
4551 private void clear () {
4652 spawnLogContext = null ;
53+ outputPath = null ;
54+ abruptExit = null ;
4755 }
4856
4957 private void initOutputs (CommandEnvironment env ) throws IOException {
@@ -88,20 +96,21 @@ private void initOutputs(CommandEnvironment env) throws IOException {
8896 Path outputBase = env .getOutputBase ();
8997
9098 if (executionOptions .executionLogCompactFile != null ) {
99+ outputPath = workingDirectory .getRelative (executionOptions .executionLogCompactFile );
100+
91101 try {
92- spawnLogContext =
93- new CompactSpawnLogContext (
94- workingDirectory . getRelative ( executionOptions . executionLogCompactFile ) ,
95- env .getExecRoot ().asFragment (),
96- env .getOptions ().getOptions (RemoteOptions .class ),
97- env .getRuntime ().getFileSystem ().getDigestFunction (),
98- env .getXattrProvider ());
102+ spawnLogContext =
103+ new CompactSpawnLogContext (
104+ outputPath ,
105+ env .getExecRoot ().asFragment (),
106+ env .getOptions ().getOptions (RemoteOptions .class ),
107+ env .getRuntime ().getFileSystem ().getDigestFunction (),
108+ env .getXattrProvider ());
99109 } catch (InterruptedException e ) {
100110 env .getReporter ()
101111 .handle (Event .error ("Error while setting up the execution log: " + e .getMessage ()));
102112 }
103113 } else {
104- Path outputPath = null ;
105114 Encoding encoding = null ;
106115
107116 if (executionOptions .executionLogBinaryFile != null ) {
@@ -159,19 +168,27 @@ public void executorInit(CommandEnvironment env, BuildRequest request, ExecutorB
159168 }
160169 }
161170
162- @ Override
163- public void afterCommand () throws AbruptExitException {
171+ @ Subscribe
172+ public void buildComplete (BuildCompleteEvent event ) {
173+ // The log must be finalized in buildComplete() instead of afterCommand(), because it's our
174+ // last chance to publish it to the build event protocol.
175+
164176 if (spawnLogContext == null ) {
165177 // No logging requested.
178+ clear ();
166179 return ;
167180 }
168181
169182 try {
170183 spawnLogContext .close ();
184+ event .getResult ().getBuildToolLogCollection ().addLocalFile ("execution.log" , outputPath );
171185 } catch (IOException e ) {
172- String message = e .getMessage () == null ? "Error writing execution log" : e .getMessage ();
173- throw new AbruptExitException (
174- createDetailedExitCode (message , Code .EXECUTION_LOG_WRITE_FAILURE ), e );
186+ abruptExit =
187+ new AbruptExitException (
188+ createDetailedExitCode (
189+ String .format ("Error writing execution log: %s" , e .getMessage ()),
190+ Code .EXECUTION_LOG_WRITE_FAILURE ),
191+ e );
175192 } finally {
176193 clear ();
177194 }
@@ -184,4 +201,11 @@ private static DetailedExitCode createDetailedExitCode(String message, Code deta
184201 .setExecution (Execution .newBuilder ().setCode (detailedCode ))
185202 .build ());
186203 }
204+
205+ @ Override
206+ public void afterCommand () throws AbruptExitException {
207+ if (abruptExit != null ) {
208+ throw abruptExit ;
209+ }
210+ }
187211}
0 commit comments