radi
Version:
**Radi** is a tiny javascript framework.
395 lines (365 loc) • 11.7 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Radi.js - DBMonster</title>
<link rel="stylesheet" href="assets/bootstrap.min.css">
<style>
table {
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 14px;
line-height: 1.42857143;
color: #333;
background-color: #fff;
}
#link {
position: fixed;
top: 0; right: 0;
font-size: 12px;
padding: 5px 10px;
background: rgba(255,255,255,0.85);
z-index: 5;
box-shadow: 0 0 8px rgba(0,0,0,0.6);
}
#link .center {
display: block;
text-align: center;
}
.Query {
position: relative;
}
.Query:hover .popover {
left: -100%;
width: 100%;
display: block;
}
</style>
</head>
<body>
<div id="app"></div>
<script>
var Monitoring = Monitoring || (function() {
var RenderRate = function () {
var container = document.createElement( 'div' );
container.id = 'stats';
container.style.cssText = 'width:150px;opacity:0.9;cursor:pointer;position:fixed;right:80px;bottom:0px;';
var msDiv = document.createElement( 'div' );
msDiv.id = 'ms';
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';
container.appendChild( msDiv );
var msText = document.createElement( 'div' );
msText.id = 'msText';
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
msText.innerHTML= 'Repaint rate: 0/sec';
msDiv.appendChild( msText );
var self = this;
var rate = 0;
var bucketSize = 20;
var bucket = [];
var lastTime = Date.now();
return {
domElement: container,
ping: function () {
var start = lastTime;
var stop = Date.now();
var rate = 1000 / (stop - start);
if (rate == Infinity) {
return;
}
bucket.push(rate);
if (bucket.length > bucketSize) {
bucket.shift();
}
var sum = 0;
for (var i = 0; i < bucket.length; i++) {
sum = sum + bucket[i];
}
self.rate = (sum / bucket.length);
msText.textContent = "Repaint rate: " + self.rate.toFixed(2) + "/sec";
lastTime = stop;
},
rate: function () {
return self.rate;
}
}
};
var renderRate = new RenderRate();
document.body.appendChild( renderRate.domElement );
return {
memoryStats: stats,
renderRate: renderRate
};
})();
var ENV = ENV || (function() {
var first = true;
var counter = 0;
var data;
var _base;
(_base = String.prototype).lpad || (_base.lpad = function(padding, toLength) {
return padding.repeat((toLength - this.length) / padding.length).concat(this);
});
function formatElapsed(value) {
var str = parseFloat(value).toFixed(2);
if (value > 60) {
minutes = Math.floor(value / 60);
comps = (value % 60).toFixed(2).split('.');
seconds = comps[0].lpad('0', 2);
ms = comps[1];
str = minutes + ":" + seconds + "." + ms;
}
return str;
}
function getElapsedClassName(elapsed) {
var className = 'Query elapsed';
if (elapsed >= 10.0) {
className += ' warn_long';
}
else if (elapsed >= 1.0) {
className += ' warn';
}
else {
className += ' short';
}
return className;
}
function countClassName(queries) {
var countClassName = "label";
if (queries >= 20) {
countClassName += " label-important";
}
else if (queries >= 10) {
countClassName += " label-warning";
}
else {
countClassName += " label-success";
}
return countClassName;
}
function updateQuery(object) {
if (!object) {
object = {};
}
var elapsed = Math.random() * 15;
object.elapsed = elapsed;
object.formatElapsed = formatElapsed(elapsed);
object.elapsedClassName = getElapsedClassName(elapsed);
object.query = "SELECT blah FROM something";
object.waiting = Math.random() < 0.5;
if (Math.random() < 0.2) {
object.query = "<IDLE> in transaction";
}
if (Math.random() < 0.1) {
object.query = "vacuum";
}
return object;
}
function cleanQuery(value) {
if (value) {
value.formatElapsed = "";
value.elapsedClassName = "";
value.query = "";
value.elapsed = null;
value.waiting = null;
} else {
return {
query: "***",
formatElapsed: "",
elapsedClassName: ""
};
}
}
function generateRow(object, keepIdentity, counter) {
var nbQueries = Math.floor((Math.random() * 10) + 1);
if (!object) {
object = {};
}
object.lastMutationId = counter;
object.nbQueries = nbQueries;
if (!object.lastSample) {
object.lastSample = {};
}
if (!object.lastSample.topFiveQueries) {
object.lastSample.topFiveQueries = [];
}
if (keepIdentity) {
// for Angular optimization
if (!object.lastSample.queries) {
object.lastSample.queries = [];
for (var l = 0; l < 12; l++) {
object.lastSample.queries[l] = cleanQuery();
}
}
for (var j in object.lastSample.queries) {
var value = object.lastSample.queries[j];
if (j <= nbQueries) {
updateQuery(value);
} else {
cleanQuery(value);
}
}
} else {
object.lastSample.queries = [];
for (var j = 0; j < 12; j++) {
if (j < nbQueries) {
var value = updateQuery(cleanQuery());
object.lastSample.queries.push(value);
} else {
object.lastSample.queries.push(cleanQuery());
}
}
}
for (var i = 0; i < 5; i++) {
var source = object.lastSample.queries[i];
object.lastSample.topFiveQueries[i] = source;
}
object.lastSample.nbQueries = nbQueries;
object.lastSample.countClassName = countClassName(nbQueries);
return object;
}
function getData(keepIdentity) {
var oldData = data;
if (!keepIdentity) { // reset for each tick when !keepIdentity
data = [];
for (var i = 1; i <= ENV.rows; i++) {
data.push({ dbname: 'cluster' + i, query: "", formatElapsed: "", elapsedClassName: "" });
data.push({ dbname: 'cluster' + i + ' slave', query: "", formatElapsed: "", elapsedClassName: "" });
}
}
if (!data) { // first init when keepIdentity
data = [];
for (var i = 1; i <= ENV.rows; i++) {
data.push({ dbname: 'cluster' + i });
data.push({ dbname: 'cluster' + i + ' slave' });
}
oldData = data;
}
for (var i in data) {
var row = data[i];
if (!keepIdentity && oldData && oldData[i]) {
row.lastSample = oldData[i].lastSample;
}
if (!row.lastSample || Math.random() < ENV.mutations()) {
counter = counter + 1;
if (!keepIdentity) {
row.lastSample = null;
}
generateRow(row, keepIdentity, counter);
} else {
data[i] = oldData[i];
}
}
first = false;
return {
toArray: function() {
return data;
}
};
}
var mutationsValue = 0.5;
function mutations(value) {
if (value) {
mutationsValue = value;
document.querySelector('#ratioval').innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';
return mutationsValue;
} else {
return mutationsValue;
}
}
var body = document.querySelector('body');
var theFirstChild = body.firstChild;
var sliderContainer = document.createElement('div');
sliderContainer.style.cssText = "display: flex";
var slider = document.createElement('input');
var text = document.createElement('label');
text.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';
text.id = "ratioval";
slider.setAttribute("type", "range");
slider.style.cssText = 'margin-bottom: 10px; margin-top: 5px';
slider.addEventListener('change', function(e) {
ENV.mutations(e.target.value / 100);
});
sliderContainer.appendChild(text);
sliderContainer.appendChild(slider);
body.insertBefore(sliderContainer, theFirstChild);
return {
generateData: getData,
rows: 50,
timeout: 0,
mutations: mutations
};
})();
</script>
<script src="http://mathieuancelin.github.io/js-repaint-perfs/lib/memory-stats.js"></script>
<script src="http://mathieuancelin.github.io/js-repaint-perfs/lib/monitor.js"></script>
<script src="../../dist/radi.js"></script>
<!-- <script src="../../src/devtools.js"></script> -->
<script>
const { r, l, component, mount } = radi;
var raf = requestAnimationFrame
|| msRequestAnimationFrame
|| mozRequestAnimationFrame
|| webkitRequestAnimationFrame
|| oRequestAnimationFrame
|| setTimeout;
const main = component({
view: function () {
return r('table',
{ class: 'table table-striped latest-data' },
r('tbody',
list(l(this.dbs), (db, i) => {
return r('tr',
r('td',
{ class: 'dbname' },
db.dbname
),
r('td',
{ class: 'query-count' },
r('span',
{
class: l(db.lastSample.countClassName)
},
l(db.nbQueries)
)
),
list(l(db.lastSample.topFiveQueries), (q, i) => {
return r('td',
{
class: l('Query ' + q.elapsedClassName)
},
l(q.formatElapsed),
r('div',
{ class: 'popover left' },
r('div',
{ class: 'popover-content' },
l(q.query)
),
r('div', { class: 'arrow' })
)
)
})
);
})
)
);
},
state: {
dbs: []
},
actions: {
onMount() {
this.dbs = [];
this.load()
},
load() {
this.dbs = ENV.generateData(true).toArray();
Monitoring.renderRate.ping();
setTimeout(this.load, ENV.timeout);
}
}
});
mount(new main(), 'app');
</script>
</body>
</html>