feat(api): add ContainerLogOptions {since, timestamps} to ContainerClient.logs (CHAOS-1322)#11
Open
chrisgeo wants to merge 1 commit into
Open
feat(api): add ContainerLogOptions {since, timestamps} to ContainerClient.logs (CHAOS-1322)#11chrisgeo wants to merge 1 commit into
chrisgeo wants to merge 1 commit into
Conversation
3e5a31a to
1df3acb
Compare
…ient.logs
Adds an additive overload to ContainerClient.logs that accepts a
ContainerLogOptions { since: Date?, timestamps: Bool } and plumbs the
two parameters through XPC into the daemon's existing log-handle path.
Motivation
----------
External orchestrators that drive the API server (the canonical use
case is a Compose-spec orchestrator implementing 'compose logs --since
<timestamp>' and '--timestamps') need to retrieve only recent log
output and optionally annotate lines with timestamps. Today
ContainerClient.logs(id:) returns raw containerLog + bootlog file
handles unconditionally; consumers either replay the entire log buffer
or implement their own line-by-line filter on the client. Surfacing
the parameters at the API boundary keeps the line scanning where the
file lives — server-side — and matches the docker-compose UX users
expect.
What this PR changes
--------------------
- Sources/ContainerResource/Container/ContainerLogOptions.swift (new):
the ContainerLogOptions struct, Sendable + Codable, with a static
'.default' equivalent to the original logs(id:) zero-config call.
- Sources/Services/ContainerAPIService/Client/XPC+.swift: two new
XPCKeys cases ('logSince', 'logTimestamps') for the optional
parameters.
- Sources/Services/ContainerAPIService/Client/ContainerClient.swift:
new logs(id:options:) overload. The existing logs(id:) is retained
as a thin wrapper over .default for source compatibility.
- Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift:
matching logs(id:options:) overload; when options.since is provided,
applies a private 'filterFileHandleSince' that parses ISO-8601
timestamps from line starts and drops older lines (lines without a
parseable timestamp pass through unchanged).
- Sources/Services/ContainerAPIService/Server/Containers/ContainersHarness.swift:
parses the two optional XPC keys, builds ContainerLogOptions, and
forwards to the new service overload.
Wire compatibility
------------------
XPC calls without the new keys decode as 'sinceRaw.timeIntervalSince1970
== 0' (the harness treats this as 'no since filter') and 'timestamps =
false', so older clients hitting a newer server see unchanged behavior.
Newer clients hitting an older server send the keys; an old harness
will silently drop them and run the original codepath.
Known limitations (intentional, follow-up work)
-----------------------------------------------
- The 'options.timestamps' parameter is plumbed end-to-end but the
daemon does not currently decorate raw log lines that lack a
timestamp prefix. Line decoration is a deliberate follow-up; keeping
the parameter on the API surface today avoids a second wire-format
break later.
- 'filterFileHandleSince' currently slurps the file into memory then
returns a Pipe-backed FileHandle. For the typical container log
size this is fine; for very large logs a streaming line iterator
would be a worthwhile optimization. Filed as a known-issue for the
follow-up timestamp-decoration PR.
Verification
------------
Full 'swift build' clean on macOS 26 / Apple silicon (release config,
all targets including downstream consumers of ContainerClient.logs).
1df3acb to
067c177
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Staging branch — fork-internal review before any apple/container upstream filing.
Linear: CHAOS-1322
Type of Change
Motivation and Context
External orchestrators that drive the API server (the canonical use case is a Compose-spec orchestrator implementing
compose logs --since <ts>/--timestamps) need to retrieve only recent log output and optionally annotate lines with timestamps. TodayContainerClient.logs(id:)returns rawcontainerLog + bootlogfile handles unconditionally; consumers either replay the entire log buffer or implement a client-side line filter.Surfacing the parameters at the API boundary keeps line scanning where the file lives — server-side — and matches the docker-compose UX users expect.
What this PR changes
Sources/ContainerResource/Container/ContainerLogOptions.swift(new):Sendable + Codablestruct withsince: Date?/timestamps: Boolfields and a.defaultzero-config equivalent to the originallogs(id:)call.Sources/Services/ContainerAPIService/Client/XPC+.swift: two newXPCKeyscases (logSince,logTimestamps) for the optional parameters.Sources/Services/ContainerAPIService/Client/ContainerClient.swift: newlogs(id:options:)overload. Existinglogs(id:)retained as a thin wrapper over.defaultfor source compatibility.Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift: matchinglogs(id:options:)overload + a privatefilterFileHandleSincethat parses ISO-8601 timestamps from line starts and drops older lines (lines without a parseable timestamp pass through unchanged).Sources/Services/ContainerAPIService/Server/Containers/ContainersHarness.swift: parses the two optional XPC keys, buildsContainerLogOptions, forwards to the new service overload.Total: 5 files (1 new + 4 modified), +122/−7.
Wire compatibility
XPC calls without the new keys decode as
sinceRaw.timeIntervalSince1970 == 0(the harness treats this as "no since filter") andtimestamps == false, so older clients hitting a newer server see unchanged behavior. Newer clients hitting an older server send the keys; an old harness silently drops them and runs the original codepath.Known limitations (intentional, follow-up work)
options.timestampsis plumbed end-to-end but not yet line-decorating. The daemon does not currently annotate raw log lines that lack a timestamp prefix. Line decoration is a deliberate follow-up; keeping the parameter on the API surface today avoids a second wire-format break later.filterFileHandleSinceslurps the file into memory then returns aPipe-backedFileHandle. Fine for typical container log sizes; for very large logs a streaming line iterator would be a worthwhile optimization. Filed as a known-issue for the timestamp-decoration follow-up.Testing
swift buildclean on macOS 26 / Apple silicon, all targets including downstream consumers ofContainerClient.logs).Status
Draft, fork-staged. Routing to
full-chaos/container:mainfirst so we can review the surface internally before opening the apple/container companion issue + upstream PR (the same pattern we ran for CHAOS-1319 → apple#1502 + apple#1504 and CHAOS-1320 → apple#1501 + apple#1503).