Skip to content

feat(besreceiver): stamp bazel.run attrs from ExecRequestConstructed - #69

Merged
chagui merged 1 commit into
mainfrom
chagui/besreceiver/issue-63-exec-request
Apr 25, 2026
Merged

chagui merged 1 commit into
mainfrom
chagui/besreceiver/issue-63-exec-request

Conversation

@chagui

@chagui chagui commented Apr 24, 2026 •

Copy link
Copy Markdown
Owner

On bazel run invocations Bazel emits ExecRequestConstructed carrying the final argv, working directory, environment, env-vars-to-unset, and whether the process will actually exec. The PR exposes those on five always-on counts/booleans plus four PII-gated detail attributes so bazel run traces are self-describing without operators having to correlate by command name. bazel build / bazel test invocations emit nothing here.

Review-driven design choices

  • Late post-flush path is the production path, not defense-in-depth. Bazel's BEP proto explicitly places ExecRequestConstructed "after a successful build and before trying to execute" — i.e. it can arrive after BuildFinished on the wire. The receiver handles both orderings: pre-flush, attrs land on the root bazel.build span (current design); post-flush, the receiver emits a standalone bazel.run child span (parented to the root via traceID/spanID) carrying the same attrs through a new lateRunSpan helper. Without this, every bazel run invocation would silently emit empty bazel.run.* attrs.
  • Split IncludeRunEnvironment from IncludeCommandArgs. Run environments routinely carry credentials, tokens, and host-derived secrets that command-line arguments do not. The original PR re-used IncludeCommandArgs for both axes; the gates are now independent so operators can show argv without exposing env, and vice versa. Docstrings and docs/attributes.md are updated accordingly.
  • environment_variable_to_clear (proto field 4) emitted. Previously dropped silently — operators saw the env-set list, ran a repro with those vars, and got different behavior because exec also unset others. Now exposed as both a slice and an always-on count.
  • UTF-8 validated on every bytes→string cast. pdata accepts arbitrary strings but OTLP/JSON exporters reject invalid UTF-8 and that failure cascades the entire span batch, not just one attribute. Non-UTF-8 entries are silently skipped (one utf8.ValidString guard per cast site).
  • Bounded argv/env. argv capped at 200 entries, env at 50, env-to-clear at 50; each value clipped at 256 bytes via the existing truncateAttrValue helper. The always-on count attributes report the full payload size, not the capped slice, so operators see the truth even when emission is clipped.
  • Server-side env sort. Bazel emits env in process-environ iteration order, which is not stable across OSes or runs. Sorting by name in the receiver makes downstream queries and diffs deterministic. Also fixed: the test helper no longer sorts on the input side, so any future receiver-side regression surfaces.

Deferred to follow-up

  • OTel semconv alignment for argv/env (process.command_args / process.runtime.environment) — separate task, requires schema discussion.
  • nolint:gocyclo replacement on eventTypeName with a map[reflect.Type]string — applies project-wide to every dispatch site, scoped out of this PR.

Closes #63.

