支持集成第三方日志库 (#190)
* 更新 ILogger 签名 改为纯可变参数兼容主流日志库 * 拆分日志类型与实现 * 新增 setLoggerFactory 方法 * tweak * getLoggerName 返回类名,默认情况下子类无需重写 * 更新日志说明文档 * 增加测试 * 使用 getSystemInstanceTypeName,避免压缩导致获取类名不一致
This commit is contained in:
@@ -238,6 +238,50 @@ class HierarchicalLoggingExample {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 集成第三方日志库
|
||||||
|
|
||||||
|
通过 `setLoggerFactory` 可以将业务代码中的日志器替换为第三方日志库(如 winston、pino、nestjs Logger 等)。
|
||||||
|
|
||||||
|
**说明**: 目前框架内部日志仍使用 ConsoleLogger,自定义日志器仅影响业务代码(如 EntitySystem)。
|
||||||
|
|
||||||
|
#### 基本用法
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { setLoggerFactory } from '@esengine/ecs-framework';
|
||||||
|
|
||||||
|
setLoggerFactory((name?: string) => {
|
||||||
|
// 返回实现 ILogger 接口的日志器实例
|
||||||
|
return yourLogger;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 使用示例
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 集成 Winston
|
||||||
|
setLoggerFactory((name?: string) => winston.createLogger({ /* ... */ }));
|
||||||
|
|
||||||
|
// 集成 Pino
|
||||||
|
setLoggerFactory((name?: string) => pino({ name }));
|
||||||
|
|
||||||
|
// 集成 NestJS Logger
|
||||||
|
setLoggerFactory((name?: string) => new Logger(name));
|
||||||
|
```
|
||||||
|
|
||||||
|
#### EntitySystem 中的使用
|
||||||
|
|
||||||
|
EntitySystem 会自动使用类名创建日志器:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class PlayerMovementSystem extends EntitySystem {
|
||||||
|
// this.logger 自动使用 'PlayerMovementSystem' 作为名称
|
||||||
|
|
||||||
|
protected process(entities: readonly Entity[]): void {
|
||||||
|
this.logger.info(`处理 ${entities.length} 个玩家实体`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 自定义输出
|
### 自定义输出
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@@ -547,4 +591,4 @@ class LoggingConfiguration {
|
|||||||
LoggingConfiguration.setupLogging();
|
LoggingConfiguration.setupLogging();
|
||||||
```
|
```
|
||||||
|
|
||||||
日志系统是调试和监控应用的重要工具,正确使用日志系统能大大提高开发效率和问题排查能力。
|
日志系统是调试和监控应用的重要工具,正确使用日志系统能大大提高开发效率和问题排查能力。
|
||||||
|
|||||||
@@ -847,10 +847,10 @@ export abstract class EntitySystem<
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取Logger名称
|
* 获取Logger名称
|
||||||
* 子类可以重写此方法来自定义logger名称
|
* 默认返回类的构造函数名称, 子类可以重写此方法来自定义logger名称
|
||||||
*/
|
*/
|
||||||
protected getLoggerName(): string {
|
protected getLoggerName(): string {
|
||||||
return 'EntitySystem';
|
return getSystemInstanceTypeName(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1093,4 +1093,4 @@ export abstract class EntitySystem<
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { createLogger } from '../../Utils/Logger';
|
|||||||
import type { IComponent } from '../../Types';
|
import type { IComponent } from '../../Types';
|
||||||
import { PlatformManager } from '../../Platform/PlatformManager';
|
import { PlatformManager } from '../../Platform/PlatformManager';
|
||||||
import type { IPlatformAdapter, PlatformWorker } from '../../Platform/IPlatformAdapter';
|
import type { IPlatformAdapter, PlatformWorker } from '../../Platform/IPlatformAdapter';
|
||||||
|
import { getSystemInstanceTypeName } from '../Decorators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Worker处理函数类型
|
* Worker处理函数类型
|
||||||
@@ -853,7 +854,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override getLoggerName(): string {
|
protected override getLoggerName(): string {
|
||||||
return 'WorkerEntitySystem';
|
return getSystemInstanceTypeName(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1007,4 +1008,4 @@ class PlatformWorkerPool {
|
|||||||
this.taskQueue.length = 0;
|
this.taskQueue.length = 0;
|
||||||
this.busyWorkers.clear();
|
this.busyWorkers.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,85 +1,6 @@
|
|||||||
/**
|
import { Colors, LogLevel } from "./Constants";
|
||||||
* 日志级别
|
import { ILogger, LoggerColorConfig, LoggerConfig } from "./Types";
|
||||||
*/
|
|
||||||
export enum LogLevel {
|
|
||||||
Debug = 0,
|
|
||||||
Info = 1,
|
|
||||||
Warn = 2,
|
|
||||||
Error = 3,
|
|
||||||
Fatal = 4,
|
|
||||||
None = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 日志接口
|
|
||||||
*/
|
|
||||||
export interface ILogger {
|
|
||||||
debug(message: string, ...args: unknown[]): void;
|
|
||||||
info(message: string, ...args: unknown[]): void;
|
|
||||||
warn(message: string, ...args: unknown[]): void;
|
|
||||||
error(message: string, ...args: unknown[]): void;
|
|
||||||
fatal(message: string, ...args: unknown[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 日志颜色配置接口
|
|
||||||
*/
|
|
||||||
export interface LoggerColorConfig {
|
|
||||||
debug?: string;
|
|
||||||
info?: string;
|
|
||||||
warn?: string;
|
|
||||||
error?: string;
|
|
||||||
fatal?: string;
|
|
||||||
reset?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 预定义的颜色常量
|
|
||||||
*/
|
|
||||||
export const Colors = {
|
|
||||||
// 基础颜色
|
|
||||||
BLACK: '\x1b[30m',
|
|
||||||
RED: '\x1b[31m',
|
|
||||||
GREEN: '\x1b[32m',
|
|
||||||
YELLOW: '\x1b[33m',
|
|
||||||
BLUE: '\x1b[34m',
|
|
||||||
MAGENTA: '\x1b[35m',
|
|
||||||
CYAN: '\x1b[36m',
|
|
||||||
WHITE: '\x1b[37m',
|
|
||||||
|
|
||||||
// 亮色版本
|
|
||||||
BRIGHT_BLACK: '\x1b[90m',
|
|
||||||
BRIGHT_RED: '\x1b[91m',
|
|
||||||
BRIGHT_GREEN: '\x1b[92m',
|
|
||||||
BRIGHT_YELLOW: '\x1b[93m',
|
|
||||||
BRIGHT_BLUE: '\x1b[94m',
|
|
||||||
BRIGHT_MAGENTA: '\x1b[95m',
|
|
||||||
BRIGHT_CYAN: '\x1b[96m',
|
|
||||||
BRIGHT_WHITE: '\x1b[97m',
|
|
||||||
|
|
||||||
// 特殊
|
|
||||||
RESET: '\x1b[0m',
|
|
||||||
BOLD: '\x1b[1m',
|
|
||||||
UNDERLINE: '\x1b[4m'
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 日志配置
|
|
||||||
*/
|
|
||||||
export interface LoggerConfig {
|
|
||||||
/** 日志级别 */
|
|
||||||
level: LogLevel;
|
|
||||||
/** 是否启用时间戳 */
|
|
||||||
enableTimestamp: boolean;
|
|
||||||
/** 是否启用颜色 */
|
|
||||||
enableColors: boolean;
|
|
||||||
/** 日志前缀 */
|
|
||||||
prefix?: string;
|
|
||||||
/** 自定义输出函数 */
|
|
||||||
output?: (level: LogLevel, message: string) => void;
|
|
||||||
/** 自定义颜色配置 */
|
|
||||||
colors?: LoggerColorConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认控制台日志实现
|
* 默认控制台日志实现
|
||||||
@@ -279,157 +200,3 @@ export class ConsoleLogger implements ILogger {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 日志管理器
|
|
||||||
*/
|
|
||||||
export class LoggerManager {
|
|
||||||
private static _instance: LoggerManager;
|
|
||||||
private _loggers = new Map<string, ILogger>();
|
|
||||||
private _defaultLogger: ILogger;
|
|
||||||
private _defaultLevel = LogLevel.Info;
|
|
||||||
|
|
||||||
private constructor() {
|
|
||||||
this._defaultLogger = new ConsoleLogger({
|
|
||||||
level: this._defaultLevel,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取日志管理器实例
|
|
||||||
* @returns 日志管理器实例
|
|
||||||
*/
|
|
||||||
public static getInstance(): LoggerManager {
|
|
||||||
if (!LoggerManager._instance) {
|
|
||||||
LoggerManager._instance = new LoggerManager();
|
|
||||||
}
|
|
||||||
return LoggerManager._instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取或创建日志器
|
|
||||||
* @param name 日志器名称
|
|
||||||
* @returns 日志器实例
|
|
||||||
*/
|
|
||||||
public getLogger(name?: string): ILogger {
|
|
||||||
if (!name) {
|
|
||||||
return this._defaultLogger;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._loggers.has(name)) {
|
|
||||||
const logger = new ConsoleLogger({
|
|
||||||
prefix: name,
|
|
||||||
level: this._defaultLevel,
|
|
||||||
});
|
|
||||||
this._loggers.set(name, logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._loggers.get(name)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置日志器
|
|
||||||
* @param name 日志器名称
|
|
||||||
* @param logger 日志器实例
|
|
||||||
*/
|
|
||||||
public setLogger(name: string, logger: ILogger): void {
|
|
||||||
this._loggers.set(name, logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置全局日志级别
|
|
||||||
* @param level 日志级别
|
|
||||||
*/
|
|
||||||
public setGlobalLevel(level: LogLevel): void {
|
|
||||||
this._defaultLevel = level;
|
|
||||||
|
|
||||||
if (this._defaultLogger instanceof ConsoleLogger) {
|
|
||||||
this._defaultLogger.setLevel(level);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const logger of this._loggers.values()) {
|
|
||||||
if (logger instanceof ConsoleLogger) {
|
|
||||||
logger.setLevel(level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建子日志器
|
|
||||||
* @param parentName 父日志器名称
|
|
||||||
* @param childName 子日志器名称
|
|
||||||
* @returns 子日志器实例
|
|
||||||
*/
|
|
||||||
public createChildLogger(parentName: string, childName: string): ILogger {
|
|
||||||
const fullName = `${parentName}.${childName}`;
|
|
||||||
return this.getLogger(fullName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置全局颜色配置
|
|
||||||
* @param colors 颜色配置
|
|
||||||
*/
|
|
||||||
public setGlobalColors(colors: LoggerColorConfig): void {
|
|
||||||
if (this._defaultLogger instanceof ConsoleLogger) {
|
|
||||||
this._defaultLogger.setColors(colors);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const logger of this._loggers.values()) {
|
|
||||||
if (logger instanceof ConsoleLogger) {
|
|
||||||
logger.setColors(colors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置为默认颜色配置
|
|
||||||
*/
|
|
||||||
public resetColors(): void {
|
|
||||||
if (this._defaultLogger instanceof ConsoleLogger) {
|
|
||||||
this._defaultLogger.setColors({});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const logger of this._loggers.values()) {
|
|
||||||
if (logger instanceof ConsoleLogger) {
|
|
||||||
logger.setColors({});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认日志器实例
|
|
||||||
*/
|
|
||||||
export const Logger = LoggerManager.getInstance().getLogger();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建命名日志器
|
|
||||||
* @param name 日志器名称
|
|
||||||
* @returns 日志器实例
|
|
||||||
*/
|
|
||||||
export function createLogger(name: string): ILogger {
|
|
||||||
return LoggerManager.getInstance().getLogger(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置全局日志颜色配置
|
|
||||||
* @param colors 颜色配置
|
|
||||||
*/
|
|
||||||
export function setLoggerColors(colors: LoggerColorConfig): void {
|
|
||||||
LoggerManager.getInstance().setGlobalColors(colors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置日志颜色为默认配置
|
|
||||||
*/
|
|
||||||
export function resetLoggerColors(): void {
|
|
||||||
LoggerManager.getInstance().resetColors();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置全局日志级别
|
|
||||||
* @param level 日志级别
|
|
||||||
*/
|
|
||||||
export function setGlobalLogLevel(level: LogLevel): void {
|
|
||||||
LoggerManager.getInstance().setGlobalLevel(level);
|
|
||||||
}
|
|
||||||
41
packages/core/src/Utils/Logger/Constants.ts
Normal file
41
packages/core/src/Utils/Logger/Constants.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 日志级别
|
||||||
|
*/
|
||||||
|
export enum LogLevel {
|
||||||
|
Debug = 0,
|
||||||
|
Info = 1,
|
||||||
|
Warn = 2,
|
||||||
|
Error = 3,
|
||||||
|
Fatal = 4,
|
||||||
|
None = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预定义的颜色常量
|
||||||
|
*/
|
||||||
|
export const Colors = {
|
||||||
|
// 基础颜色
|
||||||
|
BLACK: '\x1b[30m',
|
||||||
|
RED: '\x1b[31m',
|
||||||
|
GREEN: '\x1b[32m',
|
||||||
|
YELLOW: '\x1b[33m',
|
||||||
|
BLUE: '\x1b[34m',
|
||||||
|
MAGENTA: '\x1b[35m',
|
||||||
|
CYAN: '\x1b[36m',
|
||||||
|
WHITE: '\x1b[37m',
|
||||||
|
|
||||||
|
// 亮色版本
|
||||||
|
BRIGHT_BLACK: '\x1b[90m',
|
||||||
|
BRIGHT_RED: '\x1b[91m',
|
||||||
|
BRIGHT_GREEN: '\x1b[92m',
|
||||||
|
BRIGHT_YELLOW: '\x1b[93m',
|
||||||
|
BRIGHT_BLUE: '\x1b[94m',
|
||||||
|
BRIGHT_MAGENTA: '\x1b[95m',
|
||||||
|
BRIGHT_CYAN: '\x1b[96m',
|
||||||
|
BRIGHT_WHITE: '\x1b[97m',
|
||||||
|
|
||||||
|
// 特殊
|
||||||
|
RESET: '\x1b[0m',
|
||||||
|
BOLD: '\x1b[1m',
|
||||||
|
UNDERLINE: '\x1b[4m'
|
||||||
|
} as const;
|
||||||
194
packages/core/src/Utils/Logger/LoggerManager.ts
Normal file
194
packages/core/src/Utils/Logger/LoggerManager.ts
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
import { ConsoleLogger } from "./ConsoleLogger";
|
||||||
|
import { LogLevel } from "./Constants";
|
||||||
|
import { ILogger, LoggerColorConfig } from "./Types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志管理器
|
||||||
|
*/
|
||||||
|
export class LoggerManager {
|
||||||
|
private static _instance: LoggerManager;
|
||||||
|
private _loggers = new Map<string, ILogger>();
|
||||||
|
private _defaultLogger?: ILogger;
|
||||||
|
private _defaultLevel = LogLevel.Info;
|
||||||
|
private _loggerFactory?: (name?: string) => ILogger;
|
||||||
|
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
private get defaultLogger(): ILogger {
|
||||||
|
if (!this._defaultLogger) {
|
||||||
|
this._defaultLogger = this.createDefaultLogger();
|
||||||
|
}
|
||||||
|
return this._defaultLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增: 创建默认 logger 的逻辑
|
||||||
|
private createDefaultLogger(): ILogger {
|
||||||
|
if (this._loggerFactory) {
|
||||||
|
return this._loggerFactory();
|
||||||
|
}
|
||||||
|
return new ConsoleLogger({ level: this._defaultLevel });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志管理器实例
|
||||||
|
* @returns 日志管理器实例
|
||||||
|
*/
|
||||||
|
public static getInstance(): LoggerManager {
|
||||||
|
if (!LoggerManager._instance) {
|
||||||
|
LoggerManager._instance = new LoggerManager();
|
||||||
|
}
|
||||||
|
return LoggerManager._instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取或创建日志器
|
||||||
|
* @param name 日志器名称
|
||||||
|
* @returns 日志器实例
|
||||||
|
*/
|
||||||
|
public getLogger(name?: string): ILogger {
|
||||||
|
if (!name) {
|
||||||
|
return this.defaultLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._loggers.has(name)) {
|
||||||
|
const logger = this._loggerFactory
|
||||||
|
? this._loggerFactory(name)
|
||||||
|
: new ConsoleLogger({ prefix: name, level: this._defaultLevel });
|
||||||
|
this._loggers.set(name, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._loggers.get(name)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置日志器
|
||||||
|
* @param name 日志器名称
|
||||||
|
* @param logger 日志器实例
|
||||||
|
*/
|
||||||
|
public setLogger(name: string, logger: ILogger): void {
|
||||||
|
this._loggers.set(name, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置全局日志级别
|
||||||
|
* @param level 日志级别
|
||||||
|
*/
|
||||||
|
public setGlobalLevel(level: LogLevel): void {
|
||||||
|
this._defaultLevel = level;
|
||||||
|
|
||||||
|
if (this._defaultLogger instanceof ConsoleLogger) {
|
||||||
|
this._defaultLogger.setLevel(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const logger of this._loggers.values()) {
|
||||||
|
if (logger instanceof ConsoleLogger) {
|
||||||
|
logger.setLevel(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建子日志器
|
||||||
|
* @param parentName 父日志器名称
|
||||||
|
* @param childName 子日志器名称
|
||||||
|
* @returns 子日志器实例
|
||||||
|
*/
|
||||||
|
public createChildLogger(parentName: string, childName: string): ILogger {
|
||||||
|
const fullName = `${parentName}.${childName}`;
|
||||||
|
return this.getLogger(fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置全局颜色配置
|
||||||
|
* @param colors 颜色配置
|
||||||
|
*/
|
||||||
|
public setGlobalColors(colors: LoggerColorConfig): void {
|
||||||
|
if (this._defaultLogger instanceof ConsoleLogger) {
|
||||||
|
this._defaultLogger.setColors(colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const logger of this._loggers.values()) {
|
||||||
|
if (logger instanceof ConsoleLogger) {
|
||||||
|
logger.setColors(colors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置为默认颜色配置
|
||||||
|
*/
|
||||||
|
public resetColors(): void {
|
||||||
|
if (this._defaultLogger instanceof ConsoleLogger) {
|
||||||
|
this._defaultLogger.setColors({});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const logger of this._loggers.values()) {
|
||||||
|
if (logger instanceof ConsoleLogger) {
|
||||||
|
logger.setColors({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置日志器工厂方法
|
||||||
|
* @param factory 日志器工厂方法
|
||||||
|
*/
|
||||||
|
public setLoggerFactory(factory: (name?: string) => ILogger): void {
|
||||||
|
if (this._defaultLogger || this._loggers.size > 0) {
|
||||||
|
console.warn(
|
||||||
|
'[LoggerManager] setLoggerFactory 应该在导入 ECS 模块之前调用。' +
|
||||||
|
'已创建的 logger 引用不会被更新。'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._loggerFactory = factory;
|
||||||
|
// 清空已创建的 logger, 下次获取时使用新工厂方法
|
||||||
|
this._defaultLogger = undefined;
|
||||||
|
this._loggers.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认日志器实例
|
||||||
|
*/
|
||||||
|
export const Logger = LoggerManager.getInstance().getLogger();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建命名日志器
|
||||||
|
* @param name 日志器名称
|
||||||
|
* @returns 日志器实例
|
||||||
|
*/
|
||||||
|
export function createLogger(name: string): ILogger {
|
||||||
|
return LoggerManager.getInstance().getLogger(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置全局日志颜色配置
|
||||||
|
* @param colors 颜色配置
|
||||||
|
*/
|
||||||
|
export function setLoggerColors(colors: LoggerColorConfig): void {
|
||||||
|
LoggerManager.getInstance().setGlobalColors(colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置日志颜色为默认配置
|
||||||
|
*/
|
||||||
|
export function resetLoggerColors(): void {
|
||||||
|
LoggerManager.getInstance().resetColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置全局日志级别
|
||||||
|
* @param level 日志级别
|
||||||
|
*/
|
||||||
|
export function setGlobalLogLevel(level: LogLevel): void {
|
||||||
|
LoggerManager.getInstance().setGlobalLevel(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置日志器工厂方法
|
||||||
|
* @param factory 日志器工厂方法
|
||||||
|
*/
|
||||||
|
export function setLoggerFactory(factory: (name?: string) => ILogger): void {
|
||||||
|
LoggerManager.getInstance().setLoggerFactory(factory);
|
||||||
|
}
|
||||||
42
packages/core/src/Utils/Logger/Types.ts
Normal file
42
packages/core/src/Utils/Logger/Types.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import type { LogLevel } from "./Constants";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志接口
|
||||||
|
*/
|
||||||
|
export interface ILogger {
|
||||||
|
debug(...args: unknown[]): void;
|
||||||
|
info(...args: unknown[]): void;
|
||||||
|
warn(...args: unknown[]): void;
|
||||||
|
error(...args: unknown[]): void;
|
||||||
|
fatal(...args: unknown[]): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志颜色配置接口
|
||||||
|
*/
|
||||||
|
export interface LoggerColorConfig {
|
||||||
|
debug?: string;
|
||||||
|
info?: string;
|
||||||
|
warn?: string;
|
||||||
|
error?: string;
|
||||||
|
fatal?: string;
|
||||||
|
reset?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志配置
|
||||||
|
*/
|
||||||
|
export interface LoggerConfig {
|
||||||
|
/** 日志级别 */
|
||||||
|
level: LogLevel;
|
||||||
|
/** 是否启用时间戳 */
|
||||||
|
enableTimestamp: boolean;
|
||||||
|
/** 是否启用颜色 */
|
||||||
|
enableColors: boolean;
|
||||||
|
/** 日志前缀 */
|
||||||
|
prefix?: string;
|
||||||
|
/** 自定义输出函数 */
|
||||||
|
output?: (level: LogLevel, message: string) => void;
|
||||||
|
/** 自定义颜色配置 */
|
||||||
|
colors?: LoggerColorConfig;
|
||||||
|
}
|
||||||
4
packages/core/src/Utils/Logger/index.ts
Normal file
4
packages/core/src/Utils/Logger/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './ConsoleLogger';
|
||||||
|
export * from './Constants';
|
||||||
|
export * from './LoggerManager';
|
||||||
|
export * from './Types';
|
||||||
@@ -5,4 +5,4 @@ export * from './GlobalManager';
|
|||||||
export * from './PerformanceMonitor';
|
export * from './PerformanceMonitor';
|
||||||
export { Time } from './Time';
|
export { Time } from './Time';
|
||||||
export * from './Debug';
|
export * from './Debug';
|
||||||
export * from './Logger';
|
export * from './Logger';
|
||||||
|
|||||||
@@ -214,4 +214,11 @@ describe('EntitySystem', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('日志器命名', () => {
|
||||||
|
it('应该使用类名作为日志器名称', () => {
|
||||||
|
const loggerName = (system as any).getLoggerName();
|
||||||
|
expect(loggerName).toBe('ConcreteEntitySystem');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -153,24 +153,125 @@ describe('Logger', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('LoggerManager - 自定义工厂', () => {
|
||||||
|
let manager: LoggerManager;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
manager = LoggerManager.getInstance();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// 重置工厂,恢复默认 ConsoleLogger
|
||||||
|
(manager as any)._loggerFactory = undefined;
|
||||||
|
(manager as any)._defaultLogger = undefined;
|
||||||
|
(manager as any)._loggers.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('应该支持设置自定义日志器工厂', () => {
|
||||||
|
const mockLogger = {
|
||||||
|
debug: jest.fn(),
|
||||||
|
info: jest.fn(),
|
||||||
|
warn: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
|
fatal: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
manager.setLoggerFactory(() => mockLogger);
|
||||||
|
const logger = manager.getLogger('CustomLogger');
|
||||||
|
|
||||||
|
expect(logger).toBe(mockLogger);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('应该将日志器名称传递给工厂方法', () => {
|
||||||
|
const factorySpy = jest.fn(() => ({
|
||||||
|
debug: jest.fn(),
|
||||||
|
info: jest.fn(),
|
||||||
|
warn: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
|
fatal: jest.fn()
|
||||||
|
}));
|
||||||
|
|
||||||
|
manager.setLoggerFactory(factorySpy);
|
||||||
|
manager.getLogger('TestLogger');
|
||||||
|
|
||||||
|
expect(factorySpy).toHaveBeenCalledWith('TestLogger');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('应该在设置工厂后清空已创建的日志器', () => {
|
||||||
|
const logger1 = manager.getLogger('TestLogger');
|
||||||
|
|
||||||
|
manager.setLoggerFactory(() => ({
|
||||||
|
debug: jest.fn(),
|
||||||
|
info: jest.fn(),
|
||||||
|
warn: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
|
fatal: jest.fn()
|
||||||
|
}));
|
||||||
|
|
||||||
|
const logger2 = manager.getLogger('TestLogger');
|
||||||
|
expect(logger2).not.toBe(logger1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('应该延迟创建默认日志器直到首次使用', () => {
|
||||||
|
const factorySpy = jest.fn(() => ({
|
||||||
|
debug: jest.fn(),
|
||||||
|
info: jest.fn(),
|
||||||
|
warn: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
|
fatal: jest.fn()
|
||||||
|
}));
|
||||||
|
|
||||||
|
manager.setLoggerFactory(factorySpy);
|
||||||
|
// 此时不应该调用工厂
|
||||||
|
expect(factorySpy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
// 获取默认日志器时才调用
|
||||||
|
manager.getLogger();
|
||||||
|
expect(factorySpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('应该在已创建日志器后设置工厂时发出警告', () => {
|
||||||
|
const warnSpy = jest.spyOn(console, 'warn').mockImplementation();
|
||||||
|
|
||||||
|
// 先创建一个日志器
|
||||||
|
manager.getLogger('ExistingLogger');
|
||||||
|
|
||||||
|
// 再设置工厂
|
||||||
|
manager.setLoggerFactory(() => ({
|
||||||
|
debug: jest.fn(),
|
||||||
|
info: jest.fn(),
|
||||||
|
warn: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
|
fatal: jest.fn()
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(warnSpy).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining('setLoggerFactory 应该在导入 ECS 模块之前调用')
|
||||||
|
);
|
||||||
|
|
||||||
|
warnSpy.mockRestore();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('全局颜色配置', () => {
|
describe('全局颜色配置', () => {
|
||||||
let consoleSpy: jest.SpyInstance;
|
let consoleSpy: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
consoleSpy = jest.spyOn(console, 'info').mockImplementation();
|
consoleSpy = jest.spyOn(console, 'info').mockImplementation();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
consoleSpy.mockRestore();
|
consoleSpy.mockRestore();
|
||||||
resetLoggerColors();
|
resetLoggerColors();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('应该支持全局设置颜色配置', () => {
|
it('应该支持全局设置颜色配置', () => {
|
||||||
|
const logger = createLogger('TestLogger');
|
||||||
|
|
||||||
setLoggerColors({
|
setLoggerColors({
|
||||||
info: Colors.MAGENTA
|
info: Colors.MAGENTA
|
||||||
});
|
});
|
||||||
|
|
||||||
const logger = createLogger('TestLogger');
|
|
||||||
logger.info('测试消息');
|
logger.info('测试消息');
|
||||||
|
|
||||||
const call = consoleSpy.mock.calls[0][0];
|
const call = consoleSpy.mock.calls[0][0];
|
||||||
@@ -179,17 +280,18 @@ describe('Logger', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('应该支持重置颜色配置为默认值', () => {
|
it('应该支持重置颜色配置为默认值', () => {
|
||||||
|
const logger = createLogger('TestLogger');
|
||||||
|
|
||||||
setLoggerColors({
|
setLoggerColors({
|
||||||
info: Colors.MAGENTA
|
info: Colors.MAGENTA
|
||||||
});
|
});
|
||||||
|
|
||||||
resetLoggerColors();
|
resetLoggerColors();
|
||||||
|
|
||||||
const logger = createLogger('TestLogger');
|
|
||||||
logger.info('测试消息');
|
logger.info('测试消息');
|
||||||
|
|
||||||
const call = consoleSpy.mock.calls[0][0];
|
const call = consoleSpy.mock.calls[0][0];
|
||||||
expect(call).toContain('\x1b[32m');
|
expect(call).toContain('\x1b[32m');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user