From 40fe74ef457d7070d45aa2fa77b7a1464c6f35da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 27 Nov 2015 15:05:55 +0100 Subject: [PATCH] Cut off terminal after 3000 lines When autoscroll was disabled, terminal could run on endlessly, eating memory until the browser crashes. Now a hard upper limit ensures that not more than 3000 lines are ever stored in the terminal. If autoscroll is disabled and the limit is reached, no more log lines will be added. That ensures that the log will not scroll and the current log excerpt will stay put. --- .../static/js/app/viewmodels/terminal.js | 40 +++++++++++++++---- src/octoprint/templates/tabs/terminal.jinja2 | 2 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/octoprint/static/js/app/viewmodels/terminal.js b/src/octoprint/static/js/app/viewmodels/terminal.js index d7ec494d..7be593c6 100644 --- a/src/octoprint/static/js/app/viewmodels/terminal.js +++ b/src/octoprint/static/js/app/viewmodels/terminal.js @@ -7,6 +7,7 @@ $(function() { self.log = ko.observableArray([]); self.buffer = ko.observable(300); + self.upperLimit = ko.observable(3000); self.command = ko.observable(undefined); @@ -52,13 +53,21 @@ $(function() { self.lineCount = ko.computed(function() { var total = self.log().length; + var filtered = _.filter(self.displayedLines(), function(entry) { return entry.type == "filtered" }).length; var displayed = _.filter(self.displayedLines(), function(entry) { return entry.type == "line" }).length; - var filtered = total - displayed; - if (total == displayed) { - return _.sprintf(gettext("showing %(displayed)d lines"), {displayed: displayed}); + if (filtered > 0) { + if (total > self.upperLimit()) { + return _.sprintf(gettext("showing %(displayed)d lines (%(filtered)d of %(total)d total lines filtered, buffer full)"), {displayed: displayed, total: total, filtered: filtered}); + } else { + return _.sprintf(gettext("showing %(displayed)d lines (%(filtered)d of %(total)d total lines filtered)"), {displayed: displayed, total: total, filtered: filtered}); + } } else { - return _.sprintf(gettext("showing %(displayed)d lines (%(filtered)d of %(total)d total lines filtered)"), {displayed: displayed, total: total, filtered: filtered}); + if (total > self.upperLimit()) { + return _.sprintf(gettext("showing %(displayed)d lines (buffer full)"), {displayed: displayed}); + } else { + return _.sprintf(gettext("showing %(displayed)d lines"), {displayed: displayed}); + } } }); @@ -84,10 +93,25 @@ $(function() { }; self._processCurrentLogData = function(data) { - self.log(self.log().concat(_.map(data, function(line) { return self._toInternalFormat(line) }))); - if (self.autoscrollEnabled()) { - self.log(self.log.slice(-self.buffer())); + var length = self.log().length; + if (length >= self.upperLimit()) { + var cutoff = "--- too many lines to buffer, cut off ---"; + var last = self.log()[length-1]; + if (!last || last.type != "cut" || last.line != cutoff) { + self.log(self.log().concat(self._toInternalFormat(cutoff, "cut"))); + } + return; } + + var newLog = self.log().concat(_.map(data, function(line) { return self._toInternalFormat(line) })); + if (self.autoscrollEnabled()) { + // we only keep the last entries + newLog = newLog.slice(-self.buffer()); + } else if (newLog.length > self.upperLimit()) { + // we only keep the first entries + newLog = newLog.slice(0, self.upperLimit()); + } + self.log(newLog); }; self._processHistoryLogData = function(data) { @@ -232,4 +256,4 @@ $(function() { ["loginStateViewModel", "settingsViewModel"], "#term" ]); -}); \ No newline at end of file +}); diff --git a/src/octoprint/templates/tabs/terminal.jinja2 b/src/octoprint/templates/tabs/terminal.jinja2 index 18d2a30a..4389d725 100644 --- a/src/octoprint/templates/tabs/terminal.jinja2 +++ b/src/octoprint/templates/tabs/terminal.jinja2 @@ -1,5 +1,5 @@
-

+

{{ _("Scroll to end") }} | {{ _("Select all") }}