Skip to content

feat(metrics): label pause/resume telemetry by fs_only - #3425

Merged
bchalios merged 1 commit into
mainfrom
feat/fs-only-pause-metrics
Jul 28, 2026
Merged

bchalios merged 1 commit into
mainfrom
feat/fs-only-pause-metrics

Conversation

@bchalios

@bchalios bchalios commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Makes filesystem-only pause and resume distinguishable in metrics, so the Filesystem-only Snapshots dashboard can stop relying on "(all pauses)" context panels.

Change

  • New histogram orchestrator.sandbox.pause.duration — Pause handler, attrs fs_only + success → fs-only pause call-count / error-rate / e2e latency.
  • fs_only on orchestrator.snapshot.upload.failed — threaded via snapshotResult.
  • fs_only on orchestrator.sandbox.create.duration — set at the reboot/resume fork, so e2e create/resume latency splits filesystem-only reboot vs memory restore. Combined with the existing sandbox.resume bool: resume=false→fresh create; resume=true,fs_only=false→memory resume; resume=true,fs_only=true→fs-only reboot.

Why

fs-only-ness was recorded only as a span attribute (fs-only-snapshot), never a metric label, so pause/resume e2e latency, error rate, and upload failures couldn't be scoped to fs-only. Reboot-vs-resume was already distinguishable on the envd-init/uffd metrics (start_type); this adds it to the e2e create.duration as well.

Notes

  • Pause uses named returns so the deferred metric can read the final error.
  • Pure additive instrumentation; no pause/resume/snapshot logic changed.
  • Follow-up: monitoring-repo PR to switch the dashboard's pause/upload/resume panels to fs_only="true" once this deploys.

Verified: go build/vet/golangci-lint clean, go test ./pkg/server/ passes.

🤖 Generated with Claude Code

@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Additive OpenTelemetry instrumentation only; no changes to pause, resume, or upload logic beyond metric attributes and recording failed creates on the create-duration histogram.

Overview
This PR adds orchestrator metrics so filesystem-only pause and resume paths can be filtered in dashboards instead of blending with full memory snapshots.

It registers orchestrator.sandbox.pause.duration and records pause handler latency with fs_only and success. orchestrator.sandbox.create.duration now also carries fs_only (set when resume takes the reboot path) and success, and is emitted on failed creates as well as successes. orchestrator.snapshot.upload.failed increments with fs_only via snapshotResult.filesystemOnly. Shared telemetry registers the new pause histogram name and description. Pause uses named returns so the deferred recorder sees the final error; snapshot behavior is unchanged aside from labeling.

Reviewed by Cursor Bugbot for commit 35ff850. Bugbot is set up for automated code reviews on this repo. Configure here.

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

❌ 11 Tests Failed:

Tests completed Failed Passed Skipped
3514 11 3503 7
View the top 3 failed test(s) by shortest run time
github.com/e2b-dev/infra/tests/integration/internal/tests/proxies::TestMaskRequestHostAPIParameter
Stack Traces | 5.12s run time
=== RUN   TestMaskRequestHostAPIParameter
=== PAUSE TestMaskRequestHostAPIParameter
=== CONT  TestMaskRequestHostAPIParameter
    mask_request_host_test.go:44: Command [python3] output: event:{start:{pid:1109}}
Executing command ls in sandbox ibujdpisndb8gwnhz2xm9
    mask_request_host_test.go:68: Command [cat] output: event:{start:{pid:1110}}
    mask_request_host_test.go:68: Command [cat] output: event:{data:{stderr:"cat: /tmp/nc_output.txt: No such file or directory\n"}}
    mask_request_host_test.go:68: Command [cat] output: event:{end:{exit_code:1 exited:true status:"exit status 1" error:"exit status 1"}}
    mask_request_host_test.go:69: 
        	Error Trace:	.../tests/proxies/mask_request_host_test.go:69
        	Error:      	Received unexpected error:
        	            	command cat in sandbox iocf0qbusumi51isx4yu0 failed with exit code 1
        	Test:       	TestMaskRequestHostAPIParameter
--- FAIL: TestMaskRequestHostAPIParameter (5.12s)
github.com/e2b-dev/infra/tests/integration/internal/tests/envd::TestCACertTrustedAfterFilesystemOnlyReboot
Stack Traces | 170s run time
=== RUN   TestCACertTrustedAfterFilesystemOnlyReboot
=== PAUSE TestCACertTrustedAfterFilesystemOnlyReboot
=== CONT  TestCACertTrustedAfterFilesystemOnlyReboot
    template.go:43: test-fs-only-ca-reboot: [info] Building template u5qas1froaywobudowq9/4ec0b60b-1159-407b-bed6-bb89cdf2bf7a
Executing command cat in sandbox iol0zojzcczqairfqtewo (user: root)
    template.go:43: test-fs-only-ca-reboot: [info] [base] FROM ubuntu:22.04 [f9f564014e009a9561a82bf8c84f9314242971e833fb019936654ecba452f184]
    template.go:43: test-fs-only-ca-reboot: [info] Base Docker image size: 30 MB
    template.go:43: test-fs-only-ca-reboot: [info] Creating file system and pulling Docker image
    template.go:43: test-fs-only-ca-reboot: [info] Uncompressing layer sha256:d6834b4a794c03efa2c998853e64969fa8851b11b2ade63292268872a37759d0 30 MB
    template.go:43: test-fs-only-ca-reboot: [info] Uncompressing layer sha256:69ae44b1e1c6792a7e9300322d38a1cd35ed9b4973b786c71e8b1e9e651bf0ee 13 MB
    template.go:43: test-fs-only-ca-reboot: [info] Uncompressing layer sha256:8c4b1b28875140ed3abacaf16ad0d696f6bef912f52d2148f261a23e3349465b 168 B
    template.go:43: test-fs-only-ca-reboot: [info] Layers extracted
    template.go:43: test-fs-only-ca-reboot: [info] Root filesystem structure: bin, boot, dev, etc, home, lib, lib32, lib64, libx32, media, mnt, opt, proc, root, run, sbin, srv, sys, tmp, usr, var
Executing command cat in sandbox iupxmttcswav430vl8dr3 (user: root)
    template.go:43: test-fs-only-ca-reboot: [info] Provisioning sandbox template
    template.go:43: test-fs-only-ca-reboot: [info] Provisioning was successful, cleaning up
    template.go:43: test-fs-only-ca-reboot: [info] Sandbox template provisioned
    template.go:43: test-fs-only-ca-reboot: [info] [base] DEFAULT USER user [49e586c2171254c6bc4a09e84eedac32dbcf113a158c24248129af2f49cbed74]
    template.go:43: test-fs-only-ca-reboot: [info] [builder 1/1] RUN echo 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlekNDQVNHZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQWxNU013SVFZRFZRUURFeHBsTW1JdGRHVnoKZEMxallTMW1jeTF2Ym14NUxYSmxZbTl2ZERBZUZ3MHlOakEzTWpnd056VTFNVFphRncweU5qQTNNamd3T0RVMgpNVFphTUNVeEl6QWhCZ05WQkFNVEdtVXlZaTEwWlhOMExXTmhMV1p6TFc5dWJIa3RjbVZpYjI5ME1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVXN0ZzU3NOSkhCb2l4VU1tUzdrcGxlUXV1U3lERlgrVEtIcUUKdVNpb3ljUVppbVdZcUI3Q04zV2hFQWY3TlNRZWMva0VISTJJTGovS2cvcGtXdi8xbmFOQ01FQXdEZ1lEVlIwUApBUUgvQkFRREFnSUVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUVGR2p2YmI3Mk1pR3lBWlNUCjdsV2hiVWhwQnlVVE1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRREVTMWsrWU1iblBjb2dSZnBUYXhKemZEemgKR3ZrazBDNXppZExJdkFSOTZ3SWdIQnY3MEVlVXI3MnBJYjBSZ0FZSDZiazMyQTFvWG1EdHRxR2g4ZytCTjRZPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==' | base64 -d > .../share/ca-certificates/e2b-reboot-ca.crt root [9f14b3283530a2882560883473a29ad037c989b86dd5f9bdfaca67e0d11a5a7e]
    template.go:43: test-fs-only-ca-reboot: [info] [finalize] Finalizing template build [999ad9419be78d1b65fc24ffe9d826a83ad1367bc659521986c5adbd2f41c174]
    template.go:43: test-fs-only-ca-reboot: [error] Build failed: An internal error occurred. Please try again or contact support with the build ID.
    ca_cert_reboot_test.go:30: Build failed: {<nil> An internal error occurred. Please try again or contact support with the build ID. <nil>}
