feat: support dynamically set log level

This commit is contained in:
Gabe
2025-10-12 23:17:50 +08:00
parent f19b6ef02f
commit bfce9b525a
8 changed files with 119 additions and 18 deletions

View File

@@ -32,7 +32,7 @@ import { trySyncAllSubRules } from "./libs/subRules";
import { saveRule } from "./libs/rules";
import { getCurTabId } from "./libs/msg";
import { injectInlineJs, injectInternalCss } from "./libs/injector";
import { kissLog } from "./libs/log";
import { kissLog, logger } from "./libs/log";
import { chromeDetect, chromeTranslate } from "./libs/builtinAI";
globalThis.ContextType = "BACKGROUND";
@@ -210,11 +210,17 @@ browser.runtime.onInstalled.addListener(() => {
* 浏览器启动
*/
browser.runtime.onStartup.addListener(async () => {
// 同步数据
await trySyncSettingAndRules();
const {
clearCache,
contextMenuType,
subrulesList,
csplist,
orilist,
logLevel,
} = await getSettingWithDefault();
const { clearCache, contextMenuType, subrulesList, csplist, orilist } =
await getSettingWithDefault();
// 设置日志
logger.setLevel(logLevel);
// 清除缓存
if (clearCache) {
@@ -233,6 +239,9 @@ browser.runtime.onStartup.addListener(async () => {
// 禁用CSP
updateCspRules({ csplist, orilist });
// 同步数据
trySyncSettingAndRules();
// 同步订阅规则
trySyncAllSubRules({ subrulesList });
});

View File

@@ -19,6 +19,7 @@ import { matchRule } from "./libs/rules";
import { trySyncAllSubRules } from "./libs/subRules";
import { isInBlacklist } from "./libs/blacklist";
import { runSubtitle } from "./subtitle/subtitle";
import { logger } from "./libs/log";
/**
* 油猴脚本设置页面
@@ -180,6 +181,12 @@ function touchOperation(translator) {
*/
export async function run(isUserscript = false) {
try {
// 读取设置信息
const setting = await getSettingWithDefault();
// 日志
logger.setLevel(setting.logLevel);
const href = document.location.href;
// 设置页面
@@ -192,9 +199,6 @@ export async function run(isUserscript = false) {
return;
}
// 读取设置信息
const setting = await getSettingWithDefault();
// 黑名单
if (isInBlacklist(href, setting)) {
return;

View File

@@ -1628,6 +1628,11 @@ export const I18N = {
en: `The subtitle data is ready, please click the KT button to load it`,
zh_TW: `字幕資料已準備就緒請點擊KT按鈕加載`,
},
log_level: {
zh: `日志级别`,
en: `Log Level`,
zh_TW: `日誌等級`,
},
};
export const i18n = (lang) => (key) => I18N[key]?.[lang] || "";

View File

@@ -1,3 +1,4 @@
import { LogLevel } from "../libs/log";
import {
OPT_DICT_BING,
OPT_SUG_YOUDAO,
@@ -181,4 +182,5 @@ export const DEFAULT_SETTING = {
preInit: true, // 是否预加载脚本
transAllnow: false, // 是否立即全部翻译
subtitleSetting: DEFAULT_SUBTITLE_SETTING, // 字幕设置
logLevel: LogLevel.INFO.value, // 日志级别
};

View File

@@ -1,9 +1,16 @@
import { createContext, useCallback, useContext, useMemo } from "react";
import {
createContext,
useCallback,
useContext,
useMemo,
useEffect,
} from "react";
import Alert from "@mui/material/Alert";
import { STOKEY_SETTING, DEFAULT_SETTING, KV_SETTING_KEY } from "../config";
import { useStorage } from "./Storage";
import { debounceSyncMeta } from "../libs/storage";
import Loading from "./Loading";
import { logger } from "../libs/log";
const SettingContext = createContext({
setting: DEFAULT_SETTING,
@@ -19,6 +26,16 @@ export function SettingProvider({ children }) {
reload,
} = useStorage(STOKEY_SETTING, DEFAULT_SETTING, KV_SETTING_KEY);
useEffect(() => {
(async () => {
try {
logger.setLevel(setting?.logLevel);
} catch (error) {
logger.error("Failed to fetch log level, using default.", error);
}
})();
}, [setting]);
const updateSetting = useCallback(
(objOrFn) => {
update(objOrFn);

View File

@@ -7,6 +7,16 @@ export const LogLevel = {
SILENT: { value: 4, name: "SILENT" }, // 特殊级别,用于关闭所有日志
};
function findLogLevelByValue(value) {
return Object.values(LogLevel).find((level) => level.value === value);
}
function findLogLevelByName(name) {
if (typeof name !== "string" || name.length === 0) return undefined;
const upperCaseName = name.toUpperCase();
return Object.values(LogLevel).find((level) => level.name === upperCaseName);
}
class Logger {
/**
* @param {object} [options={}] 配置选项
@@ -25,10 +35,37 @@ class Logger {
* @param {LogLevel} level - 新的日志级别
*/
setLevel(level) {
if (level && typeof level.value === "number") {
this.config.level = level;
console.log(`[${this.config.prefix}] Log level set to ${level.name}`);
let newLevelObject;
if (typeof level === "string") {
newLevelObject = findLogLevelByName(level);
if (!newLevelObject) {
this.warn(
`Invalid log level name provided: "${level}". Keeping current level.`
);
return;
}
} else if (typeof level === "number") {
newLevelObject = findLogLevelByValue(level);
if (!newLevelObject) {
this.warn(
`Invalid log level value provided: ${level}. Keeping current level.`
);
return;
}
} else if (level && typeof level.value === "number") {
newLevelObject = level;
} else {
this.warn(
"Invalid argument passed to setLevel. Must be a LogLevel object, number, or string."
);
return;
}
this.config.level = newLevelObject;
console.log(
`[${this.config.prefix}] Log level dynamically set to ${this.config.level.name}`
);
}
/**
@@ -118,9 +155,7 @@ class Logger {
}
}
const isDevelopment =
typeof process === "undefined" || process.env.NODE_ENV !== "development";
const defaultLevel = isDevelopment ? LogLevel.DEBUG : LogLevel.INFO;
export const logger = new Logger({ level: defaultLevel });
export const logger = new Logger();
export const kissLog = logger.info.bind(logger);
// tododebug日志埋点

View File

@@ -231,6 +231,13 @@ class YouTubeCaptionProvider {
try {
const events = chunkEvents.filter((item) => item.text);
const chunkSign = `${events[0].start} --> ${events[events.length - 1].end}`;
logger.debug("Youtube Provider: aiSegment events", {
videoId,
chunkSign,
fromLang,
toLang,
events,
});
const subtitles = await apiSubtitle({
videoId,
chunkSign,
@@ -239,6 +246,7 @@ class YouTubeCaptionProvider {
events,
apiSetting: segApiSetting,
});
logger.debug("Youtube Provider: aiSegment subtitles", subtitles);
if (Array.isArray(subtitles)) {
return subtitles;
}
@@ -300,6 +308,9 @@ class YouTubeCaptionProvider {
OPT_LANGS_TO_CODE[OPT_TRANS_MICROSOFT].get(lang.slice(0, 2)) ||
"auto";
logger.debug(
`Youtube Provider: fromLang: ${fromLang}, toLang: ${toLang}`
);
if (this.#isSameLang(fromLang, toLang)) {
logger.info("Youtube Provider: skip same lang", fromLang, toLang);
return;

View File

@@ -29,7 +29,7 @@ import { useShortcut } from "../../hooks/Shortcut";
import ShortcutInput from "./ShortcutInput";
import { useFab } from "../../hooks/Fab";
import { sendBgMsg } from "../../libs/msg";
import { kissLog } from "../../libs/log";
import { kissLog, LogLevel } from "../../libs/log";
import UploadButton from "./UploadButton";
import DownloadButton from "./DownloadButton";
import { getSettingOld } from "../../libs/storage";
@@ -99,6 +99,7 @@ export default function Settings() {
orilist = DEFAULT_ORILIST.join(",\n"),
transInterval = 100,
langDetector = "-",
logLevel = 1,
preInit = true,
skipLangs = [],
// detectRemote = true,
@@ -337,6 +338,23 @@ export default function Settings() {
))}
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
fullWidth
size="small"
name="logLevel"
value={logLevel}
label={i18n("log_level")}
onChange={handleChange}
>
{Object.values(LogLevel).map(({ value, name }) => (
<MenuItem value={value} key={value}>
{name}
</MenuItem>
))}
</TextField>
</Grid>
</Grid>
</Box>