Skip to content

Commit 1064fbf

Browse files
committed
[webapp] WIP Path Latency Survey
moving path text color fix here adding test link text adding latency placeholders in path lists updated path header, fixed path latency text adding traceroute last call convert incoming paths to hash map tr appears in wrong order, but path latency updates now use best results find min/max and report min' adding stats object to trace needed stats adding stats to path graph restore traceroute
1 parent b95c51c commit 1064fbf

File tree

6 files changed

+208
-28
lines changed

6 files changed

+208
-28
lines changed

webapp/static/css/style-viz.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@ ul.tree li.open>ul {
229229
ul.tree li a {
230230
color: black;
231231
text-decoration: none;
232+
}
233+
234+
.path-text {
235+
color: white;
232236
padding-left: 5px; /* background shape */
233237
padding-right: 5px; /* background shape */
234238
border-radius: 10px; /* background shape */

webapp/static/js/asviz.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ function setPaths(type, idx, open) {
6868
} else if (type == 'UP') {
6969
addSegments(resUp, idx, num, colorSegUp, type);
7070
} else if (type == 'PATH') {
71-
addPaths(resPath, idx, num, colorPaths, type);
71+
var latencies = getPathLatencyAvg(formatPathString(resPath, idx, type));
72+
addPaths(resPath, idx, num, colorPaths, type, latencies);
7273
}
7374
self.segType = type;
7475
self.segNum = idx;
@@ -111,9 +112,9 @@ function formatPathString(res, idx, type) {
111112
/*
112113
* Adds D3 forwarding path links with arrows and a title to paths graph.
113114
*/
114-
function addPaths(res, idx, num, color, type) {
115+
function addPaths(res, idx, num, color, type, latencies) {
115116
if (graphPath) {
116-
drawPath(res, idx, color);
117+
drawPath(res, idx, color, latencies);
117118
if (res.if_lists[idx].expTime) {
118119
drawTitle(type + ' ' + num, color, res.if_lists[idx].expTime);
119120
} else {

webapp/static/js/tab-paths.js

Lines changed: 134 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ var iaLabels;
33
var iaLocations = [];
44
var iaGeoLoc;
55
var g = {};
6-
var jPathColors = [];
6+
var jPathsAvailable = {};
77

88
function setupDebug(src, dst) {
99
var src = $('#ia_cli').val();
@@ -26,14 +26,99 @@ function path_colors(n) {
2626
}
2727

2828
function getPathColor(hops) {
29-
var idx = jPathColors.indexOf(hops + '');
30-
if (idx < 0) {
29+
if (!jPathsAvailable[hops]) {
3130
return cMissingPath;
3231
} else {
33-
return path_colors(idx);
32+
return jPathsAvailable[hops].color;
3433
}
3534
}
3635

36+
/**
37+
* Updates statistics.
38+
*/
39+
function updateStats(fStat, oldStat) {
40+
var newStat = {}
41+
newStat.Last = fStat;
42+
newStat.Num = oldStat ? (oldStat.Num + 1) : 1;
43+
newStat.Avg = oldStat ? (((oldStat.Avg * oldStat.Num) + fStat) / newStat.Num)
44+
: fStat;
45+
newStat.Min = oldStat ? Math.min(fStat, oldStat.Min) : fStat;
46+
newStat.Max = oldStat ? Math.max(fStat, oldStat.Max) : fStat;
47+
return newStat;
48+
}
49+
50+
function getPathLatencyLast(hops) {
51+
return getPathLatency(hops, false);
52+
}
53+
54+
function getPathLatencyAvg(hops) {
55+
return getPathLatency(hops, true);
56+
}
57+
58+
/**
59+
* Returns array of interface and full path latency stats.
60+
*/
61+
function getPathLatency(hops, avg) {
62+
var path = {};
63+
if (jPathsAvailable[hops]) {
64+
path = jPathsAvailable[hops];
65+
}
66+
var latencies = [];
67+
for (var i = 0; i < path.interfaces.length; i++) {
68+
if (path.interfaces[i].latency) {
69+
latencies.push(avg ? path.interfaces[i].latency.Last
70+
: path.interfaces[i].latency.Avg);
71+
} else {
72+
latencies.push(undefined);
73+
}
74+
}
75+
if (path.latency) {
76+
latencies.push(avg ? path.latency.Last : path.latency.Avg);
77+
} else {
78+
latencies.push(undefined);
79+
}
80+
return latencies;
81+
}
82+
83+
function setEchoLatency(hops, latency) {
84+
var path = {};
85+
if (jPathsAvailable[hops]) {
86+
path = jPathsAvailable[hops];
87+
}
88+
path.latency = updateStats(latency, path.latency);
89+
var latStr = parseFloat(path.latency.Last).toFixed(1);
90+
$('#path-lat-' + path.listIdx).html(latStr);
91+
jPathsAvailable[hops] = path;
92+
}
93+
94+
function setTracerouteLatency(hops, interfaces) {
95+
var path = {};
96+
if (jPathsAvailable[hops]) {
97+
path = jPathsAvailable[hops];
98+
}
99+
for (var i = 0; i < interfaces.length; i++) {
100+
var if_ = interfaces[i];
101+
if (i < interfaces.length - 1) {
102+
path.interfaces[i].addr = if_.HopAddr;
103+
path.interfaces[i].latency = updateStats(if_.RespTime1,
104+
path.interfaces[i].latency);
105+
path.interfaces[i].latency = updateStats(if_.RespTime2,
106+
path.interfaces[i].latency);
107+
path.interfaces[i].latency = updateStats(if_.RespTime3,
108+
path.interfaces[i].latency);
109+
var latStr = parseFloat(path.interfaces[i].latency.Last).toFixed(1);
110+
$('#path-lat-' + path.listIdx + '-' + i).html(latStr);
111+
} else {
112+
path.latency = updateStats(if_.RespTime1, path.latency);
113+
path.latency = updateStats(if_.RespTime2, path.latency);
114+
path.latency = updateStats(if_.RespTime3, path.latency);
115+
var latStr = parseFloat(path.latency.Last).toFixed(1);
116+
$('#path-lat-' + path.listIdx).html(latStr);
117+
}
118+
}
119+
jPathsAvailable[hops] = path;
120+
}
121+
37122
function isConfigComplete(data, textStatus, jqXHR) {
38123
console.log(JSON.stringify(data));
39124
g['nodes_xml_url'] = data.nodes_xml_url;
@@ -376,11 +461,18 @@ function get_path_html(paths, csegs, usegs, dsegs, show_segs) {
376461
if_ = ent.Path.Interfaces;
377462
var hops = if_.length / 2;
378463

379-
var style = "style='background-color: "
380-
+ getPathColor(formatPathJson(paths, parseInt(p))) + "; '";
381-
html += "<li seg-type='PATH' seg-num=" + p + "><a " + style
382-
+ " href='#'>PATH " + (parseInt(p) + 1)
383-
+ "</a> <span class='badge'>" + hops + "</span>";
464+
var pathStr = formatPathJson(paths, parseInt(p));
465+
var latencies = getPathLatencyAvg(pathStr);
466+
var latencyPath = latencies[latencies.length - 1];
467+
var latPathStr = latencyPath ? parseFloat(latencyPath).toFixed(1) : '';
468+
var aStyle = "style='background-color:" + getPathColor(pathStr) + ";'";
469+
var latStyle = "style='color:purple; position:absolute; right:0;'";
470+
html += "<li seg-type='PATH' seg-num=" + p + " path='" + pathStr
471+
+ "'><a class='path-text' " + aStyle
472+
+ " href='#'><span style='color: white;'>PATH "
473+
+ (parseInt(p) + 1) + "</span></a> <span class='badge'>" + hops
474+
+ "</span> <span id='path-lat-" + p + "' " + latStyle + ">"
475+
+ latPathStr + "</span>";
384476
exp.setUTCSeconds(ent.Path.ExpTime);
385477
html += "<ul>";
386478
html += "<li><a href='#'>Mtu: " + ent.Path.Mtu + "</a>";
@@ -396,8 +488,11 @@ function get_path_html(paths, csegs, usegs, dsegs, show_segs) {
396488
html += "<li><a href='#'>Expiration: " + exp.toLocaleDateString() + " "
397489
+ exp.toLocaleTimeString() + "</a>";
398490
for (i in if_) {
491+
var latIfStr = latencies[i] ? parseFloat(latencies[i]).toFixed(1)
492+
: '';
399493
html += "<li><a href='#'>" + iaRaw2Read(if_[i].RawIsdas) + " ("
400-
+ if_[i].IfID + ")</a>";
494+
+ if_[i].IfID + ")</a> <span id='path-lat-" + p + "-" + i
495+
+ "' " + latStyle + ">" + latIfStr + "</span>";
401496
}
402497
html += "</ul>";
403498
}
@@ -662,6 +757,34 @@ function get_nonseg_links(paths, lType) {
662757
return hops;
663758
}
664759

760+
function addAvailablePaths(paths) {
761+
Object.keys(jPathsAvailable).forEach(function(key) {
762+
jPathsAvailable[key].listIdx = undefined; // reset
763+
});
764+
for (var idx = 0; idx < paths.length; idx++) {
765+
var hops = formatPathJson(paths, idx, 'PATH');
766+
if (!jPathsAvailable[hops]) {
767+
jPathsAvailable[hops] = {};
768+
}
769+
// update path preserving old values
770+
var path = jPathsAvailable[hops];
771+
var pathLen = Object.keys(jPathsAvailable).length;
772+
path.interfaces = [];
773+
var ifs = paths[idx].Entry.Path.Interfaces;
774+
for (var i = 0; i < ifs.length; i++) {
775+
var if_ = {};
776+
if_.ifid = ifs[i].IfID;
777+
if_.isdas = iaRaw2Read(ifs[i].RawIsdas);
778+
path.interfaces.push(if_);
779+
}
780+
path.expTime = paths[idx].Entry.Path.ExpTime;
781+
path.mtu = paths[idx].Entry.Path.Mtu;
782+
path.color = path_colors(pathLen - 1);
783+
path.listIdx = idx;
784+
jPathsAvailable[hops] = path;
785+
}
786+
}
787+
665788
function requestPaths() {
666789
// make sure to get path topo after IAs are loaded
667790
var form_data = $('#command-form').serializeArray();
@@ -685,12 +808,7 @@ function requestPaths() {
685808
resDown = resSegs.down_segments;
686809

687810
// store incoming paths
688-
for (var idx = 0; idx < resPath.if_lists.length; idx++) {
689-
var hops = formatPathString(resPath, idx, 'PATH');
690-
if (!jPathColors.includes(hops)) {
691-
jPathColors.push(hops);
692-
}
693-
}
811+
addAvailablePaths(data.paths);
694812

695813
jTopo = get_json_path_links(resPath, resCore, resUp, resDown);
696814
$('#path-info').html(

webapp/static/js/tab-topocola.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,17 @@ function update() {
327327
});
328328
markerPath.exit().remove();
329329

330+
svgPath.selectAll("text.latency").remove();
331+
var markerText = pathsg.selectAll("path.latency").data(markerLinks)
332+
markerText.enter().append("text").attr("dy", ".35em").attr("text-anchor",
333+
"middle").style("font-size", "12px").style("fill", "purple").attr(
334+
"class", function(d) {
335+
return "latency " + d.type;
336+
}).text(function(d) {
337+
return d.latency ? parseFloat(d.latency).toFixed(1) : '';
338+
});
339+
markerText.exit().remove();
340+
330341
var node = circlesg.selectAll(".node").data(realGraphNodes, function(d) {
331342
return d.name;
332343
})
@@ -399,6 +410,13 @@ function update() {
399410
path.attr("d", linkStraight);
400411
markerPath.attr("d", linkArc);
401412
node.attr("transform", nodeTransform);
413+
414+
markerText.attr("x", function(d) {
415+
return ((d.source.x + d.target.x) / 2);
416+
}).attr("y", function(d) {
417+
return ((d.source.y + d.target.y) / 2);
418+
});
419+
402420
});
403421

404422
colaPath.start(50, 100, 200);
@@ -591,7 +609,7 @@ function addFixedLabel(label, x, y, lastLabel) {
591609
/*
592610
* Post-rendering method to draw path arcs for the given path and color.
593611
*/
594-
function drawPath(res, path, color) {
612+
function drawPath(res, path, color, latencies) {
595613
// get the index of the routes to render
596614
var routes = [];
597615
if (path < 0) {
@@ -627,12 +645,16 @@ function drawPath(res, path, color) {
627645
for (var i = 0; i < path_ids.length - 1; i++) {
628646
// prevent src == dst links from being formed
629647
if (path_ids[i] != path_ids[i + 1]) {
648+
console.warn(latencies)
649+
var latInterIntra = latencies ? (latencies[(i * 2) + 1] + latencies[(i * 2) + 2])
650+
: undefined;
630651
graphPath.links.push({
631652
"color" : color,
632653
"path" : true,
633654
"source" : graphPath["ids"][path_ids[i]],
634655
"target" : graphPath["ids"][path_ids[i + 1]],
635-
"type" : "PARENT"
656+
"type" : "PARENT",
657+
"latency" : latInterIntra,
636658
});
637659
}
638660
}

webapp/static/js/webapp.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -463,11 +463,17 @@ function requestEchoByTime(form_data) {
463463
data.runTime = d.graph[i].ActualDuration;
464464
}
465465
console.info(JSON.stringify(data));
466-
console.info('continous echo', 'duration:',
466+
console.info('continuous echo', 'duration:',
467467
d.graph[i].ActualDuration, 'ms');
468468
// use the time the test began
469469
var time = d.graph[i].Inserted - d.graph[i].ActualDuration;
470470
updatePingGraph(chartSE, data, time)
471+
472+
// update latency stats, when valid
473+
if (d.graph[i].ResponseTime > 0) {
474+
setEchoLatency(d.graph[i].Path.match("\\[.*]"),
475+
d.graph[i].ResponseTime);
476+
}
471477
}
472478
}
473479
}
@@ -480,10 +486,10 @@ function requestTraceRouteByTime(form_data) {
480486
console.info('resp:', JSON.stringify(d));
481487
if (d != null) {
482488
if (d.active != null) {
483-
$('#switch_cont').prop("checked", d.active);
484489
if (d.active) {
485490
enableTestControls(false);
486491
lockTab("traceroute");
492+
failContinuousOff();
487493
} else {
488494
enableTestControls(true);
489495
releaseTabs();
@@ -498,11 +504,29 @@ function requestTraceRouteByTime(form_data) {
498504
// result returned, display it and reset progress
499505
handleEndCmdDisplay(d.graph[i].CmdOutput);
500506
}
501-
502-
console.info('continous traceroute', 'duration:',
507+
// var data = {
508+
// 'responseTime' : d.graph[i].ResponseTime,
509+
// 'runTime' : d.graph[i].RunTime,
510+
// 'loss' : d.graph[i].PktLoss,
511+
// 'path' : d.graph[i].Path,
512+
// 'error' : d.graph[i].Error,
513+
// };
514+
// if (data.runTime == 0) {
515+
// // for other errors, use execution time
516+
// data.runTime = d.graph[i].ActualDuration;
517+
// }
518+
// console.info(JSON.stringify(data));
519+
console.info('continuous traceroute', 'duration:',
503520
d.graph[i].ActualDuration, 'ms');
521+
// use the time the test began
522+
var time = d.graph[i].Inserted - d.graph[i].ActualDuration;
523+
// updatePingGraph(chartSE, data, time)
504524

505525
// TODO (mwfarb): implement traceroute graph
526+
527+
// update latency stats
528+
setTracerouteLatency(d.graph[i].Path.match("\\[.*]"),
529+
d.graph[i].TrHops);
506530
}
507531
}
508532
}

webapp/template/index.html

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,10 +411,21 @@ <h2>SCIONLab Apps</h2>
411411
</div>
412412

413413
<div id="as-iflist">
414-
<h2>
415-
Available Paths <span class='badge'>hops</span>
416-
</h2>
417414
<input type="button" value="Update Paths" onclick="requestPaths();" />
415+
<!--
416+
<input type="button" value="Latency"
417+
onclick="surveyLatency();" />
418+
-->
419+
<p>
420+
<div>
421+
<span class='path-text'
422+
style='background-color: black; font-weight: bold;'>
423+
Available Paths</span> <span class='path-text'
424+
style='background-color: gray; font-weight: bold;'>Hops</span> <span
425+
id='path-lat-title'
426+
style='color: purple; position: absolute; right: 5px;'>Latency
427+
</span>
428+
</div>
418429
<p>
419430
<p id="path-info"></p>
420431
</div>

0 commit comments

Comments
 (0)