Skip to content

feat: process-memory + buildkitd OTEL telemetry for CI memory diagnos… - #572

Open
gilescope wants to merge 9 commits into
mainfrom
giles-ci-telemetry
Open

feat: process-memory + buildkitd OTEL telemetry for CI memory diagnos…#572
gilescope wants to merge 9 commits into
mainfrom
giles-ci-telemetry

Conversation

@gilescope

@gilescope gilescope commented Jun 14, 2026

Copy link
Copy Markdown

Extracted from #442 (the buildkit upgrade) so the CI memory-diagnostics telemetry can land independently of the bump.

What

Adds OpenTelemetry instrumentation to help diagnose CI memory pressure (the OOM-driven flakiness that #442 fights), plus a stats-stream recovery fix:

  • Process-memory metrics (internal/telemetry) — registers OTEL gauges for process memory (RSS/heap), tagged with process role/nesting/target so inner vs outer earth processes are distinguishable. Wired into the existing telemetry Start path.
  • buildkitd OTEL env plumbing (buildkitd) — addBuildkitTelemetryEnv forwards OTEL_* exporter config into the buildkitd container, sets OTEL_SERVICE_NAME=EarthBuild-buildkitd, and appends resource attributes (role, nesting, container name, installation). appendOTELResourceAttributes merges with any caller-supplied OTEL_RESOURCE_ATTRIBUTES, dropping malformed entries. Start now uses its installationName parameter (previously discarded).
  • Stats-stream Reset() (util/statsstreamparser) — discards a buffered partial frame and re-initialises the reader, so a desynced/malformed docker stats frame (e.g. runc collector EOF emitting a partial frame) is recoverable instead of fatal.

Deliberately excluded (stay in #442)

  • The buildkit-API rename GCPolicy.KeepBytes → ReservedSpace in buildkitd.go — won't compile against current buildkit.
  • Cosmetic hint.Wrap / printBuildkitInfo line-reflows from the bump's linter.

Verification

  • go build ./... — green.
  • go test ./util/statsstreamparser/ — green (new Reset coverage).
  • go test ./buildkitd/ -run Telemetry — green (×2: env forwarding + no-op without a metrics exporter).

…tics

Signed-off-by: Giles Cope <gilescope@gmail.com>
@gilescope
gilescope requested a review from a team as a code owner June 14, 2026 14:39
@gilescope
gilescope requested review from janishorsts and removed request for a team June 14, 2026 14:39
@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown

⚠️ Are we earthbuild yet?

Warning: "earthly" occurrences have increased by 10 (0.21%)

📈 Overall Progress

Branch Total Count
main 4748
This PR 4758
Difference +10 (0.21%)

📁 Changes by file type:

File Type Change
Go files (.go) ❌ +10
Documentation (.md) ➖ No change
Earthfiles ➖ No change

Keep up the great work migrating from Earthly to Earthbuild! 🚀

💡 Tips for finding more occurrences

Run locally to see detailed breakdown:

./.github/scripts/count-earthly.sh

Note that the goal is not to reach 0.
There is anticipated to be at least some occurences of earthly in the source code due to backwards compatibility with config files and language constructs.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces OpenTelemetry metrics for tracking process memory (such as Alloc, HeapAlloc, HeapSys, and Sys) and adds telemetry environment configuration for buildkitd. It also adds a Reset method to the stats stream parser to allow recovery from malformed frames, complete with unit tests. Feedback from the review suggests avoiding if statements with initializers across several files to prevent potential linting issues, and tracking already-seen keys in appendOTELResourceAttributes to avoid duplicate resource attributes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread buildkitd/buildkitd.go Outdated
Comment thread buildkitd/buildkitd.go
Comment thread internal/telemetry/telemetry.go Outdated
Comment thread internal/telemetry/telemetry.go Outdated
Comment thread internal/telemetry/telemetry.go Outdated
Comment thread buildkitd/buildkitd.go Outdated
gilescope and others added 7 commits July 28, 2026 08:15
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Giles Cope <gilescope@gmail.com>
Signed-off-by: Giles Cope <gilescope@gmail.com>
Signed-off-by: Giles Cope <gilescope@gmail.com>
@gilescope
gilescope requested a review from janishorsts July 29, 2026 08:04
@kmannislands kmannislands added the ai-assisted Authored with AI assistance label Jul 29, 2026
Signed-off-by: Giles Cope <gilescope@gmail.com>
Target = attribute.Key("earth.target")

// BuildkitContainerName is the name of the attribute that represents the container buildkitd runs in.
BuildkitContainerName = attribute.Key("earth.buildkit.container.name")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TUse OTel's container.name attribute instead.

Comment thread buildkitd/buildkitd.go
_, ok := envOpts["OTEL_METRICS_EXPORTER"]
if !ok {
if envOpts["OTEL_EXPORTER_OTLP_ENDPOINT"] != "" || envOpts["OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"] != "" {
envOpts["OTEL_METRICS_EXPORTER"] = "otlp"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The otlp value is the default exporter type value. What is the reason for setting it as an env variable anyway?

Comment thread buildkitd/buildkitd.go
// key collision: the inherited value describes the process that spawned
// buildkitd, ours describes buildkitd itself. Emitting the key twice is not an
// option - collectors disagree on which duplicate survives.
func appendOTELResourceAttributes(base string, attrs map[string]string) string {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread buildkitd/buildkitd.go
return nil
}

func addBuildkitTelemetryEnv(envOpts map[string]string, containerName, installationName string, withDocker bool) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can a single func handle initialisation of env variables?

Suggested change
func addBuildkitTelemetryEnv(envOpts map[string]string, containerName, installationName string, withDocker bool) {
envOpts := func buildkitTelemetryEnv(settings Settings, containerName, installationName string) map[string]string {


return nil
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 [Gemini AI / Rob Pike Review]

The Go standard library provides math.MaxInt64. Redefining 1<<63 - 1 as a local constant is unnecessary noise.

if value > math.MaxInt64 {
    return math.MaxInt64
}


return attrs
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 [Gemini AI / Rob Pike Review]

In buildkitd/env.go, parseBoolEnv(key) was created specifically to catch typos like EARTHLY_WITH_DOCKER=yes and warn the user. Here strconv.ParseBool ignores the error silently. Consider using parseBoolEnv("EARTHLY_WITH_DOCKER") for consistent error handling across the codebase.

Comment thread buildkitd/env.go

value, err := strconv.ParseBool(raw)
if err != nil {
return false, fmt.Errorf(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 [Gemini AI / Rob Pike Review]

Listing every boolean variant supported by strconv.ParseBool makes the error message unnecessarily verbose. A simpler message is clearer:

return false, fmt.Errorf("%s is set to %q, which is not a valid boolean", key, raw)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-assisted Authored with AI assistance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants