fix partial server metric aggregation

This commit is contained in:
npc0-hue
2026-08-22 11:26:18 +08:00
parent 473246e5d2
commit ec63b8750d
3 changed files with 84 additions and 11 deletions
+46 -8
View File
@@ -2200,19 +2200,14 @@ func (svc *CoreService) latestMetricsForServer(instance domain.ServerInstance) d
}
}
if found {
return domain.ServerMetrics{
metrics := domain.ServerMetrics{
ServerInstanceID: latest.ServerInstanceID,
Online: latest.Online,
PlayerCount: latest.PlayerCount,
MaxPlayers: latest.MaxPlayers,
TPS: latest.TPS,
LatencyMS: latest.LatencyMS,
CPUPercent: latest.CPUPercent,
MemoryPercent: latest.MemoryPercent,
DiskPercent: latest.DiskPercent,
Source: latest.Source,
CollectedAt: latest.CollectedAt,
}
mergeRecentMetricFields(&metrics, samples, latest.CollectedAt, instance.RunEndpointID)
return metrics
}
}
return domain.ServerMetrics{
@@ -2223,6 +2218,49 @@ func (svc *CoreService) latestMetricsForServer(instance domain.ServerInstance) d
}
}
const recentMetricFieldWindow = 2 * time.Minute
// mergeRecentMetricFields keeps independently reported fields visible while
// refusing to carry values forward indefinitely when a collector stops.
func mergeRecentMetricFields(metrics *domain.ServerMetrics, samples []domain.MetricSample, latestAt time.Time, runEndpointID string) {
cutoff := latestAt.Add(-recentMetricFieldWindow)
var playerAt, maxPlayersAt, tpsAt, latencyAt, cpuAt, memoryAt, diskAt time.Time
for i := range samples {
sample := samples[i]
if (sample.RunEndpointID != "" && sample.RunEndpointID != runEndpointID) || sample.CollectedAt.Before(cutoff) || sample.CollectedAt.After(latestAt) {
continue
}
if sample.PlayerCount != nil && (metrics.PlayerCount == nil || sample.CollectedAt.After(playerAt)) {
metrics.PlayerCount = sample.PlayerCount
playerAt = sample.CollectedAt
}
if sample.MaxPlayers != nil && (metrics.MaxPlayers == nil || sample.CollectedAt.After(maxPlayersAt)) {
metrics.MaxPlayers = sample.MaxPlayers
maxPlayersAt = sample.CollectedAt
}
if sample.TPS != nil && (metrics.TPS == nil || sample.CollectedAt.After(tpsAt)) {
metrics.TPS = sample.TPS
tpsAt = sample.CollectedAt
}
if sample.LatencyMS != nil && (metrics.LatencyMS == nil || sample.CollectedAt.After(latencyAt)) {
metrics.LatencyMS = sample.LatencyMS
latencyAt = sample.CollectedAt
}
if sample.CPUPercent != nil && (metrics.CPUPercent == nil || sample.CollectedAt.After(cpuAt)) {
metrics.CPUPercent = sample.CPUPercent
cpuAt = sample.CollectedAt
}
if sample.MemoryPercent != nil && (metrics.MemoryPercent == nil || sample.CollectedAt.After(memoryAt)) {
metrics.MemoryPercent = sample.MemoryPercent
memoryAt = sample.CollectedAt
}
if sample.DiskPercent != nil && (metrics.DiskPercent == nil || sample.CollectedAt.After(diskAt)) {
metrics.DiskPercent = sample.DiskPercent
diskAt = sample.CollectedAt
}
}
}
func buildLogicalServerConfig(instance domain.ServerInstance) string {
lines := []string{
"# platform logical server config",