filtering in logger + various small fixes

pull/2/head
gorhill 10 years ago
parent 4142551c13
commit 8f2b473928

@ -583,6 +583,11 @@
"description": "Message asking user to confirm reset" "description": "Message asking user to confirm reset"
}, },
"loggerFilterInputPlaceholder" : {
"message": "filter expression(s)",
"description": "Appears in the input filed where filter expressions are entered"
},
"mainBlockedPrompt1": { "mainBlockedPrompt1": {
"message": "uMatrix has prevented the following page from loading:", "message": "uMatrix has prevented the following page from loading:",
"description": "English: uMatrix has prevented the following page from loading:" "description": "English: uMatrix has prevented the following page from loading:"

@ -43,19 +43,19 @@
display: inline-block; display: inline-block;
} }
html { body[dir="ltr"] {
direction: ltr; direction: ltr;
} }
html.rtl { body[dir="rtl"] {
direction: rtl; direction: rtl;
} }
/* http://stackoverflow.com/questions/2011142/how-to-change-the-style-of-title-attribute-inside-the-anchor-tag?answertab=votes */ /* http://stackoverflow.com/questions/2011142/how-to-change-the-style-of-title-attribute-inside-the-anchor-tag?answertab=votes */
*[data-tip] { *[data-i18n-tip] {
position: relative; position: relative;
cursor: pointer; cursor: pointer;
} }
*[data-tip]:hover:after { *[data-i18n-tip]:hover:after {
background-color: #fffffa; background-color: #fffffa;
border: 1px solid gray; border: 1px solid gray;
border-radius: 3px; border-radius: 3px;
@ -63,7 +63,6 @@ html.rtl {
color: black; color: black;
content: attr(data-tip); content: attr(data-tip);
font: 12px sans-serif; font: 12px sans-serif;
left: -100%;
line-height: 140%; line-height: 140%;
min-width: 25vw; min-width: 25vw;
padding: 4px 6px; padding: 4px 6px;
@ -73,11 +72,11 @@ html.rtl {
white-space: pre-line; white-space: pre-line;
z-index: 20; z-index: 20;
} }
html.ltr .tip-anchor-left[data-tip]:hover:after, body[dir="ltr"] .tip-anchor-left[data-i18n-tip]:hover:after,
html.rtl .tip-anchor-right[data-tip]:hover:after { body[dir="rtl"] .tip-anchor-right[data-i18n-tip]:hover:after {
left: -5vw; left: -3vw;
} }
html.ltr .tip-anchor-right[data-tip]:hover:after, body[dir="ltr"] .tip-anchor-right[data-i18n-tip]:hover:after,
html.rtl .tip-anchor-left[data-tip]:hover:after { body[dir="rtl"] .tip-anchor-left[data-i18n-tip]:hover:after {
right: -5vw; right: -3vw;
} }

@ -45,10 +45,13 @@ body #compactViewToggler.button:before {
body.compactView #compactViewToggler.button:before { body.compactView #compactViewToggler.button:before {
content: '\f103'; content: '\f103';
} }
body.filterOff #toolbar #filterButton { #filterButton {
opacity: 0.25; opacity: 0.25;
} }
#filterExpression.bad { body.f #filterButton {
opacity: 1;
}
#filterInput.bad {
background-color: #fee; background-color: #fee;
} }
#maxEntries { #maxEntries {
@ -74,20 +77,23 @@ input:focus {
width: 6em; width: 6em;
} }
#content table > colgroup > col:nth-of-type(2) { #content table > colgroup > col:nth-of-type(2) {
width: 3em; width: 2.5em;
} }
#content table > colgroup > col:nth-of-type(3) { #content table > colgroup > col:nth-of-type(3) {
width: 3em; width: 2.5em;
} }
#content table > colgroup > col:nth-of-type(4) { #content table > colgroup > col:nth-of-type(4) {
width: 5em; width: 5em;
} }
#content table > colgroup > col:nth-of-type(5) { #content table > colgroup > col:nth-of-type(5) {
width: calc(100% - 20em); width: calc(100% - 19em);
} }
#content table tr { #content table tr {
background-color: #fafafa; background-color: #fafafa;
} }
body.f table tr.f {
display: none;
}
#content table tr:nth-of-type(2n+1) { #content table tr:nth-of-type(2n+1) {
background-color: #eee; background-color: #eee;
} }
@ -104,10 +110,6 @@ input:focus {
text-align: center; text-align: center;
} }
body:not(.filterOff) #content table tr.hidden {
display: none;
}
body #content td { body #content td {
border: 1px solid #ccc; border: 1px solid #ccc;
border-top: none; border-top: none;

