feat: add summary dashboard history charts
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
import SwiftUI
|
||||
import Combine
|
||||
import UserNotifications
|
||||
import SwiftData
|
||||
import AppKit
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
@@ -37,9 +38,11 @@ struct MainView: View {
|
||||
@State private var draggedGroupID: UUID?
|
||||
@State private var groupDropIndicator: GroupDropIndicator?
|
||||
@State private var lastRefreshInterval: Int?
|
||||
@State private var lastMetricPrune: Date?
|
||||
@State private var previousServiceStates: [String: String] = [:]
|
||||
private let serverOrderKey = MainView.serverOrderKeyStatic
|
||||
private let storedGroupsKey = MainView.storedGroupsKeyStatic
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
|
||||
@State private var servers: [Server] = MainView.loadStoredServers()
|
||||
@State private var groups: [ServerGroup] = MainView.loadStoredGroups()
|
||||
@@ -351,6 +354,7 @@ struct MainView: View {
|
||||
var updated = servers[index]
|
||||
updated.info = info
|
||||
servers[index] = updated
|
||||
recordMetricSample(for: id, info: info)
|
||||
checkServiceStatusChanges(for: server.hostname, newInfo: info)
|
||||
}
|
||||
}
|
||||
@@ -386,6 +390,7 @@ struct MainView: View {
|
||||
var updated = servers[index]
|
||||
updated.info = info
|
||||
servers[index] = updated
|
||||
recordMetricSample(for: id, info: info)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
@@ -451,6 +456,53 @@ struct MainView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func recordMetricSample(for serverID: UUID, info: ServerInfo) {
|
||||
let sample = MetricSample(
|
||||
serverID: serverID,
|
||||
cpuPercent: info.load.percent,
|
||||
memoryPercent: info.memory.percent,
|
||||
swapPercent: info.swap.percent,
|
||||
diskPercent: info.diskSpace.percent
|
||||
)
|
||||
modelContext.insert(sample)
|
||||
|
||||
do {
|
||||
try modelContext.save()
|
||||
} catch {
|
||||
print("❌ [MainView] Failed to save metric sample: \(error)")
|
||||
}
|
||||
|
||||
pruneOldMetricSamplesIfNeeded()
|
||||
}
|
||||
|
||||
private func pruneOldMetricSamplesIfNeeded() {
|
||||
let now = Date()
|
||||
|
||||
if let lastMetricPrune, now.timeIntervalSince(lastMetricPrune) < 3600 {
|
||||
return
|
||||
}
|
||||
|
||||
let cutoff = now.addingTimeInterval(-30 * 24 * 60 * 60)
|
||||
let descriptor = FetchDescriptor<MetricSample>(
|
||||
predicate: #Predicate { sample in
|
||||
sample.timestamp < cutoff
|
||||
}
|
||||
)
|
||||
|
||||
do {
|
||||
let expiredSamples = try modelContext.fetch(descriptor)
|
||||
for sample in expiredSamples {
|
||||
modelContext.delete(sample)
|
||||
}
|
||||
if !expiredSamples.isEmpty {
|
||||
try modelContext.save()
|
||||
}
|
||||
lastMetricPrune = now
|
||||
} catch {
|
||||
print("❌ [MainView] Failed to prune metric samples: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func deleteGroup(_ group: ServerGroup) {
|
||||
groups.removeAll { $0.id == group.id }
|
||||
for index in servers.indices {
|
||||
|
||||
Reference in New Issue
Block a user