- Remove last runtimeEnv import from processMessage.ts - Add env: Env param to all functions with 'Cannot find name env' errors - Convert initRedisV2 to lazy initialization (ensureRedisV2 + Proxy) - Add Bindings: Env to StripeWebhookHonoEnv - Fix 12+ files across external/, internal/, queue/ modules - Scanning test passes: 1/1 (runtime-env-imports.test.ts)
114 lines
3.2 KiB
TypeScript
114 lines
3.2 KiB
TypeScript
import type pino from "pino";
|
|
import { initLogger } from "@/utils/logging/initLogger";
|
|
|
|
const createLogMethod = (pinoMethod: any, logtailMethod?: any) => {
|
|
function rewriteAppPath(str: string) {
|
|
if (typeof str !== "string") return str;
|
|
// Replace file:///app/ with ./
|
|
str = str.replace("file:///app/", "./");
|
|
return str.replace(/\/app\//g, "./");
|
|
}
|
|
|
|
function rewriteErrorStack(error: Error) {
|
|
if (error instanceof Error && typeof error.stack === "string") {
|
|
const newError = new Error(error.message);
|
|
newError.stack = rewriteAppPath(error.stack);
|
|
return newError;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
return (...args: any[]) => {
|
|
let message = "";
|
|
let mergedObj = {};
|
|
|
|
// Helper function to convert Error objects to plain objects
|
|
|
|
const strings = args
|
|
.filter((arg) => typeof arg === "string")
|
|
.map(rewriteAppPath);
|
|
|
|
const objects = args
|
|
.filter((arg) => typeof arg !== "string" && arg !== null)
|
|
.map((obj) => (obj instanceof Error ? rewriteErrorStack(obj) : obj));
|
|
|
|
// Use last string as message, or use Error message if no strings provided
|
|
if (strings.length > 0) {
|
|
message = strings[strings.length - 1];
|
|
} else {
|
|
// If no string message but we have an Error object, use its stack trace
|
|
const errorObject = args.find((arg) => arg instanceof Error);
|
|
if (errorObject) {
|
|
message = rewriteAppPath(
|
|
errorObject.stack || errorObject.message || "Error occurred",
|
|
);
|
|
}
|
|
}
|
|
|
|
// Merge all objects
|
|
mergedObj = Object.assign({}, ...objects);
|
|
|
|
// Pino format: object first, message second (if object exists)
|
|
if (Object.keys(mergedObj).length > 0) {
|
|
pinoMethod(mergedObj, message);
|
|
} else {
|
|
pinoMethod(message);
|
|
}
|
|
|
|
if (!logtailMethod) {
|
|
return;
|
|
}
|
|
|
|
// Logtail format: message first, then object (if exists)
|
|
if (Object.keys(mergedObj).length > 0) {
|
|
logtailMethod(message, mergedObj);
|
|
} else {
|
|
logtailMethod(message);
|
|
}
|
|
};
|
|
};
|
|
|
|
const createLoggerStructure = (
|
|
basePinoLogger: pino.Logger,
|
|
env: Env,
|
|
): Logger => ({
|
|
debug: createLogMethod(basePinoLogger.debug.bind(basePinoLogger)),
|
|
info: createLogMethod(basePinoLogger.info.bind(basePinoLogger)),
|
|
warn: createLogMethod(basePinoLogger.warn.bind(basePinoLogger)),
|
|
error: createLogMethod(basePinoLogger.error.bind(basePinoLogger)),
|
|
child: ({
|
|
context,
|
|
onlyProd = false,
|
|
}: {
|
|
context: any;
|
|
onlyProd?: boolean;
|
|
}) => {
|
|
if (onlyProd && (env.NODE_ENV as string | undefined) !== "production") {
|
|
return createLoggerStructure(basePinoLogger, env);
|
|
}
|
|
|
|
const childPinoLogger = basePinoLogger.child(context);
|
|
return createLoggerStructure(childPinoLogger, env);
|
|
},
|
|
});
|
|
|
|
export const createLogger = (env: Env) =>
|
|
createLoggerStructure(initLogger({}, env), env);
|
|
|
|
/**
|
|
* Lazy dual-output logger (stdout JSON + axiom). Used only by long-running
|
|
* trigger.dev tasks so their lines surface in both the trigger run UI and
|
|
* our axiom store. `createLogger` is unaffected.
|
|
*/
|
|
export const createDualLogger = (env: Env) =>
|
|
createLoggerStructure(initLogger({ mode: "dual" }, env), env);
|
|
|
|
export type Logger = {
|
|
debug: (...args: any[]) => void;
|
|
info: (...args: any[]) => void;
|
|
warn: (...args: any[]) => void;
|
|
error: (...args: any[]) => void;
|
|
child: (args: { context: any; onlyProd?: boolean }) => Logger;
|
|
};
|