--- FAIL: TestCACertTrustedAfterFilesystemOnlyReboot (170.11s)
github.com/e2b-dev/infra/tests/integration/internal/tests/api/templates::TestTemplateBuildFuseConfiguration
Stack Traces | 184s run time
=== RUN   TestTemplateBuildFuseConfiguration
=== PAUSE TestTemplateBuildFuseConfiguration
=== CONT  TestTemplateBuildFuseConfiguration
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Building template at35cvgyvf1kjsx634n9/63201394-f23e-4038-817d-a4b2e14d6901
    build_template_test.go:133: test-ubuntu-fuse-config: [info] [base] FROM ubuntu:22.04 [f9f564014e009a9561a82bf8c84f9314242971e833fb019936654ecba452f184]
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Base Docker image size: 30 MB
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Creating file system and pulling Docker image
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Uncompressing layer sha256:d6834b4a794c03efa2c998853e64969fa8851b11b2ade63292268872a37759d0 30 MB
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Uncompressing layer sha256:69ae44b1e1c6792a7e9300322d38a1cd35ed9b4973b786c71e8b1e9e651bf0ee 13 MB
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Uncompressing layer sha256:8c4b1b28875140ed3abacaf16ad0d696f6bef912f52d2148f261a23e3349465b 168 B
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Layers extracted
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Root filesystem structure: bin, boot, dev, etc, home, lib, lib32, lib64, libx32, media, mnt, opt, proc, root, run, sbin, srv, sys, tmp, usr, var
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Provisioning sandbox template
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Provisioning was successful, cleaning up
    build_template_test.go:133: test-ubuntu-fuse-config: [info] Sandbox template provisioned
    build_template_test.go:133: test-ubuntu-fuse-config: [info] [base] DEFAULT USER user [49e586c2171254c6bc4a09e84eedac32dbcf113a158c24248129af2f49cbed74]
    build_template_test.go:133: test-ubuntu-fuse-config: [info] [builder 1/2] RUN grep -q 'z /dev/fuse 0666 root root -' /etc/tmpfiles.d/fuse.conf [064c2aa80e42051b5301f9fd4b4c1bab38adc2b717535b7ca42d5dc9fdc739d1]
    build_template_test.go:133: test-ubuntu-fuse-config: [info] [builder 2/2] RUN echo "Checking /dev/fuse permissions:"; ls -la /dev/fuse; stat -c 'mode=%a owner=%U group=%G' /dev/fuse; test $(stat -c %a /dev/fuse) = '666' [53b9173a7399b3bca212e8c5d1b705f01c09a1180ef92f57f3d3fc1db134b289]
    build_template_test.go:133: test-ubuntu-fuse-config: [info] [builder 2/2] [stdout]: Checking /dev/fuse permissions:
    build_template_test.go:133: test-ubuntu-fuse-config: [info] [builder 2/2] [stdout]: crw-rw-rw- 1 root root 10, 229 Jul 28 07:57 /dev/fuse
    build_template_test.go:133: test-ubuntu-fuse-config: [info] [builder 2/2] [stdout]: mode=666 owner=root group=root
    build_template_test.go:133: test-ubuntu-fuse-config: [info] [finalize] Finalizing template build [44ab07a644985d56c51c27da9742b1dd30905f459dd707130223567c87e03c43]
    build_template_test.go:133: test-ubuntu-fuse-config: [error] Build failed: An internal error occurred. Please try again or contact support with the build ID.
    build_template_test.go:1189: Build failed: {<nil> An internal error occurred. Please try again or contact support with the build ID. <nil>}
--- FAIL: TestTemplateBuildFuseConfiguration (183.54s)
github.com/e2b-dev/infra/tests/integration/internal/tests/api/templates::TestTemplateBuildCOPY
Stack Traces | 208s run time
=== RUN   TestTemplateBuildCOPY
=== PAUSE TestTemplateBuildCOPY
=== CONT  TestTemplateBuildCOPY
    build_template_test.go:133: test-ubuntu-copy: [info] Building template zo2u92n7oh3qkrfy6iul/da6e6c3f-11f6-4a4b-9530-6a8104c7cc78
    build_template_test.go:133: test-ubuntu-copy: [info] [base] FROM ubuntu:24.04 [a9b3ad91e89daabce8685d67ae12aacb4a128e5aea703dc57457c0ef17079b25]
    build_template_test.go:133: test-ubuntu-copy: [info] Base Docker image size: 30 MB
    build_template_test.go:133: test-ubuntu-copy: [info] Creating file system and pulling Docker image
    build_template_test.go:133: test-ubuntu-copy: [info] Uncompressing layer sha256:ca2678b20700c15185707964d9211b1a6406196114bf675f568b6025d37b3888 30 MB
    build_template_test.go:133: test-ubuntu-copy: [info] Uncompressing layer sha256:69ae44b1e1c6792a7e9300322d38a1cd35ed9b4973b786c71e8b1e9e651bf0ee 13 MB
    build_template_test.go:133: test-ubuntu-copy: [info] Uncompressing layer sha256:8c4b1b28875140ed3abacaf16ad0d696f6bef912f52d2148f261a23e3349465b 168 B
    build_template_test.go:133: test-ubuntu-copy: [info] Layers extracted
    build_template_test.go:133: test-ubuntu-copy: [info] Root filesystem structure: bin, boot, dev, etc, home, lib, lib64, media, mnt, opt, proc, root, run, sbin, srv, sys, tmp, usr, var
    build_template_test.go:133: test-ubuntu-copy: [info] Provisioning sandbox template
    build_template_test.go:133: test-ubuntu-copy: [info] Provisioning was successful, cleaning up
    build_template_test.go:133: test-ubuntu-copy: [info] Sandbox template provisioned
    build_template_test.go:133: test-ubuntu-copy: [info] [base] DEFAULT USER user [f9aaa150221ef19e492ba626b8d9200ab9434ed5f63d02341f9e3be29c4b8760]
    build_template_test.go:133: test-ubuntu-copy: [info] [builder 1/2] COPY . /app/ [2449098e8b0a6a85d9aaa0edf0136f8bc69e9d618dac9611e42bba7c698fd629]
    build_template_test.go:133: test-ubuntu-copy: [info] [builder 2/2] RUN cat /app/hello.txt | grep 'Hello from COPY!' [2f22b685841af46c090bf872491df49e98da0615c4d2c99657645a92a5b4ee67]
    build_template_test.go:133: test-ubuntu-copy: [info] [builder 2/2] [stdout]: Hello from COPY!
    build_template_test.go:133: test-ubuntu-copy: [info] [finalize] Finalizing template build [d8abedde856dad9179d9e99f9778f17106da49a5286a30633b898c2e893b0482]
    build_template_test.go:133: test-ubuntu-copy: [error] Build failed: An internal error occurred. Please try again or contact support with the build ID.
    build_template_test.go:1156: Build failed: {<nil> An internal error occurred. Please try again or contact support with the build ID. <nil>}
