Created
September 9, 2013 18:43
-
-
Save phaus/6499780 to your computer and use it in GitHub Desktop.
Some more PS Plotting with D3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<title>PS</title> | |
<style> | |
.node { | |
stroke: #fff; | |
stroke-width: 1.5px; | |
} | |
.legend { | |
padding: 5px; | |
font: 10px sans-serif; | |
background: yellow; | |
box-shadow: 2px 2px 1px #888; | |
} | |
.link { | |
stroke: #999; | |
stroke-opacity: .6; | |
} | |
</style> | |
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.6.0"></script> | |
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?2.6.0"></script> | |
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js?2.6.0"></script> | |
</head> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script type="text/javascript" > | |
function sortUser(a, b){ | |
return a.uid > b.uid; | |
} | |
var width = 1280, | |
height = 720; | |
var color = d3.scale.category20(); | |
var force = d3.layout.force() | |
.charge(-240) | |
.linkDistance(33) | |
.size([width, height]); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
d3.json("ps.json", function(graph) { | |
var hash_lookup = []; | |
graph.nodes.forEach(function(d, i) { | |
hash_lookup[d.id] = d; | |
}); | |
graph.links.forEach(function(d, i) { | |
d.source = hash_lookup[d.source]; | |
d.target = hash_lookup[d.target]; | |
}); | |
force | |
.nodes(graph.nodes) | |
.links(graph.links) | |
.start(); | |
var link = svg.selectAll(".link") | |
.data(graph.links) | |
.enter().append("line") | |
.attr("class", "link") | |
.attr("id", function(d) { return "L"+d.id;}) | |
.style("stroke-width", function(d) { return 0.5; }); | |
var node = svg.selectAll(".node") | |
.data(graph.nodes) | |
.enter().append("circle") | |
.attr("class", "node") | |
.attr("id", function(d) { return "N"+d.id;}) | |
.attr("r", function(d) { return 5+d.pcpu;}) | |
.text(function(d, i) { | |
return i % 2 == 0 ? "" : d.name | |
}).style("font-family", "Arial").style("font-size", 12).style("fill", function(d) { return color(d.group); }) | |
.call(force.drag); | |
node.append("title") | |
.text(function(d) { return d.name+"("+d.group+") "+d.pmem+"M "+d.pcpu+"%"; }); | |
var c = 20; | |
var legend = svg.selectAll(".users") | |
.data(graph.users.sort(sortUser)) | |
.enter() | |
.append("g") | |
.attr("class", "legend") | |
.attr("x", 10) | |
.attr("y", 25) | |
.attr("height", 100) | |
.attr("width", 200); | |
legend.append("rect") | |
.attr("x", 10) | |
.attr("y", function(d){c += 25; return c;}) | |
.attr("width", 20) | |
.attr("height", 20) | |
.style("fill", function(d) { return color(d.uid); }); | |
var c = 20; | |
legend.append("text") | |
.attr("x", 35) | |
.attr("y", function(d){c += 25; return 15+c;}) | |
.text(function(d) { return "("+d.uid+") "+d.name; }) | |
.style("font-size","12px"); | |
force.on("tick", function() { | |
link.attr("x1", function(d) { return d.source.x; }) | |
.attr("y1", function(d) { return d.source.y; }) | |
.attr("x2", function(d) { return d.target.x; }) | |
.attr("y2", function(d) { return d.target.y; }); | |
node.attr("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }); | |
}); | |
}); | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
var sys = require('sys') | |
var exec = require('child_process').exec; | |
var fs = require('fs'); | |
var http = require('http'); | |
var url = require('url'); | |
var cmd; | |
var users = {}; | |
var userArr = []; | |
switch(process.platform){ | |
case 'darwin': | |
cmd = 'ps -A -c -o pid,ppid,pcpu,pmem,uid,ruser,comm -r'; | |
break; | |
} | |
function parse(line){ | |
var parts = line.split(" "); | |
var out = []; | |
var c = 0; | |
for(var i in parts){ | |
if(parts[i].trim().length > 0){ | |
out[c] = parts[i].trim(); | |
c++; | |
} | |
} | |
return out; | |
} | |
function addUser(uid, user){ | |
if(users[uid] == null){ | |
users[uid] = user; | |
console.log(JSON.stringify({uid:uid, name:user})); | |
userArr.push({uid:parseInt(uid), name:user}); | |
} | |
} | |
function entryFromLine(line){ | |
var parts = parse(line); | |
return { | |
pid: parts[0].trim(), | |
ppid: parts[1].trim(), | |
pcpu: parts[2].trim(), | |
pmem: parts[3].trim(), | |
uid: parts[4].trim(), | |
user: parts[5].trim(), | |
cmd: parts[6].trim() | |
}; | |
} | |
function header(){ | |
console.log("graph G {"); | |
console.log("layout=twopi;"); | |
console.log("rankdir=TB;"); | |
console.log("nodesep=5.0;"); | |
console.log("ratio=auto;"); | |
console.log("ranksep=15.0;"); | |
console.log("root=\"0\";"); | |
console.log("0 [label=\"0\"]"); | |
} | |
function scanCli(error, stdout, stderr) { | |
if (error) { | |
return console.log(error); | |
} | |
header(); | |
var lines = stdout.split("\n"); | |
for(var c in lines){ | |
if(lines[c].length > 0 && c > 0){ | |
var parts = parse(lines[c]); | |
var entry = { | |
pid: parts[0].trim(), | |
ppid: parts[1].trim(), | |
pcpu: parts[2].trim(), | |
pmem: parts[3].trim(), | |
cmd: parts[4].trim(), | |
uid: parts[5].trim() | |
}; | |
console.log(entry.pid+" [label=\""+entry.cmd+" ("+entry.uid+")\"]"); | |
console.log(entry.ppid+" -- "+entry.pid); | |
} | |
} | |
console.log("}"); | |
} | |
function scanFile(err,data){ | |
if (err) { | |
return console.log(err); | |
} | |
header(); | |
var lines = data.split("\n"); | |
for(var c in lines){ | |
if(lines[c].length > 0 && c > 0){ | |
var entry = entryFromLine(lines[c]); | |
console.log(entry.pid+" [label=\""+entry.cmd+" ("+entry.uid+")\"]"); | |
console.log(entry.ppid+" -- "+entry.pid); | |
} | |
} | |
console.log("}"); | |
} | |
function sendJson(req, res){ | |
var r=res; | |
exec(cmd, function(err, data){ | |
var nodes = []; | |
var links = []; | |
var mapping = {}; | |
var lines = data.split("\n"); | |
nodes[0] = { | |
id:0, name:"root", group:0, ppid:0, value:0 | |
}; | |
for(var c in lines){ | |
if(lines[c].length > 0 && c > 0){ | |
var entry = entryFromLine(lines[c]); | |
nodes[c] = { | |
id:parseInt(entry.pid), | |
name:entry.cmd, | |
ppid:parseInt(entry.ppid), | |
group:parseInt(entry.uid), | |
pmem:parseFloat(entry.pmem), | |
pcpu:parseFloat(entry.pcpu)}; | |
links[c-1] = { | |
id:parseInt(entry.pid), | |
source:parseInt(entry.pid), | |
target:parseInt(entry.ppid)}; | |
addUser(entry.uid, entry.user); | |
} | |
} | |
r.write('{'); | |
r.write('"nodes":'); | |
r.write(JSON.stringify(nodes)); | |
r.write(','); | |
r.write('"links":'); | |
r.write(JSON.stringify(links)); | |
r.write(','); | |
r.write('"users":'); | |
r.write(JSON.stringify(userArr)); | |
r.write('}'); | |
r.end(''); | |
}); | |
} | |
function handleJson(req, res){ | |
res.writeHead(200, {'Content-Type': 'application/json'}); | |
sendJson(req, res); | |
} | |
function handleIndex(req, res){ | |
fs.readFile('index.html', 'utf8', function(err, data){ | |
if (err) { | |
res.writeHead(500, {'Content-Type': 'text/plain'}); | |
res.end(err); | |
} | |
res.writeHead(200, {'Content-Type': 'text/html'}); | |
res.write(data); | |
res.end(); | |
}); | |
} | |
function handleRequest(req, res){ | |
var url_parts = url.parse(req.url); | |
console.log(url_parts.pathname); | |
switch(url_parts.pathname){ | |
case '/ps.json': | |
handleJson(req, res); | |
break; | |
default: | |
handleIndex(req, res); | |
} | |
} | |
http.createServer(handleRequest).listen(1337, '127.0.0.1'); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment