I'm using pubnub to power a dashboard I'm developing. All my widgets are based on code like this:
Polymer({
is: 'widget-horizon',
properties: { ... },
ready: function() {
registerCallback(this.channel, function (data) {
});
}
});
Then when that pubnub channel receives a message, the callback is called and passes the data. For this particular chart, the data looks something like this:
{
"id": "RegResponseTimes",
"type": null,
"timestamp": "2016-10-14T11:12:13.2313043-05:00",
"data": [
{
"label": "Metric1",
"Value": 0.05
},
{
"label": "Metric2",
"Value": 0.17
}
]
}
Now I'm trying to develop a widget based on cubism.js, but all the documentation is targeted at pulling data, more specifically using Cube
or Graphite
.
I'm having lots of trouble integrating the cubism code into my callback. I'm stumbling over all the language like "Metric Accessor" and "Extents".
After much trial and error, I kind of got one value working but here are the issues I need to fix:
Here is what it currently looks like:
And below is my full code (it's a polymer component). Major changes from the "random" sample include:
Instead of pushing a random number, push one of the values as a POC.
</style>
<strong id="widgetName">{{name}}</strong>
<div id="chart1"></div>
</template>
<script>
var data = [];
Polymer({
is: 'widget-horizon',
properties: {
dataid: {
type: String
},
name: {
type: String
},
gethistory: {
type: Number
},
testvalue: {
type: Number
},
isloading: {
type: Boolean,
value: true
}
},
ready: function() {
var self = this;
subscribe(self.dataid);
getHistory(self.dataid,self.gethistory);
registerCallback(this.dataid, function (data) {
context.start();
var y = data.data[0];
self.testvalue = y.Value;
self.isloading = false;
});
var context = cubism.context()
.serverDelay(0)
.clientDelay(0)
.step(1e4)
.size(600);
var foo = setval("foo");
var chart = self.$$('#chart1');
d3.select(chart).call(function(div) {
div.append("div")
.attr("class", "axis")
.call(context.axis().orient("top"));
div.selectAll(".horizon")
.data([foo])
.enter().append("div")
.attr("class", "horizon")
.call(context.horizon().extent([0, 120]));
div.append("div")
.attr("class", "rule")
.call(context.rule());
});
function setval(name) {
var value = 0,
values = [],
last;
return context.metric(function(start, stop, step, callback) {
start = +start, stop = +stop;
if (isNaN(last)) last = start;
while (last < stop) {
last += step;
value = self.testvalue;
if (value != "") {
values.push(self.testvalue);
context.stop();
}
}
callback(null, values = values.slice((start - stop) / step));
}, name);
}
context.on("focus", function(i) {
d3.selectAll(".value").style("right", i == null ? null : context.size() - i + "px");
});
}
});
</script>
I got it working. Here is my full callback:
registerCallback(this.dataid, function (data) {
if (self.isloading) {
for (var i = 0; i < data.data.length; i++){
datas[i] = setval(data.data[i].MessageBodyClassName);
}
d3.select(chart).call(function(div) {
div.append("div")
.attr("class", "axis")
.call(context.axis().orient("top"));
div.selectAll(".horizon")
.data(datas)
.enter().append("div")
.attr("class", "horizon")
.call(context.horizon().extent([0, 120]));
div.append("div")
.attr("class", "rule")
.call(context.rule());
});
} else {
for (var i = 0; i < data.data.length; i++){
vals[data.data[i].MessageBodyClassName] = data.data[i].Value;
}
}
context.start();
self.isloading = false;
});
And here is the converted random
function:
function setval(name) {
var value = 0,
values = [],
last;
return context.metric(function(start, stop, step, callback) {
start = +start, stop = +stop;
if (isNaN(last)) last = start;
while (last < stop) {
last += step;
value = self.testvalue;
if (value != "") {
values.push(vals[name]);
context.stop();
}
}
callback(null, values = values.slice((start - stop) / step));
}, name);
}
essentially I just defined a global vals
array and I'm using it to store the new values when pubnub updates and update the values with the Metric Accessor... I guess.