fix(agent): handle vnstat 1.x JSON format to prevent frontend crash#169
Conversation
Normalize vnstat JSON v1 format (used by vnstat 1.18 and earlier) to v2 format in the agent's historical export handler. Key differences handled: - "hours"/"days"/"months" (plural) renamed to "hour"/"day"/"month" (singular) - "time" field added to hour entries derived from the "id" field - "day" added to date objects when missing from hour entries Also adds defensive null checks in the frontend parser to prevent crashes if invalid data makes it through. Fixes #163
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
📝 WalkthroughWalkthroughAdds server-side normalization that converts vnstat JSON v1 (plural keys, missing hour time) into v2-like structure before timezone enrichment and frontend parsing; includes tests and frontend parser adjustments to handle missing traffic periods. Changes
Sequence Diagram(s)sequenceDiagram
participant Agent as Agent (vnStat JSON)
participant Backend as Backend normalize
participant Backend2 as Backend enrich
participant Frontend as Frontend parser
Agent->>Backend: send vnstat JSON (jsonversion "1" or "2")
Backend->>Backend: if jsonversion == "1" → normalizeVnstatV1 (rename keys, synthesize time, set "2")
Backend->>Backend2: add server_time / timezone info
Backend2->>Frontend: return normalized + enriched JSON
Frontend->>Frontend: parseMonitorUsagePeriods (guard missing periods, compute summaries)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@web/src/utils/monitorDataParser.ts`:
- Around line 21-45: The early-return in monitorDataParser (the branch that
currently returns getEmptyUsage() when !traffic.hour && !traffic.day &&
!traffic.month) discards traffic.total; change this so that when period data is
missing you still return an object that preserves the "All Time" total (use
traffic.total when present) while keeping other period entries as empty. Locate
the guard around traffic and modify it to build the final return shape (the
object with keys like "This Hour", "Last Hour", Today, "This week", "This
Month", and "All Time") so that "All Time" uses traffic.total (or converts it
into {download:0, upload:0, total: traffic.total} if needed) instead of dropping
it; keep calls to
getCurrentHour/getLastHour/getToday/getThisWeek/getCurrentMonth and
getEmptyUsage for missing periods and use
data.server_time/data.server_time_unix/ timezone logic unchanged.
🧹 Nitpick comments (1)
internal/agent/bandwidth.go (1)
170-227: Avoid time drift by reusing a singlenow.
time.Now()is called inside normalization and again forserver_time. If this crosses midnight, hour entries may get a different day thanserver_time, which can skew frontend matching. Consider capturingnowonce and passing it into normalization for consistency and deterministic behavior.♻️ Proposed refactor
- // Normalize vnstat 1.x JSON format to 2.x format - // vnstat 1.x uses "hours"/"days"/"months" (plural) and lacks "time" fields - // vnstat 2.x uses "hour"/"day"/"month" (singular) with "time" fields - if jsonVer, ok := bandwidthData["jsonversion"].(string); ok && jsonVer == "1" { - normalizeVnstatV1(bandwidthData) - } - - // Add server time information for timezone handling - now := time.Now() + // Capture time once for normalization + server_time + now := time.Now() + + // Normalize vnstat 1.x JSON format to 2.x format + // vnstat 1.x uses "hours"/"days"/"months" (plural) and lacks "time" fields + // vnstat 2.x uses "hour"/"day"/"month" (singular) with "time" fields + if jsonVer, ok := bandwidthData["jsonversion"].(string); ok && jsonVer == "1" { + normalizeVnstatV1(bandwidthData, now) + }-func normalizeVnstatV1(data map[string]any) { +func normalizeVnstatV1(data map[string]any, now time.Time) { ... - dateMap["day"] = float64(time.Now().Day()) + dateMap["day"] = float64(now.Day())
…itorDataParser Prevent crash when traffic.total is undefined by adding a null guard for the "All Time" entry. Fix getThisWeek to use UTC-safe date methods consistently when isUTC is true, ensuring week boundaries are computed correctly regardless of timezone.
Summary
hours/days/months) to singular (hour/day/month)timefield for hour entries from theidfieldparseMonitorUsagePeriodsto prevent crashes if any period data is missingconsole.logstatements from production codeMonitorPeriodtype instead of inline type literalsTest plan
normalizeVnstatV1covering: full normalization, missing day in date, no interfaces, empty trafficformatBytesPerSecondtest converted to subtestsgo test ./internal/agent/passespnpm tsc --noEmitpassesFixes #163
Summary by CodeRabbit
New Features
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.