diff --git a/master/status_httpd.cc b/master/status_httpd.cc
index 3c807783ccbdde7415aed9198d201e93fd8bcb9d..e1e1e6793ff2a8fd8cffa2b52759fd5b985b0c9e 100644
--- a/master/status_httpd.cc
+++ b/master/status_httpd.cc
@@ -1,15 +1,62 @@
 // $Id$
 
+#include <numeric>
 #include <iostream>
 #include <sstream>
 #include <string>
 #include "status_httpd.h"
 
+using namespace std;
+
 namespace dos {
 
+static void normalize(vector<double>& values)
+{
+  ostringstream ds;
+  double min = min_element(values.begin(), values.end());
+  double max = max_element(values.begin(), values.end());
+  vector<double>::iterator i;
+  for (i = values.begin(); i != values.end(); ++i)
+    *i = (*i - min) / (max - min);
+}
+
+static string to_dataset(vector<double>& values)
+{
+  static const char vchar[] = 
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+  normalize(values);
+  ostringstream ds;
+  vector<double>::const_iterator i;
+  for (i = values.begin(); i != values.end(); ++i)
+    ds << vchar[static_cast<int>(100 * (*i))];
+  return ds.str();
+}
+
+static string qps_graph(const vector<QpsTuple>& qps_values, 
+                        int width=500, int height=200) 
+{
+  ostringstream url;
+  url << "http://chart.apis.google.com/chart"
+      << "?chs=" << width << "x" << height
+      << "&cht=lc";
+
+  vector<double> stdup, avg, stddown;
+  vector<QpsTuple>::const_iterator i;
+  for (i = qps_values.begin(); i != qps_values.end(); ++i) {
+    stdup.push_back((*i).value + (*i).std_dev);
+    avg.push_back((*i).value);
+    stddown.push_back((*i).value - (*i).std_dev);
+  }
+
+  url << "&chd=s:"
+      << to_dataset(stdup) << ","
+      << to_dataset(avg) << ","
+      << to_dataset(stddown);
+}
+
 void StatusHttpd::handle_status(evhttp_request *req)
 {
-  std::ostringstream resp;
+  ostringstream resp;
 
   resp << "<?xml version=\"1.0\"?>\n"
        << "<html lang=\"en\">\n"
@@ -19,13 +66,20 @@ void StatusHttpd::handle_status(evhttp_request *req)
 
   resp << "<h1>NoDDoS Master</h1>";
 
-  resp << "<p>Global QPS: <b>" << logic->get_qps() << "</b></p>"
+  vector<QpsTuple> qps_values;
+  logic->get_store()->read_stats(qps_values, 24);
+  string graph_url = qps_graph(qps_values);
+  resp << "<table><tr><td valign=\"top\">"
+       << "<p>Global QPS: <b>" << logic->get_qps() << "</b></p>"
        << "<p>Global status: <b>" << logic->get_status().str() 
-       << "</b></p>\n";
+       << "</b></p>\n"
+       << "</td><td>"
+       << "<img src=\"" << graph_url << "\" border=\"0\"/>"
+       << "</td></tr></table>\n";
 
   resp << "<h3>Nodes</h3><ul>";
-  std::vector<std::string> nodes = logic->nodes();
-  std::vector<std::string>::const_iterator i;
+  vector<string> nodes = logic->nodes();
+  vector<string>::const_iterator i;
   for (i = nodes.begin(); i != nodes.end(); i++)
     resp << "<li><a href=\"http://" << (*i)
          << "/\">" << (*i) << "</a></li>";
@@ -33,7 +87,7 @@ void StatusHttpd::handle_status(evhttp_request *req)
 
   resp << "<h3>Blacklisted hosts</h3><table class=\"d\">"
        << "<thead><tr><th>IP</th></tr></thead><tbody>";
-  std::vector<std::string> blacklist = logic->get_blacklist();
+  vector<string> blacklist = logic->get_blacklist();
   for (i = blacklist.begin(); i != blacklist.end(); i++)
     resp << "<tr><td>" << (*i) << "</td></tr>";
   resp << "</tbody></table>\n";