Skip to content

Skip zones with no in-window logs during support bundle collection - #11198

Open
smklein wants to merge 4 commits into
support-bundle-time-range-v2from
support-bundle-skip-stale-zones
Open

Skip zones with no in-window logs during support bundle collection#11198
smklein wants to merge 4 commits into
support-bundle-time-range-v2from
support-bundle-skip-stale-zones

Conversation

@smklein

@smklein smklein commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #11113, which bounds zone-log collection with a bundle-wide time range.

On dogfood, oxlog zones | wc -l reports over 7000 zones, mostly propolis zones for VMMs that stopped running long ago. #11113 already keeps their out-of-window log files (and any ZFS snapshots for them) out of the bundle, but the collection workflow still paid a per-zone cost for every one of them: the collector fetched the full zone list and issued one support_logs_download request per zone, and each such request made the sled-agent re-run oxlog's filesystem scan, probe every debug dataset with zfs get available to pick temporary storage, and assemble an empty zip, before the collector wrote an empty logs/<zone>/ directory into the bundle.

This PR filters the zone list at the source and keeps empty results out of the bundle entirely:

  • Filter the sled-diagnostics zone listing by a log time window. oxlog gains Zones::zones_with_matching_logs, and LogsHandle::get_zones takes a LogTimeWindow, applying the same per-file date predicate as get_zone_logs. A zone omitted from the listing would only ever have produced an empty archive; the scan is metadata-only and takes no ZFS snapshots.

  • Add sled-agent API v52: time-window params on the zone-log listing. support_logs gains optional inclusive start_time/end_time query parameters; the v1 shim keeps serving older callers with an unbounded window. The simulated sled-agent filters its zone list through the same predicate as its download endpoint, and the collector passes the bundle's time range, so sleds skip zones with no in-window log content. Since omdb shares the collection crate, omdb support-bundle collect --since/--until benefits automatically.

  • Leave no bundle entry for a zone whose log archive is empty. The collector streams each zone's zip to a scratch path and skips extraction when the archive has no entries, so logs/<zone>/ exists only when it holds logs. This also covers sled-agents that predate the filtered listing (they still return the full zone list), and listing/download races.

oxlog gains Zones::zones_with_matching_logs, returning the zones with at
least one file matching a filter, and LogsHandle::get_zones takes a
LogTimeWindow and applies the same per-file date-range predicate as
get_zone_logs. A zone omitted from the listing would only ever produce
an empty archive; the scan is metadata-only and takes no ZFS snapshots.
The HTTP endpoint still lists with an unbounded window; a subsequent
change threads the bundle's time range through the API.
support_logs (GET /support/logs/zones) gains optional inclusive
start_time/end_time query parameters, served by the window-aware
sled-diagnostics listing; the v1 shim keeps serving older callers with
an unbounded window. The simulated sled-agent filters its injected
zones through the same predicate as its download endpoint, and the
support bundle collector now passes the bundle's time range so sleds
skip zones with no in-window log content.
The collector streamed each zone's log zip into logs/<zone>/ created up
front, so a zone with nothing to contribute still left an empty
directory in the final bundle. Stream the zip to a scratch path at the
sled level instead and skip extraction entirely when the archive has no
entries; a zone's directory now exists only when it holds logs. This
also covers sled-agents that predate the window-filtered zone listing,
and listing/download races.
Adds a portable oxlog test for zones_with_matching_logs over synthetic
zone directories, a unit test that extract_zip_file leaves no directory
behind for an empty archive, and a second injected sim zone in the
zone-log time-range integration test whose only log predates the
window: the bundle must contain no logs/<zone>/ entry for it at all,
and must include the zone when the window shifts over its log.
let zipfile_path = output_dir.join("logs.zip");

// Ensure the logs output directory exists.
tokio::fs::create_dir_all(&output_dir).await.with_context(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This directory is now being created when we extract the zipfile

// and its download race against log rotation and archival), and
// an empty archive must leave no trace in the bundle, not even
// an empty directory.
let zipfile_path = path.join(format!("{zone}.logs.zip.partial"));

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this doesn't matter too much (the zipfile doesn't end up in the bundle, only the extracted contents do) but this is named to "partial" while it's getting streamed.

Shouldn't matter much because we remove zipfile_path either way.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I promise this PR is smaller than it looks. It's this dang file that makes the change look enormous

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.

1 participant