TPView: Python server for loading/saving logs on the workstation
This CL extends tpview by a python server which can read/save log files
on the workstation. By accessing /edit/logname TPView will load the log
file tpview/logs/logfile.log and after shrinking save it as
/tpview/logs/logfile.log.trimmed.
TEST=python server.py
BUG=chromium-os:38304
Change-Id: I219f8950273e4027f1501d223362a25c02a9674a
Reviewed-on: https://gerrit.chromium.org/gerrit/42180
Reviewed-by: Dennis Kempin <denniskempin@chromium.org>
Commit-Queue: Dennis Kempin <denniskempin@chromium.org>
Tested-by: Dennis Kempin <denniskempin@chromium.org>
diff --git a/tpview/server.py b/tpview/server.py
new file mode 100644
index 0000000..d91b957
--- /dev/null
+++ b/tpview/server.py
@@ -0,0 +1,108 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from SimpleHTTPServer import SimpleHTTPRequestHandler
+import cgi
+import json
+import os
+import shutil
+import SimpleHTTPServer
+import socket
+import SocketServer
+import sys
+import threading
+
+# change into script in order to serve tpview files
+script_dir = os.path.dirname(os.path.realpath(__file__))
+os.chdir(script_dir)
+
+class ServerData(object):
+ def __init__(self, log):
+ self.log = log
+ self.loaded = False
+ self.saved = False
+ self.result = None
+
+class TPViewHTTPRequestHandler(SimpleHTTPRequestHandler):
+ """
+ serves static files and provides three dynamic URLs:
+ /edit serving view.html
+ /load/* serving the log file provided when starting the server
+ /save/* for POST'ing trimmed log files
+
+ The latter two are only to be used with AJAX commands from
+ /edit
+ """
+ def respond(self, data, type="text/html"):
+ # send text response to browser
+ self.send_response(200)
+ self.send_header("Content-type", type)
+ self.end_headers()
+ self.wfile.write(data)
+
+ def do_GET(self):
+ data = self.server.user_data
+
+ if self.path.startswith("/load/"):
+ self.respond(data.log, "text/plain")
+ data.loaded = True
+
+ elif self.path.startswith("/edit"):
+ self.path = "view.html"
+ SimpleHTTPRequestHandler.do_GET(self)
+
+ else:
+ SimpleHTTPRequestHandler.do_GET(self)
+
+ def do_POST(self):
+ data = self.server.user_data
+
+ if self.path.startswith("/save/"):
+ name = os.path.basename(self.path)
+ length = int(self.headers.getheader('content-length'))
+ data.result = self.rfile.read(length)
+ data.saved = True
+ self.respond("Success")
+
+
+def View(port, log=None, persistent=False):
+ """
+ Serve TPView viewing 'log'. The server will exit after serving TPView
+ unless persistent is set to True.
+ """
+ data = ServerData(log)
+ httpd = SocketServer.TCPServer(("", port), TPViewHTTPRequestHandler)
+ httpd.user_data = data
+
+ while True:
+ httpd.handle_request()
+ if not persistent and data.loaded:
+ return
+
+
+def Edit(port, log=None):
+ """
+ Serve TPView for editing 'log'. Blocks until the file has been trimmed
+ and returns the trimmed log.
+ """
+ data = ServerData(log)
+ httpd = SocketServer.TCPServer(("", port), TPViewHTTPRequestHandler)
+ httpd.user_data = data
+
+ while True:
+ httpd.handle_request()
+ if data.saved:
+ return data.result
+
+
+def Serve(port):
+ """
+ Serve TPView without any log data. The server will serve until killed
+ externally (e.g. via keyboard interrupt).
+ """
+ data = ServerData("")
+ httpd = SocketServer.TCPServer(("", port), TPViewHTTPRequestHandler)
+ httpd.user_data = data
+ while True:
+ httpd.handle_request()
diff --git a/tpview/view.html b/tpview/view.html
index 7da5d93..50e053f 100644
--- a/tpview/view.html
+++ b/tpview/view.html
@@ -2,26 +2,30 @@
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Touchpad Log Viewer</title>
-<link type="text/css" href="css/smoothness/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
+<link type="text/css" href="css/smoothness/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
<script src="js/jquery-1.6.4.min.js"></script>
<script src="js/jquery.mousewheel.js"></script>
<script src="js/jquery-ui-1.8.16.custom.min.js"></script>
<script src="js/bzip2.js"></script>
<script src="js/base64-binary.js"></script>
<script src="js/jsxcompressor.js"></script>
+<script src="js/purl.js"></script>
<script src="finger_view_controller.js"></script>
<script src="graph_controller.js"></script>
<script src="secret_entries.js"></script>
-<link rel="stylesheet" href="style.css" type="text/css" media="all" />
+<link rel="stylesheet" href="/style.css" type="text/css" media="all" />
<script type="text/javascript" charset="utf-8">
var finger_view_controller;
var current_layer = 0;
var json_obj;
+var use_server = false;
+var logname = undefined;
+
function update_range(event, ui) {
finger_view_controller.setRange(ui.values[0], ui.values[1]);
var begin_event = finger_view_controller.getEvent(ui.values[0]);
@@ -371,6 +375,12 @@
var snippet = finger_view_controller.getSnippet(values[0], values[1]);
$('#text_box').val(JSON.stringify(snippet, null, 2));
loadLogObj(snippet, true);
+
+ if (use_server) {
+ $.post('/save/' + logname, JSON.stringify(snippet, null, 2), function () {
+ alert("Saved");
+ });
+ }
}
function generateRadioButtons(obj) {
@@ -613,7 +623,17 @@
};
reader.readAsArrayBuffer(document.getElementById('bzipupload').files[0]);
});
- loadLog(secret_obj);
+
+ logname = $.url().fparam('id');
+ use_server = logname !== '';
+
+ if (use_server) {
+ $.get('/load/' + logname, function(data) {
+ loadLog(data);
+ }, 'json');
+ } else {
+ loadLog(secret_obj);
+ }
});
</script>