@ -118,11 +118,6 @@ body[dir="rtl"] #mtxSwitches > li:before {
font: 110% FontAwesome; font: 110% FontAwesome;
padding-right: 0.5em; padding-right: 0.5em;
} }
[data-i18n="matrixLoggerMenuEntry"]:before {
content: '\f022';
font: 110% FontAwesome;
padding-right: 0.5em;
}
[data-i18n="matrixDashboardMenuEntry"]:before { [data-i18n="matrixDashboardMenuEntry"]:before {
content: '\f085'; content: '\f085';
font: 110% FontAwesome; font: 110% FontAwesome;

@ -52,6 +52,16 @@ while ( i-- ) {
node.setAttribute('data-tip', vAPI.i18n(node.getAttribute('data-i18n-tip'))); node.setAttribute('data-tip', vAPI.i18n(node.getAttribute('data-i18n-tip')));
} }
nodeList = document.querySelectorAll('input[placeholder]');
i = nodeList.length;
while ( i-- ) {
node = nodeList[i];
node.setAttribute(
'placeholder',
vAPI.i18n(node.getAttribute('placeholder')) || ''
);
}
/******************************************************************************/ /******************************************************************************/
vAPI.i18n.renderElapsedTimeToString = function(tstamp) { vAPI.i18n.renderElapsedTimeToString = function(tstamp) {

@ -17,8 +17,6 @@
along with this program. If not, see {http://www.gnu.org/licenses/}. along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/sessbench Home: https://github.com/gorhill/sessbench
TODO: cleanup/refactor
*/ */
/* jshint boss: true */ /* jshint boss: true */
@ -33,10 +31,7 @@
/******************************************************************************/ /******************************************************************************/
var messager = vAPI.messaging.channel('logger-ui.js'); var messager = vAPI.messaging.channel('logger-ui.js');
var tbody = document.querySelector('#content tbody');
var doc = document;
var body = doc.body;
var tbody = doc.querySelector('#content tbody');
var trJunkyard = []; var trJunkyard = [];
var tdJunkyard = []; var tdJunkyard = [];
var firstVarDataCol = 2; // currently, column 2 (0-based index) var firstVarDataCol = 2; // currently, column 2 (0-based index)
@ -116,7 +111,7 @@ var createCellAt = function(tr, index) {
td.removeAttribute('colspan'); td.removeAttribute('colspan');
td.textContent = ''; td.textContent = '';
} else { } else {
td = doc.createElement('td'); td = document.createElement('td');
} }
if ( mustAppend ) { if ( mustAppend ) {
tr.appendChild(td); tr.appendChild(td);
@ -131,7 +126,7 @@ var createRow = function(layout) {
if ( tr ) { if ( tr ) {
tr.className = ''; tr.className = '';
} else { } else {
tr = doc.createElement('tr'); tr = document.createElement('tr');
} }
for ( var index = 0; index < firstVarDataCol; index++ ) { for ( var index = 0; index < firstVarDataCol; index++ ) {
createCellAt(tr, index); createCellAt(tr, index);
@ -198,7 +193,7 @@ var renderLogEntry = function(entry) {
} }
if ( entry.d3 ) { if ( entry.d3 ) {
tr.classList.add('blocked'); tr.classList.add('blocked');
tr.cells[fvdc].textContent = '---'; tr.cells[fvdc].textContent = '--';
} else { } else {
tr.cells[fvdc].textContent = ''; tr.cells[fvdc].textContent = '';
} }
@ -229,6 +224,8 @@ var renderLogEntry = function(entry) {
tr.classList.add('cat_' + entry.cat); tr.classList.add('cat_' + entry.cat);
} }
rowFilterer.filterOne(tr);
tbody.insertBefore(tr, tbody.firstChild); tbody.insertBefore(tr, tbody.firstChild);
}; };
@ -268,15 +265,15 @@ var renderLogEntries = function(response) {
// Chromium: // Chromium:
// body.scrollTop = good value // body.scrollTop = good value
// body.parentNode.scrollTop = 0 // body.parentNode.scrollTop = 0
if ( body.scrollTop !== 0 ) { if ( document.body.scrollTop !== 0 ) {
body.scrollTop += yDelta; document.body.scrollTop += yDelta;
return; return;
} }
// Firefox: // Firefox:
// body.scrollTop = 0 // body.scrollTop = 0
// body.parentNode.scrollTop = good value // body.parentNode.scrollTop = good value
var parentNode = body.parentNode; var parentNode = document.body.parentNode;
if ( parentNode && parentNode.scrollTop !== 0 ) { if ( parentNode && parentNode.scrollTop !== 0 ) {
parentNode.scrollTop += yDelta; parentNode.scrollTop += yDelta;
} }
@ -288,6 +285,7 @@ var truncateLog = function(size) {
if ( size === 0 ) { if ( size === 0 ) {
size = 5000; size = 5000;
} }
var tbody = document.querySelector('#content tbody');
size = Math.min(size, 10000); size = Math.min(size, 10000);
var tr; var tr;
while ( tbody.childElementCount > size ) { while ( tbody.childElementCount > size ) {
@ -356,7 +354,155 @@ var readLogBuffer = function() {
/******************************************************************************/ /******************************************************************************/
var onMaxEntriesChanged = function() {
var raw = uDom(this).val();
try {
maxEntries = parseInt(raw, 10);
if ( isNaN(maxEntries) ) {
maxEntries = 0;
}
} catch (e) {
maxEntries = 0;
}
messager.send({
what: 'userSettings',
name: 'maxLoggedRequests',
value: maxEntries
});
truncateLog(maxEntries);
};
/******************************************************************************/
var rowFilterer = (function() {
var filters = [];
var parseInput = function() {
filters = [];
var rawPart, not, hardBeg, hardEnd, reStr;
var raw = uDom('#filterInput').val().trim();
var rawParts = raw.split(/\s+/);
var i = rawParts.length;
while ( i-- ) {
rawPart = rawParts[i];
not = rawPart.charAt(0) === '!';
if ( not ) {
rawPart = rawPart.slice(1);
}
hardBeg = rawPart.charAt(0) === '[';
if ( hardBeg ) {
rawPart = rawPart.slice(1);
}
hardEnd = rawPart.slice(-1) === ']';
if ( hardEnd ) {
rawPart = rawPart.slice(0, -1);
}
if ( rawPart === '' ) {
continue;
}
// https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions
reStr = rawPart.replace(/[.+?^${}()|[\]\\]/g, '\\$&')
.replace(/\*/g, '.*');
if ( hardBeg ) {
reStr = '(?:^|\\s)' + reStr;
}
if ( hardEnd ) {
reStr += '(?:\\s|$)';
}
filters.push({
re: new RegExp(reStr, 'i'),
r: !not
});
}
};
var filterOne = function(tr) {
var cl = tr.classList;
// do not filter out doc boundaries, they help separate important
// section of log.
if ( cl.contains('doc') ) {
return;
}
var ff = filters;
var fcount = ff.length;
if ( fcount === 0 ) {
cl.remove('f');
return;
}
var cc = tr.cells;
var ccount = cc.length;
var hit, j, f;
// each filter expression must hit (implicit and-op)
// if...
// positive filter expression = there must one hit on any field
// negative filter expression = there must be no hit on all fields
for ( var i = 0; i < fcount; i++ ) {
f = ff[i];
hit = !f.r;
for ( j = 0; j < ccount; j++ ) {
if ( f.re.test(cc[j].innerText) ) {
hit = f.r;
break;
}
}
if ( !hit ) {
cl.add('f');
return;
}
}
cl.remove('f');
};
var filterAll = function() {
// Special case: no filter
if ( filters.length === 0 ) {
uDom('#content tr').removeClass('f');
return;
}
var tbody = document.querySelector('#content tbody');
var rows = tbody.rows;
var i = rows.length;
while ( i-- ) {
filterOne(rows[i]);
}
};
var onFilterChangedAsync = (function() {
var timer = null;
var commit = function() {
timer = null;
parseInput();
filterAll();
};
return function() {
if ( timer !== null ) {
clearTimeout(timer);
}
timer = setTimeout(commit, 750);
};
})();
var onFilterButton = function() {
var cl = document.body.classList;
cl.toggle('f', cl.contains('f') === false);
};
uDom('#filterButton').on('click', onFilterButton);
uDom('#filterInput').on('input', onFilterChangedAsync);
return {
filterOne: filterOne,
filterAll: filterAll
};
})();
/******************************************************************************/
var clearBuffer = function() { var clearBuffer = function() {
var tbody = document.querySelector('#content tbody');
var tr; var tr;
while ( tbody.firstChild !== null ) { while ( tbody.firstChild !== null ) {
tr = tbody.lastElementChild; tr = tbody.lastElementChild;
@ -380,9 +526,9 @@ var cleanBuffer = function() {
/******************************************************************************/ /******************************************************************************/
var toggleCompactView = function() { var toggleCompactView = function() {
body.classList.toggle( document.body.classList.toggle(
'compactView', 'compactView',
body.classList.contains('compactView') === false document.body.classList.contains('compactView') === false
); );
}; };
@ -595,28 +741,6 @@ var popupManager = (function() {
/******************************************************************************/ /******************************************************************************/
var onMaxEntriesChanged = function() {
var raw = uDom(this).val();
try {
maxEntries = parseInt(raw, 10);
if ( isNaN(maxEntries) ) {
maxEntries = 0;
}
} catch (e) {
maxEntries = 0;
}
messager.send({
what: 'userSettings',
name: 'maxLoggedRequests',
value: maxEntries
});
truncateLog(maxEntries);
};
/******************************************************************************/
uDom.onLoad(function() { uDom.onLoad(function() {
readLogBuffer(); readLogBuffer();

@ -1268,6 +1268,8 @@ var matrixSnapshotPoller = (function() {
var matches = window.location.search.match(/(?:\?|&)tabId=([^&]+)/); var matches = window.location.search.match(/(?:\?|&)tabId=([^&]+)/);
if ( matches !== null ) { if ( matches !== null ) {
tabId = matches[1]; tabId = matches[1];
// No need for logger button when embedded in logger
uDom('[data-extension-url="logger-ui.html"]').remove();
} }
} }

@ -45,7 +45,7 @@ var selfieMagic = 'iscjsfsaolnm';
// < this.cutoffLength = indexOf() // < this.cutoffLength = indexOf()
// >= this.cutoffLength = binary search // >= this.cutoffLength = binary search
var cutoffLength = 256; var cutoffLength = 256;
var mustPunycode = /[^a-z0-9.-]/; var mustPunycode = /[^\w.*-]/;
var onChangedListeners = []; var onChangedListeners = [];
@ -171,11 +171,6 @@ function parse(text, toAscii) {
exceptions = {}; exceptions = {};
rules = {}; rules = {};
// http://publicsuffix.org/list/:
// "... all rules must be canonicalized in the normal way
// for hostnames - lower-case, Punycode ..."
text = text.toLowerCase();
var lineBeg = 0, lineEnd; var lineBeg = 0, lineEnd;
var textEnd = text.length; var textEnd = text.length;
var line, store, pos, tld; var line, store, pos, tld;
@ -207,10 +202,6 @@ function parse(text, toAscii) {
continue; continue;
} }
if ( mustPunycode.test(line) ) {
line = toAscii(line);
}
// Is this an exception rule? // Is this an exception rule?
if ( line.charAt(0) === '!' ) { if ( line.charAt(0) === '!' ) {
store = exceptions; store = exceptions;
@ -219,6 +210,15 @@ function parse(text, toAscii) {
store = rules; store = rules;
} }
if ( mustPunycode.test(line) ) {
line = toAscii(line);
}
// http://publicsuffix.org/list/:
// "... all rules must be canonicalized in the normal way
// for hostnames - lower-case, Punycode ..."
line = line.toLowerCase();
// Extract TLD // Extract TLD
pos = line.lastIndexOf('.'); pos = line.lastIndexOf('.');
if ( pos < 0 ) { if ( pos < 0 ) {

@ -6,13 +6,13 @@
<link rel="stylesheet" type="text/css" href="css/logger-ui.css"> <link rel="stylesheet" type="text/css" href="css/logger-ui.css">
<title>uMatrix log</title> <title>uMatrix log</title>
</head> </head>
<body class="compactView"> <body class="compactView f">
<div id="toolbar"> <div id="toolbar">
<span id="compactViewToggler" class="button fa"></span> <span id="compactViewToggler" class="button fa"></span>
<span id="clean" class="button fa disabled">&#xf00d;</span> <span id="clean" class="button fa disabled">&#xf00d;</span>
<span id="clear" class="button fa disabled">&#xf12d;</span> <span id="clear" class="button fa disabled">&#xf12d;</span>
<span id="filterButton" class="button fa">&#xf0b0;</span><input id="filterExpression" type="text" placeholder="logFilterPrompt"> <span id="filterButton" class="button fa">&#xf0b0;</span><input id="filterInput" type="text" placeholder="loggerFilterInputPlaceholder">
<input id="maxEntries" type="text" size="5" title="logMaxEntriesTip"> <input id="maxEntries" type="text" size="5" title="logMaxEntriesTip">
</div> </div>

@ -48,11 +48,11 @@
<!-- Yandex: float works correctly only if it is the first child --> <!-- Yandex: float works correctly only if it is the first child -->
<div class="toolbar alignRight"> <div class="toolbar alignRight">
<button type="button" class="fa extensionURL tip-anchor-right" data-extension-url="logger-ui.html" data-i18n-tip="matrixLoggerMenuEntry">&#xf022;</button>
<button type="button" class="dropdown-menu-button fa tip-anchor-right">&#xf067;</button> <button type="button" class="dropdown-menu-button fa tip-anchor-right">&#xf067;</button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<ul> <ul>
<li id="buttonRevertAll" class="dropdown-menu-entry" data-i18n="matrixRevertAllEntry"> <li id="buttonRevertAll" class="dropdown-menu-entry" data-i18n="matrixRevertAllEntry">
<li class="dropdown-menu-entry extensionURL" data-extension-url="logger-ui.html" data-i18n="matrixLoggerMenuEntry">
<li class="dropdown-menu-entry extensionURL" data-extension-url="dashboard.html" data-i18n="matrixDashboardMenuEntry"> <li class="dropdown-menu-entry extensionURL" data-extension-url="dashboard.html" data-i18n="matrixDashboardMenuEntry">
</ul> </ul>
</div> </div>

Loading…
Cancel
Save