UNPKG

11.7 kBHTMLView Raw
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Radi.js - DBMonster</title>
8 <link rel="stylesheet" href="assets/bootstrap.min.css">
9 <style>
10
11 table {
12 font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
13 font-size: 14px;
14 line-height: 1.42857143;
15 color: #333;
16 background-color: #fff;
17 }
18
19 #link {
20 position: fixed;
21 top: 0; right: 0;
22 font-size: 12px;
23 padding: 5px 10px;
24 background: rgba(255,255,255,0.85);
25 z-index: 5;
26 box-shadow: 0 0 8px rgba(0,0,0,0.6);
27 }
28 #link .center {
29 display: block;
30 text-align: center;
31 }
32
33 .Query {
34 position: relative;
35 }
36
37 .Query:hover .popover {
38 left: -100%;
39 width: 100%;
40 display: block;
41 }
42 </style>
43</head>
44<body>
45 <div id="app"></div>
46 <script>
47
48 var Monitoring = Monitoring || (function() {
49
50 var RenderRate = function () {
51 var container = document.createElement( 'div' );
52 container.id = 'stats';
53 container.style.cssText = 'width:150px;opacity:0.9;cursor:pointer;position:fixed;right:80px;bottom:0px;';
54
55 var msDiv = document.createElement( 'div' );
56 msDiv.id = 'ms';
57 msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';
58 container.appendChild( msDiv );
59
60 var msText = document.createElement( 'div' );
61 msText.id = 'msText';
62 msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
63 msText.innerHTML= 'Repaint rate: 0/sec';
64 msDiv.appendChild( msText );
65
66 var self = this;
67 var rate = 0;
68 var bucketSize = 20;
69 var bucket = [];
70 var lastTime = Date.now();
71 return {
72 domElement: container,
73 ping: function () {
74 var start = lastTime;
75 var stop = Date.now();
76 var rate = 1000 / (stop - start);
77 if (rate == Infinity) {
78 return;
79 }
80 bucket.push(rate);
81 if (bucket.length > bucketSize) {
82 bucket.shift();
83 }
84 var sum = 0;
85 for (var i = 0; i < bucket.length; i++) {
86 sum = sum + bucket[i];
87 }
88 self.rate = (sum / bucket.length);
89 msText.textContent = "Repaint rate: " + self.rate.toFixed(2) + "/sec";
90 lastTime = stop;
91 },
92 rate: function () {
93 return self.rate;
94 }
95 }
96 };
97
98 var renderRate = new RenderRate();
99 document.body.appendChild( renderRate.domElement );
100
101 return {
102 memoryStats: stats,
103 renderRate: renderRate
104 };
105
106 })();
107
108 var ENV = ENV || (function() {
109
110 var first = true;
111 var counter = 0;
112 var data;
113 var _base;
114 (_base = String.prototype).lpad || (_base.lpad = function(padding, toLength) {
115 return padding.repeat((toLength - this.length) / padding.length).concat(this);
116 });
117
118 function formatElapsed(value) {
119 var str = parseFloat(value).toFixed(2);
120 if (value > 60) {
121 minutes = Math.floor(value / 60);
122 comps = (value % 60).toFixed(2).split('.');
123 seconds = comps[0].lpad('0', 2);
124 ms = comps[1];
125 str = minutes + ":" + seconds + "." + ms;
126 }
127 return str;
128 }
129
130 function getElapsedClassName(elapsed) {
131 var className = 'Query elapsed';
132 if (elapsed >= 10.0) {
133 className += ' warn_long';
134 }
135 else if (elapsed >= 1.0) {
136 className += ' warn';
137 }
138 else {
139 className += ' short';
140 }
141 return className;
142 }
143
144 function countClassName(queries) {
145 var countClassName = "label";
146 if (queries >= 20) {
147 countClassName += " label-important";
148 }
149 else if (queries >= 10) {
150 countClassName += " label-warning";
151 }
152 else {
153 countClassName += " label-success";
154 }
155 return countClassName;
156 }
157
158 function updateQuery(object) {
159 if (!object) {
160 object = {};
161 }
162 var elapsed = Math.random() * 15;
163 object.elapsed = elapsed;
164 object.formatElapsed = formatElapsed(elapsed);
165 object.elapsedClassName = getElapsedClassName(elapsed);
166 object.query = "SELECT blah FROM something";
167 object.waiting = Math.random() < 0.5;
168 if (Math.random() < 0.2) {
169 object.query = "<IDLE> in transaction";
170 }
171 if (Math.random() < 0.1) {
172 object.query = "vacuum";
173 }
174 return object;
175 }
176
177 function cleanQuery(value) {
178 if (value) {
179 value.formatElapsed = "";
180 value.elapsedClassName = "";
181 value.query = "";
182 value.elapsed = null;
183 value.waiting = null;
184 } else {
185 return {
186 query: "***",
187 formatElapsed: "",
188 elapsedClassName: ""
189 };
190 }
191 }
192
193 function generateRow(object, keepIdentity, counter) {
194 var nbQueries = Math.floor((Math.random() * 10) + 1);
195 if (!object) {
196 object = {};
197 }
198 object.lastMutationId = counter;
199 object.nbQueries = nbQueries;
200 if (!object.lastSample) {
201 object.lastSample = {};
202 }
203 if (!object.lastSample.topFiveQueries) {
204 object.lastSample.topFiveQueries = [];
205 }
206 if (keepIdentity) {
207 // for Angular optimization
208 if (!object.lastSample.queries) {
209 object.lastSample.queries = [];
210 for (var l = 0; l < 12; l++) {
211 object.lastSample.queries[l] = cleanQuery();
212 }
213 }
214 for (var j in object.lastSample.queries) {
215 var value = object.lastSample.queries[j];
216 if (j <= nbQueries) {
217 updateQuery(value);
218 } else {
219 cleanQuery(value);
220 }
221 }
222 } else {
223 object.lastSample.queries = [];
224 for (var j = 0; j < 12; j++) {
225 if (j < nbQueries) {
226 var value = updateQuery(cleanQuery());
227 object.lastSample.queries.push(value);
228 } else {
229 object.lastSample.queries.push(cleanQuery());
230 }
231 }
232 }
233 for (var i = 0; i < 5; i++) {
234 var source = object.lastSample.queries[i];
235 object.lastSample.topFiveQueries[i] = source;
236 }
237 object.lastSample.nbQueries = nbQueries;
238 object.lastSample.countClassName = countClassName(nbQueries);
239 return object;
240 }
241
242 function getData(keepIdentity) {
243 var oldData = data;
244 if (!keepIdentity) { // reset for each tick when !keepIdentity
245 data = [];
246 for (var i = 1; i <= ENV.rows; i++) {
247 data.push({ dbname: 'cluster' + i, query: "", formatElapsed: "", elapsedClassName: "" });
248 data.push({ dbname: 'cluster' + i + ' slave', query: "", formatElapsed: "", elapsedClassName: "" });
249 }
250 }
251 if (!data) { // first init when keepIdentity
252 data = [];
253 for (var i = 1; i <= ENV.rows; i++) {
254 data.push({ dbname: 'cluster' + i });
255 data.push({ dbname: 'cluster' + i + ' slave' });
256 }
257 oldData = data;
258 }
259 for (var i in data) {
260 var row = data[i];
261 if (!keepIdentity && oldData && oldData[i]) {
262 row.lastSample = oldData[i].lastSample;
263 }
264 if (!row.lastSample || Math.random() < ENV.mutations()) {
265 counter = counter + 1;
266 if (!keepIdentity) {
267 row.lastSample = null;
268 }
269 generateRow(row, keepIdentity, counter);
270 } else {
271 data[i] = oldData[i];
272 }
273 }
274 first = false;
275 return {
276 toArray: function() {
277 return data;
278 }
279 };
280 }
281
282 var mutationsValue = 0.5;
283
284 function mutations(value) {
285 if (value) {
286 mutationsValue = value;
287 document.querySelector('#ratioval').innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';
288 return mutationsValue;
289 } else {
290 return mutationsValue;
291 }
292 }
293
294 var body = document.querySelector('body');
295 var theFirstChild = body.firstChild;
296
297 var sliderContainer = document.createElement('div');
298 sliderContainer.style.cssText = "display: flex";
299 var slider = document.createElement('input');
300 var text = document.createElement('label');
301 text.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';
302 text.id = "ratioval";
303 slider.setAttribute("type", "range");
304 slider.style.cssText = 'margin-bottom: 10px; margin-top: 5px';
305 slider.addEventListener('change', function(e) {
306 ENV.mutations(e.target.value / 100);
307 });
308 sliderContainer.appendChild(text);
309 sliderContainer.appendChild(slider);
310 body.insertBefore(sliderContainer, theFirstChild);
311
312 return {
313 generateData: getData,
314 rows: 50,
315 timeout: 0,
316 mutations: mutations
317 };
318 })();
319 </script>
320 <script src="http://mathieuancelin.github.io/js-repaint-perfs/lib/memory-stats.js"></script>
321 <script src="http://mathieuancelin.github.io/js-repaint-perfs/lib/monitor.js"></script>
322 <script src="../../dist/radi.js"></script>
323 <!-- <script src="../../src/devtools.js"></script> -->
324 <script>
325 const { r, l, component, mount } = radi;
326
327 var raf = requestAnimationFrame
328 || msRequestAnimationFrame
329 || mozRequestAnimationFrame
330 || webkitRequestAnimationFrame
331 || oRequestAnimationFrame
332 || setTimeout;
333
334 const main = component({
335 view: function () {
336 return r('table',
337 { class: 'table table-striped latest-data' },
338 r('tbody',
339 list(l(this.dbs), (db, i) => {
340 return r('tr',
341 r('td',
342 { class: 'dbname' },
343 db.dbname
344 ),
345 r('td',
346 { class: 'query-count' },
347 r('span',
348 {
349 class: l(db.lastSample.countClassName)
350 },
351 l(db.nbQueries)
352 )
353 ),
354 list(l(db.lastSample.topFiveQueries), (q, i) => {
355 return r('td',
356 {
357 class: l('Query ' + q.elapsedClassName)
358 },
359 l(q.formatElapsed),
360 r('div',
361 { class: 'popover left' },
362 r('div',
363 { class: 'popover-content' },
364 l(q.query)
365 ),
366 r('div', { class: 'arrow' })
367 )
368 )
369 })
370 );
371 })
372 )
373 );
374 },
375 state: {
376 dbs: []
377 },
378 actions: {
379 onMount() {
380 this.dbs = [];
381 this.load()
382 },
383 load() {
384 this.dbs = ENV.generateData(true).toArray();
385 Monitoring.renderRate.ping();
386 setTimeout(this.load, ENV.timeout);
387 }
388 }
389 });
390
391 mount(new main(), 'app');
392 </script>
393</body>
394</html>