[Piglit] [PATCH 2/2] framework/log: add an HTTP logger

Thomas Wood thomas.wood at intel.com
Tue Sep 22 09:22:24 PDT 2015


Add an HTTP logger so that it is possible to monitor the progress and
status of piglit remotely through a webserver. The webserver runs on
port 8080 by default and can be configured to run on a different port by
setting the "port" key in the "http" section of the configuration file.
The server responds to requests for /summary, which provides a summary
of the current state in JSON format.

v2: Add appropriate locking when reading state data for the web server
    Stop the server after the request for the final results
    Remove the full results page
    Add a configuration option to set the server port

Signed-off-by: Thomas Wood <thomas.wood at intel.com>
---
 framework/log.py          | 76 +++++++++++++++++++++++++++++++++++++++++++++++
 framework/programs/run.py |  2 +-
 2 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/framework/log.py b/framework/log.py
index 6d5a31c..868561e 100644
--- a/framework/log.py
+++ b/framework/log.py
@@ -32,6 +32,14 @@ import abc
 import itertools
 import threading
 import collections
+import ConfigParser
+from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+try:
+    import simplejson as json
+except ImportError:
+    import json
+
+from framework.core import PIGLIT_CONFIG
 
 __all__ = ['LogManager']
 
@@ -252,6 +260,68 @@ class DummyLog(BaseLog):
         pass
 
 
+class HTTPLogServer(threading.Thread):
+    class RequestHandler(BaseHTTPRequestHandler):
+        INDENT = 4
+
+        def do_GET(self):
+            if self.path == "/summary":
+                self.send_response(200)
+                self.end_headers()
+                with self.server.state_lock:
+                    status = {
+                        "complete": self.server.state["complete"],
+                        "running" : self.server.state["running"],
+                        "total"   : self.server.state["total"],
+                        "results" : self.server.state["summary"],
+                    }
+                self.wfile.write(json.dumps(status, indent=self.INDENT))
+            else:
+                self.send_response(404)
+                self.end_headers()
+
+    def __init__(self, state, state_lock):
+        super(HTTPLogServer, self).__init__()
+        try:
+            port = PIGLIT_CONFIG.getint("http", "port")
+        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
+            port = 8080
+        self._httpd = HTTPServer(("", port), HTTPLogServer.RequestHandler)
+        self._httpd.state = state
+        self._httpd.state_lock = state_lock
+
+    def run(self):
+        while True:
+            with self._httpd.state_lock:
+                # stop handling requests after the request for the final results
+                if self._httpd.state["complete"] == self._httpd.state["total"]:
+                    break;
+            self._httpd.handle_request()
+
+
+class HTTPLog(BaseLog):
+    """ A Logger that serves status information over http """
+
+    def __init__(self, state, state_lock):
+        super(HTTPLog, self).__init__(state, state_lock)
+        self._name = None
+
+    def start(self, name):
+        with self._LOCK:
+            self._name = name
+            self._state['running'].append(self._name)
+
+    def log(self, status):
+        with self._LOCK:
+            self._state['running'].remove(self._name)
+            self._state['complete'] += 1
+            assert status in self.SUMMARY_KEYS
+            self._state['summary'][status] += 1
+
+    def summary(self):
+        pass
+
+
 class LogManager(object):
     """ Creates new log objects
 
@@ -274,6 +344,7 @@ class LogManager(object):
         'quiet': QuietLog,
         'verbose': VerboseLog,
         'dummy': DummyLog,
+        'http': HTTPLog,
     }
 
     def __init__(self, logger, total):
@@ -288,6 +359,11 @@ class LogManager(object):
         }
         self._state_lock = threading.Lock()
 
+        # start the http server for http logger
+        if logger == 'http':
+            self.log_server = HTTPLogServer(self._state, self._state_lock)
+            self.log_server.start()
+
     def get(self):
         """ Return a new log instance """
         return self._log(self._state, self._state_lock)
diff --git a/framework/programs/run.py b/framework/programs/run.py
index bf8cc10..da99ac6 100644
--- a/framework/programs/run.py
+++ b/framework/programs/run.py
@@ -158,7 +158,7 @@ def _run_parser(input_):
     log_parser.add_argument("-l", "--log-level",
                             dest="log_level",
                             action="store",
-                            choices=['quiet', 'verbose', 'dummy'],
+                            choices=['quiet', 'verbose', 'dummy', 'http'],
                             default='quiet',
                             help="Set the logger verbosity level")
     parser.add_argument("--test-list",
-- 
1.9.1



More information about the Piglit mailing list