4233: redraw graph when processing log events
[arvados.git] / apps / workbench / app / assets / javascripts / event_log.js
index 61b4fdcda1100111011b7f732ab353135c37f3d9..10fe5be8f10a024b9bb0133bb18cf9ecd903e663 100644 (file)
 /*
- * This file establishes a websockets connection with the API Server.
- *
- * The subscribe method takes a window element id and object id. Any log
- * events for that particular object id are added to that window element.
+ * This js establishes a websockets connection with the API Server.
  */
 
-var event_log_disp;
-
-function subscribeToEventLog (elementId) {
-  // if websockets are not supported by browser, do not attempt to subscribe for events
-  websocketsSupported = ('WebSocket' in window);
-  if (websocketsSupported == false) {
-    return;  
-  }
+/* Subscribe to websockets event log.  Do nothing if already connected. */
+function subscribeToEventLog () {
+    // if websockets are not supported by browser, do not subscribe for events
+    websocketsSupported = ('WebSocket' in window);
+    if (websocketsSupported == false) {
+        return;
+    }
 
-  // grab websocket connection from window, if one exists
-  event_log_disp = $(window).data("arv-websocket");
-  if (event_log_disp == null) {
-    // create the event log dispatcher
-    event_log_disp = new WebSocket($(window).data("websocket-url"));
+    // check if websocket connection is already stored on the window
+    event_log_disp = $(window).data("arv-websocket");
+    if (event_log_disp == null) {
+        // need to create new websocket and event log dispatcher
+        websocket_url = $('meta[name=arv-websocket-url]').attr("content");
+        if (websocket_url == null)
+            return;
 
-    event_log_disp.onopen = function(event) { onEventLogDispatcherOpen(event) };
-    event_log_disp.onmessage = function(event) { onEventLogDispatcherMessage(event) };
+        event_log_disp = new WebSocket(websocket_url);
 
-    // store websocket in window to allow reuse when multiple divs subscribe for events
-    $(window).data("arv-websocket", event_log_disp);
-  }
+        event_log_disp.onopen = onEventLogDispatcherOpen;
+        event_log_disp.onmessage = onEventLogDispatcherMessage;
 
-  // Add the elementId to listener map
-  event_log_listener_map = $(window).data("event_log_listener_map");
-  if (event_log_listener_map == null)
-    event_log_listener_map = {};
-  event_log_listener_map[elementId] = $(window).data("listening-uuid");
-  $(window).data("event_log_listener_map", event_log_listener_map);
+        // store websocket in window to allow reuse when multiple divs subscribe for events
+        $(window).data("arv-websocket", event_log_disp);
+    }
 }
 
+/* Send subscribe message to the websockets server.  Without any filters
+   arguments, this subscribes to all events */
 function onEventLogDispatcherOpen(event) {
-  event_log_disp.send('{"method":"subscribe"}');
+    this.send('{"method":"subscribe"}');
 }
 
-// Check each of the entries in the listener map. If any are waiting for
-// an event of this event's object, append to their registered element
+/* Trigger event for all applicable elements waiting for this event */
 function onEventLogDispatcherMessage(event) {
-  event_log_listener_map = $(window).data("event_log_listener_map");
+    parsedData = JSON.parse(event.data);
+    object_uuid = parsedData.object_uuid;
+
+    if (!object_uuid) {
+        return;
+    }
 
-  for (var key in event_log_listener_map) {
-    value = event_log_listener_map[key];
+    // if there are any listeners for this object uuid or "all", trigger the event
+    matches = ".arv-log-event-listener[data-object-uuid=\"" + object_uuid + "\"],.arv-log-event-listener[data-object-uuids~=\"" + object_uuid + "\"],.arv-log-event-listener[data-object-uuid=\"all\"],.arv-log-event-listener[data-object-kind=\"" + parsedData.object_kind + "\"]";
+    $(matches).trigger('arv-log-event', parsedData);
+}
 
-    new_properties = "";
-    eventData = JSON.parse(event.data);
-    if (value === eventData.object_uuid) {
-      properties = eventData.properties;
-      if (properties !== null) {
-        new_attributes = properties.new_attributes;
-        if (new_attributes !== null) {
-          new_properties = JSON.stringify(properties.new_attributes);
-        }
-      }
+/* Automatically connect if there are any elements on the page that want to
+   receive event log events. */
+$(document).on('ajax:complete ready', function() {
+    var a = $('.arv-log-event-listener');
+    if (a.length > 0) {
+        subscribeToEventLog();
+    }
+});
 
-      // append to the registered element
-      $('#'+key).append(eventData.summary + " " + new_properties + "
");
+
+function processLogLineForChart( logLine, jobGraphSeries, jobGraphData ) {
+    var match = logLine.match(/(.*)crunchstat:(.*)-- interval(.*)/);
+    if( match ) {
+        var series = match[2].trim().split(' ')[0];
+        if( $.inArray( series, jobGraphSeries) < 0 ) {
+            jobGraphSeries.push(series);
+        }
+        var intervalData = match[3].trim().split(' ');
+        var dt = parseFloat(intervalData[0]);
+        var dsum = 0.0;
+        for(var i=2; i < intervalData.length; i += 2 ) {
+            dsum += parseFloat(intervalData[i]);
+        }
+        var datum = (dsum/dt).toFixed(4);
+        var preamble = match[1].trim().split(' ');
+        var timestamp = preamble[0].replace('_','T');
+        var xpoints = $.grep( jobGraphData, function(e){ return e['t'] === timestamp; });
+        if(xpoints.length) {
+            // xpoints[0] is the x point that that matched the timestamp and so already existed: add the new datum
+            xpoints[0][series] = datum;
+        } else {
+            var entry = { 't': timestamp };
+            entry[series] = datum;
+            jobGraphData.push( entry );
+        }
     }
-  }
 }
+
+$(document).on('arv-log-event', '#log_graph_div', function(event, eventData) {
+    if( eventData.properties.text ) {
+        var series_length = jobGraphSeries.length;
+        processLogLineForChart( eventData.properties.text, jobGraphSeries, jobGraphData);
+        if( series_length < jobGraphSeries.length) {
+            // series have changed, draw entirely new graph
+            $('#log_graph_div').html('');
+            jobGraph = Morris.Line({
+                element: 'log_graph_div',
+                data: jobGraphData,
+                xkey: 't',
+                ykeys: jobGraphSeries,
+                labels: jobGraphSeries
+            });
+        } else {
+            jobGraph.setData( jobGraphData );
+        }
+    }
+
+} );
\ No newline at end of file