Bug 1324929 - Accept ':' between url and line number in server side logs backtraces. r=ochameau
authorFlorian Apolloner <florian@apolloner.eu>
Wed, 04 Jan 2017 09:11:24 -0800
changeset 327962 3535ad342933572ba2c93f056a9cdb44a085a6cf
parent 327961 8a281e6c7c56a7aa2d77b556f42fedfa2baa365a
child 327963 f9f9d3744d492aa998e893e8243d4d5aa3057f41
push id31160
push userphilringnalda@gmail.com
push dateThu, 05 Jan 2017 02:33:44 +0000
treeherdermozilla-central@f13abb8ba9f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1324929
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1324929 - Accept ':' between url and line number in server side logs backtraces. r=ochameau MozReview-Commit-ID: AtP0Gimrcxt
devtools/client/webconsole/test/browser.ini
devtools/client/webconsole/test/browser_console_server_logging.js
devtools/client/webconsole/test/test-console-server-logging-backtrace.sjs
devtools/shared/webconsole/server-logger.js
--- a/devtools/client/webconsole/test/browser.ini
+++ b/devtools/client/webconsole/test/browser.ini
@@ -71,16 +71,17 @@ support-files =
   test-console-assert.html
   test-console-clear.html
   test-console-count.html
   test-console-count-external-file.js
   test-console-extras.html
   test-console-replaced-api.html
   test-console-server-logging.sjs
   test-console-server-logging-array.sjs
+  test-console-server-logging-backtrace.sjs
   test-console.html
   test-console-workers.html
   test-console-table.html
   test-console-output-02.html
   test-console-output-03.html
   test-console-output-04.html
   test-console-output-dom-elements.html
   test-console-output-events.html
--- a/devtools/client/webconsole/test/browser_console_server_logging.js
+++ b/devtools/client/webconsole/test/browser_console_server_logging.js
@@ -60,15 +60,58 @@ add_task(function* () {
       severity: SEVERITY_LOG,
     }],
   });
   // Clean up filter
   hud.setFilterState("serverlog", false);
   yield updateServerLoggingListener(hud);
 });
 
+add_task(function* () {
+  const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test/test-console-server-logging-backtrace.sjs";
+
+  yield loadTab(TEST_URI);
+
+  let hud = yield openConsole();
+
+  // Set logging filter and wait till it's set on the backend
+  hud.setFilterState("serverlog", true);
+  yield updateServerLoggingListener(hud);
+
+  BrowserReloadSkipCache();
+  // Note that the test is also checking out the (printf like)
+  // formatters and encoding of UTF8 characters (see the one at the end).
+  yield waitForMessages({
+    webconsole: hud,
+    messages: [{
+      text: "correct 1",
+      category: CATEGORY_SERVER,
+      severity: SEVERITY_ERROR,
+      source: {url: "/some/path/to/file.py", line: 33}
+    }, {
+      text: "correct 2",
+      category: CATEGORY_SERVER,
+      severity: SEVERITY_ERROR,
+      source: {url: "/some/path/to/file.py", line: 33}
+    }, {
+      text: "wrong 1",
+      category: CATEGORY_SERVER,
+      severity: SEVERITY_ERROR,
+      source: {url: "/some/path/to/file.py:33wrong"}
+    }, {
+      text: "wrong 2",
+      category: CATEGORY_SERVER,
+      severity: SEVERITY_ERROR,
+      source: {url: "/some/path/to/file.py"}
+    }],
+  });
+  // Clean up filter
+  hud.setFilterState("serverlog", false);
+  yield updateServerLoggingListener(hud);
+});
+
 function updateServerLoggingListener(hud) {
   let deferred = promise.defer();
   hud.ui._updateServerLoggingListener(response => {
     deferred.resolve(response);
   });
   return deferred.promise;
 }
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/test-console-server-logging-backtrace.sjs
@@ -0,0 +1,44 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response)
+{
+  var page = "<!DOCTYPE html><html>" +
+    "<head><meta charset='utf-8'></head>" +
+    "<body><p>hello world!</p></body>" +
+    "</html>";
+
+  var data = {
+    "version": "4.1.0",
+    "columns": ["log", "backtrace", "type"],
+    "rows":[[
+      ["correct 1"],
+      "/some/path/to/file.py   :     33",
+      "error"
+    ], [
+      ["correct 2"],
+      "/some/path/to/file.py:33",
+      "error"
+    ], [
+      ["wrong 1"],
+      "/some/path/to/file.py:33wrong",
+      "error"
+    ], [
+      ["wrong 2"],
+      "/some/path/to/file.py",
+      "error"
+    ]],
+  };
+
+  // Put log into headers.
+  var value = b64EncodeUnicode(JSON.stringify(data));
+  response.setHeader("X-ChromeLogger-Data", value, false);
+
+  response.write(page);
+}
+
+function b64EncodeUnicode(str) {
+  return btoa(unescape(encodeURIComponent(str)));
+}
--- a/devtools/shared/webconsole/server-logger.js
+++ b/devtools/shared/webconsole/server-logger.js
@@ -300,49 +300,33 @@ var ServerLoggingListener = Class({
         if (showLabel) {
           rawLogs.unshift(label);
         }
       }
 
       // If multiple logs come from the same line only the first log
       // has info about the backtrace. So, remember the last valid
       // location and use it for those that not set.
-      let location = this.parseBacktrace(backtrace);
+      let location = parseBacktrace(backtrace);
       if (location) {
         lastLocation = location;
       } else {
         location = lastLocation;
       }
 
       parsedMessage.push({
         logs: rawLogs,
         location: location,
         type: type
       });
     }
 
     return parsedMessage;
   },
 
-  parseBacktrace: function (backtrace) {
-    if (!backtrace) {
-      return null;
-    }
-
-    let result = backtrace.match(/\s*(\d+)$/);
-    if (!result || result.length < 2) {
-      return backtrace;
-    }
-
-    return {
-      url: backtrace.slice(0, -result[0].length),
-      line: result[1]
-    };
-  },
-
   getColumnMap: function (data) {
     let columnMap = new Map();
     let columnName;
 
     for (let key in data.columns) {
       columnName = data.columns[key];
       columnMap.set(columnName, key);
     }
@@ -498,17 +482,34 @@ function format(msg) {
     if (typeof log == "object") {
       delete log.___class_name;
     }
   }
 
   return msg;
 }
 
+function parseBacktrace(backtrace) {
+  if (!backtrace) {
+    return null;
+  }
+
+  let result = backtrace.match(/^(.+?)\s*:\s*(\d+)$/);
+  if (!result || result.length != 3) {
+    return { url: backtrace };
+  }
+
+  return {
+    url: result[1],
+    line: parseInt(result[2], 10)
+  };
+}
+
 // These helper are cloned from SDK to avoid loading to
 // much SDK modules just because of two functions.
 function getInnerId(win) {
   return win.QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
 }
 
 // Exports from this module
 exports.ServerLoggingListener = ServerLoggingListener;
+exports.parseBacktrace = parseBacktrace;