You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
6.4 KiB
219 lines
6.4 KiB
/**
|
|
* Enhanced logger with self-contained database logging
|
|
*
|
|
* Provides comprehensive logging with console and database output.
|
|
*
|
|
* @author Matthew Raymer
|
|
* @version 2.0.0
|
|
* @since 2025-01-25
|
|
*/
|
|
|
|
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
|
|
|
const _memoryLogs: string[] = [];
|
|
|
|
export function appendToMemoryLogs(message: string): void {
|
|
_memoryLogs.push(`${new Date().toISOString()}: ${message}`);
|
|
if (_memoryLogs.length > 1000) {
|
|
_memoryLogs.splice(0, _memoryLogs.length - 1000);
|
|
}
|
|
}
|
|
|
|
export function getMemoryLogs(): string[] {
|
|
return [..._memoryLogs];
|
|
}
|
|
|
|
export function safeStringify(obj: unknown) {
|
|
const seen = new WeakSet();
|
|
|
|
return JSON.stringify(obj, (_key, value) => {
|
|
if (typeof value === "object" && value !== null) {
|
|
if (seen.has(value)) {
|
|
return "[Circular]";
|
|
}
|
|
seen.add(value);
|
|
}
|
|
|
|
if (typeof value === "function") {
|
|
return `[Function: ${value.name || "anonymous"}]`;
|
|
}
|
|
|
|
return value;
|
|
});
|
|
}
|
|
|
|
// Determine if we should suppress verbose logging (for Electron)
|
|
const isElectron = process.env.VITE_PLATFORM === "electron";
|
|
const isProduction = process.env.NODE_ENV === "production";
|
|
|
|
// Track initialization state to prevent circular dependencies
|
|
let isInitializing = true;
|
|
|
|
// Mark initialization as complete after a delay to allow all services to start
|
|
setTimeout(() => {
|
|
isInitializing = false;
|
|
}, 2000); // 2 second delay to allow all services to initialize
|
|
|
|
// Function to check if we should skip database logging during initialization
|
|
function shouldSkipDatabaseLogging(message: string): boolean {
|
|
// Skip during initialization phase
|
|
if (isInitializing) {
|
|
return true;
|
|
}
|
|
|
|
// Skip specific initialization-related messages even after initialization
|
|
const initializationMessages = [
|
|
"[PlatformServiceFactory]",
|
|
"[SQLWorker]",
|
|
"[WebPlatformService]",
|
|
"[CapacitorPlatformService]",
|
|
"[CapacitorMigration]",
|
|
"[DB-Integrity]",
|
|
"[Migration]",
|
|
"[IndexedDBMigrationService]",
|
|
"Creating singleton instance",
|
|
"Worker loaded",
|
|
"Worker initialized",
|
|
"Platform service",
|
|
];
|
|
|
|
return initializationMessages.some((pattern) => message.includes(pattern));
|
|
}
|
|
|
|
// Self-contained database logging function
|
|
async function logToDatabase(
|
|
message: string,
|
|
level: string = "info",
|
|
): Promise<void> {
|
|
// Prevent infinite logging loops
|
|
if (isInitializing || shouldSkipDatabaseLogging(message)) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const platform = PlatformServiceFactory.getInstance();
|
|
const todayKey = new Date().toDateString();
|
|
|
|
await platform.dbExec("INSERT INTO logs (date, message) VALUES (?, ?)", [
|
|
todayKey,
|
|
`[${level.toUpperCase()}] ${message}`,
|
|
]);
|
|
} catch (error) {
|
|
// Fallback to console if database logging fails
|
|
// eslint-disable-next-line no-console
|
|
console.error(`[Logger] Database logging failed: ${error}`);
|
|
}
|
|
}
|
|
|
|
// Enhanced logger with self-contained database methods
|
|
export const logger = {
|
|
debug: (message: string, ...args: unknown[]) => {
|
|
// Debug logs are very verbose - only show in development mode for web
|
|
if (!isProduction && !isElectron) {
|
|
// eslint-disable-next-line no-console
|
|
console.debug(message, ...args);
|
|
}
|
|
// Don't log debug messages to database to reduce noise
|
|
},
|
|
|
|
log: (message: string, ...args: unknown[]) => {
|
|
// Regular logs - show in development or for capacitor, but quiet for Electron
|
|
if (
|
|
(!isProduction && !isElectron) ||
|
|
process.env.VITE_PLATFORM === "capacitor"
|
|
) {
|
|
// eslint-disable-next-line no-console
|
|
console.log(message, ...args);
|
|
}
|
|
|
|
// Database logging
|
|
const argsString = args.length > 0 ? " - " + safeStringify(args) : "";
|
|
logToDatabase(message + argsString, "info");
|
|
},
|
|
|
|
info: (message: string, ...args: unknown[]) => {
|
|
if (
|
|
process.env.NODE_ENV !== "production" ||
|
|
process.env.VITE_PLATFORM === "capacitor" ||
|
|
process.env.VITE_PLATFORM === "electron"
|
|
) {
|
|
// eslint-disable-next-line no-console
|
|
console.info(message, ...args);
|
|
}
|
|
|
|
// Database logging
|
|
const argsString = args.length > 0 ? " - " + safeStringify(args) : "";
|
|
logToDatabase(message + argsString, "info");
|
|
},
|
|
|
|
warn: (message: string, ...args: unknown[]) => {
|
|
// Always show warnings, but for Electron, suppress routine database warnings
|
|
if (!isElectron || !message.includes("[CapacitorPlatformService]")) {
|
|
// eslint-disable-next-line no-console
|
|
console.warn(message, ...args);
|
|
}
|
|
|
|
// Database logging
|
|
const argsString = args.length > 0 ? " - " + safeStringify(args) : "";
|
|
logToDatabase(message + argsString, "warn");
|
|
},
|
|
|
|
error: (message: string, ...args: unknown[]) => {
|
|
// Errors will always be logged to console
|
|
// eslint-disable-next-line no-console
|
|
console.error(message, ...args);
|
|
|
|
// Database logging
|
|
const messageString = safeStringify(message);
|
|
const argsString = args.length > 0 ? safeStringify(args) : "";
|
|
logToDatabase(messageString + argsString, "error");
|
|
},
|
|
|
|
// New database-focused methods (self-contained)
|
|
toDb: async (message: string, level?: string): Promise<void> => {
|
|
await logToDatabase(message, level || "info");
|
|
},
|
|
|
|
toConsoleAndDb: async (message: string, isError = false): Promise<void> => {
|
|
// Console output
|
|
if (isError) {
|
|
// eslint-disable-next-line no-console
|
|
console.error(message);
|
|
} else {
|
|
// eslint-disable-next-line no-console
|
|
console.log(message);
|
|
}
|
|
// Database output
|
|
await logToDatabase(message, isError ? "error" : "info");
|
|
},
|
|
|
|
// Component context methods
|
|
withContext: (componentName?: string) => ({
|
|
log: (message: string, level?: string) =>
|
|
logToDatabase(`[${componentName}] ${message}`, level),
|
|
error: (message: string) =>
|
|
logToDatabase(`[${componentName}] ${message}`, "error"),
|
|
}),
|
|
};
|
|
|
|
// Function to manually mark initialization as complete
|
|
export function markInitializationComplete(): void {
|
|
isInitializing = false;
|
|
}
|
|
|
|
// Function to check initialization status
|
|
export function isInitializationPhase(): boolean {
|
|
return isInitializing;
|
|
}
|
|
|
|
// Add CommonJS export for Electron
|
|
if (typeof module !== "undefined" && module.exports) {
|
|
module.exports = {
|
|
logger,
|
|
markInitializationComplete,
|
|
isInitializationPhase,
|
|
};
|
|
}
|
|
|
|
// Add default export for ESM
|
|
export default { logger, markInitializationComplete, isInitializationPhase };
|
|
|