Add sync history backend
This commit is contained in:
parent
4a4d8c6d1a
commit
f552ac4abc
3 changed files with 179 additions and 12 deletions
77
plugin/src/tracing/logger.ts
Normal file
77
plugin/src/tracing/logger.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { Notice } from "obsidian";
|
||||||
|
|
||||||
|
export enum LogLevel {
|
||||||
|
DEBUG = "DEBUG",
|
||||||
|
INFO = "INFO",
|
||||||
|
WARNING = "WARNING",
|
||||||
|
ERROR = "ERROR",
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogLine {
|
||||||
|
public constructor(public level: LogLevel, public message: string) {}
|
||||||
|
|
||||||
|
public toString(): string {
|
||||||
|
return `${this.formatLevel()}: ${this.message}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatLevel(): string {
|
||||||
|
switch (this.level) {
|
||||||
|
case LogLevel.DEBUG:
|
||||||
|
return "DEBUG";
|
||||||
|
case LogLevel.INFO:
|
||||||
|
return "INFO";
|
||||||
|
case LogLevel.WARNING:
|
||||||
|
return "WARNING";
|
||||||
|
case LogLevel.ERROR:
|
||||||
|
return "ERROR";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Logger {
|
||||||
|
private static readonly MAX_MESSAGES = 1000;
|
||||||
|
|
||||||
|
private static instance: Logger | null = null;
|
||||||
|
private readonly messages: LogLine[] = [];
|
||||||
|
|
||||||
|
private constructor() {} // eslint-disable-line @typescript-eslint/no-empty-function
|
||||||
|
|
||||||
|
public static getInstance(): Logger {
|
||||||
|
if (!Logger.instance) {
|
||||||
|
Logger.instance = new Logger();
|
||||||
|
}
|
||||||
|
return Logger.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public debug(message: string): void {
|
||||||
|
this.pushMessage(message, LogLevel.DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public info(message: string): void {
|
||||||
|
this.pushMessage(message, LogLevel.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public warn(message: string): void {
|
||||||
|
this.pushMessage(message, LogLevel.WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public error(message: string): void {
|
||||||
|
this.pushMessage(message, LogLevel.ERROR);
|
||||||
|
new Notice(message, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMessages(mininumSeverity: LogLevel): LogLine[] {
|
||||||
|
return this.messages.filter(
|
||||||
|
(message) => message.level >= mininumSeverity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private pushMessage(message: string, level: LogLevel): void {
|
||||||
|
this.messages.push(new LogLine(level, message));
|
||||||
|
if (this.messages.length > Logger.MAX_MESSAGES) {
|
||||||
|
this.messages.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
plugin/src/tracing/sync-history.ts
Normal file
94
plugin/src/tracing/sync-history.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
import type { RelativePath } from "src/database/document-metadata";
|
||||||
|
import { Logger } from "./logger";
|
||||||
|
|
||||||
|
export interface CommonHistoryEntry {
|
||||||
|
status: SyncStatus;
|
||||||
|
relativePath: RelativePath;
|
||||||
|
message: string;
|
||||||
|
type?: SyncType;
|
||||||
|
source?: SyncSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SyncType {
|
||||||
|
CREATE = "CREATE",
|
||||||
|
UPDATE = "UPDATE",
|
||||||
|
DELETE = "DELETE",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SyncSource {
|
||||||
|
PUSH = "PUSH",
|
||||||
|
PULL = "PULL",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SyncStatus {
|
||||||
|
NO_OP = "NO_OP",
|
||||||
|
SUCCESS = "SUCCESS",
|
||||||
|
ERROR = "ERROR",
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HistoryEntry = CommonHistoryEntry & { timestamp: Date };
|
||||||
|
|
||||||
|
export interface HistoryStats {
|
||||||
|
success: number;
|
||||||
|
error: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SyncHistory {
|
||||||
|
private static readonly MAX_ENTRIES = 1000;
|
||||||
|
|
||||||
|
private entries: HistoryEntry[] = [];
|
||||||
|
private readonly requestCountListeners: ((status: HistoryStats) => void)[] =
|
||||||
|
[];
|
||||||
|
private status: HistoryStats = {
|
||||||
|
success: 0,
|
||||||
|
error: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
public getMessages(): HistoryEntry[] {
|
||||||
|
return this.entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public reset(): void {
|
||||||
|
this.entries = [];
|
||||||
|
this.status = {
|
||||||
|
success: 0,
|
||||||
|
error: 0,
|
||||||
|
};
|
||||||
|
this.requestCountListeners.forEach((listener) => {
|
||||||
|
listener(this.status);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public addSyncHistoryStatsChangeListener(
|
||||||
|
listener: (status: HistoryStats) => void
|
||||||
|
): void {
|
||||||
|
this.requestCountListeners.push(listener);
|
||||||
|
listener({ ...this.status });
|
||||||
|
}
|
||||||
|
|
||||||
|
public addHistoryEntry(entry: CommonHistoryEntry): void {
|
||||||
|
const historyEntry = {
|
||||||
|
...entry,
|
||||||
|
timestamp: new Date(),
|
||||||
|
};
|
||||||
|
this.entries.push(historyEntry);
|
||||||
|
|
||||||
|
if (entry.status === SyncStatus.SUCCESS) {
|
||||||
|
this.status.success++;
|
||||||
|
Logger.getInstance().info(`Synced file: ${entry.relativePath}`);
|
||||||
|
} else if (entry.status === SyncStatus.ERROR) {
|
||||||
|
this.status.error++;
|
||||||
|
Logger.getInstance().error(
|
||||||
|
`Error syncing file: ${entry.relativePath} - ${entry.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.requestCountListeners.forEach((listener) => {
|
||||||
|
listener(this.status);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.entries.length > SyncHistory.MAX_ENTRIES) {
|
||||||
|
this.entries.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,17 @@
|
||||||
import { Plugin } from "obsidian";
|
import type { Plugin } from "obsidian";
|
||||||
import { RequestCountStatus, SyncService } from "src/services/sync-service";
|
import type { HistoryStats, SyncHistory } from "src/tracing/sync-history";
|
||||||
|
|
||||||
export class StatusBar {
|
export class StatusBar {
|
||||||
private statusBarItem: HTMLElement;
|
private readonly statusBarItem: HTMLElement;
|
||||||
|
|
||||||
public constructor(plugin: Plugin, service: SyncService) {
|
public constructor(plugin: Plugin, history: SyncHistory) {
|
||||||
this.statusBarItem = plugin.addStatusBarItem();
|
this.statusBarItem = plugin.addStatusBarItem();
|
||||||
service.addRequestCountChangeListener((status) =>
|
history.addSyncHistoryStatsChangeListener((status) =>
|
||||||
this.updateStatus(status)
|
{ this.updateStatus(status); }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateStatus({
|
private updateStatus({ success, error }: HistoryStats): void {
|
||||||
waiting,
|
this.statusBarItem.setText(`${success} ✅ ${error} ❌`);
|
||||||
success,
|
|
||||||
failure,
|
|
||||||
}: RequestCountStatus): void {
|
|
||||||
this.statusBarItem.setText(`${waiting} 🔄 ${success} ✅ ${failure} ❌`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue