Merge pull request #36 from iwasakims/enhance-viewer

Refactor spans.js and add description about timeline annotations to doc
diff --git a/htrace-hbase/README.md b/htrace-hbase/README.md
index face372..8f56527 100644
--- a/htrace-hbase/README.md
+++ b/htrace-hbase/README.md
@@ -69,6 +69,18 @@
 
 ![visualization of spans](spans.png "spans view")
 
+Light blue rectangls represent spans.
+The horizontal position of rectangle describe the time.
+The width of rectangle and the number at lower left side of rect
+describes the time from start to stop of the span in milliseconds.
+Small red rectangle represents timeline annotation at that time.
+Pointing span with red rectangles shows you annotations associated with the span in popup.
+
+![timeline annotations](timelines.png "timeline annotations")
+
+Leading numbers are time of annotation relative to start of the trace.
+
+
 Receiver Configuration
 ----------------------
 
diff --git a/htrace-hbase/spans.png b/htrace-hbase/spans.png
index bd42ff2..ceac10e 100644
--- a/htrace-hbase/spans.png
+++ b/htrace-hbase/spans.png
Binary files differ
diff --git a/htrace-hbase/src/main/webapps/htrace/spans.js b/htrace-hbase/src/main/webapps/htrace/spans.js
index 0d37051..c7c38af 100644
--- a/htrace-hbase/src/main/webapps/htrace/spans.js
+++ b/htrace-hbase/src/main/webapps/htrace/spans.js
@@ -16,7 +16,14 @@
  * limitations under the License.
  */
 
-var traceid = window.location.search.substring(1).split("=")[1];
+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 = "477902"; // constants defined in org.htrace.Span
+const traceid = window.location.search.substring(1).split("=")[1];
+
 d3.json("/getspans/" + traceid, function(spans) {
     spans.map(function(s) {
         s.start = parseInt(s.start);
@@ -25,45 +32,40 @@
           s.timeline.forEach(function(t) { t.time = parseInt(t.time); });
         }
       });
-    var rootid = "477902";
-    var margin = {top: 50, right: 500, bottom: 50, left: 50};
-    var barheight = 20;
-    var width = 800;
-    var height = spans.length * barheight;
-    var gleftmargin = 300;
-    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]);
-
     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(rootid), byparent);
+    addchildren(byparent.get(ROOT_SPAN_ID), byparent);
     var sortedspans = [];
-    traverse(0, byparent.get(rootid), function(e) { sortedspans.push(e); });
+    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 + gleftmargin + margin.left + margin.right)
-      .attr("height", height + margin.top + margin.bottom)
+      .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)
-      .attr("height", height)
-      .attr("transform", "translate(" + gleftmargin + ", 0)");
+      .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 * barheight + 5) + ")";
+          return "translate(0, " + (i * height_span + 5) + ")";
         })
       .classed("timeline", function(d) { return d.timeline; });
 
@@ -71,7 +73,7 @@
       .text(function(s) { return s.process_id; })
       .style("alignment-baseline", "hanging")
       .attr("transform", function(s) {
-          return "translate(" + (s.depth * 10 - gleftmargin) + ", 0)";
+          return "translate(" + (s.depth * 10 - margin.process) + ", 0)";
         });
 
     var rect_g = span_g.append("g")
@@ -80,9 +82,9 @@
         });
 
     rect_g.append("rect")
-      .attr("height", barheight - 1)
+      .attr("height", height_span - 1)
       .attr("width", function (s) {
-          return (width * (s.stop - s.start)) / (tmax - tmin) + 1;
+          return (width_span * (s.stop - s.start)) / (tmax - tmin) + 1;
         })
       .style("fill", "lightblue")
       .attr("class", "span")
@@ -103,10 +105,10 @@
       .enter()
       .append("rect")
       .style("fill", "red")
-      .attr("height", 8)
-      .attr("width", 8)
+      .attr("height", size_tl)
+      .attr("width", size_tl)
       .attr("transform", function(t) {
-          return "translate(" + xscale(t.time) + ", 11)";
+          return "translate(" + xscale(t.time) + "," + (height_span - 1 - size_tl) + ")";
         })
       .classed("timeline");
 
@@ -124,7 +126,7 @@
             });
           text += "</table>"
           popup.html(text)
-            .style("left", "30px")
+            .style("left", (document.body.scrollLeft + 30) + "px")
             .style("top", (document.body.scrollTop + 30) + "px")
             .style("width", "700px")
             .style("background", "orange")
diff --git a/htrace-hbase/timelines.png b/htrace-hbase/timelines.png
new file mode 100644
index 0000000..7542932
--- /dev/null
+++ b/htrace-hbase/timelines.png
Binary files differ