Make logs view performant

This commit is contained in:
Andras Schmelczer 2025-03-22 17:06:32 +00:00
commit 8a27987798
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
3 changed files with 47 additions and 64 deletions

View file

@ -66,7 +66,7 @@ export default class VaultLinkPlugin extends Plugin {
); );
this.registerView( this.registerView(
LogsView.TYPE, LogsView.TYPE,
(leaf) => new LogsView(this, this.client, leaf) (leaf) => new LogsView(this.client, leaf)
); );
this.addRibbonIcon( this.addRibbonIcon(

View file

@ -1,14 +1,15 @@
import type { WorkspaceLeaf } from "obsidian"; import type { WorkspaceLeaf } from "obsidian";
import { ItemView } from "obsidian"; import { ItemView } from "obsidian";
import type VaultLinkPlugin from "../vault-link-plugin"; import { LogLevel, LogLine, type SyncClient } from "sync-client";
import { LogLevel, type SyncClient } from "sync-client";
export class LogsView extends ItemView { export class LogsView extends ItemView {
public static readonly TYPE = "logs-view"; public static readonly TYPE = "logs-view";
public static readonly ICON = "logs"; public static readonly ICON = "logs";
private logsContainer: HTMLElement | undefined;
private logLineToElement: Map<LogLine, HTMLElement> = new Map();
public constructor( public constructor(
private readonly plugin: VaultLinkPlugin,
private readonly client: SyncClient, private readonly client: SyncClient,
leaf: WorkspaceLeaf leaf: WorkspaceLeaf
) { ) {
@ -36,76 +37,58 @@ export class LogsView extends ItemView {
const container = this.containerEl.children[1]; const container = this.containerEl.children[1];
container.addClass("logs-view"); container.addClass("logs-view");
container.createEl("h4", { text: "VaultLink logs" });
this.logsContainer = container.createDiv({ cls: "logs-container" });
} }
private updateView(): void { private updateView(): void {
const container = this.containerEl.children[1]; const container = this.logsContainer;
if (container === undefined) {
let logsContainer = container
.getElementsByClassName("logs-container")
.item(0);
const scrollPosition = logsContainer?.scrollTop;
container.empty();
container.createEl("h4", { text: "VaultLink logs" });
container.createEl(
"p",
{
text: "This view displays logs generated by VaultLink. You can set the log level in the "
},
(p) => {
p.createEl(
"a",
{
text: "settings"
},
(button) => {
button.addEventListener("click", () => {
this.plugin.openSettings();
});
}
);
p.createSpan({ text: "." });
}
);
const logs = this.client.logger.getMessages(LogLevel.DEBUG);
if (logs.length === 0) {
container.createEl("p", { text: "No logs available yet." });
return; return;
} }
logsContainer = container.createDiv( const logs = this.client.logger.getMessages(LogLevel.DEBUG);
{ cls: "logs-container" },
(element) => {
logs.forEach((message) =>
element.createDiv(
{
cls: ["log-message", message.level]
},
(messageContainer) => {
messageContainer.createEl("span", {
text: LogsView.formatTimestamp(
message.timestamp
),
cls: "timestamp"
});
messageContainer.createEl("span", {
text: message.message
});
}
)
);
}
);
if (scrollPosition !== undefined) { if (this.logLineToElement.size === 0 && logs.length > 0) {
logsContainer.scrollTop = scrollPosition; // Clear the "No logs available yet" message
} else { container.empty();
logsContainer.scrollTop = logsContainer.scrollHeight; }
logs.forEach((message) => {
if (this.logLineToElement.has(message)) {
return;
}
const element = container.createDiv(
{
cls: ["log-message", message.level]
},
(messageContainer) => {
messageContainer.createEl("span", {
text: LogsView.formatTimestamp(message.timestamp),
cls: "timestamp"
});
messageContainer.createEl("span", {
text: message.message
});
}
);
this.logLineToElement.set(message, element);
});
const newLines = new Set(logs);
for (const [logLine, element] of this.logLineToElement) {
if (!newLines.has(logLine)) {
element.remove();
this.logLineToElement.delete(logLine);
}
}
if (logs.length === 0) {
container.createEl("p", {
text: "No logs available yet."
});
} }
} }
} }

View file

@ -21,7 +21,7 @@ export class LogLine {
} }
export class Logger { export class Logger {
private static readonly MAX_MESSAGES = 10000; private static readonly MAX_MESSAGES = 2000;
private readonly messages: LogLine[] = []; private readonly messages: LogLine[] = [];
private readonly onMessageListeners: ((message: LogLine) => void)[] = []; private readonly onMessageListeners: ((message: LogLine) => void)[] = [];