blob: 8e588607cb11e21e7bfbdea0a5d2333460728fb2 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const height_span = 20;
const width_span = 700;
const size_tl = 6;
const margin = {top: 50, bottom: 50, left: 50, right: 1000, process: 250};
const ROOT_SPAN_ID = "0";
const traceid = window.location.search.substring(1).split("=")[1];
d3.json("/getspans/" + traceid, function(spans) {
spans.map(function(s) {
s.start = parseInt(s.start);
s.stop = parseInt(s.stop);
if (s.timeline) {
s.timeline.forEach(function(t) { t.time = parseInt(t.time); });
}
});
var byparent = d3.nest()
.sortValues(function(a, b) {
return a.start < b.start ? -1 : a.start > b.start ? 1 : 0;
})
.key(function(e) { return e.parent_id; })
.map(spans, d3.map);
addchildren(byparent.get(ROOT_SPAN_ID), byparent);
var sortedspans = [];
traverse(0, byparent.get(ROOT_SPAN_ID), function(e) { sortedspans.push(e); });
var height_screen = spans.length * height_span;
var tmin = d3.min(spans, function(s) { return s.start; });
var tmax = d3.max(spans, function(s) { return s.stop; });
var xscale = d3.time.scale()
.domain([new Date(tmin), new Date(tmax)]).range([0, width_span]);
var svg = d3.select("body").append("svg")
.attr("width", width_span + margin.process + margin.left + margin.right)
.attr("height", height_screen + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var bars = svg.append("g")
.attr("id", "bars")
.attr("width", width_span)
.attr("height", height_screen)
.attr("transform", "translate(" + margin.process + ", 0)");
var span_g = bars.selectAll("g.span")
.data(sortedspans)
.enter()
.append("g")
.attr("transform", function(s, i) {
return "translate(0, " + (i * height_span + 5) + ")";
})
.classed("timeline", function(d) { return d.timeline; });
span_g.append("text")
.text(function(s) { return s.process_id; })
.style("alignment-baseline", "hanging")
.attr("transform", function(s) {
return "translate(" + (s.depth * 10 - margin.process) + ", 0)";
});
var rect_g = span_g.append("g")
.attr("transform", function(s) {
return "translate(" + xscale(new Date(s.start)) + ", 0)";
});
rect_g.append("rect")
.attr("height", height_span - 1)
.attr("width", function (s) {
return (width_span * (s.stop - s.start)) / (tmax - tmin) + 1;
})
.style("fill", "lightblue")
.attr("class", "span")
rect_g.append("text")
.text(function(s){ return s.description; })
.style("alignment-baseline", "hanging");
rect_g.append("text")
.text(function(s){ return s.stop - s.start; })
.style("alignment-baseline", "baseline")
.style("text-anchor", "end")
.style("font-size", "10px")
.attr("transform", function(s, i) { return "translate(0, 10)"; });
bars.selectAll("g.timeline").selectAll("rect.timeline")
.data(function(s) { return s.timeline; })
.enter()
.append("rect")
.style("fill", "red")
.attr("height", size_tl)
.attr("width", size_tl)
.attr("transform", function(t) {
return "translate(" + xscale(t.time) + "," + (height_span - 1 - size_tl) + ")";
})
.classed("timeline");
var popup = d3.select("body").append("div")
.attr("class", "popup")
.style("opacity", 0);
bars.selectAll("g.timeline")
.on("mouseover", function(d) {
popup.transition().duration(300).style("opacity", .95);
var text = "<table>";
d.timeline.forEach(function (t) {
text += "<tr><td>" + (t.time - tmin) + "</td>";
text += "<td> : " + t.message + "<td/></tr>";
});
text += "</table>"
popup.html(text)
.style("left", (document.body.scrollLeft + 30) + "px")
.style("top", (document.body.scrollTop + 30) + "px")
.style("width", "700px")
.style("background", "orange")
.style("position", "absolute");
})
.on("mouseout", function(d) {
popup.transition().duration(300).style("opacity", 0);
});
var axis = d3.svg.axis()
.scale(xscale)
.orient("top")
.tickValues(xscale.domain())
.tickFormat(d3.time.format("%x %X.%L"))
.tickSize(6, 3);
bars.append("g").attr("class", "axis").call(axis);
});
function addchildren(nodes, byparent) {
nodes.forEach(function(e) {
if (byparent.get(e.span_id)) {
e.children = byparent.get(e.span_id);
addchildren(e.children, byparent);
}
});
}
function traverse(depth, children, func) {
children.forEach(function(e) {
e.depth = depth;
func(e);
if (e.children) {
traverse (depth + 1, e.children, func);
}
});
}