104 lines
2.7 KiB
TypeScript
104 lines
2.7 KiB
TypeScript
// We have to use process.env, otherwise pino doesn't work
|
|
/* eslint-disable node/no-process-env */
|
|
import pino from "pino";
|
|
// import pinoPretty from "pino-pretty";
|
|
// import { isDevelopment, isTest } from "./isEnv";
|
|
import { isObject } from "./utils";
|
|
import { obfuscateValue } from "@/modules/app-configuration/utils";
|
|
import { BaseError, BaseTrpcError } from "@/errors";
|
|
|
|
/* c8 ignore start */
|
|
export const logger = pino({
|
|
level: process.env.APP_DEBUG ?? "info",
|
|
redact: {
|
|
paths: ["secretKey", "*[*].secretKey"],
|
|
censor: (value) => redactLogValue(value),
|
|
},
|
|
// transport:
|
|
// process.env.CI || isDevelopment() || isTest()
|
|
// ? {
|
|
// target: "pino-pretty",
|
|
// options: {
|
|
// colorize: true,
|
|
// },
|
|
// }
|
|
// : undefined,
|
|
});
|
|
/* c8 ignore stop */
|
|
|
|
export const createLogger = logger.child.bind(logger);
|
|
|
|
export const redactLogValue = (value: unknown) => {
|
|
if (typeof value !== "string") {
|
|
// non-string values are fully redacted to prevent leaks
|
|
return "[REDACTED]";
|
|
}
|
|
|
|
return obfuscateValue(value);
|
|
};
|
|
|
|
export const redactError = (error: unknown) => {
|
|
if (error instanceof BaseTrpcError) {
|
|
const { message, name, errorCode, statusCode, trpcCode } = error;
|
|
return {
|
|
message,
|
|
name,
|
|
errorCode,
|
|
statusCode,
|
|
trpcCode,
|
|
};
|
|
}
|
|
if (error instanceof BaseError) {
|
|
const { message, name, errorCode, statusCode } = error;
|
|
return {
|
|
message,
|
|
name,
|
|
errorCode,
|
|
statusCode,
|
|
};
|
|
}
|
|
if (error instanceof Error) {
|
|
const { message, name } = error;
|
|
return {
|
|
message,
|
|
name,
|
|
};
|
|
}
|
|
};
|
|
|
|
export const redactLogObject = <T extends {}>(obj: T, callCount = 1): T => {
|
|
if (callCount > 10) {
|
|
logger.warn("Exceeded max call count for redactLogObject");
|
|
return { _message: "[REDACTED - MAX CALL COUNT EXCEEDED]" } as unknown as T;
|
|
}
|
|
|
|
const entries = Object.entries(obj).map(([key, value]) => {
|
|
if (isObject(value)) {
|
|
return [key, redactLogObject(value, callCount + 1)];
|
|
}
|
|
if (Array.isArray(value)) {
|
|
return [key, redactLogArray(value)];
|
|
}
|
|
return [key, redactLogValue(value)];
|
|
});
|
|
return Object.fromEntries(entries) as T;
|
|
};
|
|
|
|
export const redactLogArray = <T extends unknown[]>(array: T | undefined, callCount = 1): T => {
|
|
if (!array) return [] as unknown as T;
|
|
if (callCount > 10) {
|
|
logger.warn("Exceeded max call count for redactLogArray");
|
|
return [] as unknown as T;
|
|
}
|
|
|
|
return array.map((item) => {
|
|
if (isObject(item)) {
|
|
return redactLogObject(item, callCount + 1);
|
|
}
|
|
if (Array.isArray(item)) {
|
|
return redactLogArray(item, callCount + 1);
|
|
}
|
|
return redactLogValue(item);
|
|
}) as T;
|
|
};
|