@chagui chagui mentioned this pull request Apr 24, 2026
1 task
@chagui
chagui force-pushed the chagui/besreceiver/issue-63-exec-request branch from 4505158 to 4aa9fd1 Compare April 25, 2026 08:00
@chagui
chagui marked this pull request as ready for review April 25, 2026 08:01
Bazel emits ExecRequestConstructed only for `bazel run` invocations, after
the build succeeds and just before the target is exec'd. Until now the
event was dropped (see #26), leaving `bazel run` traces indistinguishable
from `bazel build` at the root span.

Buffer the single per-invocation payload on invocationState alongside
WorkspaceStatus / StructuredCommandLine and stamp five attributes on the
root bazel.build span during writeRootSpan:

- bazel.run.argv (Slice[string])                — PII.IncludeCommandArgs
- bazel.run.environment (Slice[Map{name,value}])— PII.IncludeCommandArgs
- bazel.run.working_directory (string)          — PII.IncludeWorkingDir
- bazel.run.environment_variable_count (int)    — always emitted
- bazel.run.should_exec (bool)                  — always emitted

Count and should_exec are emitted even when details are redacted so
operators retain a "run invocation arrived" signal. argv and environment
share the IncludeCommandArgs gate because env commonly carries
argv-adjacent secrets.

Issue #63.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chagui
chagui force-pushed the chagui/besreceiver/issue-63-exec-request branch from 4aa9fd1 to a13ca2b Compare April 25, 2026 09:32
@chagui
chagui merged commit 7c2f136 into main Apr 25, 2026
5 checks passed
@chagui
chagui deleted the chagui/besreceiver/issue-63-exec-request branch April 25, 2026 12:34
chagui added a commit that referenced this pull request Apr 25, 2026
…cted (#69)

Lands the review feedback that was prepared for #69 but did not reach
main before the merge. The PR-#69 commit body in main describes the
pre-review-fix design (single PII gate, no late path, no
environment_variable_to_clear, byte-boundary truncation, no UTF-8
validation); this commit brings the implementation in line with the
agreed review outcome.

- Late post-flush handling: when ExecRequestConstructed arrives after
  BuildFinished (the production wire order per BEP proto:1461-1462), the
  receiver emits a standalone bazel.run child span parented to the root
  via traceID/spanID rather than silently dropping the attrs.
- environment_variable_to_clear (proto field 4) emitted as a slice plus
  always-on bazel.run.environment_variable_to_clear_count for parity with
  the existing environment_variable_count.
- IncludeRunEnvironment PII gate split from IncludeCommandArgs. Run
  environments routinely carry credentials and host secrets that argv
  does not; the gates are now independent.
- UTF-8 validation on every bytes→string cast. Non-UTF-8 entries are
  silently skipped because OTLP/JSON exporters reject invalid encoding
  and that failure cascades the entire span batch.
- Bounded argv/env emission. argv capped at 200 entries, env at 50, env-
  to-clear at 50; per-value bytes clipped at 256 via truncateAttrValue.
  Always-on count attributes still report the full payload size so
  operators see truncation explicitly.
- Server-side env sort. Bazel emits env in process-environ iteration
  order which is not stable across OSes; sorting in the receiver makes
  emission deterministic regardless of how Bazel sees the environ.

Tests: 8 new — late post-flush, pre-BuildStarted drop,
environment_variable_to_clear, non-UTF-8 skipped, argv/env caps,
split PII gates (argv-only and env-only).

Docs updated: docs/attributes.md and collector-config.yaml.
chagui added a commit that referenced this pull request Apr 25, 2026
…cted (#69)

Lands the review feedback that was prepared for #69 but did not reach
main before the merge. The PR-#69 commit body in main describes the
pre-review-fix design (single PII gate, no late path, no
environment_variable_to_clear, byte-boundary truncation, no UTF-8
validation); this commit brings the implementation in line with the
agreed review outcome.

- Late post-flush handling: when ExecRequestConstructed arrives after
  BuildFinished (the production wire order per BEP proto:1461-1462), the
  receiver emits a standalone bazel.run child span parented to the root
  via traceID/spanID rather than silently dropping the attrs.
- environment_variable_to_clear (proto field 4) emitted as a slice plus
  always-on bazel.run.environment_variable_to_clear_count for parity with
  the existing environment_variable_count.
- IncludeRunEnvironment PII gate split from IncludeCommandArgs. Run
  environments routinely carry credentials and host secrets that argv
  does not; the gates are now independent.
- UTF-8 validation on every bytes→string cast. Non-UTF-8 entries are
  silently skipped because OTLP/JSON exporters reject invalid encoding
  and that failure cascades the entire span batch.
- Bounded argv/env emission. argv capped at 200 entries, env at 50, env-
  to-clear at 50; per-value bytes clipped at 256 via truncateAttrValue.
  Always-on count attributes still report the full payload size so
  operators see truncation explicitly.
- Server-side env sort. Bazel emits env in process-environ iteration
  order which is not stable across OSes; sorting in the receiver makes
  emission deterministic regardless of how Bazel sees the environ.

Tests: 8 new — late post-flush, pre-BuildStarted drop,
environment_variable_to_clear, non-UTF-8 skipped, argv/env caps,
split PII gates (argv-only and env-only).

Docs updated: docs/attributes.md and collector-config.yaml.
chagui added a commit that referenced this pull request Apr 25, 2026
…cted (#69)

Lands the review feedback that was prepared for #69 but did not reach
main before the merge. The PR-#69 commit body in main describes the
pre-review-fix design (single PII gate, no late path, no
environment_variable_to_clear, byte-boundary truncation, no UTF-8
validation); this commit brings the implementation in line with the
agreed review outcome.

- Late post-flush handling: when ExecRequestConstructed arrives after
  BuildFinished (the production wire order per BEP proto:1461-1462), the
  receiver emits a standalone bazel.run child span parented to the root
  via traceID/spanID rather than silently dropping the attrs.
- environment_variable_to_clear (proto field 4) emitted as a slice plus
  always-on bazel.run.environment_variable_to_clear_count for parity with
  the existing environment_variable_count.
- IncludeRunEnvironment PII gate split from IncludeCommandArgs. Run
  environments routinely carry credentials and host secrets that argv
  does not; the gates are now independent.
- UTF-8 validation on every bytes→string cast. Non-UTF-8 entries are
  silently skipped because OTLP/JSON exporters reject invalid encoding
  and that failure cascades the entire span batch.
- Bounded argv/env emission. argv capped at 200 entries, env at 50, env-
  to-clear at 50; per-value bytes clipped at 256 via truncateAttrValue.
  Always-on count attributes still report the full payload size so
  operators see truncation explicitly.
- Server-side env sort. Bazel emits env in process-environ iteration
  order which is not stable across OSes; sorting in the receiver makes
  emission deterministic regardless of how Bazel sees the environ.

Tests: 8 new — late post-flush, pre-BuildStarted drop,
environment_variable_to_clear, non-UTF-8 skipped, argv/env caps,
split PII gates (argv-only and env-only).

Docs updated: docs/attributes.md and collector-config.yaml.
chagui added a commit that referenced this pull request Apr 25, 2026
…cted (#69) (#74)

Lands the review feedback that was prepared for #69 but did not reach
main before the merge. The PR-#69 commit body in main describes the
pre-review-fix design (single PII gate, no late path, no
environment_variable_to_clear, byte-boundary truncation, no UTF-8
validation); this commit brings the implementation in line with the
agreed review outcome.

- Late post-flush handling: when ExecRequestConstructed arrives after
  BuildFinished (the production wire order per BEP proto:1461-1462), the
  receiver emits a standalone bazel.run child span parented to the root
  via traceID/spanID rather than silently dropping the attrs.
- environment_variable_to_clear (proto field 4) emitted as a slice plus
  always-on bazel.run.environment_variable_to_clear_count for parity with
  the existing environment_variable_count.
- IncludeRunEnvironment PII gate split from IncludeCommandArgs. Run
  environments routinely carry credentials and host secrets that argv
  does not; the gates are now independent.
- UTF-8 validation on every bytes→string cast. Non-UTF-8 entries are
  silently skipped because OTLP/JSON exporters reject invalid encoding
  and that failure cascades the entire span batch.
- Bounded argv/env emission. argv capped at 200 entries, env at 50, env-
  to-clear at 50; per-value bytes clipped at 256 via truncateAttrValue.
  Always-on count attributes still report the full payload size so
  operators see truncation explicitly.
- Server-side env sort. Bazel emits env in process-environ iteration
  order which is not stable across OSes; sorting in the receiver makes
  emission deterministic regardless of how Bazel sees the environ.

Tests: 8 new — late post-flush, pre-BuildStarted drop,
environment_variable_to_clear, non-UTF-8 skipped, argv/env caps,
split PII gates (argv-only and env-only).

Docs updated: docs/attributes.md and collector-config.yaml.
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.

Stamp ExecRequestConstructed on the root span for bazel run

1 participant