Repository navigation
feat: the counters are subtracted on the node (ADR 0062) - #97
Merged
Merged
Conversation
The rows beside the footprint are a different kind of thing: counters that only rise since the process started. `run_delay` says how long a process has waited for a CPU in its whole life, and a life is not a question anybody asks. Where the subtraction happens is the decision. Doing it on the controller fails twice: a PID is reused, and the controller never sees a start time to tell two processes apart, so it would hold per-PID state for a fleet — growing with the cluster rather than with the workloads. And a process that exits between flushes loses its last interval, because the previous reading is what would have closed it. The node has both halves in one read. So a cache holds one reading per PID between passes, keyed by the process's start time. Three cases produce no delta rather than a wrong one: the first pass that sees a process, a reused PID, and a counter that fell — the last drops the whole delta rather than clamping a field, because a counter that fell means the reading is not of the process the last one described. A delta never travels without `observed_nanos`, the wall-clock time between the two readings. It sums with the deltas, so it is process-time and not a duration, and it is named for that. The payload carries sums and never the division: a shipped ratio cannot be re-divided by a consumer asking a different question. Field two of /proc/<pid>/stat is the executable's name and may contain spaces and parentheses, so fields are counted from the last ')' — which is also what keeps the name behind the cut rather than filtered after it. go test ./... -race, golangci-lint run ./... (host and GOOS=linux): 0 issues.
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.
The rows beside the footprint are a different kind of thing: counters that only
rise since the process started.
run_delaysays how long a process has waitedfor a CPU in its whole life, and a life is not a question anybody asks. What a
finding needs is the change over an interval.
Where the subtraction happens is the decision
Shipping raw counters and subtracting on the controller was the obvious design
and it fails twice:
and the controller has no way to tell — it never sees a start time. Holding
per-PID state for a fleet would grow the store with the cluster rather than
with the workloads.
previous reading is the only thing that would have closed it.
The node reads the counters and the start time from the same file at the same
moment, and it already keeps a cache across passes for the binary marker.
What the cache does
One reading per PID between passes — counters, the instant, and the start time.
Three cases produce no delta rather than a wrong one: the first pass that
sees a process, a reused PID, and a counter that fell. The last drops the whole
delta rather than clamping one field: a counter that fell means the reading is
not of the process the last one described, whatever the start time says.
State is bounded by the process table, dropped for every PID a pass does not
see, and losing it costs one interval and never a total.
What ships
observed_nanossums with the deltas, so it is process-time, not a duration— two processes watched for a minute each contribute two minutes. It is the
denominator every rate must be formed against, and it is named for that.
Sums, never the division.
on_cpu_nanosbesiderun_delay_nanosis CPUstarvation stated as the two numbers it is made of. A payload that ships the
ratio cannot be re-divided by a consumer asking a different question — the shape
ADR 0004 settled for money and which holds for any derived figure.
A node's next report replaces its interval rather than extending it, the same
wholesale replacement peaks use, because adding successive intervals would turn a
rate into a total over a window nobody chose.
Filtering
Field two of
/proc/<pid>/statis the executable's own name and may containspaces and parentheses, so fields are counted from the last
)rather thanby splitting the line — which is also what keeps the name behind the cut rather
than filtered after it.
rchar/wcharsit directly above the two I/O countersthat are read and are not taken: a finding about storage rests on bytes that
moved, not bytes that were asked for.
No new capability:
/proc/<pid>/iosits behind the same ptrace check the nodealready passes for
/proc/<pid>/exe.Named in the ADR, not hidden
The interval between a process's last observed pass and its exit is lost; closing
it would mean watching every process rather than sampling the table. And
processeshere is lower than inprocess_peaksfor one interval after a podstarts — a process seen once has a footprint and no difference yet.
Evidence
go test ./... -raceandgolangci-lint run ./...on host andGOOS=linux:0 issues. The inventory e2e now asserts that a delta exists at all, which proves
a second pass compared against the first for the same process, and that on-CPU
time cannot exceed the process-time observed. The e2e suites run against a kind
cluster and are not part of CI, so this has not been exercised on one.
🤖 Generated with Claude Code
https://claude.ai/code/session_011YRKuL97KRndaopfpixrhp