From dfeb04394a1e5918e2a82b8424d41a420c765769 Mon Sep 17 00:00:00 2001 From: terwer Date: Fri, 5 May 2023 23:33:40 +0800 Subject: [PATCH] feat(zhi-lib-log): add a better log system --- package.json | 6 +- packages/zhi-lib-env/src/index.spec.ts | 91 +++++++++ packages/zhi-lib-env/tsconfig.json | 3 +- packages/zhi-lib-log/src/index.spec.ts | 81 ++++++++ packages/zhi-lib-log/src/index.ts | 25 +++ packages/zhi-lib-log/src/lib/crossChalk.ts | 78 ++++++++ packages/zhi-lib-log/src/lib/defaultLogger.ts | 84 +++++++++ packages/zhi-lib-log/src/lib/envHelper.ts | 77 ++++++++ .../src/lib/factory/abstractLogFactory.ts | 65 +++++++ .../src/lib/factory/customLogFactory.ts | 54 ++++++ packages/zhi-lib-log/src/lib/logConstants.ts | 69 +++++++ packages/zhi-lib-log/src/lib/logFactory.ts | 70 +++++++ packages/zhi-lib-log/src/lib/logger.ts | 173 ++++++++++++++++++ .../zhi-lib-log/src/lib/zhi-lib-log.spec.ts | 27 ++- packages/zhi-lib-log/src/lib/zhi-lib-log.ts | 41 ++++- packages/zhi-lib-log/tsconfig.json | 3 +- pnpm-lock.yaml | 25 +++ 17 files changed, 964 insertions(+), 8 deletions(-) create mode 100644 packages/zhi-lib-env/src/index.spec.ts create mode 100644 packages/zhi-lib-log/src/index.spec.ts create mode 100644 packages/zhi-lib-log/src/lib/crossChalk.ts create mode 100644 packages/zhi-lib-log/src/lib/defaultLogger.ts create mode 100644 packages/zhi-lib-log/src/lib/envHelper.ts create mode 100644 packages/zhi-lib-log/src/lib/factory/abstractLogFactory.ts create mode 100644 packages/zhi-lib-log/src/lib/factory/customLogFactory.ts create mode 100644 packages/zhi-lib-log/src/lib/logConstants.ts create mode 100644 packages/zhi-lib-log/src/lib/logFactory.ts create mode 100644 packages/zhi-lib-log/src/lib/logger.ts diff --git a/package.json b/package.json index 48ac03b3..33a50fab 100644 --- a/package.json +++ b/package.json @@ -48,5 +48,9 @@ "vite-tsconfig-paths": "^4.0.2", "vitest": "^0.31.0" }, - "dependencies": {} + "dependencies": { + "kleur": "^4.1.5", + "loglevel": "^1.8.1", + "loglevel-plugin-prefix": "^0.8.4" + } } diff --git a/packages/zhi-lib-env/src/index.spec.ts b/packages/zhi-lib-env/src/index.spec.ts new file mode 100644 index 00000000..79b09499 --- /dev/null +++ b/packages/zhi-lib-env/src/index.spec.ts @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import { describe, expect, it } from "vitest" +import { Env, EnvConstants } from "./index" + +describe("zhiEnv", () => { + const NOT_EXIST_KEY = "NOT_EXIST_KEY" + + it("test env", () => { + const env = new Env(import.meta.env) + expect(env.getEnv(EnvConstants.NODE_ENV_KEY)).toEqual("test") + }) + + it("test debug mode", () => { + const env = new Env(import.meta.env) + expect(env.getEnv(EnvConstants.VITE_DEBUG_MODE_KEY)).toEqual("true") + }) + + it("test getEnv undefined", function () { + const env = new Env(import.meta.env) + + const val = env.getEnv(NOT_EXIST_KEY) + console.log("val=>", val) + expect(val).toBeUndefined() + }) + + it("test getEnv ok", function () { + const env = new Env(import.meta.env) + + const val = env.getEnv(EnvConstants.VITE_DEBUG_MODE_KEY) + console.log("val=>", val) + // expect(val).toBeTruthy() + }) + + it("test getStringEnv", function () { + const env = new Env(import.meta.env) + + const val = env.getStringEnv(EnvConstants.VITE_DEBUG_MODE_KEY) + console.log("val=>", val) + expect(typeof val).toBe("string") + }) + + it("test getBooleanEnv", function () { + const env = new Env(import.meta.env) + + const val = env.getBooleanEnv(EnvConstants.VITE_DEBUG_MODE_KEY) + console.log("val=>", val) + expect(typeof val).toBe("boolean") + }) + + it("test getEnvOrDefault", function () { + const env = new Env(import.meta.env) + + const val = env.getEnvOrDefault(NOT_EXIST_KEY, "hello") + console.log("val=>", val) + expect(typeof val).toBe("string") + }) + + it("test custom env", function () { + const env = new Env({ + "mykey-a": "myvalue", + }) + + const val = env.getEnv("mykey-a") + console.log("val=>", val) + expect(typeof val).toBe("string") + }) +}) diff --git a/packages/zhi-lib-env/tsconfig.json b/packages/zhi-lib-env/tsconfig.json index bdf594cd..839952da 100644 --- a/packages/zhi-lib-env/tsconfig.json +++ b/packages/zhi-lib-env/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "module": "commonjs", + "target": "esnext", + "module": "esnext", "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, diff --git a/packages/zhi-lib-log/src/index.spec.ts b/packages/zhi-lib-log/src/index.spec.ts new file mode 100644 index 00000000..869edcfb --- /dev/null +++ b/packages/zhi-lib-log/src/index.spec.ts @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import { describe, it } from "vitest" +import { Env } from "@siyuan-community/zhi-env" +import { LogFactory, LogLevelEnum } from "./index" + +describe("zhiLibLog", () => { + it("test default log", function () { + const logger = LogFactory.defaultLogger() + logger.debug("This is debug log") + logger.info("This is info log") + logger.error("This is error log") + }) + + it("test default log env", function () { + const env = new Env(import.meta.env) + const logger = LogFactory.defaultLogger(env, 4) + logger.debug("This is debug log") + logger.info("This is info log") + logger.error("This is error log") + }) + + it("test custom sign", function () { + const logger = LogFactory.customSignLogFactory("haha").getLogger() + logger.debug("This is debug log") + logger.info("This is info log") + logger.error("This is error log") + }) + + it("test default logger", function () { + const logger = LogFactory.customLogFactory().getLogger(undefined, 2) + logger.debug("This is debug log") + logger.info("This is info log") + logger.error("This is error log") + }) + + it("test custom logger", function () { + const logger = LogFactory.customLogFactory().getLogger("haha") + logger.debug("This is debug log") + logger.info("This is info log") + logger.error("This is error log") + }) + + it("test custom log level", function () { + const logger = LogFactory.customLogFactory(LogLevelEnum.LOG_LEVEL_TRACE).getLogger("test") + logger.trace("This is trace log") + logger.debug("This is debug log") + logger.info("This is info log") + // logger.error("This is error log") + }) + + it("test custom level and sign", function () { + const logger = LogFactory.customLogFactory(LogLevelEnum.LOG_LEVEL_DEBUG, "my-log").getLogger("test") + logger.debug("This is debug log") + logger.info("This is info log") + logger.error("This is error log") + }) +}) diff --git a/packages/zhi-lib-log/src/index.ts b/packages/zhi-lib-log/src/index.ts index d76c2a40..3da081f5 100644 --- a/packages/zhi-lib-log/src/index.ts +++ b/packages/zhi-lib-log/src/index.ts @@ -1 +1,26 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + export * from "./lib/zhi-lib-log" diff --git a/packages/zhi-lib-log/src/lib/crossChalk.ts b/packages/zhi-lib-log/src/lib/crossChalk.ts new file mode 100644 index 00000000..c45fb0f7 --- /dev/null +++ b/packages/zhi-lib-log/src/lib/crossChalk.ts @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import colors from "ansi-colors" +import kleur from "kleur" +import { BrowserUtil } from "@siyuan-community/zhi-device" + +/** + * 跨平台,同时支持Node和浏览器的颜色解决方案 + * + * @public + * @author terwer + * @version 1.9.2 + * @since 1.9.2 + */ +// polyfill due to https://github.com/vitejs/vite/issues/7385 +const crossChalk = { + white: (str: string): string => { + return BrowserUtil.isElectron() ? colors.whiteBright(str) : kleur.white(str) + }, + gray: (str: string): string => { + return BrowserUtil.isElectron() ? colors.gray(str) : kleur.gray(str) + }, + blue: (str: string): string => { + return BrowserUtil.isElectron() ? colors.blue(str) : kleur.blue(str) + }, + green: (str: string): string => { + return BrowserUtil.isElectron() ? colors.green(str) : kleur.green(str) + }, + yellow: (str: string): string => { + return BrowserUtil.isElectron() ? colors.yellow(str) : kleur.yellow(str) + }, + red: (str: string): string => { + return BrowserUtil.isElectron() ? colors.red(str) : kleur.red(str) + }, + bgWhite: (str: string): string => { + return BrowserUtil.isElectron() ? colors.bgWhiteBright(str) : kleur.bgWhite(str) + }, + bgGrey: (str: string): string => { + return BrowserUtil.isElectron() ? colors.bgCyanBright(str) : kleur.bgCyan(str) + }, + bgBlue: (str: string): string => { + return BrowserUtil.isElectron() ? colors.bgBlueBright(str) : kleur.bgBlue(str) + }, + bgGreen: (str: string): string => { + return BrowserUtil.isElectron() ? colors.bgGreenBright(str) : kleur.bgGreen(str) + }, + bgYellow: (str: string): string => { + return BrowserUtil.isElectron() ? colors.bgYellowBright(str) : kleur.bgYellow(str) + }, + bgRed: (str: string): string => { + return BrowserUtil.isElectron() ? colors.bgRedBright(str) : kleur.bgRed(str) + }, +} + +export default crossChalk diff --git a/packages/zhi-lib-log/src/lib/defaultLogger.ts b/packages/zhi-lib-log/src/lib/defaultLogger.ts new file mode 100644 index 00000000..e2ffa0fb --- /dev/null +++ b/packages/zhi-lib-log/src/lib/defaultLogger.ts @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ +import { Logger } from "loglevel" + +/** + * 默认日志记录器 + * + * @public + * @author terwer + * @since 1.0.7 + */ +interface DefaultLogger extends Logger { + /** + * 日志颜色 + */ + colors?: string[] + + /** + * Output trace message to console. + * This will also include a full stack trace + * + * @param msg - unknown data to log to the console + */ + trace(...msg: unknown[]): void + + /** + * Output debug message to console including appropriate icons + * + * @param msg - unknown data to log to the console + */ + debug(...msg: unknown[]): void + + /** + * Output debug message to console including appropriate icons + * + * @param msg - unknown data to log to the console + */ + log(...msg: unknown[]): void + + /** + * Output info message to console including appropriate icons + * + * @param msg - unknown data to log to the console + */ + info(...msg: unknown[]): void + + /** + * Output warn message to console including appropriate icons + * + * @param msg - unknown data to log to the console + */ + warn(...msg: unknown[]): void + + /** + * Output error message to console including appropriate icons + * + * @param msg - unknown data to log to the console + */ + error(...msg: unknown[]): void +} + +export default DefaultLogger diff --git a/packages/zhi-lib-log/src/lib/envHelper.ts b/packages/zhi-lib-log/src/lib/envHelper.ts new file mode 100644 index 00000000..2c47078d --- /dev/null +++ b/packages/zhi-lib-log/src/lib/envHelper.ts @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import LogLevelEnum, { LogConstants } from "./logConstants" +import { Env } from "@siyuan-community/zhi-env" + +/** + * 解析日志级别为枚举 + * + * @public + * @author terwer + * @since 1.4.0 + */ +class EnvHelper { + /** + * 解析日志级别为枚举 + * + * @param enumObj - 枚举对象 + * @param value - 配置的值 + */ + private static stringToEnumValue, K extends keyof T>( + enumObj: T, + value: string + ): T[keyof T] | undefined { + return enumObj[Object.keys(enumObj).filter((k) => enumObj[k as K].toString() === value)[0] as keyof typeof enumObj] + } + + /** + * 获取配置的日志级别 + */ + public static getEnvLevel(env?: Env): LogLevelEnum | undefined { + if (!env) { + return undefined + } + + const envValue = env.getEnvOrDefault(LogConstants.LOG_LEVEL_KEY, LogLevelEnum.LOG_LEVEL_INFO) + const envLevel = EnvHelper.stringToEnumValue(LogLevelEnum, envValue.toUpperCase()) + if (!envLevel) { + console.warn( + "[zhi-log] LOG_LEVEL is invalid in you .env file.It must be either debug, info, warn or error, fallback to default info level" + ) + } + + return envLevel + } + + /** + * 获取默认日志 + */ + public static getEnvLogger(env?: Env): string | undefined { + return !env ? undefined : env.getEnv(LogConstants.LOG_PREFIX_KEY) + } +} + +export default EnvHelper diff --git a/packages/zhi-lib-log/src/lib/factory/abstractLogFactory.ts b/packages/zhi-lib-log/src/lib/factory/abstractLogFactory.ts new file mode 100644 index 00000000..7c3725a8 --- /dev/null +++ b/packages/zhi-lib-log/src/lib/factory/abstractLogFactory.ts @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import LogLevelEnum from "../logConstants" +import { Env } from "@siyuan-community/zhi-env" +import Logger from "../logger" +import DefaultLogger from "../defaultLogger" + +/** + * 日志记录工厂 + * + * @public + * @author terwer + * @since 1.0.0 + */ +abstract class AbstractLogFactory { + private logger + + /** + * 默认日志级别 + * + * @param level - 可选,未设置默认INFO + * @param sign - 可选前缀,默认zhi + * @param env - 可选环境变量实例 + */ + protected constructor(level?: LogLevelEnum, sign?: string, env?: Env) { + this.logger = new Logger(level, sign, env) + } + + /** + * 获取日志记录器 + * + * @param loggerName - 日志记录器名称 + * @param stackSize - 打印栈的深度 + * @protected + */ + protected getLogger(loggerName?: string, stackSize?: number): DefaultLogger { + this.logger.setStackSize(stackSize) + return this.logger.getLogger(loggerName) + } +} + +export default AbstractLogFactory diff --git a/packages/zhi-lib-log/src/lib/factory/customLogFactory.ts b/packages/zhi-lib-log/src/lib/factory/customLogFactory.ts new file mode 100644 index 00000000..e0abf086 --- /dev/null +++ b/packages/zhi-lib-log/src/lib/factory/customLogFactory.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import AbstractLogFactory from "./abstractLogFactory" +import LogLevelEnum from "../logConstants" +import { Env } from "@siyuan-community/zhi-env" +import DefaultLogger from "../defaultLogger" + +/** + * 自定义日志工厂 + * + * @public + * @author terwer + * @since 1.0.7 + */ +class CustomLogFactory extends AbstractLogFactory { + constructor(level?: LogLevelEnum, sign?: string, env?: Env) { + super(level, sign, env) + } + + /** + * 获取默认的日志记录器 + * + * @param loggerName - 日志记录器名称 + * @param stackSize - 打印栈的深度 + */ + override getLogger(loggerName?: string, stackSize?: number): DefaultLogger { + return super.getLogger(loggerName, stackSize) + } +} + +export default CustomLogFactory diff --git a/packages/zhi-lib-log/src/lib/logConstants.ts b/packages/zhi-lib-log/src/lib/logConstants.ts new file mode 100644 index 00000000..de18bc9b --- /dev/null +++ b/packages/zhi-lib-log/src/lib/logConstants.ts @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +/** + * 日志常量 + * + * @public + * @author terwer + * @since 1.4.0 + */ +class LogConstants { + public static readonly LOG_LEVEL_KEY = "VITE_LOG_LEVEL" + public static readonly LOG_PREFIX_KEY = "VITE_LOG_PREFIX" +} + +/** + * 日志级别 + * + * @author terwer + * @since 1.0.7 + * @public + */ +enum LogLevelEnum { + /** + * TRACE + */ + LOG_LEVEL_TRACE = "TRACE", + /** + * DEBUG + */ + LOG_LEVEL_DEBUG = "DEBUG", + /** + * INFO + */ + LOG_LEVEL_INFO = "INFO", + /** + * WARN + */ + LOG_LEVEL_WARN = "WARN", + /** + * ERROR + */ + LOG_LEVEL_ERROR = "ERROR", +} + +export default LogLevelEnum +export { LogConstants } diff --git a/packages/zhi-lib-log/src/lib/logFactory.ts b/packages/zhi-lib-log/src/lib/logFactory.ts new file mode 100644 index 00000000..7d6e4d50 --- /dev/null +++ b/packages/zhi-lib-log/src/lib/logFactory.ts @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import { Env } from "@siyuan-community/zhi-env" +import DefaultLogger from "./defaultLogger" +import LogLevelEnum from "./logConstants" +import CustomLogFactory from "./factory/customLogFactory" + +/** + * 日志工具类 + * + * @public + * @author terwer + * @since 1.0.7 + */ +class LogFactory { + /** + * 默认日志记录器 + * + * @param stackSize - 栈的深度 + * @param env - 环境变量实例 + */ + public static defaultLogger(env?: Env, stackSize?: number): DefaultLogger { + return LogFactory.customLogFactory(undefined, undefined, env).getLogger(undefined, stackSize) + } + + /** + * 自定义日志工厂 + * + * @param level - 级别 + * @param sign - 标志 + * @param env - 环境变量 + */ + public static customLogFactory(level?: LogLevelEnum, sign?: string, env?: Env) { + return new CustomLogFactory(level, sign, env) + } + + /** + * 自定义日志工厂,自定义前缀 + * + * @param sign - 标志 + * @param env - 环境变量 + */ + public static customSignLogFactory(sign?: string, env?: Env) { + return new CustomLogFactory(undefined, sign, env) + } +} +export default LogFactory diff --git a/packages/zhi-lib-log/src/lib/logger.ts b/packages/zhi-lib-log/src/lib/logger.ts new file mode 100644 index 00000000..8323c8bf --- /dev/null +++ b/packages/zhi-lib-log/src/lib/logger.ts @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import loglevel from "loglevel" +import prefix from "loglevel-plugin-prefix" +import LogLevelEnum from "./logConstants" +import callsites, { CallSite } from "callsites" +import EnvHelper from "./envHelper" +import { Env } from "@siyuan-community/zhi-env" +import DefaultLogger from "./defaultLogger" +import crossChalk from "./crossChalk" + +/** + * 日志工具类 + * + * @author terwer + * @since 1.0.0 + */ +class Logger { + private consoleLogger = "console" + private stackSize = 1 + + /** + * 设置输出栈的深度,默认1 + * + * @param stackSize - 栈的深度 + */ + public setStackSize(stackSize?: number): void { + this.stackSize = stackSize ?? 1 + } + + constructor(level?: LogLevelEnum, sign?: string, env?: Env) { + this.stackSize = 1 + + // 级别 + let customLevel = undefined + if (level) { + customLevel = level + } else { + customLevel = EnvHelper.getEnvLevel(env) + } + customLevel = customLevel ?? LogLevelEnum.LOG_LEVEL_INFO + loglevel.setLevel(customLevel) + + const fmtLog = (level: LogLevelEnum, name: string, timestamp: Date, colorFn: any) => { + const strarr = [] + + // sign + const logSign = sign ?? EnvHelper.getEnvLogger(env) ?? "zhi" + strarr.push(crossChalk.gray("[") + colorFn(logSign) + crossChalk.gray("]")) + // timestamp + strarr.push(crossChalk.gray("[") + crossChalk.gray(timestamp.toString()) + crossChalk.gray("]")) + // level + strarr.push(colorFn(level.toUpperCase().toString())) + // name + strarr.push(colorFn(name)) + strarr.push(crossChalk.gray(":")) + return strarr + } + prefix.reg(loglevel) + prefix.apply(loglevel, { + format(level, name, timestamp) { + let strarr = [] + const logName = name ?? "" + + switch (level) { + case LogLevelEnum.LOG_LEVEL_TRACE: + strarr = fmtLog(level, logName, timestamp, crossChalk.gray) + break + case LogLevelEnum.LOG_LEVEL_DEBUG: + strarr = fmtLog(level, logName, timestamp, crossChalk.blue) + break + case LogLevelEnum.LOG_LEVEL_INFO: + strarr = fmtLog(level, logName, timestamp, crossChalk.green) + break + case LogLevelEnum.LOG_LEVEL_WARN: + strarr = fmtLog(level, logName, timestamp, crossChalk.yellow) + break + case LogLevelEnum.LOG_LEVEL_ERROR: + strarr = fmtLog(level, logName, timestamp, crossChalk.red) + break + default: + strarr = fmtLog(LogLevelEnum.LOG_LEVEL_INFO, logName, timestamp, crossChalk.green) + break + } + + return strarr.join(" ") + }, + }) + } + + /** + * 获取调用堆栈,若未获取到直接返回空数组 + * + * @author terwer + * @since 1.6.0 + */ + public getCallStack(): CallSite[] { + let cs: CallSite[] + try { + cs = callsites() + } catch (e) { + // if callsites not get logger, just ignore + cs = [] + } + return cs + } + + /** + * 获取日志记录器 + * + * @param loggerName - 日志记录器,默认为 console + * @author terwer + * @since 1.0.0 + */ + public getLogger = (loggerName?: string): DefaultLogger => { + let loggerFrom + // 显示优先 + if (loggerName) { + loggerFrom = loggerName + } else { + const allcs = this.getCallStack() + const baseNames = [] + + const cs = [] + + for (let i = 0; i < allcs.length; i++) { + const c = allcs[i] + const fname = c.getFileName() ?? "none" + + if (i > this.stackSize - 1) { + break + } + + const baseName = fname + "-" + c.getLineNumber() + ":" + c.getColumnNumber() + baseNames.push(baseName) + } + + if (cs.length > 0) { + loggerFrom = baseNames.join(" -> ") + } + } + + if (!loggerFrom || loggerFrom.trim().length === 0) { + loggerFrom = this.consoleLogger + } + return loglevel.getLogger(loggerFrom) as DefaultLogger + } +} + +export default Logger diff --git a/packages/zhi-lib-log/src/lib/zhi-lib-log.spec.ts b/packages/zhi-lib-log/src/lib/zhi-lib-log.spec.ts index 1b2ceb5b..152ff3c5 100644 --- a/packages/zhi-lib-log/src/lib/zhi-lib-log.spec.ts +++ b/packages/zhi-lib-log/src/lib/zhi-lib-log.spec.ts @@ -1,7 +1,30 @@ -import { zhiLibLog } from "./zhi-lib-log" +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ describe("zhiLibLog", () => { it("should work", () => { - expect(zhiLibLog()).toEqual("zhi-lib-log") + console.log("hello") }) }) diff --git a/packages/zhi-lib-log/src/lib/zhi-lib-log.ts b/packages/zhi-lib-log/src/lib/zhi-lib-log.ts index 2e03a125..7061a32e 100644 --- a/packages/zhi-lib-log/src/lib/zhi-lib-log.ts +++ b/packages/zhi-lib-log/src/lib/zhi-lib-log.ts @@ -1,3 +1,38 @@ -export function zhiLibLog(): string { - return "zhi-lib-log" -} +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import LogLevelEnum, { LogConstants } from "./logConstants" +import AbstractLogFactory from "./factory/abstractLogFactory" +import CustomLogFactory from "./factory/customLogFactory" +import LogFactory from "./logFactory" +import EnvHelper from "./envHelper" +import crossChalk from "./crossChalk" +import DefaultLogger from "./defaultLogger" + +export { LogFactory } +export { LogLevelEnum, AbstractLogFactory, CustomLogFactory } +export { LogConstants, EnvHelper } +export { crossChalk } +export type { DefaultLogger } diff --git a/packages/zhi-lib-log/tsconfig.json b/packages/zhi-lib-log/tsconfig.json index bdf594cd..839952da 100644 --- a/packages/zhi-lib-log/tsconfig.json +++ b/packages/zhi-lib-log/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "module": "commonjs", + "target": "esnext", + "module": "esnext", "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 710725cd..0de6c8e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,5 +1,16 @@ lockfileVersion: '6.0' +dependencies: + kleur: + specifier: ^4.1.5 + version: 4.1.5 + loglevel: + specifier: ^1.8.1 + version: 1.8.1 + loglevel-plugin-prefix: + specifier: ^0.8.4 + version: 0.8.4 + devDependencies: '@commitlint/config-angular': specifier: ^17.6.3 @@ -4252,6 +4263,11 @@ packages: graceful-fs: 4.2.11 dev: true + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: false + /kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} dev: true @@ -4367,6 +4383,15 @@ packages: is-unicode-supported: 0.1.0 dev: true + /loglevel-plugin-prefix@0.8.4: + resolution: {integrity: sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==} + dev: false + + /loglevel@1.8.1: + resolution: {integrity: sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==} + engines: {node: '>= 0.6.0'} + dev: false + /longest@2.0.1: resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} engines: {node: '>=0.10.0'}