feat: 添加自定义logger用于输出日志 #68

Manually merged
remilia merged 2 commits from feat/logger into master 2025-11-08 14:42:44 +08:00
14 changed files with 127 additions and 14 deletions

View File

@ -37,7 +37,7 @@ export const useMeilisearch = () => {
const host = runtimeConfig.public?.meili?.host;
if (!host) {
console.warn('Meilisearch host is not configured.');
logger.warn('Meilisearch host is not configured.');
return null;
}
const apiKey = runtimeConfig.public?.meili?.searchKey;
@ -76,7 +76,7 @@ export const useMeilisearch = () => {
const activeIndexes = indexes.value as K[];
if (!activeIndexes.length) {
console.warn('No Meilisearch indexes configured.');
logger.warn('No Meilisearch indexes configured.');
return [];
}
const rawIndexMap = Object.fromEntries(
@ -105,7 +105,7 @@ export const useMeilisearch = () => {
result.status === 'rejected'
)
.forEach((result) => {
console.error('Meilisearch query failed', result.reason);
logger.error('Meilisearch query failed', result.reason);
});
return settled

View File

@ -38,7 +38,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -23,7 +23,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -55,7 +55,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -83,7 +83,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -86,7 +86,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -46,7 +46,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -83,7 +83,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -28,7 +28,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -104,7 +104,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -105,7 +105,7 @@
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
logger.error('数据获取失败: ', value);
}
});

View File

@ -13,6 +13,7 @@ export default withNuxt(
},
},
],
'no-console': 'warn',
},
}
);

View File

@ -46,7 +46,7 @@ export async function getFileMeta(id: string): Promise<FileMeta | null> {
};
} catch (error) {
if (error instanceof Error) {
console.error('Error fetching file metadata:', error.message);
logger.error('Error fetching file metadata:', error.message);
}
return null;
}

112
shared/utils/logger.ts Normal file
View File

@ -0,0 +1,112 @@
/* eslint-disable no-console -- console is allowed inside logger implementation */
/**
* 日志等级枚举
*
* - `debug` : 开发调试日志(最低)
* - `info` : 普通信息输出
* - `warn` : 警告信息
* - `error` : 错误信息(最高级别)
* - `silent` : 屏蔽所有日志
*/
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
/**
* 每个日志级别的优先级数值
* 数值越小,级别越低
*/
const levelPriority: Record<LogLevel, number> = {
debug: 0,
info: 1,
warn: 2,
error: 3,
silent: 4,
};
/**
* 检测当前运行环境应使用的日志等级:
*
* - 开发环境:默认 `debug`
* - 生产环境:默认 `warn`
* - 浏览器允许通过 `localStorage.DEBUG = 'true'` 强制开启 `debug`
*/
function detectInitialLevel(): LogLevel {
const isProduction = process.env.NODE_ENV === 'production';
if (import.meta.client && localStorage.getItem('DEBUG') === 'true') {
return 'debug';
}
return isProduction ? 'warn' : 'debug';
}
/**
* 核心日志类
*
* 提供 `debug / info / warn / error` 四个级别
* 并支持通过 `setLevel` 动态调整输出等级
*
* @example
* ```ts
* logger.debug('User data:', user)
* logger.error(new Error('Something broke'))
* logger.setLevel('silent')
* ```
*/
class Logger {
/** 当前日志等级(默认由 detectInitialLevel 判断) */
private level: LogLevel = detectInitialLevel();
/**
* 手动设置日志输出级别
*
* @param level 目标日志级别
*
* @example
* ```ts
* logger.setLevel('silent') // 全部禁用
* logger.setLevel('debug') // 强制打印全部日志
* ```
*/
setLevel(newLevel: LogLevel) {
this.level = newLevel;
}
/**
* 判断当前等级是否允许输出指定日志
*/
private canLog(level: LogLevel): boolean {
return levelPriority[level] >= levelPriority[this.level];
}
/** 输出调试日志(开发阶段使用) */
debug(...args: unknown[]) {
if (this.canLog('debug')) console.debug('[DEBUG]', ...args);
}
/** 输出普通信息日志 */
info(...args: unknown[]) {
if (this.canLog('info')) console.info('[INFO]', ...args);
}
/** 输出警告日志 */
warn(...args: unknown[]) {
if (this.canLog('warn')) console.warn('[WARN]', ...args);
}
/** 输出错误日志 */
error(...args: unknown[]) {
if (this.canLog('error')) console.error('[ERROR]', ...args);
}
}
/**
* 默认导出的单例 logger
*
* @example
* ```ts
* import { logger } from '~/utils/logger'
*
* logger.info('App started')
* ```
*/
export const logger = new Logger();