@chaeco/logger 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +123 -0
- package/README.zh-CN.md +126 -0
- package/dist/core/logger.d.ts +41 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +233 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/types.d.ts +155 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/file/async-queue.d.ts +24 -0
- package/dist/file/async-queue.d.ts.map +1 -0
- package/dist/file/async-queue.js +95 -0
- package/dist/file/async-queue.js.map +1 -0
- package/dist/file/file-manager.d.ts +29 -0
- package/dist/file/file-manager.d.ts.map +1 -0
- package/dist/file/file-manager.js +85 -0
- package/dist/file/file-manager.js.map +1 -0
- package/dist/file/node-writer.d.ts +30 -0
- package/dist/file/node-writer.d.ts.map +1 -0
- package/dist/file/node-writer.js +219 -0
- package/dist/file/node-writer.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/caller-info.d.ts +29 -0
- package/dist/utils/caller-info.d.ts.map +1 -0
- package/dist/utils/caller-info.js +120 -0
- package/dist/utils/caller-info.js.map +1 -0
- package/dist/utils/color-utils.d.ts +19 -0
- package/dist/utils/color-utils.d.ts.map +1 -0
- package/dist/utils/color-utils.js +51 -0
- package/dist/utils/color-utils.js.map +1 -0
- package/dist/utils/formatter.d.ts +51 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +166 -0
- package/dist/utils/formatter.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.NodeWriter = void 0;
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
const path = __importStar(require("path"));
|
|
32
|
+
const zlib = __importStar(require("zlib"));
|
|
33
|
+
const util_1 = require("util");
|
|
34
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
35
|
+
const gzip = (0, util_1.promisify)(zlib.gzip);
|
|
36
|
+
const readFile = (0, util_1.promisify)(fs.readFile);
|
|
37
|
+
const writeFile = (0, util_1.promisify)(fs.writeFile);
|
|
38
|
+
const unlink = (0, util_1.promisify)(fs.unlink);
|
|
39
|
+
/**
|
|
40
|
+
* Node.js 文件写入器 - 管理日志文件的创建、轮转、压缩与清理。
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
class NodeWriter {
|
|
44
|
+
/** 初始化错误(只读),如果初始化失败则值不为 undefined */
|
|
45
|
+
get initError() { return this._initError; }
|
|
46
|
+
constructor(options) {
|
|
47
|
+
this.currentFilePath = '';
|
|
48
|
+
this.currentFileSize = 0;
|
|
49
|
+
this.fileIndex = 0;
|
|
50
|
+
this.options = {
|
|
51
|
+
...options,
|
|
52
|
+
// 清理文件名中的路径分隔符,防止目录穿越攻击(如 filename: '../../etc/passwd')
|
|
53
|
+
filename: options.filename.replace(/[/\\]/g, '_'),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
init() {
|
|
57
|
+
this.ensureLogDirectory();
|
|
58
|
+
this.initializeCurrentFile();
|
|
59
|
+
}
|
|
60
|
+
/** 写入单条消息(内部使用 appendFileSync,通过重试逻辑提供可靠性) */
|
|
61
|
+
async write(message) {
|
|
62
|
+
this.checkDateRotation();
|
|
63
|
+
if (this.shouldRotateFile())
|
|
64
|
+
this.rotateFile();
|
|
65
|
+
const content = message + '\n';
|
|
66
|
+
await this.appendToFileWithRetry(content);
|
|
67
|
+
this.currentFileSize += Buffer.byteLength(content, 'utf8');
|
|
68
|
+
}
|
|
69
|
+
/** 批量写入消息(由 AsyncQueue 刷新时调用) */
|
|
70
|
+
async writeBatch(messages) {
|
|
71
|
+
this.checkDateRotation();
|
|
72
|
+
const content = messages.join('\n') + '\n';
|
|
73
|
+
if (this.shouldRotateFile())
|
|
74
|
+
this.rotateFile();
|
|
75
|
+
await this.appendToFileWithRetry(content);
|
|
76
|
+
this.currentFileSize += Buffer.byteLength(content, 'utf8');
|
|
77
|
+
}
|
|
78
|
+
// ─── 私有方法 ────────────────────────────────────────────
|
|
79
|
+
ensureLogDirectory() {
|
|
80
|
+
try {
|
|
81
|
+
if (!fs.existsSync(this.options.path)) {
|
|
82
|
+
fs.mkdirSync(this.options.path, { recursive: true, mode: 0o755 });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
this._initError = e instanceof Error ? e : new Error(String(e));
|
|
87
|
+
console.warn(`@chaeco/logger: Failed to create log directory "${this.options.path}":`, this._initError.message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
initializeCurrentFile() {
|
|
91
|
+
try {
|
|
92
|
+
this.fileIndex = 0;
|
|
93
|
+
// 上界取 maxFiles 的两倍(最少 100),避免目录中存在大量文件时无限扫描
|
|
94
|
+
const maxIndex = Math.max(this.options.maxFiles * 2, 100);
|
|
95
|
+
while (this.fileIndex < maxIndex && fs.existsSync(this.getIndexedFilePath())) {
|
|
96
|
+
this.fileIndex++;
|
|
97
|
+
}
|
|
98
|
+
if (this.fileIndex > 0) {
|
|
99
|
+
this.fileIndex--;
|
|
100
|
+
this.currentFilePath = this.getIndexedFilePath();
|
|
101
|
+
this.currentFileSize = fs.statSync(this.currentFilePath).size;
|
|
102
|
+
if (this.shouldRotateFile()) {
|
|
103
|
+
this.fileIndex++;
|
|
104
|
+
this.currentFilePath = this.getIndexedFilePath();
|
|
105
|
+
this.currentFileSize = 0;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
this.currentFilePath = this.getIndexedFilePath();
|
|
110
|
+
this.currentFileSize = 0;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
this._initError = e instanceof Error ? e : new Error(String(e));
|
|
115
|
+
console.warn('@chaeco/logger: Failed to initialize current file:', this._initError.message);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
getIndexedFilePath() {
|
|
119
|
+
const today = (0, dayjs_1.default)().format('YYYY-MM-DD');
|
|
120
|
+
const base = `${this.options.filename}-${today}`;
|
|
121
|
+
return this.fileIndex === 0
|
|
122
|
+
? path.join(this.options.path, `${base}.log`)
|
|
123
|
+
: path.join(this.options.path, `${base}.${this.fileIndex}.log`);
|
|
124
|
+
}
|
|
125
|
+
shouldRotateFile() {
|
|
126
|
+
return this.currentFileSize >= this.options.maxSize;
|
|
127
|
+
}
|
|
128
|
+
rotateFile() {
|
|
129
|
+
this.fileIndex++;
|
|
130
|
+
this.currentFilePath = this.getIndexedFilePath();
|
|
131
|
+
this.currentFileSize = 0;
|
|
132
|
+
this.cleanupOldFiles();
|
|
133
|
+
}
|
|
134
|
+
cleanupOldFiles() {
|
|
135
|
+
try {
|
|
136
|
+
const files = fs.readdirSync(this.options.path)
|
|
137
|
+
.filter(f => f.startsWith(this.options.filename) && (f.endsWith('.log') || f.endsWith('.log.gz')))
|
|
138
|
+
.map(f => {
|
|
139
|
+
const stats = fs.statSync(path.join(this.options.path, f));
|
|
140
|
+
// 优先使用文件名中的日期,避免 mtime 因压缩操作被刷新为近期时间
|
|
141
|
+
const fileDate = f.match(/(\d{4}-\d{2}-\d{2})/)?.[1] ?? null;
|
|
142
|
+
const sortKey = fileDate ? new Date(fileDate).getTime() : stats.mtime.getTime();
|
|
143
|
+
return { name: f, path: path.join(this.options.path, f), stats, fileDate, sortKey };
|
|
144
|
+
})
|
|
145
|
+
// 按日期降序(最新在前);用文件名日期而非 mtime 排序,防止旧压缩日志因近期 mtime 排在前
|
|
146
|
+
.sort((a, b) => b.sortKey - a.sortKey);
|
|
147
|
+
// 超出 maxFiles 的文件:先收集待删集合,避免与过期清理产生重复 unlinkSync 调用
|
|
148
|
+
const toDelete = new Set();
|
|
149
|
+
if (files.length > this.options.maxFiles)
|
|
150
|
+
files.slice(this.options.maxFiles).forEach(f => toDelete.add(f.path));
|
|
151
|
+
const maxAgeMs = this.options.maxAge * 24 * 60 * 60 * 1000;
|
|
152
|
+
files.forEach(f => {
|
|
153
|
+
// 同 compressOldLogs:用文件名日期判断过期,而非 mtime。
|
|
154
|
+
// .log.gz 的 mtime 是压缩时间(近期),用 mtime 会使旧日志看起来永远"新"。
|
|
155
|
+
const ageBasis = f.fileDate ? new Date(f.fileDate).getTime() : f.stats.mtime.getTime();
|
|
156
|
+
if (Date.now() - ageBasis > maxAgeMs)
|
|
157
|
+
toDelete.add(f.path);
|
|
158
|
+
});
|
|
159
|
+
toDelete.forEach(p => { try {
|
|
160
|
+
fs.unlinkSync(p);
|
|
161
|
+
}
|
|
162
|
+
catch { /* ignore */ } });
|
|
163
|
+
if (this.options.compress)
|
|
164
|
+
this.compressOldLogs().catch(() => { });
|
|
165
|
+
}
|
|
166
|
+
catch { /* ignore cleanup errors */ }
|
|
167
|
+
}
|
|
168
|
+
async compressOldLogs() {
|
|
169
|
+
const today = (0, dayjs_1.default)().format('YYYY-MM-DD');
|
|
170
|
+
try {
|
|
171
|
+
const files = fs.readdirSync(this.options.path)
|
|
172
|
+
.filter(f => f.startsWith(this.options.filename) && f.endsWith('.log') && !f.endsWith('.log.gz'))
|
|
173
|
+
.map(f => ({ name: f, path: path.join(this.options.path, f) }));
|
|
174
|
+
for (const file of files) {
|
|
175
|
+
const dateMatch = file.name.match(/(\d{4}-\d{2}-\d{2})/);
|
|
176
|
+
const fileDate = dateMatch?.[1];
|
|
177
|
+
// 仅压缩文件名日期不是今天的文件,并排除当前写入文件。
|
|
178
|
+
// 不依赖 mtime:跨午夜写入的昨日文件 mtime < 24h 会导致 mtime 条件失效。
|
|
179
|
+
if (fileDate && fileDate !== today && file.path !== this.currentFilePath) {
|
|
180
|
+
try {
|
|
181
|
+
const compressed = await gzip(await readFile(file.path));
|
|
182
|
+
await writeFile(file.path + '.gz', compressed);
|
|
183
|
+
await unlink(file.path);
|
|
184
|
+
}
|
|
185
|
+
catch { /* compress fails silently */ }
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch { /* ignore */ }
|
|
190
|
+
}
|
|
191
|
+
checkDateRotation() {
|
|
192
|
+
const today = (0, dayjs_1.default)().format('YYYY-MM-DD');
|
|
193
|
+
const m = path.basename(this.currentFilePath).match(/(\d{4}-\d{2}-\d{2})/);
|
|
194
|
+
if ((m?.[1] ?? null) !== today)
|
|
195
|
+
this.initializeCurrentFile();
|
|
196
|
+
}
|
|
197
|
+
async appendToFileWithRetry(content) {
|
|
198
|
+
const { retryCount, retryDelay } = this.options;
|
|
199
|
+
let lastError;
|
|
200
|
+
for (let i = 0; i <= retryCount; i++) {
|
|
201
|
+
try {
|
|
202
|
+
if (i > 0)
|
|
203
|
+
await new Promise(r => setTimeout(r, retryDelay * i));
|
|
204
|
+
this.ensureLogDirectory();
|
|
205
|
+
fs.appendFileSync(this.currentFilePath, content, { mode: 0o644 });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
catch (e) {
|
|
209
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
210
|
+
if (i === 0)
|
|
211
|
+
this.initializeCurrentFile();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
console.error(`Failed to write log after ${retryCount + 1} attempts:`, lastError);
|
|
215
|
+
throw lastError;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
exports.NodeWriter = NodeWriter;
|
|
219
|
+
//# sourceMappingURL=node-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-writer.js","sourceRoot":"","sources":["../../src/file/node-writer.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @chaeco/logger - 功能完整的日志模块
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* 仅支持 Node.js 运行时,提供多级别日志、彩色控制台输出、文件写入和错误事件处理等功能。
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import { Logger } from './core/logger';
|
|
10
|
+
export { Logger };
|
|
11
|
+
/**
|
|
12
|
+
* 默认 Logger 实例(name: 'app',level: 'info',写入 ./logs)
|
|
13
|
+
*/
|
|
14
|
+
export declare const logger: Logger;
|
|
15
|
+
export type { LogLevel, LoggerOptions, FileOptions, ConsoleOptions, LogEntry, LoggerEventType, LoggerEventHandler, LoggerEvent, FormatOptions, AsyncWriteOptions, ErrorHandlingOptions, } from './core/types';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,MAAM,EAAE,CAAA;AAEjB;;GAEG;AACH,eAAO,MAAM,MAAM,QAIjB,CAAA;AAEF,YAAY,EACV,QAAQ,EACR,aAAa,EACb,WAAW,EACX,cAAc,EACd,QAAQ,EACR,eAAe,EACf,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,cAAc,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @chaeco/logger - 功能完整的日志模块
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* 仅支持 Node.js 运行时,提供多级别日志、彩色控制台输出、文件写入和错误事件处理等功能。
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.logger = exports.Logger = void 0;
|
|
12
|
+
const logger_1 = require("./core/logger");
|
|
13
|
+
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
|
|
14
|
+
/**
|
|
15
|
+
* 默认 Logger 实例(name: 'app',level: 'info',写入 ./logs)
|
|
16
|
+
*/
|
|
17
|
+
exports.logger = new logger_1.Logger({
|
|
18
|
+
name: 'app',
|
|
19
|
+
file: { enabled: true, path: './logs', maxSize: 10 * 1024 * 1024, maxFiles: 30 },
|
|
20
|
+
console: { enabled: true, colors: true, timestamp: true },
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEH,0CAAsC;AAC7B,uFADA,eAAM,OACA;AAEf;;GAEG;AACU,QAAA,MAAM,GAAG,IAAI,eAAM,CAAC;IAC/B,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;IAChF,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;CAC1D,CAAC,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 调用栈解析工具
|
|
3
|
+
* @internal
|
|
4
|
+
* 负责从 Error 堆栈中提取调用日志方法的文件路径和行号,并带 LRU 缓存。
|
|
5
|
+
*/
|
|
6
|
+
export declare class CallerInfoHelper {
|
|
7
|
+
private readonly cache;
|
|
8
|
+
private readonly maxCacheSize;
|
|
9
|
+
constructor(maxCacheSize?: number);
|
|
10
|
+
/**
|
|
11
|
+
* 获取当前调用者的文件路径和行号
|
|
12
|
+
*/
|
|
13
|
+
getCallerInfo(): {
|
|
14
|
+
file?: string;
|
|
15
|
+
line?: number;
|
|
16
|
+
};
|
|
17
|
+
/** 清除缓存 */
|
|
18
|
+
clearCache(): void;
|
|
19
|
+
/** 获取缓存大小(调试用) */
|
|
20
|
+
getCacheSize(): number;
|
|
21
|
+
/**
|
|
22
|
+
* 53 位非加密哈希(双 32 位混合),碰撞概率约为 32 位哈希的 1/20亿。
|
|
23
|
+
* 参考:https://stackoverflow.com/a/52171480
|
|
24
|
+
*/
|
|
25
|
+
private simpleHash;
|
|
26
|
+
/** LRU 缓存写入:满时淘汰最旧项 */
|
|
27
|
+
private cacheResult;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=caller-info.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caller-info.d.ts","sourceRoot":"","sources":["../../src/utils/caller-info.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2D;IACjF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;gBAEzB,YAAY,SAAO;IAI/B;;OAEG;IACH,aAAa,IAAI;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IA8EjD,WAAW;IACX,UAAU,IAAI,IAAI;IAIlB,kBAAkB;IAClB,YAAY,IAAI,MAAM;IAMtB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAclB,uBAAuB;IACvB,OAAO,CAAC,WAAW;CASpB"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CallerInfoHelper = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 调用栈解析工具
|
|
6
|
+
* @internal
|
|
7
|
+
* 负责从 Error 堆栈中提取调用日志方法的文件路径和行号,并带 LRU 缓存。
|
|
8
|
+
*/
|
|
9
|
+
class CallerInfoHelper {
|
|
10
|
+
constructor(maxCacheSize = 1000) {
|
|
11
|
+
this.cache = new Map();
|
|
12
|
+
this.maxCacheSize = maxCacheSize;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 获取当前调用者的文件路径和行号
|
|
16
|
+
*/
|
|
17
|
+
getCallerInfo() {
|
|
18
|
+
const error = new Error();
|
|
19
|
+
const stack = error.stack;
|
|
20
|
+
if (!stack)
|
|
21
|
+
return {};
|
|
22
|
+
// 尝试从缓存获取(使用堆栈的哈希作为键)
|
|
23
|
+
const stackHash = this.simpleHash(stack);
|
|
24
|
+
if (this.cache.has(stackHash)) {
|
|
25
|
+
// Map.has() 已确认键存在,get() 不会返回 undefined
|
|
26
|
+
return this.cache.get(stackHash);
|
|
27
|
+
}
|
|
28
|
+
// 解析堆栈信息
|
|
29
|
+
const stackLines = stack.split('\n');
|
|
30
|
+
for (let i = 0; i < stackLines.length; i++) {
|
|
31
|
+
const line = stackLines[i]?.trim();
|
|
32
|
+
if (!line)
|
|
33
|
+
continue;
|
|
34
|
+
// 跳过 Error 本身的行(V8 堆栈首行)
|
|
35
|
+
if (line.startsWith('Error'))
|
|
36
|
+
continue;
|
|
37
|
+
// 跳过所有 logger 内部帧,包括:
|
|
38
|
+
// CallerInfoHelper.getCallerInfo → 当前函数
|
|
39
|
+
// Logger.createLogEntry → 内部调用 getCallerInfo 的方法
|
|
40
|
+
// Logger.log / .debug / .info … → 公开日志方法
|
|
41
|
+
if (line.includes('Logger.log') ||
|
|
42
|
+
line.includes('Logger.info') ||
|
|
43
|
+
line.includes('Logger.warn') ||
|
|
44
|
+
line.includes('Logger.error') ||
|
|
45
|
+
line.includes('Logger.debug') ||
|
|
46
|
+
line.includes('Logger.createLogEntry') ||
|
|
47
|
+
line.includes('getCallerInfo') ||
|
|
48
|
+
line.includes('CallerInfoHelper')) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
// 匹配文件路径和行号
|
|
52
|
+
const match = line.match(/\((.+?):(\d+):\d+\)$/) || line.match(/at (.+?):(\d+):\d+$/);
|
|
53
|
+
if (match && match[1] && match[2]) {
|
|
54
|
+
const filePath = match[1];
|
|
55
|
+
const lineNumber = parseInt(match[2], 10);
|
|
56
|
+
// 排除 Node.js 内部文件和 logger 模块文件
|
|
57
|
+
if (filePath &&
|
|
58
|
+
!filePath.includes('/plugins/logger/') &&
|
|
59
|
+
!filePath.includes('\\plugins\\logger\\') &&
|
|
60
|
+
!filePath.includes('node:internal') &&
|
|
61
|
+
!filePath.includes('node_modules') &&
|
|
62
|
+
!filePath.startsWith('node:')) {
|
|
63
|
+
// 使用 process.cwd() 裁剪为相对路径
|
|
64
|
+
let simplifiedPath = filePath;
|
|
65
|
+
try {
|
|
66
|
+
const cwd = process.cwd();
|
|
67
|
+
if (filePath.startsWith(cwd)) {
|
|
68
|
+
simplifiedPath = filePath.slice(cwd.length).replace(/^[/\\]/, '');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// 忽略路径简化失败
|
|
73
|
+
}
|
|
74
|
+
const result = { file: simplifiedPath, line: lineNumber };
|
|
75
|
+
this.cacheResult(stackHash, result);
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
/** 清除缓存 */
|
|
83
|
+
clearCache() {
|
|
84
|
+
this.cache.clear();
|
|
85
|
+
}
|
|
86
|
+
/** 获取缓存大小(调试用) */
|
|
87
|
+
getCacheSize() {
|
|
88
|
+
return this.cache.size;
|
|
89
|
+
}
|
|
90
|
+
// ─── 私有方法 ─────────────────────────────────────────────
|
|
91
|
+
/**
|
|
92
|
+
* 53 位非加密哈希(双 32 位混合),碰撞概率约为 32 位哈希的 1/20亿。
|
|
93
|
+
* 参考:https://stackoverflow.com/a/52171480
|
|
94
|
+
*/
|
|
95
|
+
simpleHash(str) {
|
|
96
|
+
let h1 = 0xdeadbeef;
|
|
97
|
+
let h2 = 0x41c6ce57;
|
|
98
|
+
for (let i = 0; i < str.length; i++) {
|
|
99
|
+
const char = str.charCodeAt(i);
|
|
100
|
+
h1 = Math.imul(h1 ^ char, 2654435761);
|
|
101
|
+
h2 = Math.imul(h2 ^ char, 1597334677);
|
|
102
|
+
}
|
|
103
|
+
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
|
104
|
+
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
|
105
|
+
const hash = 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
|
106
|
+
return hash.toString(36);
|
|
107
|
+
}
|
|
108
|
+
/** LRU 缓存写入:满时淘汰最旧项 */
|
|
109
|
+
cacheResult(key, info) {
|
|
110
|
+
if (this.cache.size >= this.maxCacheSize) {
|
|
111
|
+
const firstKey = this.cache.keys().next().value;
|
|
112
|
+
if (firstKey !== undefined) {
|
|
113
|
+
this.cache.delete(firstKey);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
this.cache.set(key, info);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.CallerInfoHelper = CallerInfoHelper;
|
|
120
|
+
//# sourceMappingURL=caller-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caller-info.js","sourceRoot":"","sources":["../../src/utils/caller-info.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
/**
|
|
3
|
+
* 颜色工具类
|
|
4
|
+
* @internal
|
|
5
|
+
* @remarks
|
|
6
|
+
* 用于处理控制台输出的颜色。为不同级别的日志提供不同的颜色显示。
|
|
7
|
+
*/
|
|
8
|
+
export declare class ColorUtils {
|
|
9
|
+
static getLevelColor(level: string): typeof chalk;
|
|
10
|
+
static colorizeLevel(level: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* 将时间戳渲染为灰色,内部添加方括号(与 colorizeName / colorizeFileLocation 约定一致)
|
|
13
|
+
*/
|
|
14
|
+
static colorizeTimestamp(timestamp: string): string;
|
|
15
|
+
static colorizeName(name: string): string;
|
|
16
|
+
static colorizeFileLocation(location: string): string;
|
|
17
|
+
static colorizeMessage(level: string, message: string): string;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=color-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color-utils.d.ts","sourceRoot":"","sources":["../../src/utils/color-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,KAAK;IAejD,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAK3C;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAInD,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIzC,MAAM,CAAC,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAIrD,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;CAI/D"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ColorUtils = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
/**
|
|
9
|
+
* 颜色工具类
|
|
10
|
+
* @internal
|
|
11
|
+
* @remarks
|
|
12
|
+
* 用于处理控制台输出的颜色。为不同级别的日志提供不同的颜色显示。
|
|
13
|
+
*/
|
|
14
|
+
class ColorUtils {
|
|
15
|
+
static getLevelColor(level) {
|
|
16
|
+
switch (level.toLowerCase()) {
|
|
17
|
+
case 'debug':
|
|
18
|
+
return chalk_1.default.gray;
|
|
19
|
+
case 'info':
|
|
20
|
+
return chalk_1.default.blue;
|
|
21
|
+
case 'warn':
|
|
22
|
+
return chalk_1.default.yellow;
|
|
23
|
+
case 'error':
|
|
24
|
+
return chalk_1.default.red;
|
|
25
|
+
default:
|
|
26
|
+
return chalk_1.default.white;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
static colorizeLevel(level) {
|
|
30
|
+
const color = this.getLevelColor(level);
|
|
31
|
+
return color(level.toUpperCase().padEnd(6));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 将时间戳渲染为灰色,内部添加方括号(与 colorizeName / colorizeFileLocation 约定一致)
|
|
35
|
+
*/
|
|
36
|
+
static colorizeTimestamp(timestamp) {
|
|
37
|
+
return chalk_1.default.gray(`[${timestamp}]`);
|
|
38
|
+
}
|
|
39
|
+
static colorizeName(name) {
|
|
40
|
+
return chalk_1.default.cyan(`[${name}]`);
|
|
41
|
+
}
|
|
42
|
+
static colorizeFileLocation(location) {
|
|
43
|
+
return chalk_1.default.gray(`(${location})`);
|
|
44
|
+
}
|
|
45
|
+
static colorizeMessage(level, message) {
|
|
46
|
+
const color = this.getLevelColor(level);
|
|
47
|
+
return color(message);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.ColorUtils = ColorUtils;
|
|
51
|
+
//# sourceMappingURL=color-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color-utils.js","sourceRoot":"","sources":["../../src/utils/color-utils.ts"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAEzB;;;;;GAKG;AACH,MAAa,UAAU;IACrB,MAAM,CAAC,aAAa,CAAC,KAAa;QAChC,QAAQ,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC5B,KAAK,OAAO;gBACV,OAAO,eAAK,CAAC,IAAI,CAAA;YACnB,KAAK,MAAM;gBACT,OAAO,eAAK,CAAC,IAAI,CAAA;YACnB,KAAK,MAAM;gBACT,OAAO,eAAK,CAAC,MAAM,CAAA;YACrB,KAAK,OAAO;gBACV,OAAO,eAAK,CAAC,GAAG,CAAA;YAClB;gBACE,OAAO,eAAK,CAAC,KAAK,CAAA;QACtB,CAAC;IACH,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,KAAa;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;QACvC,OAAO,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,SAAiB;QACxC,OAAO,eAAK,CAAC,IAAI,CAAC,IAAI,SAAS,GAAG,CAAC,CAAA;IACrC,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,IAAY;QAC9B,OAAO,eAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,CAAA;IAChC,CAAC;IAED,MAAM,CAAC,oBAAoB,CAAC,QAAgB;QAC1C,OAAO,eAAK,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAA;IACpC,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,KAAa,EAAE,OAAe;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;QACvC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAA;IACvB,CAAC;CACF;AAxCD,gCAwCC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { LogEntry, FormatOptions } from '../core/types';
|
|
2
|
+
/**
|
|
3
|
+
* 格式化器运行时配置
|
|
4
|
+
*/
|
|
5
|
+
export interface FormatterSettings {
|
|
6
|
+
consoleTimestamp: boolean;
|
|
7
|
+
consoleColors: boolean;
|
|
8
|
+
format: {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
timestampFormat: string;
|
|
11
|
+
formatter?: (entry: LogEntry) => string;
|
|
12
|
+
includeStack: boolean;
|
|
13
|
+
includeName: boolean;
|
|
14
|
+
json: boolean;
|
|
15
|
+
jsonIndent: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 日志格式化器
|
|
20
|
+
* @internal
|
|
21
|
+
* 负责将 LogEntry 转换为可输出的字符串,支持普通文本、彩色控制台和 JSON 格式。
|
|
22
|
+
*/
|
|
23
|
+
export declare class LogFormatter {
|
|
24
|
+
settings: FormatterSettings;
|
|
25
|
+
constructor(settings: FormatterSettings);
|
|
26
|
+
/**
|
|
27
|
+
* 更新格式化选项(支持部分更新)
|
|
28
|
+
*/
|
|
29
|
+
updateFormat(options: Partial<FormatOptions>): void;
|
|
30
|
+
/**
|
|
31
|
+
* 格式化为文件输出字符串。
|
|
32
|
+
* 注意:文件日志始终包含时间戳,与控制台的 consoleTimestamp 开关无关。
|
|
33
|
+
*/
|
|
34
|
+
formatMessage(entry: LogEntry): string;
|
|
35
|
+
/**
|
|
36
|
+
* 格式化为带 ANSI 颜色的控制台字符串。
|
|
37
|
+
* 无色模式下使用纯文本,且遵守 consoleTimestamp 开关(与文件格式独立)。
|
|
38
|
+
* 自定义 formatter 函数的优先级高于颜色开关。
|
|
39
|
+
*/
|
|
40
|
+
formatConsoleMessage(entry: LogEntry): string;
|
|
41
|
+
/**
|
|
42
|
+
* 构建纯文本日志行,供文件输出和无色控制台复用。
|
|
43
|
+
* @param includeTimestamp 是否包含时间戳(文件格式始终传 true;控制台按 consoleTimestamp 传入)
|
|
44
|
+
*/
|
|
45
|
+
private buildPlainText;
|
|
46
|
+
/**
|
|
47
|
+
* 安全的 JSON 序列化,处理循环引用
|
|
48
|
+
*/
|
|
49
|
+
private safeStringify;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAIvD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,OAAO,CAAA;IACzB,aAAa,EAAE,OAAO,CAAA;IACtB,MAAM,EAAE;QACN,OAAO,EAAE,OAAO,CAAA;QAChB,eAAe,EAAE,MAAM,CAAA;QACvB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,MAAM,CAAA;QACvC,YAAY,EAAE,OAAO,CAAA;QACrB,WAAW,EAAE,OAAO,CAAA;QACpB,IAAI,EAAE,OAAO,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;KACnB,CAAA;CACF;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,QAAQ,EAAE,iBAAiB,CAAA;gBAEf,QAAQ,EAAE,iBAAiB;IAIvC;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAanD;;;OAGG;IACH,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;IAiCtC;;;;OAIG;IACH,oBAAoB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;IA0C7C;;;OAGG;IACH,OAAO,CAAC,cAAc;IAwBtB;;OAEG;IACH,OAAO,CAAC,aAAa;CA0BtB"}
|