1
+ {{- /*gotype: github.com/grafana/dskit/kv/memberlist.StatusPageData */ -}}
2
+ <!DOCTYPE html>
3
+ <html class="h-100">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+
9
+ <title>Memberlist: Grafana Phlare</title>
10
+
11
+ <link rel="stylesheet" href="{{ AddPathPrefix "/static/bootstrap-5.1.3.min.css" }}">
12
+ <link rel="stylesheet" href="{{ AddPathPrefix "/static/bootstrap-icons-1.8.1.css" }}">
13
+ <link rel="stylesheet" href="{{ AddPathPrefix "/static/phlare-styles.css" }}">
14
+ <script src="{{ AddPathPrefix "/static/bootstrap-5.1.3.bundle.min.js" }}"></script>
15
+ </head>
16
+ <body class="d-flex flex-column h-100">
17
+ <main class="flex-shrink-0">
18
+ <div class="container">
19
+ <div class="header row border-bottom py-3 flex-column-reverse flex-sm-row">
20
+ <div class="col-12 col-sm-9 text-center text-sm-start">
21
+ <h1>Memberlist: Grafana Phlare</h1>
22
+ </div>
23
+ <div class="col-12 col-sm-3 text-center text-sm-end mb-3 mb-sm-0">
24
+ <img alt="Phlare logo" class="phlare-brand" src="{{ AddPathPrefix "/static/phlare-logo.png" }}">
25
+ </div>
26
+ </div>
27
+ <div class="row my-3">
28
+ <div class="col-12">
29
+ {{ $HealthScore := .Memberlist.GetHealthScore }}
30
+ {{ if eq $HealthScore 0 }}
31
+ <div class="alert alert-success" role="alert">
32
+ Memberlist cluster has <strong>{{ .Memberlist.NumMembers }}</strong> members and it is <strong>healthy</strong>.
33
+ </div>
34
+ {{ else }}
35
+ <div class="alert alert-warning" role="alert">
36
+ Memberlist cluster has <strong>{{ .Memberlist.NumMembers }}</strong> members but health score
37
+ is {{ $HealthScore }} (lower is better, 0 = healthy).
38
+ </div>
39
+ {{ end }}
40
+ </div>
41
+
42
+ <h2>KV Store</h2>
43
+ <div class="table-responsive">
44
+ <table class="table table-bordered table-hover table-striped">
45
+ <thead>
46
+ <tr>
47
+ <th>Key</th>
48
+ <th class="fit-width">Codec</th>
49
+ <th class="fit-width">
50
+ <span class="text-nowrap">
51
+ Version
52
+ <i class="bi bi-info-circle"
53
+ data-bs-toggle="tooltip" data-bs-placement="top"
54
+ title="Note that value 'version' is node-specific. It starts with 0 (on restart), and increases on each received update."></i>
55
+ </span>
56
+ </th>
57
+ <th class="fit-width">Actions</th>
58
+ </tr>
59
+ </thead>
60
+
61
+ <tbody>
62
+ {{ range $k, $v := .Store }}
63
+ <tr>
64
+ <td class="align-middle font-monospace small">{{ $k }}</td>
65
+ <td class="align-middle font-monospace small fit-width">{{ $v.CodecID }}</td>
66
+ <td class="align-middle font-monospace small fit-width">{{ $v.Version }}</td>
67
+ <td class="fit-width">
68
+ <span class="text-nowrap">
69
+ <a href="?viewKey={{ $k }}&format=json-pretty" title="JSON pretty" class="text-decoration-none">
70
+ <i class="bi bi-filetype-json text-success"></i>
71
+ </a>
72
+ <a href="?viewKey={{ $k }}&format=json" title="JSON" class="text-decoration-none">
73
+ <i class="bi bi-filetype-json"></i>
74
+ </a>
75
+ <a href="?viewKey={{ $k }}&format=struct" title="Struct" class="text-decoration-none">
76
+ <i class="bi bi-file-earmark-code"></i>
77
+ </a>
78
+ <a href="?downloadKey={{ $k }}" title="Download" class="text-decoration-none">
79
+ <i class="bi bi-file-earmark-arrow-down"></i>
80
+ </a>
81
+ </span>
82
+ </td>
83
+ </tr>
84
+ {{ end }}
85
+ </tbody>
86
+ </table>
87
+ </div>
88
+
89
+ <h2>Memberlist Cluster Members</h2>
90
+ <div class="table-responsive">
91
+ <table class="table table-bordered table-hover table-striped">
92
+ <thead>
93
+ <tr>
94
+ <th>Name</th>
95
+ <th>Address</th>
96
+ <th class="fit-width">
97
+ <span class="text-nowrap">
98
+ State
99
+ <i class="bi bi-info-circle"
100
+ data-bs-toggle="tooltip" data-bs-placement="left"
101
+ title="State: 0 = Alive, 1 = Suspect, 2 = Dead, 3 = Left"></i>
102
+ </span>
103
+ </th>
104
+ </tr>
105
+ </thead>
106
+
107
+ <tbody>
108
+ {{ range .SortedMembers }}
109
+ <tr>
110
+ <td class="align-middle font-monospace small">{{ .Name }}</td>
111
+ <td class="align-middle font-monospace small">{{ .Address }}</td>
112
+ <td class="fit-width text-center py-1">
113
+ {{ if eq .State 0}}
114
+ <span class="badge bg-success">Alive</span>
115
+ {{ else if eq .State 1 }}
116
+ <span class="badge bg-warning text-dark">Suspect</span>
117
+ {{ else if eq .State 2 }}
118
+ <span class="badge bg-danger">Dead</span>
119
+ {{ else if eq.State 3}}
120
+ <span class="badge bg-info">Left</span>
121
+ {{ else }}
122
+ <span class="badge bg-info">Unknown: {{ .State }}</span>
123
+ {{ end }}
124
+ </td>
125
+ </tr>
126
+ {{ end }}
127
+ </tbody>
128
+ </table>
129
+ </div>
130
+
131
+ <h2>Message History
132
+ {{ if .MessageHistoryBufferBytes }}
133
+ <a class="btn btn-outline-warning" href="?deleteMessages=true" data-bs-toggle="tooltip"
134
+ data-bs-placement="right" title="Delete sent and received messages buffer">Flush</a>
135
+ {{ end }}
136
+ </h2>
137
+
138
+ {{ if .MessageHistoryBufferBytes }}
139
+ <div class="accordion">
140
+ <div class="accordion-item">
141
+ <h3 class="accordion-header" id="heading-received-messages">
142
+ <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
143
+ data-bs-target="#collapse-received-messages" aria-expanded="false"
144
+ aria-controls="collapse-received-messages">
145
+ Received Messages
146
+ </button>
147
+ </h3>
148
+ <div id="collapse-received-messages" class="accordion-collapse collapse"
149
+ aria-labelledby="heading-received-messages">
150
+ <div class="accordion-body p-0 table-responsive">
151
+ {{ if .ReceivedMessages }}
152
+ <table class="table table-hover table-striped">
153
+ <thead>
154
+ <tr>
155
+ <th class="fit-width">ID</th>
156
+ <th>Time</th>
157
+ <th>Key</th>
158
+ <th class="fit-width">Size (B)</th>
159
+ <th class="fit-width">Codec</th>
160
+ <th class="fit-width">
161
+ <span class="text-nowrap">
162
+ Version
163
+ <i class="bi bi-info-circle"
164
+ data-bs-toggle="tooltip" data-bs-placement="top"
165
+ title="Version after update. 0 = No change."></i>
166
+ </span>
167
+ </th>
168
+ <th>Changes</th>
169
+ <th class="fit-width">Actions</th>
170
+ </tr>
171
+ </thead>
172
+
173
+ <tbody class="font-monospace small">
174
+ {{ range .ReceivedMessages }}
175
+ <tr>
176
+ <td class="font-monospace small fit-width">{{ .ID }}</td>
177
+ <td class="font-monospace small">{{ .Time.Format "15:04:05.000" }}</td>
178
+ <td class="font-monospace small">{{ .Pair.Key }}</td>
179
+ <td class="font-monospace small fit-width">{{ .Pair.Value | len }}</td>
180
+ <td class="font-monospace small fit-width">{{ .Pair.Codec }}</td>
181
+ <td class="font-monospace small fit-width">{{ .Version }}</td>
182
+ <td class="font-monospace small">{{ StringsJoin .Changes ", " }}</td>
183
+ <td class="fit-width">
184
+ <span class="text-nowrap">
185
+ <a href="?viewMsg={{ .ID }}&format=json-pretty" class="text-decoration-none">
186
+ <i class="bi bi-filetype-json text-success"></i>
187
+ </a>
188
+ <a href="?viewMsg={{ .ID }}&format=json" class="text-decoration-none">
189
+ <i class="bi bi-filetype-json"></i>
190
+ </a>
191
+ <a href="?viewMsg={{ .ID }}&format=struct" class="text-decoration-none">
192
+ <i class="bi bi-file-earmark-code"></i>
193
+ </a>
194
+ </span>
195
+ </td>
196
+ </tr>
197
+ {{ end }}
198
+ </tbody>
199
+
200
+ </table>
201
+ {{ else }}
202
+ <span><i>There are no received messages.</i></span>
203
+ {{ end }}
204
+ </div>
205
+ </div>
206
+ </div>
207
+ <div class="accordion-item">
208
+ <h3 class="accordion-header" id="heading-sent-messages">
209
+ <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
210
+ data-bs-target="#collapse-sent-messages" aria-expanded="false"
211
+ aria-controls="collapse-sent-messages">
212
+ Sent Messages
213
+ </button>
214
+ </h3>
215
+ <div id="collapse-sent-messages" class="accordion-collapse collapse"
216
+ aria-labelledby="heading-sent-messages">
217
+ <div class="accordion-body p-0 table-responsive">
218
+
219
+ {{ if .SentMessages }}
220
+ <table class="table table-hover table-striped">
221
+ <thead>
222
+ <tr>
223
+ <th>ID</th>
224
+ <th>Time</th>
225
+ <th>Key</th>
226
+ <th>Size</th>
227
+ <th>Codec</th>
228
+ <th>Version</th>
229
+ <th>Changes</th>
230
+ <th>Actions</th>
231
+ </tr>
232
+ </thead>
233
+
234
+ <tbody>
235
+ {{ range .SentMessages }}
236
+ <tr>
237
+ <td class="font-monospace small">{{ .ID }}</td>
238
+ <td class="font-monospace small">{{ .Time.Format "15:04:05.000" }}</td>
239
+ <td class="font-monospace small">{{ .Pair.Key }}</td>
240
+ <td class="font-monospace small">{{ .Pair.Value | len }}</td>
241
+ <td class="font-monospace small">{{ .Pair.Codec }}</td>
242
+ <td class="font-monospace small">{{ .Version }}</td>
243
+ <td class="font-monospace small">{{ StringsJoin .Changes ", " }}</td>
244
+ <td>
245
+ <span class="text-nowrap">
246
+ <a href="?viewMsg={{ .ID }}&format=json-pretty" class="text-decoration-none">
247
+ <i class="bi bi-filetype-json text-success"></i>
248
+ </a>
249
+ <a href="?viewMsg={{ .ID }}&format=json" class="text-decoration-none">
250
+ <i class="bi bi-filetype-json"></i>
251
+ </a>
252
+ <a href="?viewMsg={{ .ID }}&format=struct" class="text-decoration-none">
253
+ <i class="bi bi-file-earmark-code"></i>
254
+ </a>
255
+ </span>
256
+ </td>
257
+ </tr>
258
+ {{ end }}
259
+ </tbody>
260
+ </table>
261
+
262
+ {{ else }}
263
+ <span><i>There are no sent messages.</i></span>
264
+ {{ end }}
265
+ </div>
266
+ </div>
267
+ </div>
268
+ </div>
269
+ {{ else }}
270
+
271
+ <div class="col-12">
272
+ <div class="alert alert-info" role="alert">
273
+ Message history buffer is disabled.
274
+ <br />Enable it by setting the <code>-memberlist.message-history-buffer-bytes</code> flag or the corresponding config key.
275
+ </div>
276
+ </div>
277
+ {{ end }}
278
+ </div>
279
+ </div>
280
+ </main>
281
+ <footer class="footer mt-auto py-3 bg-light">
282
+ <div class="container">
283
+ <small class="text-muted">Status @ {{ .Now.Format "2006-01-02 15:04:05.000" }}</small>
284
+ </div>
285
+ </footer>
286
+ <script type="text/javascript">
287
+ var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
288
+ var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
289
+ return new bootstrap.Tooltip(tooltipTriggerEl)
290
+ })
291
+ </script>
292
+ </body>
293
+ </html>
0 commit comments