litestack 0.2.6 → 0.4.1
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/BENCHMARKS.md +11 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- 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/bench/uljob.rb +1 -1
- data/lib/action_cable/subscription_adapter/litecable.rb +1 -11
- data/lib/active_support/cache/litecache.rb +1 -1
- data/lib/generators/litestack/install/templates/database.yml +5 -1
- data/lib/litestack/liteboard/liteboard.rb +172 -35
- data/lib/litestack/liteboard/views/index.erb +52 -20
- data/lib/litestack/liteboard/views/layout.erb +189 -38
- 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/litecable.rb +27 -37
- data/lib/litestack/litecable.sql.yml +1 -1
- data/lib/litestack/litecache.rb +7 -18
- data/lib/litestack/litedb.rb +17 -2
- data/lib/litestack/litejob.rb +2 -3
- data/lib/litestack/litejobqueue.rb +51 -48
- data/lib/litestack/litemetric.rb +46 -69
- data/lib/litestack/litemetric.sql.yml +14 -12
- data/lib/litestack/litemetric_collector.sql.yml +4 -4
- data/lib/litestack/litequeue.rb +9 -20
- data/lib/litestack/litescheduler.rb +84 -0
- data/lib/litestack/litesearch/index.rb +230 -0
- data/lib/litestack/litesearch/model.rb +178 -0
- data/lib/litestack/litesearch/schema.rb +193 -0
- data/lib/litestack/litesearch/schema_adapters/backed_adapter.rb +147 -0
- data/lib/litestack/litesearch/schema_adapters/basic_adapter.rb +128 -0
- data/lib/litestack/litesearch/schema_adapters/contentless_adapter.rb +17 -0
- data/lib/litestack/litesearch/schema_adapters/standalone_adapter.rb +33 -0
- data/lib/litestack/litesearch/schema_adapters.rb +9 -0
- data/lib/litestack/litesearch.rb +37 -0
- data/lib/litestack/litesupport.rb +55 -125
- data/lib/litestack/version.rb +1 -1
- data/lib/litestack.rb +2 -1
- data/lib/sequel/adapters/litedb.rb +3 -2
- metadata +20 -3
@@ -15,17 +15,17 @@
|
|
15
15
|
h1 { font-family: antonio }
|
16
16
|
#content{ padding-right: 12px; padding-left: 12px; padding-bottom: 60px;}
|
17
17
|
table.head { margin-top: 12px; margin-bottom:12px}
|
18
|
-
|
18
|
+
select { color: #078; background-color: #fff; font-weight: normal }
|
19
19
|
.table th { color: #078; font-weight: normal; }
|
20
20
|
.table th.sorted { font-weight: bold }
|
21
21
|
.table td { color: #444; vertical-align:middle; font-size: 18px}
|
22
22
|
.table td:first-child { color: #444; vertical-align:middle; font-size: 15px; font-weight:normal}
|
23
23
|
.table td.empty { text-align:center}
|
24
|
-
a { color: #078; }
|
24
|
+
a, a.nav-link { color: #078; }
|
25
|
+
.nav-pills .nav-link.active { color: #fff; background-color: #078}
|
25
26
|
a .logo { color: #000;}
|
26
27
|
a:visited { color: #078; }
|
27
|
-
|
28
|
-
span.hidden { display: none}
|
28
|
+
.hidden { display: none}
|
29
29
|
div#search {margin-bottom: 8px}
|
30
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
31
|
.logo{font-family: antonio}
|
@@ -41,23 +41,46 @@
|
|
41
41
|
<div id="header">
|
42
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
43
|
</div>
|
44
|
-
<
|
45
|
-
<
|
46
|
-
|
47
|
-
|
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)">
|
48
52
|
<%= mapping = {'hour' => '60 minutes', 'day' => '24 hours', 'week' => '7 days', 'year' => '52 weeks'}%>
|
49
53
|
<% ['hour', 'day', 'week', 'year'].each do |res| %>
|
50
54
|
<option value=<%=res%> <%='selected' if res == @res%>><%=mapping[res]%></option>
|
51
55
|
<% end %>
|
52
|
-
</select>
|
53
|
-
|
54
|
-
|
55
|
-
</
|
56
|
-
<
|
57
|
-
|
58
|
-
</
|
59
|
-
</table>
|
56
|
+
</select></div>
|
57
|
+
</nav>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
<div class = "row">
|
61
|
+
<br/>
|
62
|
+
</div>
|
60
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
|
+
|
61
84
|
</div>
|
62
85
|
<div id="footer">
|
63
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>
|
@@ -65,44 +88,170 @@
|
|
65
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>
|
66
89
|
</body>
|
67
90
|
<script>
|
68
|
-
google.charts.load('current', {'packages':['corechart']});
|
91
|
+
google.charts.load('current', {'packages':['corechart', 'bar']});
|
69
92
|
|
70
|
-
google.charts.setOnLoadCallback(
|
93
|
+
google.charts.setOnLoadCallback(drawMiniColumnChart);
|
94
|
+
google.charts.setOnLoadCallback(drawColumnChart);
|
95
|
+
google.charts.setOnLoadCallback(drawPieChart);
|
96
|
+
google.charts.setOnLoadCallback(drawStackedColumnChart);
|
71
97
|
|
72
|
-
|
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() {
|
73
141
|
elements = document.querySelectorAll(".inlinecolumn")
|
74
142
|
elements.forEach(element => {
|
75
|
-
//console.log(element)
|
76
143
|
var label = element.dataset.label;
|
77
144
|
var mydata = eval(element.innerText)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
data.addColumn('string', 'Time');
|
83
|
-
data.addColumn('number', label);
|
145
|
+
element.innerText = ''
|
146
|
+
element.classList.remove("hidden")
|
147
|
+
if(mydata.length > 1) {
|
84
148
|
mydata.forEach(row => {
|
85
|
-
|
86
|
-
|
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
|
+
}
|
87
157
|
})
|
88
|
-
|
158
|
+
var data = google.visualization.arrayToDataTable(
|
159
|
+
mydata
|
160
|
+
)
|
89
161
|
var options = {
|
90
162
|
animation: {'startup': true, 'duration': 300},
|
91
|
-
width:
|
92
|
-
height:
|
163
|
+
width: 550,
|
164
|
+
height: 350,
|
165
|
+
chartArea: {width:'100%', height: '80%'},
|
93
166
|
backgroundColor: 'none',
|
94
|
-
|
95
|
-
colors : ['#089'],
|
96
|
-
vAxis: {'gridlines': {'count' : 0}, 'textPosition' : 'none', 'baselineColor' : 'none'
|
167
|
+
bar: {groupWidth: "61.8%"},
|
168
|
+
colors : ['#089', 'silver' ],
|
169
|
+
vAxis: {'gridlines': {'count' : 0}, 'textPosition' : 'none', 'baselineColor' : 'none'},
|
97
170
|
hAxis: { 'count' : 0, 'textPosition' : 'none', 'baselineColor' : 'none'},
|
98
|
-
legend: {'position': '
|
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'
|
99
247
|
}
|
100
248
|
var chart = new google.visualization.AreaChart(element);
|
101
249
|
chart.draw(data, options);
|
102
|
-
element.classList.remove("hidden")
|
103
250
|
}
|
104
251
|
})
|
105
252
|
}
|
253
|
+
|
254
|
+
|
106
255
|
function search_kd(el){
|
107
256
|
//store the current value
|
108
257
|
el.oldvalue = el.value
|
@@ -122,10 +271,11 @@
|
|
122
271
|
el.timeout = window.setTimeout(function(){
|
123
272
|
el.timeout = null
|
124
273
|
window.location = locationWithParam('search', el.value)
|
125
|
-
},
|
274
|
+
}, 500)
|
126
275
|
}
|
127
276
|
|
128
277
|
$(document).ready(function(){
|
278
|
+
/*
|
129
279
|
el = $('#search-field')[0]
|
130
280
|
el.focus()
|
131
281
|
if(el.value && el.value.length > 0){
|
@@ -137,7 +287,8 @@
|
|
137
287
|
var re = new RegExp("("+el.value+")", "giu")
|
138
288
|
link.innerHTML = link.innerHTML.replaceAll(re, "<span class='token'>$1</span>") ;
|
139
289
|
}
|
140
|
-
}
|
290
|
+
}
|
291
|
+
*/
|
141
292
|
})
|
142
293
|
|
143
294
|
function locationWithParam(param, value){
|
@@ -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
|
+
|