The data would be passed from splunk enterprise search.
I am following this tutorial
http://dev.splunk.com/view/SP-CAAAE2X#UIandvisualization
but still Formatdata function is unclear to me with respect to the circle packing chart. Please tell me how can i embed the code given here
http://bl.ocks.org/mbostock/4063530
in the formatdata function in wrapper code here
The xml code for the main dashboard is :-
<dashboard script="autodiscover.js" >
<row>
<panel>
<html>
<h2>Vulnerability Chart</h2>
<div id="circle_search" class="splunk-manager" data-require="splunkjs/mvc/searchmanager"
data-options='{"search":"| tstats summariesonly=true count from datamodel=Vulnerabilities where Vulnerabilities.dest="10.0.1.4" by Vulnerabilities.signature,Vulnerabilities.severity,Vulnerabilities.vendor_product | join max=0 Vulnerabilities.signature [| tstats summariesonly=true count from datamodel=Vulnerabilities where earliest=-4h@m latest=+0s by Vulnerabilities.signature,Vulnerabilities.dest ] | search Vulnerabilities.severity ="high" |stats count(Vulnerabilities.dest) as count by Vulnerabilities.signature,Vulnerabilities.dest "
,
"preview": true,
"earliest_time": "-1d@d",
"latest_time": "@d"
}'>
</div>
<div id="circle_chart" class="splunk-view" data-require="app/acalvio_app/components/circle_packing/circle_packing"
data-options='{
"managerid": "circle_search",
"root_label": "Vulnerability"
}'></div>
</html>
</panel>
</row>
</dashboard>
circle_packing.js code :-
define(function(require, exports, module) {
var _ = require("underscore");
var d3 = require("../d3/d3");
var SimpleSplunkView = require("splunkjs/mvc/simplesplunkview");
require("css!./circle_packing.css");
var Circle_chart = SimpleSplunkView.extend({
//className: "splunk-toolkit-chord-chart",
options: {
"managerid": null,
"data": "preview"
},
output_mode: "json",
initialize: function() {
SimpleSplunkView.prototype.initialize.apply(this, arguments);
},
createView: function() {
this.$el.html('');
var svg=d3.select(this.el).append("svg")
.attr("width", diameter)
.attr("height", diameter)
return { container: this.$el, svg: svg};
//return true;
},
// Making the data look how we want it to for updateView to do its job
formatData: function(data) {
var newData = { name :"root", children : [] },
levels = ["Vulnerabilities.signature"];
// For each data row, loop through the expected levels traversing the output tree
data.forEach(function(d){
// Keep this as a reference to the current level
var depthCursor = newData.children;
// Go down one level at a time
levels.forEach(function( property, depth ){
// Look to see if a branch has already been created
var index;
depthCursor.forEach(function(child,i){
if ( d[property] == child.name ) index = i;
});
// Add a branch if it isn't there
if ( isNaN(index) ) {
depthCursor.push({ name : d[property], children : []});
index = depthCursor.length - 1;
}
// Now reference the new child array as we go deeper into the tree
depthCursor = depthCursor[index].children;
// This is a leaf, so add the last element to the specified branch
if ( depth === levels.length - 1 ) depthCursor.push({ name : d.Vulnerabilities.dest, size : d.count });
});
});
return {
"name": this.settings.get("root_label"),
"children": data
};
//return formatted_data; // this is passed into updateView as 'data'
},
updateView: function(viz, data) {
this.$el.html("");
var diameter = 960,
format = d3.format(",d");
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) { return d.size; });
var vis = d3.select(this.el).append("svg:svg")
.attr("width", diameter)
.attr("height", diameter)
.append("svg:g")
.attr("transform", "translate(2,2)");
}
});
return Circle_chart;
});
circle_packing.css
circle {
fill: rgb(31, 119, 180);
fill-opacity: .25;
stroke: rgb(31, 119, 180);
stroke-width: 1px;
}
.leaf circle {
fill: #ff7f0e;
fill-opacity: 1;
}
text {
font: 10px sans-serif;
}
autodiscover.js
require.config({
paths: {
"app": "../app"
}
});
require(["splunkjs/mvc",'splunkjs/mvc/simplexml/ready!'], function(mvc){
require(['splunkjs/ready!'], function(){
// The splunkjs/ready loader script will automatically instantiate all elements
// declared in the dashboard's HTML.
});
});
I have no idea whether search query result data is incompatible to the flare.json or there's some error in my files . but when i open the dashboard it says "No search set" and no chart appears. Please help me figure this out.
Thanks in advance.
So, the error was in circle_packing.js file with formatdata function i.e. the data was not in the proper flare format which is required for circle packing chart. Also there was a little change in the query syntax.
Here are the updated files which worked for me.
Dashboard Xml file -
<form script="autodiscover.js">
<row>
<html>
<div id="customsearch1"
class="splunk-manager"
data-require="splunkjs/mvc/searchmanager"
data-options='{
"search": { "type": "token_safe", "value": "| tstats summariesonly=true count from
datamodel=Vulnerabilities where Vulnerabilities.dest=\"192.168.1.84\" by Vulnerabilities.signature,Vulnerabilities.severity| join max=0 Vulnerabilities.signature [| tstats summariesonly=true count from datamodel=Vulnerabilities where earliest=-4h@m latest=+0s by Vulnerabilities.signature,Vulnerabilities.dest ] | search Vulnerabilities.severity =\"high\" |stats count(Vulnerabilities.dest) as count by Vulnerabilities.signature,Vulnerabilities.dest
| rename Vulnerabilities.signature as signature | rename Vulnerabilities.dest as dest" }
}'>
</div>
<div align="center" valign="middle" id="custom"
class="splunk-view"
data-require="app/acalvio_app2/components/circle_packing/circle_packing"
data-options='{
"managerid": "customsearch1"
}'>
</div>
</html>
</row>
</form>
circle_packing.js -
/*Chart-cloud visualization
* This view is an example for a simple visualization based on search results
*/
define(function(require, module) {
var _ = require('underscore');
var d3 = require("../d3/d3");
var SimpleSplunkView = require('splunkjs/mvc/simplesplunkview');
var Drilldown = require('splunkjs/mvc/drilldown');
require("css!./circle_packing.css");
var CircleChart = SimpleSplunkView.extend({
moduleId: module.id,
className: 'circlechart-viz',
options: {
data: 'preview'
},
output_mode: 'json',
createView: function() {
this.$el.html('');
return true;
},
formatData: function(data) {
console.log(data);
var newData = { name :"", children : [] };
var map = [];
for( i in data){
var sign = data[i].signature;
if(!map[sign]) map[sign] = [];
map[sign].push({"dest":data[i].dest,"count":data[i].count});
}
for(j in map){
var hosts = [];
for(k in map[j]){
if(map[j][k].count){
hosts.push({"name":map[j][k].dest,"size":map[j][k].count});
}
}
if(hosts.length > 0)
newData.children.push({"name":j,"children":hosts});
}
console.log(newData);
return newData;
},
updateView: function(viz, data) {
console.log(data);
var diameter = 500,
format = d3.format(",d");
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) { return d.size; });
var svg = d3.select(this.el).append("svg")
.attr("width", diameter)
.attr("height", diameter)
.append("g");
//if (error) throw error;
var node = svg.datum(data).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("title")
.text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });
node.append("circle").attr("r", function(d) { return d.r; });
node.filter(function(d) { return d.depth>0; }).append("text")
.attr("dy", function(d){
if(!d.name)
return "-7em";
}
)
.attr("dx",function(d){
if(!d.name) return "3em";
})
.style("text-anchor", function(d){
if(!d.name) return "end";
if(d.depth === 2) return "middle";
return "start";
}
)
.text(function(d) {
if(d && d.depth === 2 && d.name)
return "*." + d.name.substring(d.r / 3);
if(d.parent)
return d.parent.name.substring(0,15);
return d.name;
});
d3.select(self.frameElement).style("height", diameter + "px");
}
});
return CircleChart;
});
,Create dashboard xml file
<label>Circle chart</label>
<row>
<html>
<div align="center" valign="middle" id="custom"
class="splunk-view"
data-require="app/<Your_app>/components/circlechart/circlechart"
'>
</div>
</html>
</row>
then next create app//components/circlechart/circlechart.js file and paste the code given below.
/*
* Simple TagCloud visualization
* This view is an example for a simple visualization based on search results
*/
define(function(require, module) {
var _ = require('underscore'), $ = require('jquery');
var d3 = require("../d3.v3.min.js"); // create //d3js.org/d3.v3.min.js inside components folder
var SimpleSplunkView = require('splunkjs/mvc/simplesplunkview');
var Drilldown = require('splunkjs/mvc/drilldown');
var Circle= SimpleSplunkView.extend({
moduleId: module.id,
output_mode: 'json',
/* Create svg inside the create view*/
createView: function() {
this.$el.html('');
var svg=d3.select(this.el).append("svg")
.attr("width", diameter)
.attr("height", diameter)
return { container: this.$el, svg: svg};
},
/* result svg append to g tag inside the update view*/
updateView: function(viz, data) {
var diameter = 960,
format = d3.format(",d");
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) { return d.size; });
viz.svg.
.append("g")
.attr("transform", "translate(2,2)");
d3.json("./flare.json", function(error, root) {
if (error) throw error;
var node = svg.datum(root).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("title")
.text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });
node.append("circle")
.attr("r", function(d) { return d.r; });
node.filter(function(d) { return !d.children; }).append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.name.substring(0, d.r / 3); });
});
d3.select(self.frameElement).style("height", diameter + "px");
}
});
return Circle;
});
at last return Circle will display the Circle chart
Hi raghu,
I've uploaded all the files that I am using for the dashboard. I am still not getting the circle packing chart displayed on the dashboard. Please see the code and help me out with this.
Thanks in advance
HI Gitanjali,
Please try this http://d3js.org/d3.v3.min.js plugin download and replace with d3.js file in the below code.
...
...
define(function(require, exports, module) {
var _ = require("underscore");
var d3 = require("../d3/d3");
This will work. or else please forward data in csv or json through gmail raghu.venkat260@gmail.com I will try out from myside.
/*Chart-cloud visualization
* This view is an example for a simple visualization based on search results
*/
define(function(require, module) {
var _ = require('underscore'), $ = require('jquery');
var d3 = require("../d3/d3.v3.min");
var SimpleSplunkView = require('splunkjs/mvc/simplesplunkview');
var Drilldown = require('splunkjs/mvc/drilldown');
require("css!./circle_packing.css");
var CircleChart = SimpleSplunkView.extend({
moduleId: module.id,
className: 'circlechart-viz',
options: {
data: 'preview'
},
output_mode: 'json',
createView: function() {
this.$el.html('');
return true;
},
formatData: function(data) {
console.log(data);
var newData = { name :"root", children : [] },
levels = ["Vulnerabilities.signature","name"];
// For each data row, loop through the expected levels traversing the output tree
data.forEach(function(d){
// Keep this as a reference to the current level
var depthCursor = newData.children;
// Go down one level at a time
levels.forEach(function( property, depth ){
// Look to see if a branch has already been created
var index;
depthCursor.forEach(function(child,i){
if ( d[property] == child.name ) index = i;
});
// Add a branch if it isn't there
if ( isNaN(index)) {
depthCursor.push({ name : d[property], children : []});
index = depthCursor.length - 1;
}
// Now reference the new child array as we go deeper into the tree
depthCursor = depthCursor[index].children;
// This is a leaf, so add the last element to the specified branch
if ( depth === levels.length - 1 ) depthCursor.push({ name : d.Vulnerabilities.dest, size : d.count });
});
});
console.log(newData);
return newData;
},
updateView: function(viz, data) {
console.log(data); //please provide the json data getting from the search query or else convert this ouptut to below data1 json format in formatData propety
var diameter = 500,
format = d3.format(",d");
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) { return d.size; });
var svg = d3.select(this.el).append("svg")
.attr("width", diameter)
.attr("height", diameter)
.append("g")
.attr("transform", "translate(2,2)");
//if (error) throw error;
var node = svg.datum(data).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("title")
.text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });
node.append("circle")
.attr("r", function(d) { return d.r; });
node.filter(function(d) { return !d.children; }).append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.name.substring(0, d.r / 3); });
d3.select(self.frameElement).style("height", diameter + "px");
}
});
return CircleChart;
});