@kitamersion/kita-logging
v1.0.6
Published
Lightweight IndexDB logging library for web applications.
Readme
@kitamersion/kita-logging a lightweight, browser-focused logging library that buffers logs in-memory and persists them to IndexedDB in batches.
Key features
- Buffered, fire-and-forget logging for minimal runtime impact
- Persists logs to IndexedDB with a
by_timestampindex (newest-first reads) - Configurable log prefix and retention period
- Small public API:
logger(default),config, andhistory - Safe local snapshot to
localStorageon failures (optional)
Install
npm install @kitamersion/kita-loggingQuick usage
Default exports: a buffered logger instance (default export) plus named history and config helpers.
import logger, { history, config } from "@kitamersion/kita-logging";
// fire-and-forget
logger.info("App started");
logger.warn("Possible issue detected");
// wait for persistence when needed
await logger.flush();
// read logs (newest first)
const logs = await history.getLogs();
console.log(logs[0].timestampISO, logs[0].message, logs[0].prefix);
// configure
await config.setLogPrefix("[MY_APP]");
await config.setLogRetentionDays(14);
// configure buffered logger options (persisted)
await config.setBufferedOptions({ flushIntervalMs: 1000, batchSize: 25 });
const current = await config.getBufferedOptions();
console.log(current);
// capture an Error inside a try/catch — the stack will be persisted on the log entry
try {
throw new Error("example");
} catch (err) {
// logger.error accepts an optional Error (or string) as a second argument
await logger.error("caught failure", err);
}React: Provider + hook example
import React, {
createContext,
useContext,
useEffect,
useState,
PropsWithChildren,
} from "react";
import { config } from "@kitamersion/kita-logging";
type SimpleLoggerConfig = {
logPrefix: string;
logRetentionDays: number;
};
const SimpleLoggerContext = createContext<SimpleLoggerConfig | undefined>(
undefined
);
export const useSimpleLoggerConfig = () => {
const ctx = useContext(SimpleLoggerContext);
if (!ctx)
throw new Error(
"useSimpleLoggerConfig must be used within LoggerProviderSimple"
);
return ctx;
};
// Minimal provider that ensures defaults and exposes current values
export const LoggerProviderSimple = ({
children,
}: PropsWithChildren<object>) => {
const [logPrefix, setLogPrefix] = useState("[KITA_LOGGING]");
const [logRetentionDays, setLogRetentionDays] = useState(7);
useEffect(() => {
let mounted = true;
(async () => {
const cfg = await config.viewCurrentConfigurations();
let prefix = cfg.logPrefix;
if (!prefix || prefix.trim() === "") {
prefix = "[KITA_LOGGING]";
await config.setLogPrefix(prefix);
}
let days = cfg.logRetentionDays;
if (!days || days <= 0) {
days = 1;
await config.setLogRetentionDays(days);
}
if (!mounted) return;
setLogPrefix(prefix);
setLogRetentionDays(days);
})();
return () => {
mounted = false;
};
}, []);
return (
<SimpleLoggerContext.Provider value={{ logPrefix, logRetentionDays }}>
{children}
</SimpleLoggerContext.Provider>
);
};
export default LoggerProviderSimple;Exposed APIs
logger (default export)
logger.info(message: string): void— push an info-level loglogger.debug(message: string): void— push a debug-level loglogger.warn(message: string): void— push a warn-level loglogger.error(message: string): void— push an error-level loglogger.error(message: string, err?: Error | string): Promise<void>— push an error-level log; if anErroror stack string is provided it will be saved on the log entry asstacklogger.flush(): Promise<void>— force flush buffered entries to IndexedDBlogger.start(): void— start periodic flush (enabled by default)logger.stop(): Promise<void>— stop periodic flush and flush remaining entrieslogger.config— read-only object with runtime configuration valueslogger.refresh(): Promise<void>— refresh prefix from persisted config
config (named export)
config.setLogPrefix(prefix: string): Promise<void>config.getLogPrefix(): Promise<string>config.setLogRetentionDays(days: number): Promise<void>config.getLogRetentionDays(): Promise<number>config.viewCurrentConfigurations(): Promise<{ logPrefix: string, logRetentionDays: number }>config.setBufferedOptions(opts: BufferedOptions): Promise<void>— persist buffered logger options (flushIntervalMs, batchSize, maxBufferSize, persistToLocalStorage, captureStack, maxStackChars)config.getBufferedOptions(): Promise<BufferedOptions>— read persisted buffered options (or defaults)config.onBufferedOptionsChange(fn: (opts: BufferedOptions) => void): () => void— subscribe to changes to buffered options; returns an unsubscribe functionconfig.setCaptureStack(capture: boolean): Promise<void>— toggle capturing of stacks for error logs (persists to config)config.getCaptureStack(): Promise<boolean>— read persisted captureStack settingconfig.setMaxStackChars(chars: number): Promise<void>— set maximum characters to store for stack traces (persists to config)config.getMaxStackChars(): Promise<number>— read persisted maximum stack chars
history (named export)
history.getLogs(): Promise<LogEntry[]>— returns newest-first;LogEntryincludes:id,timestamp(ms),timestampISO,level,message,prefix, andstack(when available)history.deleteExpiredLogs(retentionDays?: number): Promise<void>history.deleteAllLogs(): Promise<void>
logger helpers
createLogger(opts?: BufferedOptions)— create a custom buffered logger instance with the same API as the defaultlogger(useful for per-module or per-environment customization). TheBufferedOptionsshape is the same as described in "Configuration options (buffered logger)" below.- The default exported
loggerinstance will attempt to read persisted buffered options fromconfigon startup and will reconfigure itself ifconfig.setBufferedOptionsis called at runtime. Existing references to the exportedloggerremain valid when the implementation is swapped.
Configuration options (buffered logger)
When creating a custom buffered logger via createLogger(opts) or when persisting options via config.setBufferedOptions, available options:
flushIntervalMs(number) — automatic flush interval in ms (default:2000)batchSize(number) — entries per flush (default:50)maxBufferSize(number) — max entries in memory (default:5000)persistToLocalStorage(boolean) — snapshot buffer tolocalStorageon failures (default:true)captureStack(boolean) — capture and persist stack traces for error logs (default:true)maxStackChars(number) — maximum characters stored for stack traces (default:2000)
Note: stacks are truncated to a reasonable default length (2000 characters) to avoid very large DB entries; this limit is configurable via config.setMaxStackChars and the default is defined in src/defaults.ts.
Tests & development
Run build and tests locally:
npm run build
npm run testNotes
- The logger is intentionally buffered. Call
logger.flush()when you need to guarantee persistence (e.g., before a critical navigation or test assertion). - Log entries include both a numeric
timestamp(ms since epoch) andtimestampISOfor UI display. history.getLogs()returns newest-first by default. For very large datasets use cursor-based reads on theby_timestampindex for streaming/pagination.
