From b119d08764fe793753d8dae3beeea651a6f87d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Tue, 17 Mar 2026 22:37:38 +0800 Subject: [PATCH] fix(ccm,ocm): add usage logging to status stream, remove redundant isFirstUpdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit connectStatusStream updated credential state silently — no log on first frame or value changes. After restart, external credentials get usage via stream before any request, so pollIfStale skips them and no usage log ever appears. Add the same change-detection log to connectStatusStream. Also remove redundant isFirstUpdate guards from pollUsage and updateStateFromHeaders: when old values are zero, any non-zero new value already satisfies the integer-percent comparison. --- service/ccm/credential_external.go | 12 ++++++++++-- service/ocm/credential_external.go | 15 +++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/service/ccm/credential_external.go b/service/ccm/credential_external.go index 98332e41d..f51205203 100644 --- a/service/ccm/credential_external.go +++ b/service/ccm/credential_external.go @@ -631,7 +631,6 @@ func (c *externalCredential) pollUsage(ctx context.Context) { } c.stateAccess.Lock() - isFirstUpdate := c.state.lastUpdated.IsZero() oldFiveHour := c.state.fiveHourUtilization oldWeekly := c.state.weeklyUtilization c.state.consecutivePollFailures = 0 @@ -649,7 +648,7 @@ func (c *externalCredential) pollUsage(ctx context.Context) { if c.state.hardRateLimited && time.Now().After(c.state.rateLimitResetAt) { c.state.hardRateLimited = false } - if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { + if int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { resetSuffix := "" if !c.state.weeklyReset.IsZero() { resetSuffix = ", resets=" + log.FormatDuration(time.Until(c.state.weeklyReset)) @@ -739,6 +738,8 @@ func (c *externalCredential) connectStatusStream(ctx context.Context) (statusStr } c.stateAccess.Lock() + oldFiveHour := c.state.fiveHourUtilization + oldWeekly := c.state.weeklyUtilization c.state.consecutivePollFailures = 0 c.state.fiveHourUtilization = statusResponse.FiveHourUtilization c.state.weeklyUtilization = statusResponse.WeeklyUtilization @@ -754,6 +755,13 @@ func (c *externalCredential) connectStatusStream(ctx context.Context) (statusStr if c.state.hardRateLimited && time.Now().After(c.state.rateLimitResetAt) { c.state.hardRateLimited = false } + if int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { + resetSuffix := "" + if !c.state.weeklyReset.IsZero() { + resetSuffix = ", resets=" + log.FormatDuration(time.Until(c.state.weeklyReset)) + } + c.logger.Debug("poll usage for ", c.tag, ": 5h=", c.state.fiveHourUtilization, "%, weekly=", c.state.weeklyUtilization, "%", resetSuffix) + } shouldInterrupt := c.checkTransitionLocked() c.stateAccess.Unlock() if shouldInterrupt { diff --git a/service/ocm/credential_external.go b/service/ocm/credential_external.go index 47b6c0d5e..3bcae1391 100644 --- a/service/ocm/credential_external.go +++ b/service/ocm/credential_external.go @@ -460,7 +460,6 @@ func (c *externalCredential) openReverseConnection(ctx context.Context) (net.Con func (c *externalCredential) updateStateFromHeaders(headers http.Header) { c.stateAccess.Lock() - isFirstUpdate := c.state.lastUpdated.IsZero() oldFiveHour := c.state.fiveHourUtilization oldWeekly := c.state.weeklyUtilization oldPlanWeight := c.state.remotePlanWeight @@ -516,7 +515,7 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) { c.state.consecutivePollFailures = 0 c.state.lastUpdated = time.Now() } - if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { + if int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { resetSuffix := "" if !c.state.weeklyReset.IsZero() { resetSuffix = ", resets=" + log.FormatDuration(time.Until(c.state.weeklyReset)) @@ -673,7 +672,6 @@ func (c *externalCredential) pollUsage(ctx context.Context) { } c.stateAccess.Lock() - isFirstUpdate := c.state.lastUpdated.IsZero() oldFiveHour := c.state.fiveHourUtilization oldWeekly := c.state.weeklyUtilization c.state.consecutivePollFailures = 0 @@ -691,7 +689,7 @@ func (c *externalCredential) pollUsage(ctx context.Context) { if c.state.hardRateLimited && time.Now().After(c.state.rateLimitResetAt) { c.state.hardRateLimited = false } - if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { + if int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { resetSuffix := "" if !c.state.weeklyReset.IsZero() { resetSuffix = ", resets=" + log.FormatDuration(time.Until(c.state.weeklyReset)) @@ -781,6 +779,8 @@ func (c *externalCredential) connectStatusStream(ctx context.Context) (statusStr } c.stateAccess.Lock() + oldFiveHour := c.state.fiveHourUtilization + oldWeekly := c.state.weeklyUtilization c.state.consecutivePollFailures = 0 c.state.fiveHourUtilization = statusResponse.FiveHourUtilization c.state.weeklyUtilization = statusResponse.WeeklyUtilization @@ -796,6 +796,13 @@ func (c *externalCredential) connectStatusStream(ctx context.Context) (statusStr if c.state.hardRateLimited && time.Now().After(c.state.rateLimitResetAt) { c.state.hardRateLimited = false } + if int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { + resetSuffix := "" + if !c.state.weeklyReset.IsZero() { + resetSuffix = ", resets=" + log.FormatDuration(time.Until(c.state.weeklyReset)) + } + c.logger.Debug("poll usage for ", c.tag, ": 5h=", c.state.fiveHourUtilization, "%, weekly=", c.state.weeklyUtilization, "%", resetSuffix) + } shouldInterrupt := c.checkTransitionLocked() c.stateAccess.Unlock() if shouldInterrupt {