[llvm-commits] [zorg] r125906 - in /zorg/trunk/llvmlab/llvmlab: ci/status.py ui/app.py ui/ci/views.py ui/templates/buildbot_monitor.html

Daniel Dunbar daniel at zuster.org
Fri Feb 18 08:43:00 PST 2011


Author: ddunbar
Date: Fri Feb 18 10:43:00 2011
New Revision: 125906

URL: http://llvm.org/viewvc/llvm-project?rev=125906&view=rev
Log:
llvmlab: Start sketching code to actively monitor a buildbot instance from the
web app and add a simple monitor page for debugging.

Added:
    zorg/trunk/llvmlab/llvmlab/ui/templates/buildbot_monitor.html
Modified:
    zorg/trunk/llvmlab/llvmlab/ci/status.py
    zorg/trunk/llvmlab/llvmlab/ui/app.py
    zorg/trunk/llvmlab/llvmlab/ui/ci/views.py

Modified: zorg/trunk/llvmlab/llvmlab/ci/status.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/llvmlab/llvmlab/ci/status.py?rev=125906&r1=125905&r2=125906&view=diff
==============================================================================
--- zorg/trunk/llvmlab/llvmlab/ci/status.py (original)
+++ zorg/trunk/llvmlab/llvmlab/ci/status.py Fri Feb 18 10:43:00 2011
@@ -2,6 +2,9 @@
 Status information for the CI infrastructure, for use by the dashboard.
 """
 
+import threading
+import time
+
 from llvmlab import util
 import buildbot.statusclient
 
@@ -33,6 +36,65 @@
         self.start_time = start_time
         self.end_time = end_time
 
+class StatusMonitor(threading.Thread):
+    def __init__(self, status):
+        threading.Thread.__init__(self)
+        self.status = status
+
+    def run(self):
+        # Constantly read events from the status client.
+        while 1:
+            for event in self.status.statusclient.pull_events():
+                # Log the event (for debugging).
+                self.status.event_log.append((time.time(), event))
+                self.status.event_log = self.status.event_log[-100:]
+
+                kind = event[0]
+                if kind == 'added_builder':
+                    name = event[1]
+                    if name not in self.status.builders:
+                        self.status.builders[name] = []
+                        self.status.build_map[name] = {}
+                elif kind == 'removed_builder':
+                    name = event[1]
+                    self.status.builders.pop(name)
+                    self.status.build_map.pop(name)
+                elif kind == 'reset_builder':
+                    name = event[1]
+                    self.status.builders[name] = []
+                    self.status.build_map[name] = {}
+                elif kind == 'invalid_build':
+                    _,name,id = event
+                    build = self.status.build_map[name].get(id)
+                    if build is not None:
+                        self.status.builders[name].remove(build)
+                        self.status.build_map[name].pop(id)
+                elif kind in ('add_build', 'completed_build'):
+                    _,name,id = event
+                    build = self.status.build_map[name].get(id)
+                    if build is None:
+                        build = BuildStatus(name, id, None, None, None, None)
+                        self.status.build_map[name][id] = build
+
+                        # Add to the builds list, maintaining order.
+                        builds = self.status.builders[name]
+                        builds.append(build)
+                        if len(builds)>1 and build.number < builds[-2].number:
+                            builds.sort(key = lambda b: b.number)
+
+                    # Get the build information.
+                    res = self.status.statusclient.get_json_result((
+                            'builders', name, 'builds', str(build.number)))
+                    build.result = res['results']
+                    build.source_stamp = res['sourceStamp']['revision']
+                    build.start_time = res['times'][0]
+                    build.end_time = res['times'][1]
+                else:
+                    # FIXME: Use flask logging APIs.
+                    print >>sys.stderr,"warning: unknown event '%r'" % (event,)
+
+            time.sleep(.1)
+        
 class Status(util.simple_repr_mixin):
     @staticmethod
     def fromdata(data):
@@ -63,3 +125,15 @@
         if statusclient is None and master_url:
             statusclient = buildbot.statusclient.StatusClient(master_url)
         self.statusclient = statusclient
+
+        # Transient data.
+        self.event_log = []
+        self.build_map = dict((name, dict((b.number, b)
+                                          for b in builds))
+                              for name,builds in self.builders.items())
+
+    def start_monitor(self):
+        if self.statusclient:
+            monitor = StatusMonitor(self)
+            monitor.start()
+            return monitor

Modified: zorg/trunk/llvmlab/llvmlab/ui/app.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/llvmlab/llvmlab/ui/app.py?rev=125906&r1=125905&r2=125906&view=diff
==============================================================================
--- zorg/trunk/llvmlab/llvmlab/ui/app.py (original)
+++ zorg/trunk/llvmlab/llvmlab/ui/app.py Fri Feb 18 10:43:00 2011
@@ -32,6 +32,9 @@
         app.register_module(ci_views)
         app.register_module(frontend_views)
 
+        # Spawn the status monitor thread.
+        app.monitor = app.config.status.start_monitor()
+
         return app
 
     @staticmethod
@@ -62,6 +65,7 @@
 
     def __init__(self, name):
         super(App, self).__init__(name)
+        self.monitor = None
 
     def load_config(self, config = None, config_path = None):
         if config_path is not None:

Modified: zorg/trunk/llvmlab/llvmlab/ui/ci/views.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/llvmlab/llvmlab/ui/ci/views.py?rev=125906&r1=125905&r2=125906&view=diff
==============================================================================
--- zorg/trunk/llvmlab/llvmlab/ui/ci/views.py (original)
+++ zorg/trunk/llvmlab/llvmlab/ui/ci/views.py Fri Feb 18 10:43:00 2011
@@ -80,3 +80,7 @@
 def dashboard():
     return render_template("dashboard.html", ci_config=g_config)
 
+ at ci.route('/monitor')
+def buildbot_monitor():
+    return render_template("buildbot_monitor.html",
+                           bb_status=current_app.config.status)

Added: zorg/trunk/llvmlab/llvmlab/ui/templates/buildbot_monitor.html
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/llvmlab/llvmlab/ui/templates/buildbot_monitor.html?rev=125906&view=auto
==============================================================================
--- zorg/trunk/llvmlab/llvmlab/ui/templates/buildbot_monitor.html (added)
+++ zorg/trunk/llvmlab/llvmlab/ui/templates/buildbot_monitor.html Fri Feb 18 10:43:00 2011
@@ -0,0 +1,50 @@
+{% extends "layout.html" %}
+{% block title %}buildbot monitor{% endblock %}
+{% block body %}
+
+<h1>Buildbot Status Monitor</h1>
+
+<b>Monitoring:</b> {{ bb_status.master_url }}
+
+{% for name,builds in bb_status.builders|dictsort %}
+
+<h3>{{ name }}</h3>
+
+<table>
+<thead>
+  <tr>
+    <th>Number</th>
+    <th>Source Stamp</th>
+    <th>Result</th>
+    <th>Start Time</th>
+    <th>End Time</th>
+  </tr>
+</thead>
+{% for build in builds %}
+<tr>
+  <td>{{ build.number }}</td>
+  <td>{{ build.source_stamp }}</td>
+  <td>{{ build.result }}</td>
+  <td>{{ build.start_time }}</td>
+  <td>{{ build.end_time }}</td>
+</tr>
+{% endfor %}
+</table>
+
+{% endfor %}
+
+<h2>Event Log</h2>
+
+<table>
+<thead>
+  <tr><th>Time</th><th>Event</th></tr>
+</thead>
+{% for time,event in bb_status.event_log|reverse %}
+<tr>
+  <td>{{ time }}</td>
+  <td>{{ event }}</td>
+</tr>
+{% endfor %}
+</table>
+
+{% endblock %}





More information about the llvm-commits mailing list