forked from zotero/zotero
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add HTML-based console viewer for easier real-time debug output
Since 1) debug output logging via the prefs isn't necessarily possible for startup errors in Standalone, 2) real-time output is prohibitively slow and has a miniscule scrollback buffer on Windows unless you use a Cygwin or Git terminal, and 3) copying/pasting/emailing was annoying anyway, make -ZoteroDebug open a popup window that shows errors and debug output and allows submitting straight to the server with a Debug ID. This should replace the existing debug output viewer as well, but that's less of a priority. -ZoteroDebugText or the debug.log pref can still be used to dump to the terminal.
- Loading branch information
Showing
4 changed files
with
414 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Debug Output</title> | ||
<script src="include.js"></script> | ||
<script src="debugViewer.js"></script> | ||
|
||
<style> | ||
body { | ||
margin: 0; | ||
} | ||
|
||
header { | ||
position: fixed; | ||
top: 0; | ||
background: lightgrey; | ||
display: flex; | ||
align-items: center; | ||
width: calc(100% - 20px); | ||
height: 18px; | ||
padding: 10px; | ||
margin-bottom: 10px; | ||
font-family: sans-serif; | ||
font-size: 11pt; | ||
} | ||
|
||
header > * { | ||
margin-right: 10px; | ||
} | ||
|
||
progress { | ||
width: 125px; | ||
} | ||
|
||
#debug-id { | ||
font-weight: bold; | ||
} | ||
|
||
#submit-result { | ||
line-height: 1.25em; | ||
} | ||
|
||
#submit-result-copy-id { | ||
cursor: pointer; | ||
padding-left: 2px; | ||
} | ||
|
||
#submit-error { | ||
font-weight: bold; | ||
color: red; | ||
} | ||
|
||
#content { | ||
margin-top: 38px; | ||
padding: 10px 9px; | ||
font-family: Monaco, Consolas, Inconsolata, monospace; | ||
font-size: 9pt; | ||
} | ||
|
||
#errors { | ||
padding-bottom: 12px; | ||
border-bottom: 1px lightgray solid; | ||
white-space: pre-wrap; | ||
} | ||
|
||
|
||
|
||
/* | ||
CSS tooltip, adapted from http://stackoverflow.com/a/25836471 | ||
*/ | ||
[data-tooltip] { | ||
display: inline-block; | ||
position: relative; | ||
cursor: pointer; | ||
padding: 2px; | ||
} | ||
[data-tooltip]:before { | ||
content: attr(data-tooltip); | ||
display: none; | ||
position: absolute; | ||
background: #000; | ||
color: #fff; | ||
padding: 4px 8px; | ||
font-size: 12px; | ||
font-family: sans-serif; | ||
line-height: 1.4; | ||
text-align: center; | ||
border-radius: 4px; | ||
|
||
left: 50%; | ||
transform: translateX(-50%); | ||
|
||
top: 100%; | ||
margin-top: 6px; | ||
|
||
white-space: nowrap; | ||
} | ||
[data-tooltip]:after { | ||
content: ''; | ||
display: none; | ||
position: absolute; | ||
width: 0; | ||
height: 0; | ||
border-color: transparent; | ||
border-style: solid; | ||
|
||
left: 50%; | ||
margin-left: -6px; | ||
|
||
top: 100%; | ||
border-width: 0 6px 6px; | ||
border-bottom-color: #000; | ||
} | ||
/* Show the tooltip when hovering */ | ||
[data-tooltip]:hover:before, | ||
[data-tooltip]:hover:after { | ||
display: block; | ||
z-index: 50; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<header> | ||
<button id="submit-button" onclick="submit(this)" disabled>Submit…</button> | ||
<button id="clear-button" onclick="clearOutput(this)" disabled>Clear</button> | ||
<progress id="submit-progress" hidden></progress> | ||
<p id="submit-result" hidden> | ||
Submitted with Debug ID <span id="debug-id"></span> | ||
<span id="submit-result-copy-id" onclick="copyIDToClipboard(this)">📋</span> | ||
</p> | ||
<p id="submit-error" hidden></p> | ||
</header> | ||
<div id="content"> | ||
<div id="errors"></div> | ||
<div id="output"></div> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
"use strict"; | ||
|
||
var interval = 1000; | ||
var intervalID; | ||
var stopping = false; | ||
|
||
function start() { | ||
updateErrors().then(function () { | ||
if (stopping) return; | ||
|
||
addInitialOutput(); | ||
Zotero.Debug.addConsoleViewerListener(addLine) | ||
intervalID = setInterval(() => updateErrors(), interval); | ||
}); | ||
} | ||
|
||
function stop() { | ||
stopping = true; | ||
if (intervalID) { | ||
clearInterval(intervalID); | ||
intervalID = null; | ||
} | ||
Zotero.Debug.removeConsoleViewerListener() | ||
} | ||
|
||
function updateErrors() { | ||
return Zotero.getSystemInfo() | ||
.then(function (sysInfo) { | ||
if (stopping) return; | ||
|
||
var errors = Zotero.getErrors(true); | ||
var errorStr = errors.length ? errors.join('\n\n') + '\n\n' : ''; | ||
|
||
var scroll = atPageBottom(); | ||
|
||
document.getElementById('errors').textContent = errorStr + sysInfo; | ||
|
||
// TODO: This doesn't seem to work for some reason -- when errors are logged, it doesn't stay | ||
// at the bottom | ||
if (scroll) { | ||
scrollToPageBottom(); | ||
} | ||
}); | ||
} | ||
|
||
function addInitialOutput() { | ||
Zotero.Debug.getConsoleViewerOutput().forEach(function (line) { | ||
addLine(line); | ||
}); | ||
} | ||
|
||
function addLine(line) { | ||
var scroll = atPageBottom() | ||
|
||
var p = document.createElement('p'); | ||
p.textContent = line; | ||
var output = document.getElementById('output'); | ||
output.appendChild(p); | ||
|
||
// If scrolled to the bottom of the page, stay there | ||
if (scroll) { | ||
scrollToPageBottom(); | ||
} | ||
|
||
document.getElementById('submit-button').removeAttribute('disabled'); | ||
document.getElementById('clear-button').removeAttribute('disabled'); | ||
} | ||
|
||
function atPageBottom() { | ||
return (window.innerHeight + window.scrollY) >= document.body.offsetHeight - 100; | ||
} | ||
|
||
function scrollToPageBottom() { | ||
window.scrollTo(0, document.body.scrollHeight); | ||
} | ||
|
||
function submit(button) { | ||
button.setAttribute('disabled', ''); | ||
clearSubmitStatus(); | ||
|
||
Components.utils.import("resource://zotero/config.js"); | ||
var url = ZOTERO_CONFIG.REPOSITORY_URL + "report?debug=1"; | ||
var output = document.getElementById('errors').textContent | ||
+ "\n\n" + "=========================================================\n\n" | ||
+ Array.from(document.getElementById('output').childNodes).map(p => p.textContent).join("\n\n"); | ||
var pm = document.getElementById('submit-progress'); | ||
pm.removeAttribute('hidden'); | ||
|
||
Zotero.HTTP.request( | ||
"POST", | ||
url, | ||
{ | ||
compressBody: true, | ||
body: output, | ||
logBodyLength: 30, | ||
timeout: 30000, | ||
// Update progress meter | ||
requestObserver: function (req) { | ||
req.channel.notificationCallbacks = { | ||
onProgress: function (request, context, progress, progressMax) { | ||
if (!pm.value || progress > pm.value) { | ||
pm.value = progress; | ||
} | ||
if (!pm.max || progressMax > pm.max) { | ||
pm.max = progressMax; | ||
} | ||
}, | ||
|
||
// nsIInterfaceRequestor | ||
getInterface: function (iid) { | ||
try { | ||
return this.QueryInterface(iid); | ||
} | ||
catch (e) { | ||
throw Components.results.NS_NOINTERFACE; | ||
} | ||
}, | ||
|
||
QueryInterface: function(iid) { | ||
if (iid.equals(Components.interfaces.nsISupports) || | ||
iid.equals(Components.interfaces.nsIInterfaceRequestor) || | ||
iid.equals(Components.interfaces.nsIProgressEventSink)) { | ||
return this; | ||
} | ||
throw Components.results.NS_NOINTERFACE; | ||
}, | ||
|
||
} | ||
} | ||
} | ||
) | ||
.then(function (xmlhttp) { | ||
var reported = xmlhttp.responseXML.getElementsByTagName('reported'); | ||
if (reported.length != 1) { | ||
showSubmitError(e); | ||
return false; | ||
} | ||
|
||
showSubmitResult(reported[0].getAttribute('reportID')); | ||
}) | ||
.catch(function (e) { | ||
showSubmitError(e); | ||
return false; | ||
}) | ||
.finally(function () { | ||
pm.setAttribute('hidden', ''); | ||
button.removeAttribute('disabled'); | ||
}); | ||
} | ||
|
||
function showSubmitResult(id) { | ||
var elem = document.getElementById('submit-result'); | ||
elem.removeAttribute('hidden'); | ||
document.getElementById('debug-id').textContent = "D" + id; | ||
var copyID = document.getElementById('submit-result-copy-id'); | ||
copyID.style.visibility = 'visible'; | ||
copyID.setAttribute('data-tooltip', 'Copy ID to Clipboard'); | ||
} | ||
|
||
function copyIDToClipboard(elem) { | ||
var id = document.getElementById('debug-id').textContent; | ||
Components.classes["@mozilla.org/widget/clipboardhelper;1"] | ||
.getService(Components.interfaces.nsIClipboardHelper) | ||
.copyString(id); | ||
elem.setAttribute('data-tooltip', 'Copied'); | ||
setTimeout(() => elem.style.visibility = 'hidden', 750); | ||
} | ||
|
||
function showSubmitError(e) { | ||
var elem = document.getElementById('submit-error'); | ||
elem.removeAttribute('hidden'); | ||
elem.textContent = "Error submitting output"; | ||
Components.utils.reportError(e); | ||
Zotero.debug(e, 1); | ||
} | ||
|
||
function clearSubmitStatus() { | ||
document.getElementById('submit-result').setAttribute('hidden', ''); | ||
document.getElementById('submit-error').setAttribute('hidden', ''); | ||
} | ||
|
||
function clearOutput(button) { | ||
button.setAttribute('disabled', ''); | ||
document.getElementById('output').textContent = ''; | ||
clearSubmitStatus(); | ||
} | ||
|
||
window.addEventListener('load', start); | ||
window.addEventListener("unload", stop); |
Oops, something went wrong.