Skip to content

Commit

Permalink
Log viewer: only render lines around visible area (#2905)
Browse files Browse the repository at this point in the history
This should fix the performance problems in the log viewer when the
number of items reaches the max buffer size.

---------

Signed-off-by: Yannick Schaus <github@schaus.net>
  • Loading branch information
ghys authored Dec 13, 2024
1 parent dfd1e45 commit c2ae0ab
Showing 1 changed file with 43 additions and 25 deletions.
68 changes: 43 additions & 25 deletions bundles/org.openhab.ui/web/src/pages/developer/log-viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -173,21 +173,7 @@
<f7-card class="custom-card">
<div class="table-container" ref="tableContainer" @scroll="handleScroll">
<table ref="dataTable">
<tbody>
<!-- <tr v-for="entity in filteredTableData" :key="entity.id" class="table-rows"
:class="entity.level.toLowerCase()">
<td class="sticky">
{{ entity.time }}<span class="milliseconds">{{ entity.milliseconds }}</span>
</td>
<td>
{{ entity.level }}
</td>
<td>
{{ entity.loggerName }}
</td>
<td v-html="highlightText(entity.message)" class="nowrap" />
</tr> -->
</tbody>
<tbody />
</table>
</div>
</f7-card>
Expand Down Expand Up @@ -245,6 +231,9 @@
background #f1f1f1
z-index 1
tr.table-rows
height 31px
tr.error
background-color rgb(255, 96, 96)
color black
Expand Down Expand Up @@ -299,10 +288,6 @@
.log-period
white-space nowrap !important
// @media (max-width: 767px)
// .log-viewer .log-period
// display none
#color-picker-popover
.color-palette
display flex
Expand Down Expand Up @@ -560,13 +545,17 @@ export default {
this.logStart = removedElement.time
if (removedElement.visible) {
this.filterCount--
this.$refs.dataTable.firstChild.removeChild(this.$refs.dataTable.firstChild.firstChild)
let firstRow = this.$refs.dataTable.firstChild.firstChild
if (firstRow.className === 'padder') firstRow = firstRow.nextSibling
this.$refs.dataTable.firstChild.removeChild(firstRow)
}
}
})
this.batchLogs.length = 0
if (this.autoScroll) {
this.$nextTick(() => this.scrollToBottom())
} else {
this.$nextTick(() => this.handleScroll())
}
this.batchUpdatePending = false
Expand Down Expand Up @@ -606,6 +595,7 @@ export default {
// Delay manual scroll detection to avoid autoscrolling being defeated when new logs arrive
this.scrollTime = Date.now() + 250
}
this.redrawPartOfTable()
},
handleScroll () {
const tableContainer = this.$refs.tableContainer
Expand All @@ -615,6 +605,38 @@ export default {
// Detect if the user has scrolled up
const isAtBottom = tableContainer.scrollHeight - tableContainer.scrollTop < (tableContainer.clientHeight + 20)
this.autoScroll = isAtBottom
this.redrawPartOfTable()
},
redrawPartOfTable () {
const LINE_HEIGHT = 31
const tableContainer = this.$refs.tableContainer
const tableBody = this.$refs.dataTable.firstChild
const filteredItemsCount = this.filteredTableData.length
const currentIndexAtTop = Math.floor(tableContainer.scrollTop / LINE_HEIGHT)
const nbVisibleLines = Math.floor(tableContainer.offsetHeight / LINE_HEIGHT)
// make sure to redraw only 50 elements below around visible area
const firstIndexToRedraw = Math.max(0, currentIndexAtTop - 50)
const lastIndexToRedraw = Math.min(currentIndexAtTop + nbVisibleLines + 50, filteredItemsCount - 1)
console.debug(`Should redraw ${firstIndexToRedraw}/${lastIndexToRedraw}`)
tableBody.innerHTML = ''
if (firstIndexToRedraw > 0) {
const padder = document.createElement('tr')
padder.className = 'padder'
padder.style.height = (LINE_HEIGHT * firstIndexToRedraw) + 'px'
tableBody.appendChild(padder)
}
for (let i = firstIndexToRedraw; i <= lastIndexToRedraw; i++) {
tableBody.appendChild(this.renderEntry(this.filteredTableData[i]))
}
if (lastIndexToRedraw < filteredItemsCount - 1) {
const padder = document.createElement('tr')
padder.className = 'padder'
padder.style.height = (LINE_HEIGHT * (filteredItemsCount - 1 - lastIndexToRedraw)) + 'px'
tableBody.appendChild(padder)
}
},
handleLogPackageEnter (event) {
let logger = {
Expand Down Expand Up @@ -652,13 +674,9 @@ export default {
this.$refs.dataTable.firstChild.innerHTML = ''
for (const entry of this.tableData) {
entry.visible = this.processFilter(entry)
if (entry.visible) {
cnt++
const tr = this.renderEntry(entry)
this.$refs.dataTable.firstChild.appendChild(tr)
}
}
this.filterCount = cnt
this.redrawPartOfTable()
},
highlightText (text) {
if (this.activeHighlights.length === 0) {
Expand Down

0 comments on commit c2ae0ab

Please sign in to comment.