summaryrefslogtreecommitdiffstats
path: root/mirrors
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2012-11-10 17:09:51 -0600
committerDan McGee <dan@archlinux.org>2012-11-11 14:36:14 -0600
commita358e132886972dc4e9f1f546e36a5f3a2218a39 (patch)
tree5443b12922e987f9a9afee5492703cbdce516e13 /mirrors
parentaeeb4718e83cd2f82d94b1aa0c0ba36ba21a2b37 (diff)
downloadarchweb-a358e132886972dc4e9f1f546e36a5f3a2218a39.tar.gz
archweb-a358e132886972dc4e9f1f546e36a5f3a2218a39.zip
Mirror status graph, now with points AND lines
We might have to tweak the interpolation method once we see this with real data, but for now it looks really pretty locally. Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'mirrors')
-rw-r--r--mirrors/static/mirror_status.js58
-rw-r--r--mirrors/views.py3
2 files changed, 44 insertions, 17 deletions
diff --git a/mirrors/static/mirror_status.js b/mirrors/static/mirror_status.js
index 277d3c88..d107d7d1 100644
--- a/mirrors/static/mirror_status.js
+++ b/mirrors/static/mirror_status.js
@@ -6,7 +6,7 @@ function mirror_status(chart_id, data_url) {
width = jq_div.width() - margin.left - margin.right,
height = jq_div.height() - margin.top - margin.bottom;
- var color = d3.scale.category20(),
+ var color = d3.scale.category10(),
x = d3.time.scale.utc().range([0, width]),
y = d3.scale.linear().range([height, 0]),
x_axis = d3.svg.axis().scale(x).orient("bottom"),
@@ -20,8 +20,14 @@ function mirror_status(chart_id, data_url) {
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
- x.domain(d3.extent(data, function(d) { return d.check_time; })).nice(d3.time.hour);
- y.domain(d3.extent(data, function(d) { return d.duration; })).nice();
+ x.domain([
+ d3.min(data, function(c) { return d3.min(c.logs, function(v) { return v.check_time; }); }),
+ d3.max(data, function(c) { return d3.max(c.logs, function(v) { return v.check_time; }); })
+ ]);
+ y.domain([
+ d3.min(data, function(c) { return d3.min(c.logs, function(v) { return v.duration; }); }),
+ d3.max(data, function(c) { return d3.max(c.logs, function(v) { return v.duration; }); })
+ ]);
/* build the axis lines... */
svg.append("g")
@@ -46,12 +52,32 @@ function mirror_status(chart_id, data_url) {
.style("text-anchor", "end")
.text("Duration (seconds)");
- /* ...then the points themselves. */
- svg.selectAll(".dot")
+ var line = d3.svg.line()
+ .interpolate("basis")
+ .x(function(d) { return x(d.check_time); })
+ .y(function(d) { return y(d.duration); });
+
+ /* ...then the points and lines between them. */
+ var urls = svg.selectAll(".url")
.data(data)
.enter()
+ .append("g")
+ .attr("class", "url");
+
+ urls.append("path")
+ .attr("class", "url-line")
+ .attr("d", function(d) { return line(d.logs); })
+ .style("stroke", function(d) { return color(d.url); });
+
+ urls.selectAll("circle")
+ .data(function(u) {
+ return jQuery.map(u.logs, function(l, i) {
+ return {url: u.url, check_time: l.check_time, duration: l.duration};
+ });
+ })
+ .enter()
.append("circle")
- .attr("class", "dot")
+ .attr("class", "url-dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.check_time); })
.attr("cy", function(d) { return y(d.duration); })
@@ -81,16 +107,16 @@ function mirror_status(chart_id, data_url) {
/* invoke the data-fetch + first draw */
var cached_data = null;
d3.json(data_url, function(json) {
- cached_data = jQuery.map(json['urls'],
- function(url, i) {
- return jQuery.map(url['logs'],
- function(log, j) {
- return {
- url: url['url'],
- duration: log['duration'],
- check_time: new Date(log['check_time'])
- };
- });
+ cached_data = jQuery.map(json.urls, function(url, i) {
+ return {
+ url: url.url,
+ logs: jQuery.map(url.logs, function(log, j) {
+ return {
+ duration: log.duration,
+ check_time: new Date(log.check_time)
+ };
+ })
+ };
});
draw_graph(cached_data);
});
diff --git a/mirrors/views.py b/mirrors/views.py
index 4b9721dc..be01e919 100644
--- a/mirrors/views.py
+++ b/mirrors/views.py
@@ -267,7 +267,8 @@ class ExtendedMirrorStatusJSONEncoder(MirrorStatusJSONEncoder):
if isinstance(obj, MirrorUrl):
data = super(ExtendedMirrorStatusJSONEncoder, self).default(obj)
cutoff = now() - DEFAULT_CUTOFF
- data['logs'] = obj.logs.filter(check_time__gte=cutoff)
+ data['logs'] = obj.logs.filter(
+ check_time__gte=cutoff).order_by('check_time')
return data
if isinstance(obj, MirrorLog):
data = dict((attr, getattr(obj, attr))