/
percentage.go
95 lines (75 loc) · 2.41 KB
/
percentage.go
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
package metrics
import (
"fmt"
"sync"
"github.com/ethereum/go-ethereum/metrics"
)
// Percentage implements the GaugeFloat64 interface for percentage statistic.
type Percentage interface {
Mark(marked bool)
Value() float64 // e.g. 99.38 means 99.38%
}
// NewPercentage constructs a new standard percentage metric.
func NewPercentage() Percentage {
if !metrics.Enabled {
return &noopPercentage{}
}
return &standardPercentage{}
}
// GetOrRegisterPercentage returns an existing Percentage or constructs and registers a new standard Percentage.
func GetOrRegisterPercentage(name string, args ...interface{}) Percentage {
return getOrRegisterPercentage(NewPercentage, name, args...)
}
// getOrRegisterPercentage gets or constructs Percentage with specified factory.
func getOrRegisterPercentage(factory func() Percentage, name string, args ...interface{}) Percentage {
metricName := fmt.Sprintf(name, args...)
return InfuraRegistry.GetOrRegister(metricName, factory).(Percentage)
}
// noopPercentage is no-op implementation for Percentage interface.
type noopPercentage struct{}
func (p *noopPercentage) Mark(marked bool) {}
func (p *noopPercentage) Value() float64 { return 0 }
func (p *noopPercentage) Update(float64) {}
func (p *noopPercentage) Snapshot() metrics.GaugeFloat64 { return p }
type percentageData struct {
total uint64
marks uint64
}
func (data *percentageData) update(marked bool) {
data.total++
if marked {
data.marks++
}
}
// 10.19 means 10.19%
func (data *percentageData) value() float64 {
if data.total == 0 {
// percentage is 0 when never marked
return 0
}
return float64(data.marks*10000/data.total) / 100
}
// standardPercentage is the standard implementation for Percentage interface.
type standardPercentage struct {
data percentageData
mu sync.Mutex
}
func (p *standardPercentage) Mark(marked bool) {
p.mu.Lock()
defer p.mu.Unlock()
p.data.update(marked)
}
// Value implements the metrics.GaugeFloat64 interface.
func (p *standardPercentage) Value() float64 {
p.mu.Lock()
defer p.mu.Unlock()
return p.data.value()
}
// Update implements the metrics.GaugeFloat64 interface.
func (p *standardPercentage) Update(float64) {
panic("Update called on a standardPercentage")
}
// Snapshot implements the metrics.GaugeFloat64 interface.
func (p *standardPercentage) Snapshot() metrics.GaugeFloat64 {
return metrics.GaugeFloat64Snapshot(p.Value())
}