the fd-exhaustion ETA subtracts a window net-delta from the ulimit as if it were the current open-fd count, so a process actually near its limit gets a wildly optimistic time-to-failure.
internal/doctor/rules.go:271-280:
if s.FD.GrowthRate > 0 {
remainingFDs := 65536.0 - float64(s.FD.NetDelta)
if remainingFDs > 0 {
etaSecs := remainingFDs / s.FD.GrowthRate
...
but NetDelta is totalOpens - totalCloses accumulated only over the observation window, system-wide, not a process's current open count (internal/collector/fd.go:163). a process sitting at 64000 open fds with a window delta of 600 reports remaining = 64936 and a hugely optimistic ETA. it also mixes a system-wide delta against a per-process ulimit. same math in predictFDExhaustion at internal/doctor/predict.go:106.
the "will hit ulimit in X" line is the headline impact operators act on, so the number needs to mean something. either read the real open-fd count for the top process, or reframe the ETA so it doesn't claim ulimit headroom it can't measure.
the fd-exhaustion ETA subtracts a window net-delta from the ulimit as if it were the current open-fd count, so a process actually near its limit gets a wildly optimistic time-to-failure.
internal/doctor/rules.go:271-280:but
NetDeltaistotalOpens - totalClosesaccumulated only over the observation window, system-wide, not a process's current open count (internal/collector/fd.go:163). a process sitting at 64000 open fds with a window delta of 600 reportsremaining = 64936and a hugely optimistic ETA. it also mixes a system-wide delta against a per-process ulimit. same math inpredictFDExhaustionatinternal/doctor/predict.go:106.the "will hit ulimit in X" line is the headline impact operators act on, so the number needs to mean something. either read the real open-fd count for the top process, or reframe the ETA so it doesn't claim ulimit headroom it can't measure.