--- FAIL: TestTemplateBuildCOPY (208.45s)
github.com/e2b-dev/infra/tests/integration/internal/tests/api/templates::TestTemplateBuildInstalledPackagesAvailable
Stack Traces | 300s run time
=== RUN   TestTemplateBuildInstalledPackagesAvailable
=== PAUSE TestTemplateBuildInstalledPackagesAvailable
=== CONT  TestTemplateBuildInstalledPackagesAvailable
    build_template_test.go:133: test-ubuntu-packages-available: [info] Building template 7acvg3l1sodrziorj5it/98488e6a-3443-4827-8a24-58a45411f679
    build_template_test.go:133: test-ubuntu-packages-available: [info] [base] FROM ubuntu:22.04 [f9f564014e009a9561a82bf8c84f9314242971e833fb019936654ecba452f184]
    build_template_test.go:133: test-ubuntu-packages-available: [info] Base Docker image size: 30 MB
    build_template_test.go:133: test-ubuntu-packages-available: [info] Creating file system and pulling Docker image
    build_template_test.go:133: test-ubuntu-packages-available: [info] Uncompressing layer sha256:d6834b4a794c03efa2c998853e64969fa8851b11b2ade63292268872a37759d0 30 MB
    build_template_test.go:133: test-ubuntu-packages-available: [info] Uncompressing layer sha256:69ae44b1e1c6792a7e9300322d38a1cd35ed9b4973b786c71e8b1e9e651bf0ee 13 MB
    build_template_test.go:133: test-ubuntu-packages-available: [info] Uncompressing layer sha256:8c4b1b28875140ed3abacaf16ad0d696f6bef912f52d2148f261a23e3349465b 168 B
    build_template_test.go:133: test-ubuntu-packages-available: [info] Layers extracted
    build_template_test.go:133: test-ubuntu-packages-available: [info] Root filesystem structure: bin, boot, dev, etc, home, lib, lib32, lib64, libx32, media, mnt, opt, proc, root, run, sbin, srv, sys, tmp, usr, var
    build_template_test.go:133: test-ubuntu-packages-available: [info] Provisioning sandbox template
    build_template_test.go:133: test-ubuntu-packages-available: [info] Provisioning was successful, cleaning up
    build_template_test.go:133: test-ubuntu-packages-available: [info] Sandbox template provisioned
    build_template_test.go:133: test-ubuntu-packages-available: [info] [base] DEFAULT USER user [49e586c2171254c6bc4a09e84eedac32dbcf113a158c24248129af2f49cbed74]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 1/15] RUN dpkg-query -W -f='${Status}' systemd | grep -q 'install ok installed' [de826f48fc8f28496580ff9e64f4cd6b59aaeff2811a9bae9b4fffe6645c289e]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 2/15] RUN dpkg-query -W -f='${Status}' systemd-sysv | grep -q 'install ok installed' [15d29149113620d83e56ad1512042bc0b247306802dcdb366ccf1b398b4c3cdb]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 3/15] RUN dpkg-query -W -f='${Status}' openssh-server | grep -q 'install ok installed' [c7ce729a2e1d50236dd8fa2338bcd463909c353853df395eeae5a6d86c5aaaff]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 4/15] RUN dpkg-query -W -f='${Status}' sudo | grep -q 'install ok installed' [401020ed635dcfa25a0d55aed045a457439f6d3712e439ecc3b33e4ba9db14eb]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 5/15] RUN dpkg-query -W -f='${Status}' chrony | grep -q 'install ok installed' [a355929061ef18ba0b427ce239bb340d317d7a078f06d70889300591280426e8]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 6/15] RUN dpkg-query -W -f='${Status}' socat | grep -q 'install ok installed' [d7e232005823e31f2c8a1e83ee175812553529abba39cf318b950f8963d1f969]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 7/15] RUN dpkg-query -W -f='${Status}' curl | grep -q 'install ok installed' [37a6ea018deed85204e0c0105881f83ca383e092f6e16b7fab1a42bb4b3254bc]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 8/15] RUN dpkg-query -W -f='${Status}' ca-certificates | grep -q 'install ok installed' [cf67f41976592227bbb1514b70f29ff6c3f187d36c227b7982bb823c86c78962]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 9/15] RUN dpkg-query -W -f='${Status}' fuse3 | grep -q 'install ok installed' [b0257640d1594b1b9ea66664d67097cbdaf423169d1769d43d697e0f8f44ae5b]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 10/15] RUN dpkg-query -W -f='${Status}' iptables | grep -q 'install ok installed' [1e7b717aefd403d504c973491220d70475fc8b7fa762444d2b6e37bfcaa2e84a]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 11/15] RUN dpkg-query -W -f='${Status}' git | grep -q 'install ok installed' [564561d2d945e6366c96a35e281a547dfd07bbfc4096352651cbfd121930d20f]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 12/15] RUN dpkg-query -W -f='${Status}' less | grep -q 'install ok installed' [7ed9ff27623a2f82daaec96e1f91e9d6b468447b732e0bcd5b61a948a0ae3c26]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 13/15] RUN dpkg-query -W -f='${Status}' nftables | grep -q 'install ok installed' [fab2299ee2f5ef1eb4f33ab12637b71234a2f7a21c8fdcd2bae150612084624f]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 14/15] RUN dpkg-query -W -f='${Status}' iputils-ping | grep -q 'install ok installed' [ad11c2e7f602b13f86e8f844936230c94e79bd96164a4abbdc5cf39f5fd5ba9a]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [builder 15/15] RUN dpkg-query -W -f='${Status}' jq | grep -q 'install ok installed' [13dad491042119a252a9b8d1861921889102ffdb6e0521e4940798ddf88a38b5]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [finalize] Finalizing template build [eb7b37d59c5e9b33cba4e503ad5ee98acad3960c365c3c520ed6d346004f79cb]
    build_template_test.go:133: test-ubuntu-packages-available: [info] [optimize] Optimizing template [f1746441596e199e31ff320cbc21dbca1a7bb77389dd59f9a3378b002c496de1]
    build_template_test.go:1060: 
        	Error Trace:	.../api/templates/build_template_test.go:96
        	            				.../api/templates/build_template_test.go:1060
        	Error:      	Received unexpected error:
        	            	Get "http://localhost:.../builds/98488e6a-3443-4827-8a24-58a45411f679/status?logsOffset=30&level=info": context deadline exceeded
        	Test:       	TestTemplateBuildInstalledPackagesAvailable
--- FAIL: TestTemplateBuildInstalledPackagesAvailable (300.50s)
View the full list of 7 ❄️ flaky test(s)
github.com/e2b-dev/infra/tests/integration/internal/tests/api/templates::TestTemplateBuildRUN

Flake rate in main: 16.33% (Passed 41 times, Failed 8 times)

Stack Traces | 0s run time
=== RUN   TestTemplateBuildRUN
=== PAUSE TestTemplateBuildRUN
=== CONT  TestTemplateBuildRUN
--- FAIL: TestTemplateBuildRUN (0.00s)
github.com/e2b-dev/infra/tests/integration/internal/tests/api/templates::TestTemplateBuildRUN/Single_RUN_command

Flake rate in main: 16.33% (Passed 41 times, Failed 8 times)

Stack Traces | 186s run time
=== RUN   TestTemplateBuildRUN/Single_RUN_command
=== PAUSE TestTemplateBuildRUN/Single_RUN_command
=== CONT  TestTemplateBuildRUN/Single_RUN_command
    build_template_test.go:133: test-ubuntu-run: [info] Building template s04ach2wwirh8vzswpy0/2c8b47c0-736f-4091-99b2-eb6fa51ccae3
    build_template_test.go:133: test-ubuntu-run: [info] [base] FROM ubuntu:22.04 [f9f564014e009a9561a82bf8c84f9314242971e833fb019936654ecba452f184]
    build_template_test.go:133: test-ubuntu-run: [info] Base Docker image size: 30 MB
    build_template_test.go:133: test-ubuntu-run: [info] Creating file system and pulling Docker image
    build_template_test.go:133: test-ubuntu-run: [info] Uncompressing layer sha256:d6834b4a794c03efa2c998853e64969fa8851b11b2ade63292268872a37759d0 30 MB
    build_template_test.go:133: test-ubuntu-run: [info] Uncompressing layer sha256:69ae44b1e1c6792a7e9300322d38a1cd35ed9b4973b786c71e8b1e9e651bf0ee 13 MB
    build_template_test.go:133: test-ubuntu-run: [info] Uncompressing layer sha256:8c4b1b28875140ed3abacaf16ad0d696f6bef912f52d2148f261a23e3349465b 168 B
    build_template_test.go:133: test-ubuntu-run: [info] Layers extracted
    build_template_test.go:133: test-ubuntu-run: [info] Root filesystem structure: bin, boot, dev, etc, home, lib, lib32, lib64, libx32, media, mnt, opt, proc, root, run, sbin, srv, sys, tmp, usr, var
    build_template_test.go:133: test-ubuntu-run: [info] Provisioning sandbox template
    build_template_test.go:133: test-ubuntu-run: [info] Provisioning was successful, cleaning up
    build_template_test.go:133: test-ubuntu-run: [info] Sandbox template provisioned
    build_template_test.go:133: test-ubuntu-run: [info] [base] DEFAULT USER user [49e586c2171254c6bc4a09e84eedac32dbcf113a158c24248129af2f49cbed74]
    build_template_test.go:133: test-ubuntu-run: [info] [builder 1/1] RUN echo 'Hello, World!' [c72b4f813c2a16b0fc1a1c5da7b1365a304cbac516b22dc304a71f70aae48ac0]
    build_template_test.go:133: test-ubuntu-run: [info] [builder 1/1] [stdout]: Hello, World!
    build_template_test.go:133: test-ubuntu-run: [info] [finalize] Finalizing template build [92c524e30533398ebb41ce04c2596130f0cdecc9aa328e28fdb16a1b11f61d62]
    build_template_test.go:133: test-ubuntu-run: [error] Build failed: An internal error occurred. Please try again or contact support with the build ID.
    build_template_test.go:166: Build failed: {<nil> An internal error occurred. Please try again or contact support with the build ID. <nil>}
--- FAIL: TestTemplateBuildRUN/Single_RUN_command (185.68s)
github.com/e2b-dev/infra/tests/integration/internal/tests/envd::TestListDir

Flake rate in main: 16.88% (Passed 64 times, Failed 13 times)

Stack Traces | 2.27s run time
=== RUN   TestListDir
=== PAUSE TestListDir
=== CONT  TestListDir
--- FAIL: TestListDir (2.27s)
Executing command python in sandbox i3t29x5n7jhjap0spk5p4
github.com/e2b-dev/infra/tests/integration/internal/tests/envd::TestListDir/depth_0_lists_only_root_directory

Flake rate in main: 25.93% (Passed 20 times, Failed 7 times)

