123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import { inWorker } from "@/next/env";
- import { isDevBuild } from "./env";
- import { logToDisk as webLogToDisk } from "./log-web";
- import { workerBridge } from "./worker/worker-bridge";
- /**
- * Write a {@link message} to the on-disk log.
- *
- * This is used by the renderer process (via the contextBridge) to add entries
- * in the log that is saved on disk.
- */
- export const logToDisk = (message: string) => {
- const electron = globalThis.electron;
- if (electron) electron.logToDisk(message);
- else if (inWorker()) workerLogToDisk(message);
- else webLogToDisk(message);
- };
- const workerLogToDisk = (message: string) => {
- workerBridge.logToDisk(message).catch((e) => {
- console.error(
- "Failed to log a message from worker",
- e,
- "\nThe message was",
- message,
- );
- });
- };
- const messageWithError = (message: string, e?: unknown) => {
- if (!e) return message;
- let es: string;
- if (e instanceof Error) {
- // In practice, we expect ourselves to be called with Error objects, so
- // this is the happy path so to say.
- return `${e.name}: ${e.message}\n${e.stack}`;
- } else {
- // For the rest rare cases, use the default string serialization of e.
- es = String(e);
- }
- return `${message}: ${es}`;
- };
- const logError = (message: string, e?: unknown) => {
- const m = `[error] ${messageWithError(message, e)}`;
- if (isDevBuild) console.error(m);
- logToDisk(m);
- };
- const logWarn = (message: string, e?: unknown) => {
- const m = `[warn] ${messageWithError(message, e)}`;
- if (isDevBuild) console.error(m);
- logToDisk(m);
- };
- const logInfo = (...params: unknown[]) => {
- const message = params
- .map((p) => (typeof p == "string" ? p : JSON.stringify(p)))
- .join(" ");
- const m = `[info] ${message}`;
- if (isDevBuild) console.log(m);
- logToDisk(m);
- };
- const logDebug = (param: () => unknown) => {
- if (isDevBuild) console.log("[debug]", param());
- };
- /**
- * Ente's logger.
- *
- * This is an object that provides three functions to log at the corresponding
- * levels - error, info or debug.
- *
- * Whenever we need to save a log message to disk,
- *
- * - When running under electron these messages are saved to the log maintained
- * by the electron app we're running under.
- *
- * - Otherwise such messages are written to a ring buffer in local storage.
- */
- export default {
- /**
- * Log an error message with an optional associated error object.
- *
- * {@link e} is generally expected to be an `instanceof Error` but it can be
- * any arbitrary object that we obtain, say, when in a try-catch handler (in
- * JavaScript any arbitrary value can be thrown).
- *
- * The log is written to disk. In development builds, the log is also
- * printed to the browser console.
- */
- error: logError,
- /**
- * Sibling of {@link error}, with the same parameters and behaviour, except
- * it gets prefixed with a warning instead of an error tag.
- */
- warn: logWarn,
- /**
- * Log a message.
- *
- * This is meant as a replacement of {@link console.log}, and takes an
- * arbitrary number of arbitrary parameters that it then serializes.
- *
- * The log is written to disk. In development builds, the log is also
- * printed to the browser console.
- */
- info: logInfo,
- /**
- * Log a debug message.
- *
- * To avoid running unnecessary code in release builds, this takes a
- * function to call to get the log message instead of directly taking the
- * message. The provided function will only be called in development builds.
- *
- * The function can return an arbitrary value which is serialized before
- * being logged.
- *
- * This log is NOT written to disk. And it is printed to the browser
- * console, but only in development builds.
- */
- debug: logDebug,
- };
|