Skip to content

Commit

Permalink
BuildEventStreamer supports status INCOMPLETE (--nokeep_going) and IN…
Browse files Browse the repository at this point in the history
…TERNAL (catastrophe)

  - Add and Report AbortReason.INCOMPLETE when the build is incomplete due to an earlier build failure (--nokeep_going).
  - Report AbortReason.INTERNAL when the build is incomplete due to a catastrophic failure.
  - If multiple BuildEventStreamer AbortReasons are reported then the last one wins (no change), but all reasons are reported the Aborted event description (new behavior).

RELNOTES: none

PiperOrigin-RevId: 248037389
  • Loading branch information
Googler authored and copybara-github committed May 13, 2019
1 parent a57b0a0 commit d990a0a
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ syntax = "proto3";

package build_event_stream;

import "src/main/protobuf/command_line.proto";
import "src/main/protobuf/invocation_policy.proto";

option java_package = "com.google.devtools.build.lib.buildeventstream";
option java_outer_classname = "BuildEventStreamProtos";

import "src/main/protobuf/invocation_policy.proto";
import "src/main/protobuf/command_line.proto";

// Identifier for a build event. It is deliberately structured to also provide
// information about which build target etc the event is related to.
//
Expand Down Expand Up @@ -49,13 +49,11 @@ message BuildEventId {

// Identifier of an event indicating the beginning of a build; this will
// normally be the first event.
message BuildStartedId {
}
message BuildStartedId {}

// Identifier on an event indicating the original commandline received by
// the bazel server.
message UnstructuredCommandLineId {
}
message UnstructuredCommandLineId {}

// Identifier on an event describing the commandline received by Bazel.
message StructuredCommandLineId {
Expand All @@ -67,13 +65,11 @@ message BuildEventId {
}

// Identifier of an event indicating the workspace status.
message WorkspaceStatusId {
}
message WorkspaceStatusId {}

// Identifier on an event reporting on the options included in the command
// line, both explicitly and implicitly.
message OptionsParsedId {
}
message OptionsParsedId {}

// Identifier of an event reporting that an external resource was fetched
// from.
Expand Down Expand Up @@ -180,18 +176,15 @@ message BuildEventId {
}

// Identifier of the BuildFinished event, indicating the end of a build.
message BuildFinishedId {
}
message BuildFinishedId {}

// Identifier of an event providing additional logs/statistics after
// completion of the build.
message BuildToolLogsId {
}
message BuildToolLogsId {}

// Identifier of an event providing build metrics after completion
// of the build.
message BuildMetricsId {
}
message BuildMetricsId {}

oneof id {
UnknownBuildEventId unknown = 1;
Expand Down Expand Up @@ -266,6 +259,10 @@ message Aborted {

// Target build was skipped (e.g. due to incompatible CPU constraints).
SKIPPED = 7;

// Build incomplete due to an earlier build failure (e.g. --keep_going was
// set to false causing the build be ended upon failure).
INCOMPLETE = 10;
}
AbortReason reason = 1;

Expand Down Expand Up @@ -357,8 +354,7 @@ message Configuration {
// The main information is in the chaining part: the id will contain the
// target pattern that was expanded and the children id will contain the
// target or target pattern it was expanded to.
message PatternExpanded {
}
message PatternExpanded {}

// Enumeration type characterizing the size of a test, as specified by the
// test rule.
Expand Down Expand Up @@ -499,7 +495,7 @@ enum TestStatus {
REMOTE_FAILURE = 6;
FAILED_TO_BUILD = 7;
TOOL_HALTED_BEFORE_TESTING = 8;
};
}

// Payload on events reporting about individual test action.
message TestResult {
Expand Down Expand Up @@ -695,5 +691,5 @@ message BuildEvent {
BuildFinished finished = 14;
BuildToolLogs build_tool_logs = 23;
BuildMetrics build_metrics = 24;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.google.devtools.build.lib.buildeventstream.BuildCompletingEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventId;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.Aborted.AbortReason;
import com.google.devtools.build.lib.buildeventstream.BuildEventTransport;
import com.google.devtools.build.lib.buildeventstream.BuildEventWithConfiguration;
Expand All @@ -66,6 +67,7 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
Expand Down Expand Up @@ -100,7 +102,10 @@ public class BuildEventStreamer {

private final CountingArtifactGroupNamer artifactGroupNamer;
private OutErrProvider outErrProvider;
private volatile AbortReason abortReason = AbortReason.UNKNOWN;

@GuardedBy("this")
private final Set<AbortReason> abortReasons = new LinkedHashSet<>();

// Will be set to true if the build was invoked through "bazel test" or "bazel coverage".
private boolean isTestCommand;

Expand Down Expand Up @@ -293,15 +298,19 @@ private synchronized void clearMissingStartEvent(BuildEventId id) {
.map(BuildEvent::getEventId)
.collect(ImmutableSet.<BuildEventId>toImmutableSet()));
buildEvent(
new AbortedEvent(BuildEventId.buildStartedId(), children.build(), abortReason, ""));
new AbortedEvent(
BuildEventId.buildStartedId(),
children.build(),
getLastAbortReason(),
getAbortReasonDetails()));
}
}

/** Clear pending events by generating aborted events for all their requisits. */
private synchronized void clearPendingEvents() {
while (!pendingEvents.isEmpty()) {
BuildEventId id = pendingEvents.keySet().iterator().next();
buildEvent(new AbortedEvent(id, abortReason, ""));
buildEvent(new AbortedEvent(id, getLastAbortReason(), getAbortReasonDetails()));
}
}

Expand All @@ -319,7 +328,7 @@ private synchronized void clearAnnouncedEvents(Collection<BuildEventId> dontclea
}
for (BuildEventId id : ids) {
if (!dontclear.contains(id)) {
post(new AbortedEvent(id, abortReason, ""));
post(new AbortedEvent(id, getLastAbortReason(), getAbortReasonDetails()));
}
}
}
Expand All @@ -339,7 +348,7 @@ public synchronized void close(@Nullable AbortReason reason) {
}
closed = true;
if (reason != null) {
abortReason = reason;
addAbortReason(reason);
}

if (finalEventsToCome == null) {
Expand Down Expand Up @@ -403,17 +412,17 @@ private void maybeReportConfiguration(BuildEvent configuration) {

@Subscribe
public void buildInterrupted(BuildInterruptedEvent event) {
abortReason = AbortReason.USER_INTERRUPTED;
addAbortReason(AbortReason.USER_INTERRUPTED);
}

@Subscribe
public void noAnalyze(NoAnalyzeEvent event) {
abortReason = AbortReason.NO_ANALYZE;
addAbortReason(AbortReason.NO_ANALYZE);
}

@Subscribe
public void noExecution(NoExecutionEvent event) {
abortReason = AbortReason.NO_BUILD;
addAbortReason(AbortReason.NO_BUILD);
}

@Subscribe
Expand Down Expand Up @@ -469,8 +478,15 @@ public void buildEvent(BuildEvent event) {
buildEvent(freedEvent);
}

if (event instanceof BuildCompleteEvent && isCrash((BuildCompleteEvent) event)) {
abortReason = AbortReason.INTERNAL;
if (event instanceof BuildCompleteEvent) {
BuildCompleteEvent buildCompleteEvent = (BuildCompleteEvent) event;
if (isCrash(buildCompleteEvent)) {
addAbortReason(AbortReason.INTERNAL);
} else if (isCatastrophe(buildCompleteEvent)) {
addAbortReason(AbortReason.INTERNAL);
} else if (isIncomplete(buildCompleteEvent)) {
addAbortReason(AbortReason.INCOMPLETE);
}
}

if (event instanceof BuildCompletingEvent) {
Expand All @@ -492,6 +508,16 @@ private static boolean isCrash(BuildCompleteEvent event) {
return event.getResult().getUnhandledThrowable() != null;
}

private static boolean isCatastrophe(BuildCompleteEvent event) {
return event.getResult().wasCatastrophe();
}

private boolean isIncomplete(BuildCompleteEvent event) {
return !event.getResult().getSuccess()
&& !event.getResult().wasCatastrophe()
&& event.getResult().getStopOnFirstFailure();
}

private synchronized BuildEvent flushStdoutStderrEvent(String out, String err) {
BuildEvent updateEvent = ProgressEvent.progressUpdate(progressCount, out, err);
progressCount++;
Expand Down Expand Up @@ -713,6 +739,34 @@ public synchronized ImmutableMap<BuildEventTransport, ListenableFuture<Void>> ge
return halfCloseFuturesMap;
}

/**
* Stores the abort reason for later reporting on BEP pending events. In case of multiple abort
* reasons:
*
* <ul>
* <li>Only the most recent reason will be reported as the main AbortReason in BEP.
* <li>All previous AbortReason will appear in Aborted#getDescription message.
* </ul>
*/
private synchronized void addAbortReason(BuildEventStreamProtos.Aborted.AbortReason reason) {
abortReasons.add(reason);
}

/** @return the most recent AbortReason or UNKNOWN if no value was set. */
private synchronized AbortReason getLastAbortReason() {
return abortReasons.isEmpty() ? AbortReason.UNKNOWN : Iterables.getLast(abortReasons);
}

/**
* @return Detailed message explaining the most recent AbortReason (and possibly previous
* reasons).
*/
private synchronized String getAbortReasonDetails() {
return abortReasons.size() <= 1
? ""
: String.format("Multiple abort reasons reported: %s", abortReasons);
}

/** A builder for {@link BuildEventStreamer}. */
public static class Builder {
private Set<BuildEventTransport> buildEventTransports;
Expand Down
Loading

0 comments on commit d990a0a

Please sign in to comment.