aboutsummaryrefslogtreecommitdiff
path: root/weed/worker/tasks/vacuum/monitoring.go
blob: c7dfd673e806b6088f9dc56906c4cb2139a64976 (plain)
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
}