Skip to content

feat(besreceiver): route Progress events to logs pipeline - #68

Merged
chagui merged 1 commit into
mainfrom
chagui/besreceiver/issue-60-progress
Apr 25, 2026
Merged

chagui merged 1 commit into
mainfrom
chagui/besreceiver/issue-60-progress

Conversation

@chagui

@chagui chagui commented Apr 24, 2026 •

Copy link
Copy Markdown
Owner

Adds opt-in consumption of Bazel Progress BEP events as OTel log records. Each non-empty stream produces one record at INFO severity, stamped with bazel.progress.{stream,bytes,truncated,opaque_count}. When the body exceeds progress.max_chunk_size the receiver clips at a UTF-8 rune boundary (never producing invalid encoding) and bazel.progress.truncated=true. max_chunk_size: 0 disables the cap; config validation rejects negative values.

Default is progress.enabled: false to avoid surprise log volume — Bazel builds with --build_event_publish_all_actions produce a lot of Progress. Operators opt in explicitly, and the bundled 64 KiB chunk size keeps the worst-case per-record payload bounded once they do.

Review-driven design choices

  • Severity is INFO on both streams. Bazel routes normal-build chatter (Loading:, Analyzing:, Build completed successfully) through stderr — mapping stderr to ERROR would page on every green build. Operators who need elevation can stack a transformprocessor downstream.
  • Emission order is stderr-first, matching the BEP spec (build_event_stream.proto:303-304: "stderr has been emitted before stdout if both are present"). Both records on a single Progress event share the same opaque_count so consumers can pair them and reconstruct chunk order.
  • Rune-safe truncation. The body clip backs off to a UTF-8 rune boundary using a new shared truncateUTF8 helper (also adopted by reconstructCommandLine to dedup the existing manual loop).
  • Always-on bytes and truncated attributes. Both are stamped on every record so downstream queries can rely on attribute presence rather than guarding for absent keys. The previous original_bytes-only-on-truncation contract is gone — replaced by bytes (always = original byte length).
  • Post-flush gate. handleProgress checks state.flushed, matching the gate every other event handler uses; late Progress arriving after BuildFinished is dropped silently rather than appearing in a separate consumer batch.
  • emitLog / emitProgressLog deduplication. Both now share a newLogPayload helper for the resource/scope boilerplate, eliminating the duplicated service.name="bazel" literal and the duplicated record-construction logic.

Memory bounding — explicit non-goal

This PR truncates the log record body, not the inbound gRPC payload. The full Progress message is still allocated by proto.Unmarshal before the handler runs. See docs/adr/0002-large-payload-handling.md and the concrete follow-ups #64/#65/#66 for the heap-bounding story.

ACK back-pressure — known trade-off, follow-up filed

Routing Progress through the existing synchronous ConsumeLogs path widens an existing back-pressure surface: a stalled logs pipeline now holds BES ACKs on the highest-volume BEP event class. The pattern pre-exists for every other handler, so fixing it correctly is project-wide. Filed as #72 (async/bounded logs path).

Deferred to follow-ups

Closes #60.

@chagui chagui mentioned this pull request Apr 24, 2026
1 task
@chagui
chagui force-pushed the chagui/besreceiver/issue-60-progress branch from accd31d to d903569 Compare April 25, 2026 08:00
@chagui
chagui marked this pull request as ready for review April 25, 2026 08:01
@chagui
chagui force-pushed the chagui/besreceiver/issue-60-progress branch from d903569 to b5af6af Compare April 25, 2026 08:14
Bazel Progress BEP events (streaming stdout/stderr) were previously
discarded. Operators couldn't see the output stream without parsing Bazel
logs out-of-band. Route them through the logs pipeline behind an opt-in
config so operators can correlate build output with traces.

- New progress.{enabled, max_chunk_size} config block; disabled by
  default because payloads are large and may contain secrets echoed by
  actions. max_chunk_size: 0 disables the per-record cap.
- One log record per non-empty stream: stdout -> INFO, stderr -> ERROR,
  with bazel.progress.{stream,truncated,original_bytes} attributes and
  the invocation's TraceID for correlation.
- Unknown invocation ids (Progress before BuildStarted) are silently
  dropped, matching the pattern used by every other handler.
- Config validation rejects negative max_chunk_size.

Closes #60.
@chagui
chagui force-pushed the chagui/besreceiver/issue-60-progress branch from b5af6af to 22f904e Compare April 25, 2026 09:19
@chagui
chagui merged commit 5039bdf into main Apr 25, 2026
5 checks passed
@chagui
chagui deleted the chagui/besreceiver/issue-60-progress branch April 25, 2026 09:23
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.

Consume Progress BEP events as OTel log records with size cap

1 participant