Skip to content

Commit

Permalink
Add interactive log viewer
Browse files Browse the repository at this point in the history
One can now filter the log files for substring and regexes.

Issue: https://progress.opensuse.org/issues/162218
  • Loading branch information
perlpunk committed Aug 14, 2024
1 parent b24c267 commit b76b60c
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 3 deletions.
3 changes: 3 additions & 0 deletions assets/javascripts/anser-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ const module = {};
function ansiToHtml(data) {
return Anser.linkify(Anser.ansiToHtml(Anser.escapeForHtml(data), {use_classes: true}));
}
function ansiToText(data) {
return Anser.ansiToText(data);
}
101 changes: 99 additions & 2 deletions assets/javascripts/test_result.js
Original file line number Diff line number Diff line change
Expand Up @@ -578,14 +578,97 @@ function setupResult(jobid, state, result, status_url) {
setInfoPanelClassName(state, result);
}

function loadEmbeddedLogFiles() {
function delay(callback, ms) {
let timer;
return function () {
clearTimeout(timer);
timer = setTimeout(callback.bind(this, ...arguments), ms || 0);
};
}

function filterLogLines(input) {
if (input === undefined) {
return;
}
const string = input.value;
let regex = undefined;
const match = string.match(/^\/(.*)\/([i]*)$/);
if (match) {
regex = new RegExp(match[1], match[2]);
}
displaySearchInfo('Searching…');
$('.embedded-logfile').each(function (index, logFileElement) {
let content = logFileElement.dataset.content;
if (content === undefined) {
return;
}
if (string.length > 0) {
const lines = content.split(/\r?\n/);
const wanted = [];
for (let i = 0; i < lines.length; i++) {
if (regex) {
// For searching for /^something/ we need to remove ansi control characters
const text = ansiToText(lines[i]);
if (text.match(regex)) {
wanted.push(lines[i]);
}
continue;
}
if (lines[i].includes(string)) {
wanted.push(lines[i]);
}
}
content = wanted.join('\n');
displaySearchInfo(`Showing ${wanted.length} / ${lines.length} lines`);
} else {
displaySearchInfo('');
}
logFileElement.innerHTML = ansiToHtml(content);
});
const fullCurrentUrl = window.location.href;
const urlParts = fullCurrentUrl.split('#');
const currentUrl = urlParts[0];
const fragment = urlParts[1];
if (string.length > 0) {
window.location.href = `${currentUrl}#filter=${encodeURIComponent(string)}`;
} else if (fragment) {
// leaving off the # here would reload the page
window.location.href = currentUrl + '#';
}
}

function filterEmbeddedLogFiles() {
const searchBox = document.getElementById('filter-log-file');
if (searchBox) {
const currentUrl = window.location.href;
const fragment = currentUrl.split('#')[1];
if (fragment) {
const params = fragment.split('&');
for (let i = 0; i < params.length; i++) {
const keyval = params[i].split('=');
if (keyval[0] === 'filter') {
searchBox.value = decodeURIComponent(keyval[1]);
}
}
}
}
const filter = filterLogLines.bind(null, searchBox);
loadEmbeddedLogFiles(filter);
}

function loadEmbeddedLogFiles(filter) {
$('.embedded-logfile').each(function (index, logFileElement) {
if (logFileElement.dataset.contentsLoaded) {
return;
}
$.ajax(logFileElement.dataset.src)
.done(function (response) {
logFileElement.innerHTML = ansiToHtml(response);
logFileElement.dataset.content = response;
if (filter) {
filter();
} else {
logFileElement.innerHTML = ansiToHtml(response);
}
logFileElement.dataset.contentsLoaded = true;
})
.fail(function (jqXHR, textStatus, errorThrown) {
Expand All @@ -594,6 +677,20 @@ function loadEmbeddedLogFiles() {
});
}

window.onload = function () {
const searchBox = document.getElementById('filter-log-file');
if (!searchBox) {
return;
}
const filter = filterLogLines.bind(null, searchBox);
searchBox.addEventListener('keyup', delay(filter), 1000);
searchBox.addEventListener('change', filter, false);
};

function displaySearchInfo(text) {
document.getElementById('filter-info').innerHTML = text;
}

function setCurrentPreviewFromStepLinkIfPossible(stepLink) {
if (tabConfiguration.details.hasContents && !stepLink.parent().is('.current_preview')) {
setCurrentPreview(stepLink.parent());
Expand Down
12 changes: 12 additions & 0 deletions t/ui/18-tests-details.t
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,18 @@ subtest 'misc details: title, favicon, go back, go to source view, go to log vie

wait_for_ajax msg => 'log contents';
like $driver->find_element('.embedded-logfile .ansi-blue-fg')->get_text, qr/send(autotype|key)/, 'log is colorful';
like $driver->find_element('.embedded-logfile')->get_text, qr{/usr/bin/qemu-kvm}, 'qemu-kvm is shown in log viewer';

$driver->find_element('#filter-log-file')->send_keys('kate');
like $driver->find_element('#filter-info')->get_text, qr{Showing 3 / 1292 lines},
'Showing filter result info for substring';
unlike $driver->find_element('.embedded-logfile')->get_text, qr{/usr/bin/qemu-kvm},
'qemu-kvm is not shown when filtering for something else';
$driver->find_element('#filter-log-file')->clear;
like $driver->find_element('#filter-info')->get_text, qr{^$}, 'Filter result info cleared';
$driver->find_element('#filter-log-file')->send_keys('/kate-[12]/');
like $driver->find_element('#filter-info')->get_text, qr{Showing 2 / 1292 lines},
'Showing filter result info for regex';
};

my $t = Test::Mojo->new('OpenQA::WebAPI');
Expand Down
4 changes: 3 additions & 1 deletion templates/webapi/test/logfile.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
%= asset $_ for qw(test_result.js anser.js ansi-colors.css)
% end
% content_for 'ready_function' => begin
loadEmbeddedLogFiles();
filterEmbeddedLogFiles();
% end

% my $url = url_for('test_file', testid => $testid, filename => $filename);
<div class="corner-buttons" style="margin-top: -5px;">
<span id="filter-info"></span>
<input id="filter-log-file" placeholder="substring or /regex/i" type="search">
<a class="btn btn-light" href=".#downloads">
<i class="fa fa-chevron-left"></i> Back to job <%= $testid %>
</a>
Expand Down

0 comments on commit b76b60c

Please sign in to comment.