litestack 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile +2 -0
- data/README.md +5 -11
- data/assets/event_page.png +0 -0
- data/assets/index_page.png +0 -0
- data/assets/topic_page.png +0 -0
- data/bench/bench_jobs_rails.rb +1 -1
- data/bench/bench_jobs_raw.rb +1 -1
- data/bin/liteboard +81 -0
- data/lib/action_cable/subscription_adapter/litecable.rb +1 -11
- data/lib/generators/litestack/install/USAGE +11 -0
- data/lib/generators/litestack/install/install_generator.rb +35 -0
- data/lib/generators/litestack/install/templates/cable.yml +11 -0
- data/lib/generators/litestack/install/templates/database.yml +34 -0
- data/lib/litestack/liteboard/liteboard.rb +305 -0
- data/lib/litestack/liteboard/views/event.erb +32 -0
- data/lib/litestack/liteboard/views/index.erb +54 -0
- data/lib/litestack/liteboard/views/layout.erb +303 -0
- data/lib/litestack/liteboard/views/litecable.erb +118 -0
- data/lib/litestack/liteboard/views/litecache.erb +144 -0
- data/lib/litestack/liteboard/views/litedb.erb +168 -0
- data/lib/litestack/liteboard/views/litejob.erb +151 -0
- data/lib/litestack/liteboard/views/topic.erb +48 -0
- data/lib/litestack/litecable.rb +25 -35
- data/lib/litestack/litecable.sql.yml +1 -1
- data/lib/litestack/litecache.rb +31 -28
- data/lib/litestack/litedb.rb +124 -1
- data/lib/litestack/litejob.rb +2 -2
- data/lib/litestack/litejobqueue.rb +8 -8
- data/lib/litestack/litemetric.rb +177 -88
- data/lib/litestack/litemetric.sql.yml +312 -42
- data/lib/litestack/litemetric_collector.sql.yml +56 -0
- data/lib/litestack/litequeue.rb +28 -29
- data/lib/litestack/litequeue.sql.yml +11 -0
- data/lib/litestack/litesupport.rb +137 -57
- data/lib/litestack/railtie.rb +10 -0
- data/lib/litestack/version.rb +1 -1
- data/lib/litestack.rb +1 -0
- data/lib/sequel/adapters/litedb.rb +1 -1
- data/template.rb +7 -0
- metadata +81 -5
- data/lib/litestack/metrics_app.rb +0 -5
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
<div class="container">
|
6
|
+
<% @topics.each do |topic|%>
|
7
|
+
|
8
|
+
<div class = "row justify-content-center">
|
9
|
+
|
10
|
+
<div class = "col-6">
|
11
|
+
<div class="card">
|
12
|
+
<div class="card-header">
|
13
|
+
<a href="./topics/<%=encode(topic[0])%>?res=<%=@res%>"><%=topic[0]%></a>
|
14
|
+
</div>
|
15
|
+
<div class="card-body">
|
16
|
+
<div class="container">
|
17
|
+
<div class= "row">
|
18
|
+
<div class= "col">
|
19
|
+
<h1><%=topic[3]%> <span class="fs-4">events</span></h1>
|
20
|
+
</div>
|
21
|
+
<div class= "col">
|
22
|
+
<span class="inlineminicolumn hidden" data-label="Count"><%=Oj.dump(topic[4].unshift(['Time', 'Count'])) if topic[4]%></span>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
</div>
|
31
|
+
|
32
|
+
<div class = "row">
|
33
|
+
<br/>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
|
37
|
+
<%end%>
|
38
|
+
<% if @topics.empty? %>
|
39
|
+
<div class = "row justify-content-center">
|
40
|
+
|
41
|
+
<div class = "col-6">
|
42
|
+
<div class="card">
|
43
|
+
<div class="card-header">
|
44
|
+
Topics
|
45
|
+
</div>
|
46
|
+
<div class="card-body justify-content-center">
|
47
|
+
No data to display
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
|
52
|
+
</div>
|
53
|
+
<%end%>
|
54
|
+
</div>
|
@@ -0,0 +1,303 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<title>liteboard</title>
|
5
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
|
6
|
+
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
|
7
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
|
8
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Antonio">
|
9
|
+
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
10
|
+
<style>
|
11
|
+
body {background-color: #fff}
|
12
|
+
input, select { border-radius: 3px}
|
13
|
+
div#header { width: 100%; border-bottom: 1px solid #089;}
|
14
|
+
div.label {max-width:400px;overflow:hidden}
|
15
|
+
h1 { font-family: antonio }
|
16
|
+
#content{ padding-right: 12px; padding-left: 12px; padding-bottom: 60px;}
|
17
|
+
table.head { margin-top: 12px; margin-bottom:12px}
|
18
|
+
select { color: #078; background-color: #fff; font-weight: normal }
|
19
|
+
.table th { color: #078; font-weight: normal; }
|
20
|
+
.table th.sorted { font-weight: bold }
|
21
|
+
.table td { color: #444; vertical-align:middle; font-size: 18px}
|
22
|
+
.table td:first-child { color: #444; vertical-align:middle; font-size: 15px; font-weight:normal}
|
23
|
+
.table td.empty { text-align:center}
|
24
|
+
a, a.nav-link { color: #078; }
|
25
|
+
.nav-pills .nav-link.active { color: #fff; background-color: #078}
|
26
|
+
a .logo { color: #000;}
|
27
|
+
a:visited { color: #078; }
|
28
|
+
.hidden { display: none}
|
29
|
+
div#search {margin-bottom: 8px}
|
30
|
+
div#footer {position:fixed; left:0px; height: 40px; width:100%; background-color:#0891; border-top: #0893 1px solid; padding: 8px; bottom: 0; text-align: right}
|
31
|
+
.logo{font-family: antonio}
|
32
|
+
.logo-half{ color: #078 }
|
33
|
+
.smaller { font-size: 24px; font-weight: normal}
|
34
|
+
.token {background-color: #ed9}
|
35
|
+
svg > g > g.google-visualization-tooltip { pointer-events : none }
|
36
|
+
.material-icons { vertical-align: middle}
|
37
|
+
</style>
|
38
|
+
</head>
|
39
|
+
<body>
|
40
|
+
<div id="content">
|
41
|
+
<div id="header">
|
42
|
+
<h1><span class="logo"><span class="logo-half">lite</span>board | </span> <span class="logo smaller">the <span class="logo-half">lite</span>metric dashboard</span></span></h1>
|
43
|
+
</div>
|
44
|
+
<div class="container">
|
45
|
+
<div class = "row">
|
46
|
+
<br/>
|
47
|
+
</div>
|
48
|
+
<div class="row">
|
49
|
+
<div class="col">
|
50
|
+
<nav class="navbar bg-body-tertiary">
|
51
|
+
<div> Showing data for the last <select onchange="window.location = locationWithParam('res', this.value)">
|
52
|
+
<%= mapping = {'hour' => '60 minutes', 'day' => '24 hours', 'week' => '7 days', 'year' => '52 weeks'}%>
|
53
|
+
<% ['hour', 'day', 'week', 'year'].each do |res| %>
|
54
|
+
<option value=<%=res%> <%='selected' if res == @res%>><%=mapping[res]%></option>
|
55
|
+
<% end %>
|
56
|
+
</select></div>
|
57
|
+
</nav>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
<div class = "row">
|
61
|
+
<br/>
|
62
|
+
</div>
|
63
|
+
<%= yield %>
|
64
|
+
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<div class="container" style="position: fixed; left:0px; top: 145px">
|
68
|
+
<div class="row justify-content-center">
|
69
|
+
<div class="col">
|
70
|
+
<div class="card" style="width: 15rem;">
|
71
|
+
<div class="card-body">
|
72
|
+
<ul class="nav nav-pills nav-fill flex-column list-group list-group-flush">
|
73
|
+
<li class="list-group-item"><a class="nav-link <%='active' unless @topic%>" href="<%=index_url%>">Home</a></li>
|
74
|
+
<%@topics.each do |topic|%>
|
75
|
+
<li class="list-group-item"><a class="nav-link <%='active' if @topic == topic[0]%>" href="<%=topic_url(topic[0])%>"><%=topic[0]%></a></li>
|
76
|
+
<%end%>
|
77
|
+
</ul>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
</div>
|
81
|
+
</div>
|
82
|
+
</div>
|
83
|
+
|
84
|
+
</div>
|
85
|
+
<div id="footer">
|
86
|
+
Powered by <a href="https://www.github.com/oldmoe/litestack" target="_blank"><span class="logo"><span class="logo-half">lite</span>stack</span></a>
|
87
|
+
</div>
|
88
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
|
89
|
+
</body>
|
90
|
+
<script>
|
91
|
+
google.charts.load('current', {'packages':['corechart', 'bar']});
|
92
|
+
|
93
|
+
google.charts.setOnLoadCallback(drawMiniColumnChart);
|
94
|
+
google.charts.setOnLoadCallback(drawColumnChart);
|
95
|
+
google.charts.setOnLoadCallback(drawPieChart);
|
96
|
+
google.charts.setOnLoadCallback(drawStackedColumnChart);
|
97
|
+
|
98
|
+
|
99
|
+
function drawMiniColumnChart() {
|
100
|
+
elements = document.querySelectorAll(".inlineminicolumn")
|
101
|
+
elements.forEach(element => {
|
102
|
+
var label = element.dataset.label;
|
103
|
+
var mydata = eval(element.innerText)
|
104
|
+
element.innerText = ''
|
105
|
+
element.classList.remove("hidden")
|
106
|
+
if(mydata.length > 1) {
|
107
|
+
mydata.forEach(row => {
|
108
|
+
if(mydata[0].length == 5){ // we are doing custom tooltips
|
109
|
+
if(row[0] != "Time"){
|
110
|
+
row[1] = Number(row[1].toPrecision(4))
|
111
|
+
row[3] = Number(row[2].toPrecision(4))
|
112
|
+
row[2] = row[0]+': '+mydata[0][1]+' '+row[1]
|
113
|
+
row[4] = row[0]+': '+mydata[0][3]+' '+row[3]
|
114
|
+
}
|
115
|
+
}
|
116
|
+
})
|
117
|
+
var data = google.visualization.arrayToDataTable(
|
118
|
+
mydata
|
119
|
+
)
|
120
|
+
var options = {
|
121
|
+
animation: {'startup': true, 'duration': 300},
|
122
|
+
width: 300,
|
123
|
+
height: 70,
|
124
|
+
chartArea: {width:'100%', height: '100%'},
|
125
|
+
backgroundColor: 'none',
|
126
|
+
bar: {groupWidth: "61.8%"},
|
127
|
+
colors : ['#089', 'silver' ],
|
128
|
+
vAxis: {'gridlines': {'count' : 0}, 'textPosition' : 'none', 'baselineColor' : 'none'},
|
129
|
+
hAxis: { 'count' : 0, 'textPosition' : 'none', 'baselineColor' : 'none'},
|
130
|
+
legend: {'position': 'none'},
|
131
|
+
tooltip: {showColorCode: true, isHtml: true},
|
132
|
+
isStacked: true
|
133
|
+
}
|
134
|
+
var chart = new google.visualization.ColumnChart(element);
|
135
|
+
chart.draw(data, options);
|
136
|
+
}
|
137
|
+
})
|
138
|
+
}
|
139
|
+
|
140
|
+
function drawColumnChart() {
|
141
|
+
elements = document.querySelectorAll(".inlinecolumn")
|
142
|
+
elements.forEach(element => {
|
143
|
+
var label = element.dataset.label;
|
144
|
+
var mydata = eval(element.innerText)
|
145
|
+
element.innerText = ''
|
146
|
+
element.classList.remove("hidden")
|
147
|
+
if(mydata.length > 1) {
|
148
|
+
mydata.forEach(row => {
|
149
|
+
if(mydata[0].length == 5){ // we are doing custom tooltips
|
150
|
+
if(row[0] != "Time"){
|
151
|
+
row[1] = Number(row[1].toPrecision(4))
|
152
|
+
row[3] = Number(row[2].toPrecision(4))
|
153
|
+
row[2] = row[0]+': '+mydata[0][1]+' '+row[1]
|
154
|
+
row[4] = row[0]+': '+mydata[0][3]+' '+row[3]
|
155
|
+
}
|
156
|
+
}
|
157
|
+
})
|
158
|
+
var data = google.visualization.arrayToDataTable(
|
159
|
+
mydata
|
160
|
+
)
|
161
|
+
var options = {
|
162
|
+
animation: {'startup': true, 'duration': 300},
|
163
|
+
width: 550,
|
164
|
+
height: 350,
|
165
|
+
chartArea: {width:'100%', height: '80%'},
|
166
|
+
backgroundColor: 'none',
|
167
|
+
bar: {groupWidth: "61.8%"},
|
168
|
+
colors : ['#089', 'silver' ],
|
169
|
+
vAxis: {'gridlines': {'count' : 0}, 'textPosition' : 'none', 'baselineColor' : 'none'},
|
170
|
+
hAxis: { 'count' : 0, 'textPosition' : 'none', 'baselineColor' : 'none'},
|
171
|
+
legend: {'position': 'bottom'},
|
172
|
+
tooltip: {showColorCode: true, isHtml: true},
|
173
|
+
isStacked: true
|
174
|
+
}
|
175
|
+
var chart = new google.visualization.ColumnChart(element);
|
176
|
+
chart.draw(data, options);
|
177
|
+
}
|
178
|
+
})
|
179
|
+
}
|
180
|
+
|
181
|
+
function drawPieChart() {
|
182
|
+
elements = document.querySelectorAll(".inlinepie")
|
183
|
+
elements.forEach(element => {
|
184
|
+
var label = element.dataset.label;
|
185
|
+
var mydata = eval(element.innerText)
|
186
|
+
element.innerText = ''
|
187
|
+
element.classList.remove("hidden")
|
188
|
+
if(mydata.length >= 2) {
|
189
|
+
var data = google.visualization.arrayToDataTable(
|
190
|
+
mydata
|
191
|
+
)
|
192
|
+
var options = {
|
193
|
+
animation: {'startup': true, 'duration': 300},
|
194
|
+
annotations: {textStyle: {bold: true}, alwaysOutside: false },
|
195
|
+
width: 600,
|
196
|
+
height: 350,
|
197
|
+
backgroundColor: 'none',
|
198
|
+
bar: {groupWidth: "80%"},
|
199
|
+
colors : ['#089', 'silver', '#545B77' ],
|
200
|
+
axisTitlesPosition: 'none',
|
201
|
+
chartArea: {width:'90%', height: '85%'},
|
202
|
+
tooltip : {showColorCode: true},
|
203
|
+
vAxis: {gridlines: {count : 0}, textPosition : 'in', baselineColor : 'none', textStyle: {color: '#089', bold: true} },
|
204
|
+
hAxis: {gridlines: {count : 0}, textPosition : 'none', baselineColor : 'none'},
|
205
|
+
legend: {'position': 'bottom'},
|
206
|
+
isStacked: true,
|
207
|
+
bars: 'horizontal'
|
208
|
+
}
|
209
|
+
var chart = new google.visualization.PieChart(element);
|
210
|
+
if(mydata[1][1] == 0 && mydata[2][1] == 0){
|
211
|
+
return 0
|
212
|
+
}
|
213
|
+
chart.draw(data, options);
|
214
|
+
}
|
215
|
+
})
|
216
|
+
}
|
217
|
+
|
218
|
+
|
219
|
+
function drawStackedColumnChart() {
|
220
|
+
elements = document.querySelectorAll(".inlinestackedcolumn")
|
221
|
+
elements.forEach(element => {
|
222
|
+
var label = element.dataset.label;
|
223
|
+
var mydata = eval(element.innerText)
|
224
|
+
element.innerText = ''
|
225
|
+
element.classList.remove("hidden")
|
226
|
+
if(mydata.length > 1) {
|
227
|
+
console.log(mydata)
|
228
|
+
var data = google.visualization.arrayToDataTable(
|
229
|
+
mydata
|
230
|
+
)
|
231
|
+
var options = {
|
232
|
+
animation: {'startup': true, 'duration': 300},
|
233
|
+
annotations: {textStyle: {bold: true}, alwaysOutside: false },
|
234
|
+
width: 600,
|
235
|
+
height: 350,
|
236
|
+
backgroundColor: 'none',
|
237
|
+
bar: {groupWidth: "80%"},
|
238
|
+
colors : [ '#089', 'silver', '#545B77', 'silver'],
|
239
|
+
axisTitlesPosition: 'none',
|
240
|
+
chartArea: {width:'100%', height: '85%'},
|
241
|
+
tooltip : {showColorCode: true},
|
242
|
+
vAxis: {gridlines: {count : 0}, textPosition : 'none', baselineColor : 'none', textStyle: {color: '#089', bold: true} },
|
243
|
+
hAxis: {gridlines: {count : 0}, textPosition : 'none', baselineColor : 'none'},
|
244
|
+
legend: {'position': 'bottom'},
|
245
|
+
isStacked: true,
|
246
|
+
bars: 'horizontal'
|
247
|
+
}
|
248
|
+
var chart = new google.visualization.AreaChart(element);
|
249
|
+
chart.draw(data, options);
|
250
|
+
}
|
251
|
+
})
|
252
|
+
}
|
253
|
+
|
254
|
+
|
255
|
+
function search_kd(el){
|
256
|
+
//store the current value
|
257
|
+
el.oldvalue = el.value
|
258
|
+
}
|
259
|
+
function search_ku(el){
|
260
|
+
//check if the value has changed and if so
|
261
|
+
// set a new timer to fire a request in 300ms
|
262
|
+
// removing any existing timer first
|
263
|
+
if(el.value == el.oldvalue){
|
264
|
+
return
|
265
|
+
}else{
|
266
|
+
el.oldvalue = null
|
267
|
+
}
|
268
|
+
if(el.timeout){
|
269
|
+
window.clearTimeout(el.timeout)
|
270
|
+
}
|
271
|
+
el.timeout = window.setTimeout(function(){
|
272
|
+
el.timeout = null
|
273
|
+
window.location = locationWithParam('search', el.value)
|
274
|
+
}, 500)
|
275
|
+
}
|
276
|
+
|
277
|
+
$(document).ready(function(){
|
278
|
+
/*
|
279
|
+
el = $('#search-field')[0]
|
280
|
+
el.focus()
|
281
|
+
if(el.value && el.value.length > 0){
|
282
|
+
el.setSelectionRange(el.value.length, el.value.length)
|
283
|
+
var list = $("table.sortable div.label") //[0].children[0].children
|
284
|
+
for(var i=0; i < list.length; i++){
|
285
|
+
//console.log(list[i])
|
286
|
+
var link = list[i].children[0] //.children[0].children[0]
|
287
|
+
var re = new RegExp("("+el.value+")", "giu")
|
288
|
+
link.innerHTML = link.innerHTML.replaceAll(re, "<span class='token'>$1</span>") ;
|
289
|
+
}
|
290
|
+
}
|
291
|
+
*/
|
292
|
+
})
|
293
|
+
|
294
|
+
function locationWithParam(param, value){
|
295
|
+
var query = window.location.search
|
296
|
+
var params = new URLSearchParams(query)
|
297
|
+
params.set(param, value)
|
298
|
+
var l = window.location
|
299
|
+
return l.origin + l.pathname + '?' + params.toString()
|
300
|
+
}
|
301
|
+
</script>
|
302
|
+
</html>
|
303
|
+
|
@@ -0,0 +1,118 @@
|
|
1
|
+
<div class = "row">
|
2
|
+
|
3
|
+
<div class = "col">
|
4
|
+
<div class="card">
|
5
|
+
<div class="card-header">
|
6
|
+
Subscriptions
|
7
|
+
</div>
|
8
|
+
<div class="card-body">
|
9
|
+
<h1><%=format(@subscription_count)%></h1>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class = "col">
|
15
|
+
<div class="card">
|
16
|
+
<div class="card-header">
|
17
|
+
Messages Received
|
18
|
+
</div>
|
19
|
+
<div class="card-body">
|
20
|
+
<h1><%=format(@broadcast_count)%></h1>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div class = "col">
|
26
|
+
<div class="card">
|
27
|
+
<div class="card-header">
|
28
|
+
Messages delivered
|
29
|
+
</div>
|
30
|
+
<div class="card-body">
|
31
|
+
<h1><%=format(@message_count)%></h1>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<div class = "row">
|
39
|
+
<br/>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
<div class="row">
|
43
|
+
|
44
|
+
<div class = "col">
|
45
|
+
<div class="card">
|
46
|
+
<div class="card-header">
|
47
|
+
Subscriptions over time
|
48
|
+
</div>
|
49
|
+
<div class="card-body">
|
50
|
+
<span class="hidden inlinecolumn">
|
51
|
+
<%=[["Time", "Count"]] + @subscriptions_over_time.to_a%>
|
52
|
+
</span>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
|
57
|
+
<div class = "col">
|
58
|
+
<div class="card">
|
59
|
+
<div class="card-header">
|
60
|
+
Messages received/delivered over time
|
61
|
+
</div>
|
62
|
+
<div class="card-body">
|
63
|
+
<span class="hidden inlinestackedcolumn">
|
64
|
+
<%=[["Time", "Recieved Count", "Delivered Count"]] + @messages_over_time.to_a%>
|
65
|
+
</span>
|
66
|
+
</div>
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
|
70
|
+
</div>
|
71
|
+
|
72
|
+
<div class = "row">
|
73
|
+
<br/>
|
74
|
+
</div>
|
75
|
+
|
76
|
+
<div class = "row">
|
77
|
+
|
78
|
+
<div class = "col-6">
|
79
|
+
<div class="card">
|
80
|
+
<div class="card-header">
|
81
|
+
Channels with most subscriptions
|
82
|
+
</div>
|
83
|
+
<div class="card-body">
|
84
|
+
<table class="table">
|
85
|
+
<%@top_subscribed_channels.each do |r| %>
|
86
|
+
<tr>
|
87
|
+
<td><%=r['key']%></td>
|
88
|
+
<td align="right"><h6><%=format(r['rcount'])%> subs</h6></td>
|
89
|
+
</tr>
|
90
|
+
<% end %>
|
91
|
+
</table>
|
92
|
+
</div>
|
93
|
+
</div>
|
94
|
+
</div>
|
95
|
+
|
96
|
+
<div class = "col-6">
|
97
|
+
<div class="card">
|
98
|
+
<div class="card-header">
|
99
|
+
Channels with most messages delivered
|
100
|
+
</div>
|
101
|
+
<div class="card-body">
|
102
|
+
<table class="table">
|
103
|
+
<%@top_messaged_channels.each do |r| %>
|
104
|
+
<tr>
|
105
|
+
<td><%=r['key']%></td>
|
106
|
+
<td align="right"><h6><%=format(r['rcount'])%> messages</h6></td>
|
107
|
+
</tr>
|
108
|
+
<% end %>
|
109
|
+
</table>
|
110
|
+
</div>
|
111
|
+
</div>
|
112
|
+
</div>
|
113
|
+
|
114
|
+
</div>
|
115
|
+
|
116
|
+
<div class = "row">
|
117
|
+
<br/>
|
118
|
+
</div>
|
@@ -0,0 +1,144 @@
|
|
1
|
+
|
2
|
+
<div class = "row">
|
3
|
+
|
4
|
+
<div class = "col">
|
5
|
+
<div class="card">
|
6
|
+
<div class="card-header">
|
7
|
+
Current size / Max size
|
8
|
+
</div>
|
9
|
+
<div class="card-body">
|
10
|
+
<h1><%=format(round(@size))%>MB / <%=format(round(@max_size))%>MB <span class="fs-4"><%=round(@full)%>% full</span></h1>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class = "col">
|
16
|
+
<div class="card">
|
17
|
+
<div class="card-header">
|
18
|
+
Number of entries
|
19
|
+
</div>
|
20
|
+
<div class="card-body">
|
21
|
+
<h1><%=format(@entries)%></h1>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<div class = "row">
|
29
|
+
<br/>
|
30
|
+
</div>
|
31
|
+
|
32
|
+
<div class = "row">
|
33
|
+
|
34
|
+
<div class = "col">
|
35
|
+
<div class="card">
|
36
|
+
<div class="card-header">
|
37
|
+
Reads / Writes
|
38
|
+
</div>
|
39
|
+
<div class="card-body">
|
40
|
+
<h1><%=format(@reads)%> / <%=format(@writes)%> <span class="fs-4"><%=round(@reads.to_f/@writes) rescue 0%> reads/write</span></h1>
|
41
|
+
<hr/>
|
42
|
+
<span class="hidden inlinepie"><%=[["name", "value"],["reads", @reads],["writes", @writes]]%></span>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<div class = "col">
|
48
|
+
<div class="card">
|
49
|
+
<div class="card-header">
|
50
|
+
Read hits / Misses
|
51
|
+
</div>
|
52
|
+
<div class="card-body">
|
53
|
+
<h1><%=format(@hits)%> / <%=format(@misses)%> <span class="fs-4"><%=round(@hitrate*100)%>% hit rate</span></h1>
|
54
|
+
<hr/>
|
55
|
+
<span class="hidden inlinepie"><%=[["name", "value"],["hits", @hits],["misses", @misses]]%></span>
|
56
|
+
</div>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div class = "row">
|
63
|
+
<br/>
|
64
|
+
</div>
|
65
|
+
|
66
|
+
<div class = "row">
|
67
|
+
|
68
|
+
<div class = "col">
|
69
|
+
<div class="card">
|
70
|
+
<div class="card-header">
|
71
|
+
Reads, writes over time
|
72
|
+
</div>
|
73
|
+
<div class="card-body">
|
74
|
+
<div class="hidden inlinecolumn">
|
75
|
+
<%=Oj.dump([["Time", "Reads", "Writes"]] + @reads_vs_writes)%>
|
76
|
+
</div>
|
77
|
+
</div>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<div class = "col">
|
82
|
+
<div class="card">
|
83
|
+
<div class="card-header">
|
84
|
+
Hits vs misses over time
|
85
|
+
</div>
|
86
|
+
<div class="card-body">
|
87
|
+
<span class="hidden inlinecolumn">
|
88
|
+
<%=Oj.dump([["Time", "Hits", "Misses"]] + @hits_vs_misses)%>
|
89
|
+
</span>
|
90
|
+
</div>
|
91
|
+
</div>
|
92
|
+
</div>
|
93
|
+
|
94
|
+
</div>
|
95
|
+
|
96
|
+
<div class = "row">
|
97
|
+
<br/>
|
98
|
+
</div>
|
99
|
+
|
100
|
+
<div class = "row">
|
101
|
+
|
102
|
+
<div class = "col">
|
103
|
+
<div class="card">
|
104
|
+
<div class="card-header">
|
105
|
+
Most read entries
|
106
|
+
</div>
|
107
|
+
<div class="card-body">
|
108
|
+
<table class="table">
|
109
|
+
<%@top_reads.each do |r| %>
|
110
|
+
<tr>
|
111
|
+
<td><%=r['key']%></td>
|
112
|
+
<td align="right"><h5><%=format(r['rcount'])%></h5></td>
|
113
|
+
</tr>
|
114
|
+
<% end %>
|
115
|
+
</table>
|
116
|
+
</div>
|
117
|
+
</div>
|
118
|
+
</div>
|
119
|
+
|
120
|
+
<div class = "col">
|
121
|
+
<div class="card">
|
122
|
+
<div class="card-header">
|
123
|
+
Most written entries
|
124
|
+
</div>
|
125
|
+
<div class="card-body">
|
126
|
+
<table class="table">
|
127
|
+
<%@top_writes.each do |r| %>
|
128
|
+
<tr>
|
129
|
+
<td><%=r['key']%></td>
|
130
|
+
<td align="right"><h5><%=format(r['rcount'])%></h5></td>
|
131
|
+
</tr>
|
132
|
+
<% end %>
|
133
|
+
</table>
|
134
|
+
</div>
|
135
|
+
</div>
|
136
|
+
</div>
|
137
|
+
|
138
|
+
</div>
|
139
|
+
|
140
|
+
<div class = "row">
|
141
|
+
<br/>
|
142
|
+
</div>
|
143
|
+
|
144
|
+
|