Commits

Sylvain Hellegouarch committed c899e1b

monitor HTTP traffic through websockets

Comments (0)

Files changed (2)

web/websockets/http_traffic/__init__.py

+# -*- coding: utf-8 -*-
+import json
+import logging
+import os
+import random
+
+import cherrypy
+from cherrypy.lib import cpstats
+from cherrypy.process import plugins
+
+from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
+from ws4py.websocket import WebSocket
+from ws4py.messaging import TextMessage
+
+base_dir = os.path.abspath(os.path.dirname(__file__))
+
+class MetricsWebSocketHandler(WebSocket):
+    def received_message(self, m):
+        pass
+
+class MetricsBroadcaster(plugins.Monitor):
+    def __init__(self, bus):
+        plugins.Monitor.__init__(self, bus, callback=self.broadcast, frequency=0.2)
+
+    def broadcast(self):
+        s = cpstats.extrapolate_statistics(logging.statistics)
+        data = []
+        for k in s:
+            if k.startswith("CherryPy HTTPServer"):
+                for w in s[k]["Worker Threads"]:
+                    data.append(s[k]["Worker Threads"][w])
+                break
+            
+        data = json.dumps(data, sort_keys=True, indent=4)
+        cherrypy.engine.publish('websocket-broadcast', TextMessage(data))
+        
+class Root(object):
+    @cherrypy.expose
+    def index(self):
+        return file(os.path.join(base_dir, 'index.html'))
+
+    @cherrypy.expose
+    def dummy(self):
+        return '*' * random.randint(1, 256)
+
+    @cherrypy.expose
+    def metrics(self):
+        cherrypy.log("Handler created: %s" % repr(cherrypy.request.ws_handler))
+        
+if __name__ == '__main__':
+    
+    root = Root()
+    root.cpstats = cpstats.StatsPage()
+    
+    cherrypy.config.update({'server.socket_port': 8090,
+                            'server.statistics': True,
+                            'server.thread_pool': 3})
+
+    WebSocketPlugin(cherrypy.engine).subscribe()
+    cherrypy.tools.websocket = WebSocketTool()
+
+    MetricsBroadcaster(cherrypy.engine).subscribe()
+    
+    cherrypy.quickstart(root, '/', {
+        '/': {
+            'tools.cpstats.on': True
+            },
+        '/metrics': {
+            'tools.cpstats.on': False,
+            'tools.websocket.on': True,
+            'tools.websocket.handler_cls': MetricsWebSocketHandler
+            }
+        }
+    )

web/websockets/http_traffic/index.html

+<html>
+    <head>
+      <script type="application/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+      <script type="application/javascript" src="https://raw.github.com/joewalnes/smoothie/master/smoothie.js"></script>
+      <script type="application/javascript">
+        $(document).ready(function() {
+	  var dummytimer = null;
+	
+	  var smoothie = new SmoothieChart({ grid: { strokeStyle: 'rgb(125, 0, 0)', fillStyle: 'rgb(60, 0, 0)', lineWidth: 1, millisPerLine: 250, verticalSections: 6 } });
+	  smoothie.streamTo(document.getElementById("metrics"));
+	  var worker1 = new TimeSeries();
+	  var worker2 = new TimeSeries();
+	  var worker3 = new TimeSeries();
+
+          websocket = "ws://localhost:8090/metrics";
+          if (window.WebSocket) {
+            ws = new WebSocket(websocket);
+          }
+          else if (window.MozWebSocket) {
+            ws = MozWebSocket(websocket);
+          }
+          else {
+            console.log("WebSocket Not Supported");
+            return;
+          }
+
+          window.onbeforeunload = function(e) {
+            ws.close(1000, "Client left");
+                 
+            if(!e) e = window.event;
+            e.stopPropagation();
+            e.preventDefault();
+          };
+          ws.onmessage = function (evt) {
+	    var now = new Date().getTime();
+	    $("#data").text(evt.data);
+	    var data = $.parseJSON(evt.data);
+	    worker1.append(now, data[0]["Bytes Written"]);
+	    worker2.append(now, data[1]["Bytes Written"]);
+	    worker3.append(now, data[2]["Bytes Written"]);
+          };
+          ws.onopen = function() {
+	    smoothie.addTimeSeries(worker1, { strokeStyle: 'rgb(0, 255, 0)', fillStyle: 'rgba(0, 255, 0, 0.4)', lineWidth: 3 });
+	    smoothie.addTimeSeries(worker2, { strokeStyle: 'rgb(255, 0, 255)', fillStyle: 'rgba(255, 0, 255, 0.3)', lineWidth: 3 });
+	    smoothie.addTimeSeries(worker3, { strokeStyle: 'rgb(0, 0, 255)', fillStyle: 'rgba(0, 255, 255, 0.8)', lineWidth: 3 });
+	
+	    var dummytimer = setInterval(function() {
+	       $.ajax({url: "http://localhost:8090/dummy"})
+	    }, 1000);
+          };
+          ws.onclose = function(evt) {
+	    clearInterval(dummytimer);
+          };
+        });
+      </script>
+    </head>
+    <body>
+      <canvas id="metrics" width="900" height="400"></canvas>
+      <p id="data" />
+    </body>
+    </html>