-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdashboard_handler.go
More file actions
125 lines (100 loc) · 2.71 KB
/
Copy pathdashboard_handler.go
File metadata and controls
125 lines (100 loc) · 2.71 KB
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
package main
import (
"cmp"
_ "embed"
"html/template"
"log"
"net/http"
"slices"
"github.com/tinyauthapp/analytics/queries"
)
//go:embed dashboard.html
var dashboardTemplate string
type DashboardHandler struct {
queries *queries.Queries
minTagInstances int
}
type versionStats struct {
Total int
MostUsed string
VersionLabels []string
VersionValues []int
}
func NewDashboardHandler(queries *queries.Queries, minTagInstances int) *DashboardHandler {
return &DashboardHandler{
queries: queries,
minTagInstances: minTagInstances,
}
}
func (h *DashboardHandler) sortVersionStats(stats versionStats) versionStats {
type versionKv struct {
label string
value int
}
versionKvs := make([]versionKv, len(stats.VersionLabels))
for i, version := range stats.VersionLabels {
versionKvs[i] = versionKv{version, stats.VersionValues[i]}
}
slices.SortStableFunc(versionKvs, func(a, b versionKv) int {
if order := cmp.Compare(b.value, a.value); order != 0 {
return order
}
return cmp.Compare(a.label, b.label)
})
stats.VersionLabels = make([]string, len(versionKvs))
stats.VersionValues = make([]int, len(versionKvs))
for i, kv := range versionKvs {
stats.VersionLabels[i] = kv.label
stats.VersionValues[i] = kv.value
}
return stats
}
func (h *DashboardHandler) compileVersionStats(instances []queries.Instance) versionStats {
stats := make(map[string]int)
total := 0
for _, instance := range instances {
stats[instance.Version]++
total++
}
mostUsed := "unknown"
maxCount := 0
versionLabels := make([]string, 0, len(stats))
versionValues := make([]int, 0, len(stats))
for version, count := range stats {
if count < h.minTagInstances {
continue
}
if count > maxCount {
maxCount = count
mostUsed = version
}
versionLabels = append(versionLabels, version)
versionValues = append(versionValues, count)
}
return versionStats{
Total: total,
MostUsed: mostUsed,
VersionLabels: versionLabels,
VersionValues: versionValues,
}
}
func (h *DashboardHandler) Dashboard(w http.ResponseWriter, r *http.Request) {
instances, err := h.queries.GetAllInstances(r.Context())
if err != nil {
log.Printf("failed to get instances: %v", err)
http.Error(w, "Failed to retrieve instances", http.StatusInternalServerError)
return
}
versionStats := h.compileVersionStats(instances)
versionStatsSorted := h.sortVersionStats(versionStats)
tmpl, err := template.New("dashboard").Parse(dashboardTemplate)
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
err = tmpl.Execute(w, versionStatsSorted)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}