5.5.1 Build Event Protocol (BEP)
Console output answers a person's question: "What did Bazel just print?" The Build Event Protocol (BEP) answers a tool's question: "What happened during the entire invocation?" It is a structured stream of Protocol Buffer messages about the command, configurations, target and test results, artifacts, and command completion. An integration can consume that contract instead of guessing what colored terminal text means.1
Per-action tracing in 6.6.2 Action-Internal Telemetry complements this invocation event stream when the question moves from lifecycle evidence to execution spans.
IDs encode the graph. Position in this row does not create an edge.
The Stream Is a Graph, Not a Log
Every BEP event has an identifier, a list of identifiers for events it
announces as children, and a type-specific payload. The parent-child
relationships form a DAG. BuildStarted is always the first event. Results
appear before BuildFinished, while some summaries, such as metrics, may arrive
after it.1
This structure changes how you write a consumer:
- correlate events by identifier instead of relying on adjacency.
- treat
BuildFinishedand its exit code as the authoritative command result. - handle
Aborted, which can replace an expected payload when Bazel did not produce the normal event. - do not assume completeness after a process or transport failure, because an announced event may never arrive.1,2
Different event types answer different questions. CommandLine and
OptionsParsed describe the effective invocation. TargetConfigured reports
what completed analysis, while TargetComplete reports the execution result for
a target, configuration, and aspect combination. TestResult represents one
test attempt, shard, and run. TestSummary aggregates them into a result for a
test target. BuildMetrics contains counters for work actually performed by
the command, not cached work that was reused.2
ActionExecuted requires particular care: by default, BEP publishes this event
for failed actions, not every action. Publishing all of them requires
--build_event_publish_all_actions.2 BEP therefore does not replace a
profile or an execution log. A profile exposes the build timeline, while an
execution log supports comparing inputs and execution details. BEP supplies the
cross-cutting integration contract for the invocation as a whole.3
Start by Writing a File
The simplest experiment needs no server:
bazel test //... --build_event_json_file=/tmp/bep.json
JSON is convenient for exploration and parser prototypes. For production
processing, --build_event_binary_file=/tmp/bep.bin is often a better fit: it
writes a sequence of binary protobuf messages, each prefixed by a
varint-encoded length. --build_event_text_file is also available when you
want to inspect the text representation.1
Do not design the parser as a search for a few fields in consecutive JSON
records. For example, TargetComplete usually does not embed its artifacts.
Its output groups refer to NamedSetOfFiles events, which can share files and
refer to further named sets. This structure mirrors a depset. A consumer
should index sets by ID, traverse them with a visited set, and retain at least
the label, configuration, and aspect in each result key. Repeatedly expanding
shared sets with a naive traversal can lead to quadratic work.4
Then Stream to BES
A file demonstrates the protocol. Continuous monitoring needs a transport.
Bazel can publish BEP to a Build Event Service (BES), a generic gRPC service
selected with --bes_backend. BES treats BEP events as opaque bytes: the
service protocol and the event data protocol are separate layers.1
bazel test //... \
--bes_backend=grpcs://bes.example.internal:443 \
--bes_results_url=https://builds.example.internal/invocation/
The grpc:// scheme selects plaintext gRPC, while grpcs:// selects gRPC over
TLS. An empty --bes_backend, the default, disables uploads. The
--bes_upload_mode setting controls whether command completion waits for the
upload. Its default mode waits for the upload to finish.5 Make this decision
explicitly in CI: releasing a runner sooner has different reliability semantics
from confirming that its telemetry arrived. 6.6.1 Tracing a Build Across Services
develops the joins needed to follow that evidence across Bazel, BES, CI, and
downstream consumers.
Invocation metadata, test results, and artifact URIs are enough to build a view of one run. The same stream can inform CI work selection, but BEP describes what Bazel actually processed. It does not derive a safe target set from a source diff. 5.2.7 Query in CI Pipelines develops the separate graph evidence and fail-closed boundary needed before such a pipeline can schedule less work.
When BES is used as a deployment hook, keep artifact selection, provenance, and promotion policy separate from event ingestion. The end-to-end pattern is covered in 6.5.8 Complete CI Results with BEP/BES.
Keep Observation Separate from Starlark Debugging
print() and the DAP debugger in 4.3 Starlark Development Tools help a rule author
understand the loading and analysis of particular Starlark code. BEP has a
different boundary: it conveys a stable, machine-readable history of the whole
command to CI, a dashboard, or an IDE. Do not build an observability system by
parsing diagnostic prints, and do not expect BEP to replace an interactive
debugger.
Likewise, a file URI in an event does not guarantee that a remote backend can read the file. A log may exist only on the machine running Bazel. The official documentation recommends a shared remote cache as a way to make files referenced by BEP available to the backend.1 A consumer should therefore model event metadata, artifact-byte availability, and read authorization as separate concerns.
BEP is the machine-readable contract for one Bazel invocation. Its events form
an ID-linked graph, and the authoritative command result comes from
BuildFinished. Start with a JSON file, but make a production consumer handle
configurations, aspects, Aborted, and shared NamedSetOfFiles instead of
assuming a simple, complete list of records.
Binary BEP is suitable for efficient storage, while BES streams BEP over gRPC. BEP complements profiles, execution logs, and Starlark debugging. It does not replace them.
Check your understanding · 4 questions
1.Match each data source to the problem it is best suited to investigate:
Drag each answer onto the matching prompt, or click an answer and then click a prompt
2.A team wants to prototype an analyzer locally, then receive events continuously in a central service. Which plan preserves the correct separation of roles?
Select one answer
3.A consumer must collect artifacts from TargetComplete output groups. Which design choices are appropriate?
Select all that apply
4.Evaluate these assumptions about BEP stream completion and completeness:
Choose True or False for each sentence
Footnotes
-
Build Event Protocol — event model, graph, file formats, and BES transport ↩1 ↩2 ↩3 ↩4 ↩5 ↩6
-
Build Event Protocol Glossary — completion, action, target, test, and metric event semantics ↩1 ↩2 ↩3
-
Extracting build performance metrics — distinct roles of BEP, profiles, and execution logs ↩
-
Build Event Protocol Examples — artifact references and safe
NamedSetOfFilestraversal ↩ -
Command-Line Reference — current BEP/BES flag syntax and defaults ↩