@embeddable.com/sdk-core
Version:
Core Embeddable SDK module responsible for web-components bundling and publishing.
113 lines (99 loc) • 2.89 kB
text/typescript
import * as fs from "node:fs/promises";
import * as path from "node:path";
import { getSDKVersions } from "./utils";
const LOG_DIR = path.join(process.cwd(), ".embeddable", "logs");
export const ERROR_LOG_FILE = path.join(LOG_DIR, "error.log");
const MAX_LOG_SIZE = 5 * 1024 * 1024; // 5 MB
const MAX_LOG_FILES = 5;
interface LogEntry {
timestamp: string;
command: string;
breadcrumbs: string[];
error: string;
}
interface LogErrorParams {
command: string;
breadcrumbs: string[];
error: unknown;
}
export async function initLogger(command: string) {
try {
await fs.mkdir(LOG_DIR, { recursive: true });
} catch (error) {
console.error("Failed to create log directory:", error);
}
setupGlobalErrorHandlers(command);
}
export async function logError({
command,
breadcrumbs,
error,
}: LogErrorParams) {
const sdkVersions = getSDKVersions();
const logEntry: LogEntry = {
timestamp: new Date().toISOString(),
command,
breadcrumbs,
error:
error instanceof Error
? `${error.name}: ${error.message}\n${error.stack}`
: String(error),
};
const logMessage = `
[${logEntry.timestamp}] Command: ${logEntry.command}
Breadcrumbs: ${logEntry.breadcrumbs.join(" > ")}
Error: ${logEntry.error}
OS: ${process.platform}
Node: ${process.version}
SDK Versions: ${JSON.stringify(sdkVersions, null, 2)}
----------------------------------------
`;
try {
await rotateLogIfNeeded();
await fs.appendFile(ERROR_LOG_FILE, logMessage);
console.error(
`An error occurred during ${command}. Check the log file for details: ${ERROR_LOG_FILE}`,
);
} catch (error) {
console.error("Failed to write to log file:", error);
}
}
async function rotateLogIfNeeded() {
try {
const stats = await fs.stat(ERROR_LOG_FILE);
if (stats.size < MAX_LOG_SIZE) {
return;
}
for (let i = MAX_LOG_FILES - 1; i > 0; i--) {
const oldFile = `${ERROR_LOG_FILE}.${i}`;
const newFile = `${ERROR_LOG_FILE}.${i + 1}`;
try {
await fs.rename(oldFile, newFile);
} catch (error) {
// Ignore error if file doesn't exist
}
}
await fs.rename(ERROR_LOG_FILE, `${ERROR_LOG_FILE}.1`);
await fs.writeFile(ERROR_LOG_FILE, ""); // Create a new empty log file
} catch (error: any) {
if (error.code !== "ENOENT") {
console.error("Error rotating log file:", error);
}
}
}
function setupGlobalErrorHandlers(command: string) {
process.on("uncaughtException", async (error) => {
await logError({ command, breadcrumbs: ["uncaughtException"], error });
console.error(error);
process.exit(1);
});
process.on("unhandledRejection", async (reason) => {
await logError({
command,
breadcrumbs: ["unhandledRejection"],
error: reason as Error | string,
});
console.error(reason);
process.exit(1);
});
}