feat(destination-buffer): add SmartlogDestinationBuffer in-memory circular buffer destination with query/filter/pagination and tests

This commit is contained in:
2026-02-19 17:08:44 +00:00
parent aa4db8a8af
commit d70954f3ef
7 changed files with 198 additions and 1 deletions

View File

@@ -0,0 +1,67 @@
import type { ILogDestination, ILogPackage, TLogLevel } from '../dist_ts_interfaces/index.js';
export interface IDestinationBufferOptions {
maxEntries?: number;
}
export interface IBufferQueryOptions {
level?: TLogLevel | TLogLevel[];
search?: string;
limit?: number;
offset?: number;
since?: number;
}
export class SmartlogDestinationBuffer implements ILogDestination {
private logPackages: ILogPackage[] = [];
private maxEntries: number;
constructor(options?: IDestinationBufferOptions) {
this.maxEntries = options?.maxEntries ?? 2000;
}
public async handleLog(logPackage: ILogPackage): Promise<void> {
this.logPackages.push(logPackage);
if (this.logPackages.length > this.maxEntries) {
this.logPackages.shift();
}
}
public getEntries(options?: IBufferQueryOptions): ILogPackage[] {
const limit = options?.limit ?? 100;
const offset = options?.offset ?? 0;
let results = this.logPackages;
// Filter by level
if (options?.level) {
const levels = Array.isArray(options.level) ? options.level : [options.level];
results = results.filter((pkg) => levels.includes(pkg.level));
}
// Filter by search (message content)
if (options?.search) {
const searchLower = options.search.toLowerCase();
results = results.filter((pkg) => pkg.message.toLowerCase().includes(searchLower));
}
// Filter by timestamp
if (options?.since) {
results = results.filter((pkg) => pkg.timestamp >= options.since);
}
// Return newest-first, with pagination
return results
.slice()
.reverse()
.slice(offset, offset + limit);
}
public getEntryCount(): number {
return this.logPackages.length;
}
public clear(): void {
this.logPackages = [];
}
}