Stack Traces | 0.02s run time
=== RUN   TestListDir/depth_0_lists_only_root_directory
=== PAUSE TestListDir/depth_0_lists_only_root_directory
=== CONT  TestListDir/depth_0_lists_only_root_directory
    filesystem_test.go:96: 
        	Error Trace:	.../tests/envd/filesystem_test.go:96
        	Error:      	Received unexpected error:
        	            	unavailable: 502 Bad Gateway
        	Test:       	TestListDir/depth_0_lists_only_root_directory
--- FAIL: TestListDir/depth_0_lists_only_root_directory (0.02s)
github.com/e2b-dev/infra/tests/integration/internal/tests/envd::TestListDir/depth_1_lists_root_directory

Flake rate in main: 16.13% (Passed 52 times, Failed 10 times)

Stack Traces | 0.01s run time
=== RUN   TestListDir/depth_1_lists_root_directory
=== PAUSE TestListDir/depth_1_lists_root_directory
=== CONT  TestListDir/depth_1_lists_root_directory
    filesystem_test.go:96: 
        	Error Trace:	.../tests/envd/filesystem_test.go:96
        	Error:      	Received unexpected error:
        	            	unavailable: 502 Bad Gateway
        	Test:       	TestListDir/depth_1_lists_root_directory
--- FAIL: TestListDir/depth_1_lists_root_directory (0.01s)
github.com/e2b-dev/infra/tests/integration/internal/tests/envd::TestListDir/depth_2_lists_first_level_of_subdirectories_(in_this_case_the_root_directory)

Flake rate in main: 50.00% (Passed 1 times, Failed 1 times)

Stack Traces | 0.01s run time
=== RUN   TestListDir/depth_2_lists_first_level_of_subdirectories_(in_this_case_the_root_directory)
=== PAUSE TestListDir/depth_2_lists_first_level_of_subdirectories_(in_this_case_the_root_directory)
=== CONT  TestListDir/depth_2_lists_first_level_of_subdirectories_(in_this_case_the_root_directory)
    filesystem_test.go:96: 
        	Error Trace:	.../tests/envd/filesystem_test.go:96
        	Error:      	Received unexpected error:
        	            	unavailable: 502 Bad Gateway
        	Test:       	TestListDir/depth_2_lists_first_level_of_subdirectories_(in_this_case_the_root_directory)
--- FAIL: TestListDir/depth_2_lists_first_level_of_subdirectories_(in_this_case_the_root_directory) (0.01s)
github.com/e2b-dev/infra/tests/integration/internal/tests/envd::TestListDir/depth_3_lists_all_directories_and_files

Flake rate in main: 25.93% (Passed 20 times, Failed 7 times)

Stack Traces | 0.01s run time
=== RUN   TestListDir/depth_3_lists_all_directories_and_files
=== PAUSE TestListDir/depth_3_lists_all_directories_and_files
=== CONT  TestListDir/depth_3_lists_all_directories_and_files
    filesystem_test.go:96: 
        	Error Trace:	.../tests/envd/filesystem_test.go:96
        	Error:      	Received unexpected error:
        	            	unavailable: 502 Bad Gateway
        	Test:       	TestListDir/depth_3_lists_all_directories_and_files
--- FAIL: TestListDir/depth_3_lists_all_directories_and_files (0.01s)

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@claude claude 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.

LGTM — straightforward telemetry addition with no behavioral changes.

Extended reasoning...

Overview

This PR adds a new histogram (orchestrator.sandbox.pause.duration) recorded in the orchestrator's Pause gRPC handler, labeled by fs_only and success, and threads a filesystemOnly bool through snapshotResult so the existing orchestrator.snapshot.upload.failed counter can also carry an fs_only label. The Pause handler is converted to named returns (resp, err) so a deferred closure can read the final error to label success. Changes are confined to packages/orchestrator/pkg/server/{main.go,sandboxes.go} and the metric registry in packages/shared/pkg/telemetry/meters.go.

Security risks

None. This is pure observability instrumentation — no new inputs, auth paths, or data exposure. The only attribute values recorded (a client-supplied bool and a derived success bool) are low-cardinality and non-sensitive.

Level of scrutiny

Low-to-moderate is appropriate: it touches the production Pause RPC path (a critical flow), but only by wrapping it with metric recording, not altering pause/snapshot/upload logic itself. I traced the named-return conversion to confirm err is correctly finalized before the deferred metric recorder reads it on every return path in Pause (all early returns explicitly set err via the return statement), so instrumentation cannot silently mislabel success/failure.

Other factors

The change is small, additive, and mechanical (new histogram registration following the exact pattern of the existing sandboxCreateDuration histogram; a new struct field threaded one hop from snapshotAndCacheSandbox to uploadSnapshotAsync). No tests were added, but none of the existing behavior changed, and the PR description notes go build/vet/golangci-lint/go test ./pkg/server/ pass. No open review comments to address.

