1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
package vacuum
import (
"sync"
"time"
)
// VacuumMetrics contains vacuum-specific monitoring data
type VacuumMetrics struct {
// Execution metrics
VolumesVacuumed int64 `json:"volumes_vacuumed"`
TotalSpaceReclaimed int64 `json:"total_space_reclaimed"`
TotalFilesProcessed int64 `json:"total_files_processed"`
TotalGarbageCollected int64 `json:"total_garbage_collected"`
LastVacuumTime time.Time `json:"last_vacuum_time"`
// Performance metrics
AverageVacuumTime int64 `json:"average_vacuum_time_seconds"`
AverageGarbageRatio float64 `json:"average_garbage_ratio"`
SuccessfulOperations int64 `json:"successful_operations"`
FailedOperations int64 `json:"failed_operations"`
// Current task metrics
CurrentGarbageRatio float64 `json:"current_garbage_ratio"`
VolumesPendingVacuum int `json:"volumes_pending_vacuum"`
mutex sync.RWMutex
}
// NewVacuumMetrics creates a new vacuum metrics instance
func NewVacuumMetrics() *VacuumMetrics {
return &VacuumMetrics{
LastVacuumTime: time.Now(),
}
}
// RecordVolumeVacuumed records a successful volume vacuum operation
func (m *VacuumMetrics) RecordVolumeVacuumed(spaceReclaimed int64, filesProcessed int64, garbageCollected int64, vacuumTime time.Duration, garbageRatio float64) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.VolumesVacuumed++
m.TotalSpaceReclaimed += spaceReclaimed
m.TotalFilesProcessed += filesProcessed
m.TotalGarbageCollected += garbageCollected
m.SuccessfulOperations++
m.LastVacuumTime = time.Now()
// Update average vacuum time
if m.AverageVacuumTime == 0 {
m.AverageVacuumTime = int64(vacuumTime.Seconds())
} else {
// Exponential moving average
newTime := int64(vacuumTime.Seconds())
m.AverageVacuumTime = (m.AverageVacuumTime*4 + newTime) / 5
}
// Update average garbage ratio
if m.AverageGarbageRatio == 0 {
m.AverageGarbageRatio = garbageRatio
} else {
// Exponential moving average
m.AverageGarbageRatio = 0.8*m.AverageGarbageRatio + 0.2*garbageRatio
}
}
// RecordFailure records a failed vacuum operation
func (m *VacuumMetrics) RecordFailure() {
m.mutex.Lock()
defer m.mutex.Unlock()
m.FailedOperations++
}
// UpdateCurrentGarbageRatio updates the current volume's garbage ratio
func (m *VacuumMetrics) UpdateCurrentGarbageRatio(ratio float64) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.CurrentGarbageRatio = ratio
}
// SetVolumesPendingVacuum sets the number of volumes pending vacuum
func (m *VacuumMetrics) SetVolumesPendingVacuum(count int) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.VolumesPendingVacuum = count
}
// GetMetrics returns a copy of the current metrics (without the mutex)
func (m *VacuumMetrics) GetMetrics() VacuumMetrics {
m.mutex.RLock()
defer m.mutex.RUnlock()
// Create a copy without the mutex to avoid copying lock value
return VacuumMetrics{
VolumesVacuumed: m.VolumesVacuumed,
TotalSpaceReclaimed: m.TotalSpaceReclaimed,
TotalFilesProcessed: m.TotalFilesProcessed,
TotalGarbageCollected: m.TotalGarbageCollected,
LastVacuumTime: m.LastVacuumTime,
AverageVacuumTime: m.AverageVacuumTime,
AverageGarbageRatio: m.AverageGarbageRatio,
SuccessfulOperations: m.SuccessfulOperations,
FailedOperations: m.FailedOperations,
CurrentGarbageRatio: m.CurrentGarbageRatio,
VolumesPendingVacuum: m.VolumesPendingVacuum,
}
}
// GetSuccessRate returns the success rate as a percentage
func (m *VacuumMetrics) GetSuccessRate() float64 {
m.mutex.RLock()
defer m.mutex.RUnlock()
total := m.SuccessfulOperations + m.FailedOperations
if total == 0 {
return 100.0
}
return float64(m.SuccessfulOperations) / float64(total) * 100.0
}
// GetAverageSpaceReclaimed returns the average space reclaimed per volume
func (m *VacuumMetrics) GetAverageSpaceReclaimed() float64 {
m.mutex.RLock()
defer m.mutex.RUnlock()
if m.VolumesVacuumed == 0 {
return 0
}
return float64(m.TotalSpaceReclaimed) / float64(m.VolumesVacuumed)
}
// Reset resets all metrics to zero
func (m *VacuumMetrics) Reset() {
m.mutex.Lock()
defer m.mutex.Unlock()
*m = VacuumMetrics{
LastVacuumTime: time.Now(),
}
}
// Global metrics instance for vacuum tasks
var globalVacuumMetrics = NewVacuumMetrics()
// GetGlobalVacuumMetrics returns the global vacuum metrics instance
func GetGlobalVacuumMetrics() *VacuumMetrics {
return globalVacuumMetrics
}
|