@bchalios
bchalios enabled auto-merge (squash) July 28, 2026 07:15
@bchalios
bchalios force-pushed the feat/fs-only-pause-metrics branch from 7797da0 to b21e180 Compare July 28, 2026 07:23
@bchalios bchalios changed the title feat(metrics): label pause telemetry by fs_only feat(metrics): label pause/resume telemetry by fs_only Jul 28, 2026
s.sandboxPauseDuration.Record(ctx, time.Since(pauseStart).Milliseconds(),
metric.WithAttributes(
attribute.Bool("fs_only", in.GetFilesystemOnly()),
attribute.Bool("success", err == nil),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not strictly a part of this, but Claude is telling me that we don't differentiate success/failure for Create like we do for Pause. Seems like we can make it uniform via:

        defer func() { 
                s.sandboxCreateDuration.Record(ctx, time.Since(createStart).Milliseconds(),
                        metric.WithAttributes(
                                attribute.Bool("sandbox.resume", isResume),
                                attribute.Bool("fs_only", fsOnly),
                                attribute.Bool("success", createErr == nil),
                        ),
                )
        }()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call — done in 35ff850. create.duration now records on every exit with a success attribute (matching pause.duration), so create/resume error rate is queryable too, and pause/create are uniform.

One behavioral note: it now also records failed creates (previously success-only), so any existing create-latency panel that wants the old semantics should add success="true".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Applied your snippet exactly in 35ff85035create.duration now records on every exit with sandbox.resume + fs_only + success, uniform with pause.duration, so create/resume error-rate is queryable too.

One behavioral change to flag: it now records failed creates as well (previously success-only via an early return), so any existing create-latency panel that wants the old semantics should filter success="true".

Reopened the thread so it's yours to close — lmk if the semantics look right (and whether you'd like the success="true" filter added to the current create.duration dashboard panels as part of the follow-up).

Make filesystem-only pause and resume distinguishable in metrics:

- New `orchestrator.sandbox.pause.duration` histogram, recorded in the Pause
  handler with `fs_only` and `success` attributes.
- `fs_only` attribute on `orchestrator.snapshot.upload.failed` (threaded
  through snapshotResult).
- `fs_only` attribute on `orchestrator.sandbox.create.duration`, set at the
  reboot/resume fork, so e2e create/resume latency splits filesystem-only
  reboot vs memory restore (combined with the existing sandbox.resume bool).

Previously fs-only-ness was only a span attribute, so pause/resume e2e
latency, error rate, and upload failures could not be scoped to fs-only in
metrics. (Reboot vs resume was already available on the envd-init/uffd
metrics via start_type; this adds it to the e2e create.duration too.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bchalios
bchalios force-pushed the feat/fs-only-pause-metrics branch from b21e180 to 35ff850 Compare July 28, 2026 07:50
@bchalios
bchalios merged commit 411b63e into main Jul 28, 2026
43 checks passed
@bchalios
bchalios deleted the feat/fs-only-pause-metrics branch July 28, 2026 09:33
bchalios added a commit that referenced this pull request Jul 28, 2026
Add two histograms so pause latency can be decomposed into its snapshot
sub-steps:

- orchestrator.sandbox.snapshot.process_rootfs.duration {fs_only, success}
  — rootfs export+diff, runs for both pause kinds (threads
  pauseOpts.filesystemSnapshot into pauseProcessRootfs).
- orchestrator.sandbox.snapshot.process_memory.duration {success}
  — memory export+diff, memory pauses only (fs-only skips it), so no
  fs_only label.

Together with pause.duration (#3425), a filesystem-only pause now
decomposes into guest_sync (quiesce) + process_rootfs (rootfs export/diff);
memory pauses additionally get process_memory. Pure additive
instrumentation; no snapshot logic changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Babis Chalios <babis.chalios@e2b.dev>
bchalios added a commit that referenced this pull request Jul 28, 2026
Follow-up to #3425. Adds per-step snapshot latency histograms so a pause
can be decomposed into where the time actually goes.

## Change
- **`orchestrator.sandbox.snapshot.process_rootfs.duration`**
{`fs_only`, `success`} — rootfs export+diff, recorded in
`pauseProcessRootfs` (runs for both pause kinds;
`pauseOpts.filesystemSnapshot` is threaded in for the label).
- **`orchestrator.sandbox.snapshot.process_memory.duration`**
{`success`} — memory export+diff, recorded in `pauseProcessMemory`.
Memory pauses only (fs-only skips memory processing), so no `fs_only`
label. Times the synchronous export; the async header-dedup goroutine
correctly outlives the span/timer as before.

## Why
`process-memory`/`process-rootfs` existed only as **trace spans**, so
pause latency couldn't be decomposed in metrics/dashboards. With these +
`pause.duration` (#3425), a filesystem-only pause decomposes as:
```
pause.duration{fs_only="true"}                 e2e
  ├── guest_sync.duration                       quiesce (sync/freeze)
  └── process_rootfs.duration{fs_only="true"}   rootfs export/diff
```
and memory pauses additionally get `process_memory.duration`.

## Notes
- Pure additive instrumentation; no pause/snapshot behavior changed.
- Follow-up: a monitoring-repo panel stacking these per-step durations
(held until this deploys — the series have no data before then).

Verified: `go build`/`vet`/`golangci-lint` clean on changed files, `go
test ./pkg/sandbox/ -run TestGuestPrepareFsForPause` passes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
charlie-e2b added a commit that referenced this pull request Jul 30, 2026
🤖 I have created a release *beep* *boop*
---


## 0.0.1 (2026-07-30)


### Features

* **api:** add sandbox IAM workload token configuration
([13ddb3d](13ddb3d))
* **api:** add sandbox workload identity permission
([#3319](#3319))
([13ddb3d](13ddb3d))
* **api:** SOCKS5 egress proxy on sandbox network config (BYOP)
([#2642](#2642))
([1fc3820](1fc3820))
* **cfg:** add DISABLE_STARTUP_RECLAIM flag
([#3081](#3081))
([7677ca6](7677ca6))
* **clickhouse:** implement multi-cluster fan-out for events and stats
([#2925](#2925))
([39594c6](39594c6))
* dynamic sandbox log routing and ClickHouse-backed log reads
([#3236](#3236))
([1b19a3b](1b19a3b))
* **envd:** give envd realtime IO priority, reset for user processes
([#2681](#2681))
([f4bd1b2](f4bd1b2))
* **envd:** split collapse stats into real migrations vs already-huge
([#3021](#3021))
([0d77614](0d77614))
* **envd:** support user-defined file metadata via xattrs
([#2732](#2732))
([da8fbe4](da8fbe4))
* **featureflags:** support per-service context providers
([#3100](#3100))
([65297c1](65297c1))
* freeze user cgroup across pause/resume to keep envd /init responsive
([#2688](#2688))
([eceb741](eceb741))
* **metrics:** break down pause-snapshot latency by step
([#3426](#3426))
([657559e](657559e))
* **metrics:** label pause telemetry by fs_only
([#3425](#3425))
([411b63e](411b63e))
* **observability:** add kill_reason to sandbox.lifecycle.killed
([#2833](#2833))
([e45418f](e45418f))
* **observability:** include kill_reason in kill-path structured logs
([#2846](#2846))
([33c49f7](33c49f7))
* **orch:** add envd-version to LaunchDarkly sandbox context
([#3051](#3051))
([37d3b92](37d3b92))
* **orch:** add less, nftables, iputils-ping, and jq to base
provisioning ([#2736](#2736))
([a1e010e](a1e010e))
* **orch:** collapse envd's heap into 2 MiB hugepages before pause to
cut cold-resume faults
([#2997](#2997))
([6677f73](6677f73))
* **orch:** debug a sandbox guest kernel with resume-build -gdb
([#3040](#3040))
([37bb0dc](37bb0dc))
* **orch:** decouple warm resume from memfile dedup
([#3166](#3166))
([77f25a0](77f25a0))
* **orch:** distro-aware template base-image provisioning
([#3411](#3411))
([f8c7b5b](f8c7b5b))
* **orchestrator/cgroup:** list and destroy leaked sandbox cgroups
([#3086](#3086))
([bce1d84](bce1d84))
* **orchestrator/nbd:** inspect and disconnect connected devices
([#3087](#3087))
([4d47148](4d47148))
* **orchestrator/network:** list slot namespaces
([#3089](#3089))
([c23dbc7](c23dbc7))
* **orchestrator/network:** list slot namespaces
([#3090](#3090))
([fbfce25](fbfce25))
* **orchestrator:** add -force-reboot to resume-build to cold-boot
memory-snaphsot builds
([#3208](#3208))
([cf8f15b](cf8f15b))
* **orchestrator:** add allocated resource metrics for sandboxes
([#2943](#2943))
([95cb6d3](95cb6d3))
* **orchestrator:** add dummy orchestrator binary for local API dev
([#2744](#2744))
([ab56e25](ab56e25))
* **orchestrator:** add NetworkAssignHook for sandbox lifecycle
extensions ([#3290](#3290))
([3261963](3261963))
* **orchestrator:** add soft-delete marker label to the check metric
([#3144](#3144))
([1ce64f8](1ce64f8))
* **orchestrator:** add v4HeaderForUncompressed FF bit
([#2669](#2669))
([1f459ee](1f459ee))
* **orchestrator:** always include execution metrics in sandbox webhook
events ([#2852](#2852))
([440edfe](440edfe))
* **orchestrator:** classify envd-init by exit type
([#3139](#3139))
([1e39a4f](1e39a4f))
* **orchestrator:** graceful sandbox drain on shutdown
([#3069](#3069))
([6ce68e3](6ce68e3))
* **orchestrator:** graceful template-build drain on shutdown
([#3079](#3079))
([1b3001c](1b3001c))
* **orchestrator:** improved read-path telemetry
([#3063](#3063))
([bc3fe84](bc3fe84))
* **orchestrator:** LD-gated ClickHouse write fan-out feature flag
([#3152](#3152))
([f046fcf](f046fcf))
* **orchestrator:** make build-reserved-disk-space-mb default 256MB
([#3065](#3065))
([d473f98](d473f98))
* **orchestrator:** record upload compression metrics
([#2761](#2761))
([9092e35](9092e35))
* **orchestrator:** report hugepage metrics to API
([#3182](#3182))
([7735bae](7735bae))
* **orchestrator:** run startup reclaim on boot
([#3123](#3123))
([79b838e](79b838e))
* **orchestrator:** single-instance flock on startup
([#3143](#3143))
([1320d6e](1320d6e))
* **orchestrator:** soft-delete consumer enforcement for storage index
([#3034](#3034))
([fbfc918](fbfc918))
* **orchestrator:** tag envd-init meters with start_type
([#3125](#3125))
([4466b48](4466b48))
* **orchestrator:** track and report last status change timestamp
([#2980](#2980))
([f79be77](f79be77))
* **orchestrator:** track sandbox lifecycles
([#2998](#2998))
([057f20c](057f20c))
* **orchestrator:** write layer sizes (logical/mapped/diff) to object
metadata ([#3122](#3122))
([11869c0](11869c0))
* **orch:** harvest resume-prefetch trace on pause
([#3067](#3067))
([97bd4a5](97bd4a5))
* **orch:** last-cycle memory prefetch on resume
([#3258](#3258))
([b22e820](b22e820))
* **orch:** make resume-build -gdb work on real nodes + add copy-build
-gdb ([#3108](#3108))
([c684bd2](c684bd2))
* **orch:** opt-in DSCP marker for sandbox egress (SANDBOX_EGRESS_DSCP)
([#3039](#3039))
([a98cf2c](a98cf2c))
* **orch:** per-start UFFD startup working-set metric
([#2960](#2960))
([dc386b2](dc386b2))
* **orch:** premade NixOS base-image support
([#3412](#3412))
([776ba39](776ba39))
* **orch:** record envd init duration histogram on failure with success
attribute ([#2749](#2749))
([afa7458](afa7458))
* **orch:** snapshot fragmentation metrics
([#2931](#2931))
([842b007](842b007))
* per-team events TTL limit (tier + addons)
([#3181](#3181))
([f76b2cb](f76b2cb))
* **shared:** add OTEL instrumentation to AWS S3 storage client
([#3172](#3172))
([25b0fd1](25b0fd1))
* **storage:** per-role storage URLs, env-free storage library
([#3246](#3246))
([fcbe909](fcbe909))
* **storage:** stamp provenance custom metadata on uploaded objects
(incl. headers) ([#3033](#3033))
([ba8604e](ba8604e))
* **storage:** write-through compressed templates to NFS on upload
([#2827](#2827))
([57503c1](57503c1))


### Bug Fixes

* added api and orch
([#3454](#3454))
([fda5e45](fda5e45))
* **block:** rephrase misleading error message in pwritevAll
([#2816](#2816))
([1555f1b](1555f1b))
* **cache:** use 512-byte units for stat.Blocks in FileSize
([#2949](#2949))
([0f632a9](0f632a9))
* **clean-nfs-cache:** exclude zombies from delete_age
([#3191](#3191))
([3fa2aeb](3fa2aeb))
* **compression:** correctness findings from compression audit
([#2803](#2803))
([d21a6a9](d21a6a9))
* **copy-build:** resolve compression suffix for build data files
([#2859](#2859))
([8966f7e](8966f7e))
* correct 3 CVES ([#3218](#3218))
([076823b](076823b))
* **envd:** stop freezing socat cgroup across pause/resume
([#2923](#2923))
([8b6f2b9](8b6f2b9))
* **inspect-build:** adapt validate to new Chunker upstream API
([#2989](#2989))
([2e0d3da](2e0d3da))
* **nbd:** adjust status poll sleep from 100ns to 100µs
([02bf51b](02bf51b))
* **nbd:** change NBD status poll sleep from 100ns to 100µs to avoid
useless busy spinning
([#2884](#2884))
([02bf51b](02bf51b))
* **nfsproxy:** deflake TestRoundTrip EADDRINUSE
([#2987](#2987))
([55f4d18](55f4d18))
* **orch:** denormalize upload metric file type
([#2865](#2865))
([b1646ca](b1646ca))
* **orch:** disable the chronyd seccomp filter on Alpine when using PHC
([#3453](#3453))
([e58af28](e58af28))
* **orchestrator:** anchor rsync CWD to root in template file copy
([#2835](#2835))
([7160db9](7160db9))
* **orchestrator:** atomically replace metadata
([#3321](#3321))
([0c4ad6b](0c4ad6b))
* **orchestrator:** avoid serializing upload headers twice
([#2762](#2762))
([9b7b149](9b7b149))
* **orchestrator:** chunk readiness bug in P2P-&gt;compressed
([#3185](#3185))
([74a6e5b](74a6e5b))
* **orchestrator:** deschedule flaky eviction-loop race in TestDiffSto…
([#3173](#3173))
([88ff17c](88ff17c))
* **orchestrator:** discard poisoned nftables conn on firewall errors
([#3008](#3008))
([03f10e0](03f10e0))
* **orchestrator:** drop stale pre-init logs
([#3297](#3297))
([8ec4be5](8ec4be5))
* **orchestrator:** emit compression ratios as fractions, not BP
([#2772](#2772))
([866f4c1](866f4c1))
* **orchestrator:** export dirty-page stall counter from process start
([#2992](#2992))
([badc8ad](badc8ad))
* **orchestrator:** harden Firecracker process shutdown
([#2996](#2996))
([df662e7](df662e7))
* **orchestrator:** harden shutdown network cleanup
([#3000](#3000))
([de2f391](de2f391))
* **orchestrator:** implement Docker COPY merge semantics in template
builds ([#3283](#3283))
([9174104](9174104))
* **orchestrator:** keep dedup empty-pages telemetry scan-only
([#2991](#2991))
([35d0832](35d0832))
* **orchestrator:** let build-cache threshold flag raise above its fal…
([#3175](#3175))
([06393c3](06393c3))
* **orchestrator:** log missing egress proxy in startup reclaim instead
of defaulting silently
([#3116](#3116))
([6ca3163](6ca3163))
* **orchestrator:** make copy-build handle filesystem-only snapshots
([#3299](#3299))
([62add04](62add04))
* **orchestrator:** measure ext4 free space from block groups
([#3282](#3282))
([f18f05f](f18f05f))
* **orchestrator:** normalize upload metric file labels
([#2767](#2767))
([6dec8b3](6dec8b3))
* **orchestrator:** order egress config/firewall updates to close BYOP
enable race ([#3313](#3313))
([7faa59e](7faa59e))
* **orchestrator:** order envd.service after local-fs.target
([#3043](#3043))
([ea2663e](ea2663e))
* **orchestrator:** order envd.service after systemd-tmpfiles-setup
([#3130](#3130))
([9481811](9481811))
* **orchestrator:** pause upload retain retry
([#2993](#2993))
([4f81799](4f81799))
* **orchestrator:** pin tap device host-side MAC address
([#3271](#3271))
([3c786ba](3c786ba))
* **orchestrator:** pin UFFD copy source buffers
([#2745](#2745))
([837fa91](837fa91))
* **orchestrator:** preserve full ENV value across stdout chunks
([#2740](#2740))
([4822e6d](4822e6d))
* **orchestrator:** read V3 ancestors as uncompressed instead of failing
([#2994](#2994))
([c479dd3](c479dd3))
* **orchestrator:** reject standby while draining
([#3325](#3325))
([475a7ee](475a7ee))
* **orchestrator:** report real V4 header compression ratio
([#2771](#2771))
([ecd344e](ecd344e))
* **orchestrator:** resolve remaining P2P/compression/V5 issues
([#3015](#3015))
([1e4379e](1e4379e))
* **orchestrator:** sanitize OCI pull errors
([#3096](#3096))
([a3af6c0](a3af6c0))
* **orchestrator:** scope rootfs hash to provision default
([#3129](#3129))
([475f955](475f955))
* **orchestrator:** stop Checks health-loop leaking
([#2739](#2739))
([17e6e60](17e6e60))
* **orchestrator:** survive SIGBUS from failing disks under mmap'd
caches ([#3385](#3385))
([728bba3](728bba3))
* **orchestrator:** tolerate missing header for legacy templates
([#3026](#3026))
([8a44bfe](8a44bfe))
* **orch:** fall back to ID_LIKE with a warning instead of rejecting
([#3459](#3459))
([7167818](7167818))
* **orch:** prevent NBD dispatch read-loop stall on WRITE_ZEROES (behind
flag) ([#3048](#3048))
([efd3d4d](efd3d4d))
* **orch:** split scheduling base build id per artifact
([#2920](#2920))
([3e35a2a](3e35a2a))
* **orch:** validate copy-build -gdb buckets before the snapshot copy
([#3446](#3446))
([586ad74](586ad74))
* **shared:** never report a failed envd command stream as success
([#3281](#3281))
([69c06b6](69c06b6))
* **storage:** compression upload & cache correctness fixes
([#3231](#3231))
([980748f](980748f))
* **storage:** don't assume V4+ ancestor gaps are uncompressed
([#3447](#3447))
([bfdbb24](bfdbb24))
* **uffd:** dedupe deferred page faults
([#2864](#2864))
([9680a41](9680a41))
* WrapContextAsUserError should not misclassify internal timeouts as
user cancellations
([#3155](#3155))
([8f83959](8f83959))


### Performance Improvements

* **build:** cache resolved Diff per BuildId within File.ReadAt
([#2838](#2838))
([53de07f](53de07f))
* **build:** parallelize fragmented backing reads
([#2872](#2872))
([c7655a7](c7655a7))
* **clean-nfs-cache:** restore dirfd-relative statx
([#2766](#2766))
([6bdbedb](6bdbedb))
* **header:** add V5 columnar varint header format
([#2847](#2847))
([9dd931b](9dd931b))
* **header:** pack cached Header.Mapping into a compact form
([#2844](#2844))
([7f0b13c](7f0b13c))
* **orchestrator:** add memfile dedup density threshold
([#2862](#2862))
([7ccfa02](7ccfa02))
* **orchestrator:** avoid V3-ancestor header refresh
([#2999](#2999))
([cb6aa0b](cb6aa0b))
* **orch:** metrics for dirty page throttling
([#2858](#2858))
([d2aa554](d2aa554))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: e2b-release-please[bot] <298072688+e2b-release-please[bot]@users.noreply.github.com>
Co-authored-by: Charlie Wyse <charlie.wyse@e2b.dev>
jakubno pushed a commit that referenced this pull request Aug 3, 2026
Makes filesystem-only pauses distinguishable in metrics, so the
[Filesystem-only Snapshots
dashboard](https://github.com/e2b-dev/monitoring) can stop relying on
"(all pauses)" context panels.

## Change
- **New histogram `orchestrator.sandbox.pause.duration`** — recorded in
the `Pause` handler with attributes `fs_only` (filesystem-only vs
memory) and `success`. Gives fs-only pause **call-count** (count),
**error rate** (`success="false"`), and **e2e latency** (quantiles) —
none of which were separable before, since the gRPC Pause RPC metric
carries no fs-only label (fs-only-ness was only a span attribute).
- **`fs_only` attribute on `orchestrator.snapshot.upload.failed`** —
threaded through `snapshotResult` so the async upload can label failures
fs-only vs memory.

## Why
The orchestrator recorded fs-only-ness only as a *span* attribute
(`fs-only-snapshot`), not a metric label, so pause e2e latency / errors
/ upload failures could not be scoped to fs-only pauses. The dashboard
worked around this with clearly-labeled "(all pauses)" panels; these
labels let those panels filter `fs_only="true"` and become real.

## Notes
- `Pause` now uses named returns so the deferred metric can capture
success.
- No change to the resume side — fs-only resume is already
distinguishable via `envd_init.duration{start_type="reboot"}`.
- Follow-up: a small monitoring-repo PR will switch the dashboard's
pause/upload panels to `fs_only="true"` once this deploys.

Verified: `go build`/`vet`/`golangci-lint` clean, `go test
./pkg/server/` passes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jakubno pushed a commit that referenced this pull request Aug 3, 2026
Follow-up to #3425. Adds per-step snapshot latency histograms so a pause
can be decomposed into where the time actually goes.

## Change
- **`orchestrator.sandbox.snapshot.process_rootfs.duration`**
{`fs_only`, `success`} — rootfs export+diff, recorded in
`pauseProcessRootfs` (runs for both pause kinds;
`pauseOpts.filesystemSnapshot` is threaded in for the label).
- **`orchestrator.sandbox.snapshot.process_memory.duration`**
{`success`} — memory export+diff, recorded in `pauseProcessMemory`.
Memory pauses only (fs-only skips memory processing), so no `fs_only`
label. Times the synchronous export; the async header-dedup goroutine
correctly outlives the span/timer as before.

## Why
`process-memory`/`process-rootfs` existed only as **trace spans**, so
pause latency couldn't be decomposed in metrics/dashboards. With these +
`pause.duration` (#3425), a filesystem-only pause decomposes as:
```
pause.duration{fs_only="true"}                 e2e
  ├── guest_sync.duration                       quiesce (sync/freeze)
  └── process_rootfs.duration{fs_only="true"}   rootfs export/diff
```
and memory pauses additionally get `process_memory.duration`.

## Notes
- Pure additive instrumentation; no pause/snapshot behavior changed.
- Follow-up: a monitoring-repo panel stacking these per-step durations
(held until this deploys — the series have no data before then).

Verified: `go build`/`vet`/`golangci-lint` clean on changed files, `go
test ./pkg/sandbox/ -run TestGuestPrepareFsForPause` passes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jakubno pushed a commit that referenced this pull request Aug 3, 2026
🤖 I have created a release *beep* *boop*
---


## 0.0.1 (2026-07-30)


### Features

* **api:** add sandbox IAM workload token configuration
([13ddb3d](13ddb3d))
* **api:** add sandbox workload identity permission
([#3319](#3319))
([13ddb3d](13ddb3d))
* **api:** SOCKS5 egress proxy on sandbox network config (BYOP)
([#2642](#2642))
([1fc3820](1fc3820))
* **cfg:** add DISABLE_STARTUP_RECLAIM flag
([#3081](#3081))
([7677ca6](7677ca6))
* **clickhouse:** implement multi-cluster fan-out for events and stats
([#2925](#2925))
([39594c6](39594c6))
* dynamic sandbox log routing and ClickHouse-backed log reads
([#3236](#3236))
([1b19a3b](1b19a3b))
* **envd:** give envd realtime IO priority, reset for user processes
([#2681](#2681))
([f4bd1b2](f4bd1b2))
* **envd:** split collapse stats into real migrations vs already-huge
([#3021](#3021))
([0d77614](0d77614))
* **envd:** support user-defined file metadata via xattrs
([#2732](#2732))
([da8fbe4](da8fbe4))
* **featureflags:** support per-service context providers
([#3100](#3100))
([65297c1](65297c1))
* freeze user cgroup across pause/resume to keep envd /init responsive
([#2688](#2688))
([eceb741](eceb741))
* **metrics:** break down pause-snapshot latency by step
([#3426](#3426))
([f551118](f551118))
* **metrics:** label pause telemetry by fs_only
([#3425](#3425))
([4be33ba](4be33ba))
* **observability:** add kill_reason to sandbox.lifecycle.killed
([#2833](#2833))
([e45418f](e45418f))
* **observability:** include kill_reason in kill-path structured logs
([#2846](#2846))
([33c49f7](33c49f7))
* **orch:** add envd-version to LaunchDarkly sandbox context
([#3051](#3051))
([37d3b92](37d3b92))
* **orch:** add less, nftables, iputils-ping, and jq to base
provisioning ([#2736](#2736))
([a1e010e](a1e010e))
* **orch:** collapse envd's heap into 2 MiB hugepages before pause to
cut cold-resume faults
([#2997](#2997))
([6677f73](6677f73))
* **orch:** debug a sandbox guest kernel with resume-build -gdb
([#3040](#3040))
([37bb0dc](37bb0dc))
* **orch:** decouple warm resume from memfile dedup
([#3166](#3166))
([77f25a0](77f25a0))
* **orch:** distro-aware template base-image provisioning
([#3411](#3411))
([1abece1](1abece1))
* **orchestrator/cgroup:** list and destroy leaked sandbox cgroups
([#3086](#3086))
([bce1d84](bce1d84))
* **orchestrator/nbd:** inspect and disconnect connected devices
([#3087](#3087))
([4d47148](4d47148))
* **orchestrator/network:** list slot namespaces
([#3089](#3089))
([c23dbc7](c23dbc7))
* **orchestrator/network:** list slot namespaces
([#3090](#3090))
([fbfce25](fbfce25))
* **orchestrator:** add -force-reboot to resume-build to cold-boot
memory-snaphsot builds
([#3208](#3208))
([cf8f15b](cf8f15b))
* **orchestrator:** add allocated resource metrics for sandboxes
([#2943](#2943))
([95cb6d3](95cb6d3))
* **orchestrator:** add dummy orchestrator binary for local API dev
([#2744](#2744))
([ab56e25](ab56e25))
* **orchestrator:** add NetworkAssignHook for sandbox lifecycle
extensions ([#3290](#3290))
([3261963](3261963))
* **orchestrator:** add soft-delete marker label to the check metric
([#3144](#3144))
([1ce64f8](1ce64f8))
* **orchestrator:** add v4HeaderForUncompressed FF bit
([#2669](#2669))
([1f459ee](1f459ee))
* **orchestrator:** always include execution metrics in sandbox webhook
events ([#2852](#2852))
([440edfe](440edfe))
* **orchestrator:** classify envd-init by exit type
([#3139](#3139))
([1e39a4f](1e39a4f))
* **orchestrator:** graceful sandbox drain on shutdown
([#3069](#3069))
([6ce68e3](6ce68e3))
* **orchestrator:** graceful template-build drain on shutdown
([#3079](#3079))
([1b3001c](1b3001c))
* **orchestrator:** improved read-path telemetry
([#3063](#3063))
([bc3fe84](bc3fe84))
* **orchestrator:** LD-gated ClickHouse write fan-out feature flag
([#3152](#3152))
([f046fcf](f046fcf))
* **orchestrator:** make build-reserved-disk-space-mb default 256MB
([#3065](#3065))
([d473f98](d473f98))
* **orchestrator:** record upload compression metrics
([#2761](#2761))
([9092e35](9092e35))
* **orchestrator:** report hugepage metrics to API
([#3182](#3182))
([7735bae](7735bae))
* **orchestrator:** run startup reclaim on boot
([#3123](#3123))
([79b838e](79b838e))
* **orchestrator:** single-instance flock on startup
([#3143](#3143))
([1320d6e](1320d6e))
* **orchestrator:** soft-delete consumer enforcement for storage index
([#3034](#3034))
([fbfc918](fbfc918))
* **orchestrator:** tag envd-init meters with start_type
([#3125](#3125))
([4466b48](4466b48))
* **orchestrator:** track and report last status change timestamp
([#2980](#2980))
([f79be77](f79be77))
* **orchestrator:** track sandbox lifecycles
([#2998](#2998))
([057f20c](057f20c))
* **orchestrator:** write layer sizes (logical/mapped/diff) to object
metadata ([#3122](#3122))
([11869c0](11869c0))
* **orch:** harvest resume-prefetch trace on pause
([#3067](#3067))
([97bd4a5](97bd4a5))
* **orch:** last-cycle memory prefetch on resume
([#3258](#3258))
([ea94196](ea94196))
* **orch:** make resume-build -gdb work on real nodes + add copy-build
-gdb ([#3108](#3108))
([5385594](5385594))
* **orch:** opt-in DSCP marker for sandbox egress (SANDBOX_EGRESS_DSCP)
([#3039](#3039))
([a98cf2c](a98cf2c))
* **orch:** per-start UFFD startup working-set metric
([#2960](#2960))
([dc386b2](dc386b2))
* **orch:** premade NixOS base-image support
([#3412](#3412))
([4bd42d2](4bd42d2))
* **orch:** record envd init duration histogram on failure with success
attribute ([#2749](#2749))
([afa7458](afa7458))
* **orch:** snapshot fragmentation metrics
([#2931](#2931))
([842b007](842b007))
* per-team events TTL limit (tier + addons)
([#3181](#3181))
([f76b2cb](f76b2cb))
* **shared:** add OTEL instrumentation to AWS S3 storage client
([#3172](#3172))
([25b0fd1](25b0fd1))
* **storage:** per-role storage URLs, env-free storage library
([#3246](#3246))
([fcbe909](fcbe909))
* **storage:** stamp provenance custom metadata on uploaded objects
(incl. headers) ([#3033](#3033))
([ba8604e](ba8604e))
* **storage:** write-through compressed templates to NFS on upload
([#2827](#2827))
([57503c1](57503c1))


### Bug Fixes

* added api and orch
([#3454](#3454))
([d56e0a8](d56e0a8))
* **block:** rephrase misleading error message in pwritevAll
([#2816](#2816))
([1555f1b](1555f1b))
* **cache:** use 512-byte units for stat.Blocks in FileSize
([#2949](#2949))
([0f632a9](0f632a9))
* **clean-nfs-cache:** exclude zombies from delete_age
([#3191](#3191))
([3fa2aeb](3fa2aeb))
* **compression:** correctness findings from compression audit
([#2803](#2803))
([d21a6a9](d21a6a9))
* **copy-build:** resolve compression suffix for build data files
([#2859](#2859))
([8966f7e](8966f7e))
* correct 3 CVES ([#3218](#3218))
([076823b](076823b))
* **envd:** stop freezing socat cgroup across pause/resume
([#2923](#2923))
([8b6f2b9](8b6f2b9))
* **inspect-build:** adapt validate to new Chunker upstream API
([#2989](#2989))
([2e0d3da](2e0d3da))
* **nbd:** adjust status poll sleep from 100ns to 100µs
([02bf51b](02bf51b))
* **nbd:** change NBD status poll sleep from 100ns to 100µs to avoid
useless busy spinning
([#2884](#2884))
([02bf51b](02bf51b))
* **nfsproxy:** deflake TestRoundTrip EADDRINUSE
([#2987](#2987))
([55f4d18](55f4d18))
* **orch:** denormalize upload metric file type
([#2865](#2865))
([b1646ca](b1646ca))
* **orch:** disable the chronyd seccomp filter on Alpine when using PHC
([#3453](#3453))
([dfa9764](dfa9764))
* **orchestrator:** anchor rsync CWD to root in template file copy
([#2835](#2835))
([7160db9](7160db9))
* **orchestrator:** atomically replace metadata
([#3321](#3321))
([0c4ad6b](0c4ad6b))
* **orchestrator:** avoid serializing upload headers twice
([#2762](#2762))
([9b7b149](9b7b149))
* **orchestrator:** chunk readiness bug in P2P-&gt;compressed
([#3185](#3185))
([74a6e5b](74a6e5b))
* **orchestrator:** deschedule flaky eviction-loop race in TestDiffSto…
([#3173](#3173))
([88ff17c](88ff17c))
* **orchestrator:** discard poisoned nftables conn on firewall errors
([#3008](#3008))
([03f10e0](03f10e0))
* **orchestrator:** drop stale pre-init logs
([#3297](#3297))
([8ec4be5](8ec4be5))
* **orchestrator:** emit compression ratios as fractions, not BP
([#2772](#2772))
([866f4c1](866f4c1))
* **orchestrator:** export dirty-page stall counter from process start
([#2992](#2992))
([badc8ad](badc8ad))
* **orchestrator:** harden Firecracker process shutdown
([#2996](#2996))
([df662e7](df662e7))
* **orchestrator:** harden shutdown network cleanup
([#3000](#3000))
([de2f391](de2f391))
* **orchestrator:** implement Docker COPY merge semantics in template
builds ([#3283](#3283))
([9174104](9174104))
* **orchestrator:** keep dedup empty-pages telemetry scan-only
([#2991](#2991))
([35d0832](35d0832))
* **orchestrator:** let build-cache threshold flag raise above its fal…
([#3175](#3175))
([06393c3](06393c3))
* **orchestrator:** log missing egress proxy in startup reclaim instead
of defaulting silently
([#3116](#3116))
([6ca3163](6ca3163))
* **orchestrator:** make copy-build handle filesystem-only snapshots
([#3299](#3299))
([62add04](62add04))
* **orchestrator:** measure ext4 free space from block groups
([#3282](#3282))
([f18f05f](f18f05f))
* **orchestrator:** normalize upload metric file labels
([#2767](#2767))
([6dec8b3](6dec8b3))
* **orchestrator:** order egress config/firewall updates to close BYOP
enable race ([#3313](#3313))
([7faa59e](7faa59e))
* **orchestrator:** order envd.service after local-fs.target
([#3043](#3043))
([ea2663e](ea2663e))
* **orchestrator:** order envd.service after systemd-tmpfiles-setup
([#3130](#3130))
([9481811](9481811))
* **orchestrator:** pause upload retain retry
([#2993](#2993))
([4f81799](4f81799))
* **orchestrator:** pin tap device host-side MAC address
([#3271](#3271))
([3c786ba](3c786ba))
* **orchestrator:** pin UFFD copy source buffers
([#2745](#2745))
([837fa91](837fa91))
* **orchestrator:** preserve full ENV value across stdout chunks
([#2740](#2740))
([4822e6d](4822e6d))
* **orchestrator:** read V3 ancestors as uncompressed instead of failing
([#2994](#2994))
([c479dd3](c479dd3))
* **orchestrator:** reject standby while draining
([#3325](#3325))
([475a7ee](475a7ee))
* **orchestrator:** report real V4 header compression ratio
([#2771](#2771))
([ecd344e](ecd344e))
* **orchestrator:** resolve remaining P2P/compression/V5 issues
([#3015](#3015))
([1e4379e](1e4379e))
* **orchestrator:** sanitize OCI pull errors
([#3096](#3096))
([a3af6c0](a3af6c0))
* **orchestrator:** scope rootfs hash to provision default
([#3129](#3129))
([475f955](475f955))
* **orchestrator:** stop Checks health-loop leaking
([#2739](#2739))
([17e6e60](17e6e60))
* **orchestrator:** survive SIGBUS from failing disks under mmap'd
caches ([#3385](#3385))
([8694d08](8694d08))
* **orchestrator:** tolerate missing header for legacy templates
([#3026](#3026))
([8a44bfe](8a44bfe))
* **orch:** fall back to ID_LIKE with a warning instead of rejecting
([#3459](#3459))
([73399b3](73399b3))
* **orch:** prevent NBD dispatch read-loop stall on WRITE_ZEROES (behind
flag) ([#3048](#3048))
([efd3d4d](efd3d4d))
* **orch:** split scheduling base build id per artifact
([#2920](#2920))
([3e35a2a](3e35a2a))
* **orch:** validate copy-build -gdb buckets before the snapshot copy
([#3446](#3446))
([9be382f](9be382f))
* **shared:** never report a failed envd command stream as success
([#3281](#3281))
([69c06b6](69c06b6))
* **storage:** compression upload & cache correctness fixes
([#3231](#3231))
([980748f](980748f))
* **storage:** don't assume V4+ ancestor gaps are uncompressed
([#3447](#3447))
([f828d12](f828d12))
* **uffd:** dedupe deferred page faults
([#2864](#2864))
([9680a41](9680a41))
* WrapContextAsUserError should not misclassify internal timeouts as
user cancellations
([#3155](#3155))
([8f83959](8f83959))


### Performance Improvements

* **build:** cache resolved Diff per BuildId within File.ReadAt
([#2838](#2838))
([53de07f](53de07f))
* **build:** parallelize fragmented backing reads
([#2872](#2872))
([c7655a7](c7655a7))
* **clean-nfs-cache:** restore dirfd-relative statx
([#2766](#2766))
([6bdbedb](6bdbedb))
* **header:** add V5 columnar varint header format
([#2847](#2847))
([9dd931b](9dd931b))
* **header:** pack cached Header.Mapping into a compact form
([#2844](#2844))
([7f0b13c](7f0b13c))
* **orchestrator:** add memfile dedup density threshold
([#2862](#2862))
([7ccfa02](7ccfa02))
* **orchestrator:** avoid V3-ancestor header refresh
([#2999](#2999))
([cb6aa0b](cb6aa0b))
* **orch:** metrics for dirty page throttling
([#2858](#2858))
([d2aa554](d2aa554))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: e2b-release-please[bot] <298072688+e2b-release-please[bot]@users.noreply.github.com>
Co-authored-by: Charlie Wyse <charlie.wyse@e2b.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants