@lppx/nlearn 1.1.19 → 1.1.21

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.
@@ -141,7 +141,7 @@ async function executeDemoFunction(demoFunc) {
141
141
  }
142
142
  // 执行函数
143
143
  await module[demoFunc.functionName]();
144
- console.log('\n' + '='.repeat(50) + '用户选择的函数执行结束' + '='.repeat(50));
144
+ console.log('\n' + '='.repeat(20) + '用户选择的函数执行结束' + '='.repeat(20));
145
145
  // console.log('✓ \n');
146
146
  }
147
147
  catch (error) {
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ /**
3
+ * Winston 基础概念
4
+ * ================
5
+ * Winston 是 Node.js 中最流行的日志库,支持多种传输方式和日志级别
6
+ * 适用版本: winston ^3.0.0
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.createBasicLogger = createBasicLogger;
13
+ exports.demonstrateLogLevels = demonstrateLogLevels;
14
+ exports.useDefaultLogger = useDefaultLogger;
15
+ exports.logWithMetadata = logWithMetadata;
16
+ exports.multipleTransports = multipleTransports;
17
+ const winston_1 = __importDefault(require("winston"));
18
+ // #region 示例1: 创建基础日志记录器
19
+ function createBasicLogger() {
20
+ console.log('\n=== 创建基础日志记录器 ===\n');
21
+ // 创建一个简单的 logger
22
+ const logger = winston_1.default.createLogger({
23
+ level: 'info',
24
+ format: winston_1.default.format.simple(),
25
+ transports: [
26
+ new winston_1.default.transports.Console()
27
+ ]
28
+ });
29
+ // 使用不同级别记录日志
30
+ logger.error('这是一个错误日志');
31
+ logger.warn('这是一个警告日志');
32
+ logger.info('这是一个信息日志');
33
+ logger.debug('这是一个调试日志(不会显示,因为 level 设置为 info)');
34
+ console.log('\n日志级别优先级: error > warn > info > http > verbose > debug > silly');
35
+ }
36
+ // #endregion
37
+ // #region 示例2: 日志级别详解
38
+ function demonstrateLogLevels() {
39
+ console.log('\n=== 日志级别详解 ===\n');
40
+ const logger = winston_1.default.createLogger({
41
+ level: 'silly', // 设置为最低级别,显示所有日志
42
+ format: winston_1.default.format.simple(),
43
+ transports: [
44
+ new winston_1.default.transports.Console()
45
+ ]
46
+ });
47
+ // Winston 默认的日志级别(从高到低)
48
+ logger.error('error - 错误信息,最高优先级');
49
+ logger.warn('warn - 警告信息');
50
+ logger.info('info - 一般信息');
51
+ logger.http('http - HTTP 请求日志');
52
+ logger.verbose('verbose - 详细信息');
53
+ logger.debug('debug - 调试信息');
54
+ logger.silly('silly - 最详细的信息,最低优先级');
55
+ console.log('\n提示: 设置 level 为某个级别后,只会显示该级别及更高优先级的日志');
56
+ }
57
+ // #endregion
58
+ // #region 示例3: 使用默认 logger
59
+ function useDefaultLogger() {
60
+ console.log('\n=== 使用默认 logger ===\n');
61
+ // Winston 提供了一个默认的 logger
62
+ winston_1.default.info('使用默认 logger 记录信息');
63
+ winston_1.default.warn('默认 logger 的警告');
64
+ winston_1.default.error('默认 logger 的错误');
65
+ console.log('\n注意: 默认 logger 配置简单,生产环境建议自定义配置');
66
+ }
67
+ // #endregion
68
+ // #region 示例4: 日志元数据
69
+ function logWithMetadata() {
70
+ console.log('\n=== 日志元数据 ===\n');
71
+ const logger = winston_1.default.createLogger({
72
+ level: 'info',
73
+ format: winston_1.default.format.json(),
74
+ transports: [
75
+ new winston_1.default.transports.Console()
76
+ ]
77
+ });
78
+ // 添加元数据
79
+ logger.info('用户登录', {
80
+ userId: '12345',
81
+ username: 'john_doe',
82
+ ip: '192.168.1.1',
83
+ timestamp: new Date().toISOString()
84
+ });
85
+ logger.error('数据库连接失败', {
86
+ database: 'users_db',
87
+ host: 'localhost',
88
+ port: 5432,
89
+ error: 'Connection timeout'
90
+ });
91
+ console.log('\n元数据以 JSON 格式输出,便于日志分析和检索');
92
+ }
93
+ // #endregion
94
+ // #region 示例5: 多个 transport
95
+ function multipleTransports() {
96
+ console.log('\n=== 多个 transport ===\n');
97
+ const logger = winston_1.default.createLogger({
98
+ level: 'info',
99
+ format: winston_1.default.format.json(),
100
+ transports: [
101
+ // 控制台输出
102
+ new winston_1.default.transports.Console({
103
+ format: winston_1.default.format.simple()
104
+ }),
105
+ // 文件输出 - 所有日志
106
+ new winston_1.default.transports.File({
107
+ filename: 'logs/combined.log'
108
+ }),
109
+ // 文件输出 - 仅错误日志
110
+ new winston_1.default.transports.File({
111
+ filename: 'logs/error.log',
112
+ level: 'error'
113
+ })
114
+ ]
115
+ });
116
+ logger.info('这条日志会输出到控制台和 combined.log');
117
+ logger.error('这条错误会输出到控制台、combined.log 和 error.log');
118
+ console.log('\n日志已写入 logs/ 目录');
119
+ }
120
+ // #endregion
121
+ if (require.main === module) {
122
+ const examples = [
123
+ { name: '创建基础日志记录器', fn: createBasicLogger },
124
+ { name: '日志级别详解', fn: demonstrateLogLevels },
125
+ { name: '使用默认 logger', fn: useDefaultLogger },
126
+ { name: '日志元数据', fn: logWithMetadata },
127
+ { name: '多个 transport', fn: multipleTransports }
128
+ ];
129
+ const exampleNumber = process.argv[2] ? parseInt(process.argv[2]) : null;
130
+ if (exampleNumber && exampleNumber >= 1 && exampleNumber <= examples.length) {
131
+ examples[exampleNumber - 1].fn();
132
+ }
133
+ else {
134
+ console.log('Winston 基础概念示例\n');
135
+ console.log('使用方法: ts-node 01-基础概念.ts [示例编号]\n');
136
+ examples.forEach((example, index) => {
137
+ console.log(`${index + 1}. ${example.name}`);
138
+ });
139
+ console.log('\n运行所有示例:');
140
+ examples.forEach(example => example.fn());
141
+ }
142
+ }
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ /**
3
+ * Winston 格式化输出
4
+ * ==================
5
+ * Winston 提供了丰富的格式化选项,可以自定义日志输出格式
6
+ * 适用版本: winston ^3.0.0
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.builtInFormatters = builtInFormatters;
13
+ exports.combineFormatters = combineFormatters;
14
+ exports.addTimestamp = addTimestamp;
15
+ exports.customFormat = customFormat;
16
+ exports.colorizedOutput = colorizedOutput;
17
+ exports.alignedFormat = alignedFormat;
18
+ const winston_1 = __importDefault(require("winston"));
19
+ // #region 示例1: 内置格式化器
20
+ function builtInFormatters() {
21
+ console.log('\n=== 内置格式化器 ===\n');
22
+ // JSON 格式
23
+ const jsonLogger = winston_1.default.createLogger({
24
+ level: 'info',
25
+ format: winston_1.default.format.json(),
26
+ transports: [new winston_1.default.transports.Console()]
27
+ });
28
+ console.log('1. JSON 格式:');
29
+ jsonLogger.info('JSON 格式的日志', { userId: 123, action: 'login' });
30
+ // Simple 格式
31
+ const simpleLogger = winston_1.default.createLogger({
32
+ level: 'info',
33
+ format: winston_1.default.format.simple(),
34
+ transports: [new winston_1.default.transports.Console()]
35
+ });
36
+ console.log('\n2. Simple 格式:');
37
+ simpleLogger.info('简单格式的日志');
38
+ // Prettyprint 格式
39
+ const prettyLogger = winston_1.default.createLogger({
40
+ level: 'info',
41
+ format: winston_1.default.format.prettyPrint(),
42
+ transports: [new winston_1.default.transports.Console()]
43
+ });
44
+ console.log('\n3. Pretty Print 格式:');
45
+ prettyLogger.info('美化打印的日志', { user: { id: 123, name: 'John' } });
46
+ }
47
+ // #endregion
48
+ // #region 示例2: 组合格式化器
49
+ function combineFormatters() {
50
+ console.log('\n=== 组合格式化器 ===\n');
51
+ const logger = winston_1.default.createLogger({
52
+ level: 'info',
53
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston_1.default.format.errors({ stack: true }), winston_1.default.format.splat(), winston_1.default.format.json()),
54
+ transports: [new winston_1.default.transports.Console()]
55
+ });
56
+ logger.info('组合格式化的日志');
57
+ logger.error('错误日志', new Error('示例错误'));
58
+ console.log('\n使用 combine 可以组合多个格式化器');
59
+ }
60
+ // #endregion
61
+ // #region 示例3: 添加时间戳
62
+ function addTimestamp() {
63
+ console.log('\n=== 添加时间戳 ===\n');
64
+ const logger = winston_1.default.createLogger({
65
+ level: 'info',
66
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp({
67
+ format: 'YYYY-MM-DD HH:mm:ss'
68
+ }), winston_1.default.format.printf(info => {
69
+ return `[${info.timestamp}] ${info.level}: ${info.message}`;
70
+ })),
71
+ transports: [new winston_1.default.transports.Console()]
72
+ });
73
+ logger.info('带时间戳的日志');
74
+ logger.warn('警告信息');
75
+ logger.error('错误信息');
76
+ }
77
+ // #endregion
78
+ // #region 示例4: 自定义格式化
79
+ function customFormat() {
80
+ console.log('\n=== 自定义格式化 ===\n');
81
+ const customFormat = winston_1.default.format.printf(({ level, message, timestamp, ...metadata }) => {
82
+ let msg = `${timestamp} [${level.toUpperCase()}] ${message}`;
83
+ if (Object.keys(metadata).length > 0) {
84
+ msg += ` | ${JSON.stringify(metadata)}`;
85
+ }
86
+ return msg;
87
+ });
88
+ const logger = winston_1.default.createLogger({
89
+ level: 'info',
90
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), customFormat),
91
+ transports: [new winston_1.default.transports.Console()]
92
+ });
93
+ logger.info('自定义格式的日志');
94
+ logger.info('带元数据的日志', { userId: 123, action: 'update' });
95
+ }
96
+ // #endregion
97
+ // #region 示例5: 彩色输出
98
+ function colorizedOutput() {
99
+ console.log('\n=== 彩色输出 ===\n');
100
+ const logger = winston_1.default.createLogger({
101
+ level: 'silly',
102
+ format: winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.timestamp({ format: 'HH:mm:ss' }), winston_1.default.format.printf(({ timestamp, level, message }) => {
103
+ return `${timestamp} ${level}: ${message}`;
104
+ })),
105
+ transports: [new winston_1.default.transports.Console()]
106
+ });
107
+ logger.error('错误日志 - 红色');
108
+ logger.warn('警告日志 - 黄色');
109
+ logger.info('信息日志 - 绿色');
110
+ logger.debug('调试日志 - 蓝色');
111
+ console.log('\n彩色输出让日志更易读');
112
+ }
113
+ // #endregion
114
+ // #region 示例6: 对齐格式
115
+ function alignedFormat() {
116
+ console.log('\n=== 对齐格式 ===\n');
117
+ const logger = winston_1.default.createLogger({
118
+ level: 'info',
119
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'HH:mm:ss' }), winston_1.default.format.align(), winston_1.default.format.printf(info => {
120
+ const { timestamp, level, message, ...args } = info;
121
+ const ts = typeof timestamp === 'string' ? timestamp : String(timestamp);
122
+ return `${ts} [${level}]: ${message} ${Object.keys(args).length ? JSON.stringify(args, null, 2) : ''}`;
123
+ })),
124
+ transports: [new winston_1.default.transports.Console()]
125
+ });
126
+ logger.info('对齐的日志输出');
127
+ logger.warn('警告信息');
128
+ logger.error('错误信息', { code: 500, details: 'Internal Server Error' });
129
+ }
130
+ // #endregion
131
+ if (require.main === module) {
132
+ const examples = [
133
+ { name: '内置格式化器', fn: builtInFormatters },
134
+ { name: '组合格式化器', fn: combineFormatters },
135
+ { name: '添加时间戳', fn: addTimestamp },
136
+ { name: '自定义格式化', fn: customFormat },
137
+ { name: '彩色输出', fn: colorizedOutput },
138
+ { name: '对齐格式', fn: alignedFormat }
139
+ ];
140
+ const exampleNumber = process.argv[2] ? parseInt(process.argv[2]) : null;
141
+ if (exampleNumber && exampleNumber >= 1 && exampleNumber <= examples.length) {
142
+ examples[exampleNumber - 1].fn();
143
+ }
144
+ else {
145
+ console.log('Winston 格式化输出示例\n');
146
+ console.log('使用方法: ts-node 02-格式化输出.ts [示例编号]\n');
147
+ examples.forEach((example, index) => {
148
+ console.log(`${index + 1}. ${example.name}`);
149
+ });
150
+ console.log('\n运行所有示例:');
151
+ examples.forEach(example => example.fn());
152
+ }
153
+ }
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ /**
3
+ * Winston 传输方式
4
+ * =================
5
+ * Winston 支持多种传输方式(Transport),可以将日志输出到不同的目标
6
+ * 适用版本: winston ^3.0.0
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.consoleTransport = consoleTransport;
13
+ exports.fileTransport = fileTransport;
14
+ exports.separateLogsByLevel = separateLogsByLevel;
15
+ exports.logRotation = logRotation;
16
+ exports.customTransport = customTransport;
17
+ exports.dynamicTransports = dynamicTransports;
18
+ const winston_1 = __importDefault(require("winston"));
19
+ // #region 示例1: Console Transport
20
+ function consoleTransport() {
21
+ console.log('\n=== Console Transport ===\n');
22
+ const logger = winston_1.default.createLogger({
23
+ level: 'info',
24
+ transports: [
25
+ new winston_1.default.transports.Console({
26
+ format: winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.simple())
27
+ })
28
+ ]
29
+ });
30
+ logger.info('输出到控制台');
31
+ logger.warn('控制台警告');
32
+ logger.error('控制台错误');
33
+ console.log('\nConsole Transport 适合开发环境调试');
34
+ }
35
+ // #endregion
36
+ // #region 示例2: File Transport
37
+ function fileTransport() {
38
+ console.log('\n=== File Transport ===\n');
39
+ const logger = winston_1.default.createLogger({
40
+ level: 'info',
41
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.json()),
42
+ transports: [
43
+ new winston_1.default.transports.File({
44
+ filename: 'logs/app.log',
45
+ maxsize: 5242880, // 5MB
46
+ maxFiles: 5,
47
+ })
48
+ ]
49
+ });
50
+ logger.info('写入文件的日志');
51
+ logger.warn('文件警告');
52
+ logger.error('文件错误');
53
+ console.log('日志已写入 logs/app.log');
54
+ console.log('maxsize: 单个文件最大大小');
55
+ console.log('maxFiles: 保留的文件数量');
56
+ }
57
+ // #endregion
58
+ // #region 示例3: 按级别分离日志文件
59
+ function separateLogsByLevel() {
60
+ console.log('\n=== 按级别分离日志文件 ===\n');
61
+ const logger = winston_1.default.createLogger({
62
+ level: 'debug',
63
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.json()),
64
+ transports: [
65
+ // 所有日志
66
+ new winston_1.default.transports.File({
67
+ filename: 'logs/combined.log'
68
+ }),
69
+ // 仅错误日志
70
+ new winston_1.default.transports.File({
71
+ filename: 'logs/error.log',
72
+ level: 'error'
73
+ }),
74
+ // 仅警告及以上
75
+ new winston_1.default.transports.File({
76
+ filename: 'logs/warn.log',
77
+ level: 'warn'
78
+ }),
79
+ // 控制台输出
80
+ new winston_1.default.transports.Console({
81
+ format: winston_1.default.format.simple()
82
+ })
83
+ ]
84
+ });
85
+ logger.debug('调试信息');
86
+ logger.info('一般信息');
87
+ logger.warn('警告信息');
88
+ logger.error('错误信息');
89
+ console.log('\n日志已按级别分离到不同文件');
90
+ }
91
+ // #endregion
92
+ // #region 示例4: 日志轮转
93
+ function logRotation() {
94
+ console.log('\n=== 日志轮转 ===\n');
95
+ const logger = winston_1.default.createLogger({
96
+ level: 'info',
97
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.json()),
98
+ transports: [
99
+ new winston_1.default.transports.File({
100
+ filename: 'logs/application.log',
101
+ maxsize: 20971520, // 20MB
102
+ maxFiles: 14
103
+ })
104
+ ]
105
+ });
106
+ logger.info('日志轮转示例');
107
+ console.log('\n配置说明:');
108
+ console.log('- maxsize: 单个文件最大 20MB');
109
+ console.log('- maxFiles: 保留 14 个日志文件');
110
+ console.log('\n注意: 更高级的日期轮转功能需要安装 winston-daily-rotate-file 包');
111
+ }
112
+ // #endregion
113
+ // #region 示例5: 自定义 Transport
114
+ function customTransport() {
115
+ console.log('\n=== 自定义 Transport ===\n');
116
+ // 创建一个简单的自定义 Transport
117
+ class CustomTransport extends winston_1.default.transports.Stream {
118
+ constructor(opts) {
119
+ super(opts);
120
+ }
121
+ log(info, callback) {
122
+ setImmediate(() => {
123
+ this.emit('logged', info);
124
+ });
125
+ // 自定义处理逻辑
126
+ console.log(`[自定义输出] ${info.level}: ${info.message}`);
127
+ callback();
128
+ }
129
+ }
130
+ const logger = winston_1.default.createLogger({
131
+ level: 'info',
132
+ transports: [
133
+ new CustomTransport()
134
+ ]
135
+ });
136
+ logger.info('使用自定义 Transport');
137
+ logger.warn('自定义警告');
138
+ console.log('\n可以创建自定义 Transport 将日志发送到任何目标');
139
+ }
140
+ // #endregion
141
+ // #region 示例6: 动态添加和移除 Transport
142
+ function dynamicTransports() {
143
+ console.log('\n=== 动态添加和移除 Transport ===\n');
144
+ const logger = winston_1.default.createLogger({
145
+ level: 'info',
146
+ format: winston_1.default.format.simple()
147
+ });
148
+ // 初始没有 transport
149
+ logger.info('这条日志不会输出');
150
+ // 动态添加 Console transport
151
+ const consoleTransport = new winston_1.default.transports.Console();
152
+ logger.add(consoleTransport);
153
+ logger.info('添加 Console transport 后的日志');
154
+ // 动态添加 File transport
155
+ const fileTransport = new winston_1.default.transports.File({ filename: 'logs/dynamic.log' });
156
+ logger.add(fileTransport);
157
+ logger.info('同时输出到控制台和文件');
158
+ // 移除 Console transport
159
+ logger.remove(consoleTransport);
160
+ logger.info('移除 Console transport 后,只输出到文件');
161
+ console.log('\n可以在运行时动态管理 transports');
162
+ }
163
+ // #endregion
164
+ if (require.main === module) {
165
+ const examples = [
166
+ { name: 'Console Transport', fn: consoleTransport },
167
+ { name: 'File Transport', fn: fileTransport },
168
+ { name: '按级别分离日志文件', fn: separateLogsByLevel },
169
+ { name: '日志轮转', fn: logRotation },
170
+ { name: '自定义 Transport', fn: customTransport },
171
+ { name: '动态添加和移除 Transport', fn: dynamicTransports }
172
+ ];
173
+ const exampleNumber = process.argv[2] ? parseInt(process.argv[2]) : null;
174
+ if (exampleNumber && exampleNumber >= 1 && exampleNumber <= examples.length) {
175
+ examples[exampleNumber - 1].fn();
176
+ }
177
+ else {
178
+ console.log('Winston 传输方式示例\n');
179
+ console.log('使用方法: ts-node 03-传输方式.ts [示例编号]\n');
180
+ examples.forEach((example, index) => {
181
+ console.log(`${index + 1}. ${example.name}`);
182
+ });
183
+ console.log('\n运行所有示例:');
184
+ examples.forEach(example => example.fn());
185
+ }
186
+ }
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ /**
3
+ * Winston 实战案例
4
+ * ================
5
+ * 实际项目中 Winston 的应用场景和最佳实践
6
+ * 适用版本: winston ^3.0.0
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.productionLoggerConfig = productionLoggerConfig;
13
+ exports.httpRequestLogger = httpRequestLogger;
14
+ exports.errorTracking = errorTracking;
15
+ exports.childLoggers = childLoggers;
16
+ exports.performanceMonitoring = performanceMonitoring;
17
+ exports.logFiltering = logFiltering;
18
+ const winston_1 = __importDefault(require("winston"));
19
+ // #region 示例1: 生产环境日志配置
20
+ function productionLoggerConfig() {
21
+ console.log('\n=== 生产环境日志配置 ===\n');
22
+ const logger = winston_1.default.createLogger({
23
+ level: process.env.LOG_LEVEL || 'info',
24
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston_1.default.format.errors({ stack: true }), winston_1.default.format.json()),
25
+ defaultMeta: { service: 'user-service' },
26
+ transports: [
27
+ // 错误日志
28
+ new winston_1.default.transports.File({
29
+ filename: 'logs/error.log',
30
+ level: 'error',
31
+ maxsize: 5242880, // 5MB
32
+ maxFiles: 5
33
+ }),
34
+ // 所有日志
35
+ new winston_1.default.transports.File({
36
+ filename: 'logs/combined.log',
37
+ maxsize: 5242880,
38
+ maxFiles: 5
39
+ })
40
+ ]
41
+ });
42
+ // 开发环境添加控制台输出
43
+ if (process.env.NODE_ENV !== 'production') {
44
+ logger.add(new winston_1.default.transports.Console({
45
+ format: winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.simple())
46
+ }));
47
+ }
48
+ logger.info('应用启动', { port: 3000 });
49
+ logger.error('数据库连接失败', new Error('Connection timeout'));
50
+ console.log('\n生产环境配置要点:');
51
+ console.log('- 使用环境变量控制日志级别');
52
+ console.log('- 文件大小和数量限制');
53
+ console.log('- 开发和生产环境区分');
54
+ }
55
+ // #endregion
56
+ // #region 示例2: HTTP 请求日志中间件
57
+ function httpRequestLogger() {
58
+ console.log('\n=== HTTP 请求日志中间件 ===\n');
59
+ const logger = winston_1.default.createLogger({
60
+ level: 'http',
61
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.json()),
62
+ transports: [
63
+ new winston_1.default.transports.File({ filename: 'logs/http.log' }),
64
+ new winston_1.default.transports.Console({ format: winston_1.default.format.simple() })
65
+ ]
66
+ });
67
+ // 模拟 Express 中间件
68
+ function loggerMiddleware(req, res, next) {
69
+ const start = Date.now();
70
+ res.on('finish', () => {
71
+ const duration = Date.now() - start;
72
+ logger.http('HTTP Request', {
73
+ method: req.method,
74
+ url: req.url,
75
+ status: res.statusCode,
76
+ duration: `${duration}ms`,
77
+ ip: req.ip,
78
+ userAgent: req.get('user-agent')
79
+ });
80
+ });
81
+ next();
82
+ }
83
+ // 模拟请求
84
+ const mockReq = {
85
+ method: 'GET',
86
+ url: '/api/users',
87
+ ip: '192.168.1.1',
88
+ get: (header) => 'Mozilla/5.0'
89
+ };
90
+ const mockRes = {
91
+ statusCode: 200,
92
+ on: (event, callback) => {
93
+ if (event === 'finish') {
94
+ setTimeout(callback, 100);
95
+ }
96
+ }
97
+ };
98
+ loggerMiddleware(mockReq, mockRes, () => { });
99
+ console.log('\n可以集成到 Express/Koa 等框架中记录 HTTP 请求');
100
+ }
101
+ // #endregion
102
+ // #region 示例3: 错误追踪和堆栈信息
103
+ function errorTracking() {
104
+ console.log('\n=== 错误追踪和堆栈信息 ===\n');
105
+ const logger = winston_1.default.createLogger({
106
+ level: 'error',
107
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.errors({ stack: true }), winston_1.default.format.json()),
108
+ transports: [
109
+ new winston_1.default.transports.Console({
110
+ format: winston_1.default.format.prettyPrint()
111
+ })
112
+ ]
113
+ });
114
+ try {
115
+ // 模拟错误
116
+ throw new Error('数据库查询失败');
117
+ }
118
+ catch (error) {
119
+ logger.error('捕获到错误', {
120
+ error,
121
+ context: {
122
+ userId: '12345',
123
+ operation: 'getUserProfile'
124
+ }
125
+ });
126
+ }
127
+ console.log('\n错误日志包含完整的堆栈信息,便于调试');
128
+ }
129
+ // #endregion
130
+ // #region 示例4: 子 Logger 和模块化
131
+ function childLoggers() {
132
+ console.log('\n=== 子 Logger 和模块化 ===\n');
133
+ // 主 logger
134
+ const mainLogger = winston_1.default.createLogger({
135
+ level: 'info',
136
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.json()),
137
+ transports: [
138
+ new winston_1.default.transports.Console({ format: winston_1.default.format.simple() })
139
+ ]
140
+ });
141
+ // 为不同模块创建子 logger
142
+ const dbLogger = mainLogger.child({ module: 'database' });
143
+ const authLogger = mainLogger.child({ module: 'authentication' });
144
+ const apiLogger = mainLogger.child({ module: 'api' });
145
+ dbLogger.info('数据库连接成功', { host: 'localhost', port: 5432 });
146
+ authLogger.warn('登录尝试失败', { username: 'john', attempts: 3 });
147
+ apiLogger.info('API 请求', { endpoint: '/users', method: 'GET' });
148
+ console.log('\n子 logger 自动继承父 logger 的配置,并添加额外的元数据');
149
+ }
150
+ // #endregion
151
+ // #region 示例5: 性能监控日志
152
+ function performanceMonitoring() {
153
+ console.log('\n=== 性能监控日志 ===\n');
154
+ const logger = winston_1.default.createLogger({
155
+ level: 'info',
156
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.json()),
157
+ transports: [
158
+ new winston_1.default.transports.Console({ format: winston_1.default.format.simple() })
159
+ ]
160
+ });
161
+ // 性能监控辅助函数
162
+ function measurePerformance(operation, fn) {
163
+ const start = Date.now();
164
+ try {
165
+ fn();
166
+ const duration = Date.now() - start;
167
+ logger.info('操作完成', {
168
+ operation,
169
+ duration: `${duration}ms`,
170
+ status: 'success'
171
+ });
172
+ }
173
+ catch (error) {
174
+ const duration = Date.now() - start;
175
+ logger.error('操作失败', {
176
+ operation,
177
+ duration: `${duration}ms`,
178
+ status: 'failed',
179
+ error: error instanceof Error ? error.message : String(error)
180
+ });
181
+ }
182
+ }
183
+ // 使用示例
184
+ measurePerformance('数据库查询', () => {
185
+ // 模拟耗时操作
186
+ const start = Date.now();
187
+ while (Date.now() - start < 50) { }
188
+ });
189
+ measurePerformance('API 调用', () => {
190
+ const start = Date.now();
191
+ while (Date.now() - start < 30) { }
192
+ });
193
+ console.log('\n性能日志帮助识别系统瓶颈');
194
+ }
195
+ // #endregion
196
+ // #region 示例6: 日志过滤和敏感信息脱敏
197
+ function logFiltering() {
198
+ console.log('\n=== 日志过滤和敏感信息脱敏 ===\n');
199
+ // 自定义格式化器,过滤敏感信息
200
+ const maskSensitiveData = winston_1.default.format((info) => {
201
+ if (info.password) {
202
+ info.password = '******';
203
+ }
204
+ if (info.creditCard && typeof info.creditCard === 'string') {
205
+ info.creditCard = info.creditCard.replace(/\d(?=\d{4})/g, '*');
206
+ }
207
+ if (info.email && typeof info.email === 'string') {
208
+ info.email = info.email.replace(/(.{2})(.*)(@.*)/, '$1***$3');
209
+ }
210
+ return info;
211
+ });
212
+ const logger = winston_1.default.createLogger({
213
+ level: 'info',
214
+ format: winston_1.default.format.combine(maskSensitiveData(), winston_1.default.format.timestamp(), winston_1.default.format.json()),
215
+ transports: [
216
+ new winston_1.default.transports.Console({ format: winston_1.default.format.simple() })
217
+ ]
218
+ });
219
+ logger.info('用户注册', {
220
+ username: 'john_doe',
221
+ email: 'john.doe@example.com',
222
+ password: 'MySecretPassword123'
223
+ });
224
+ logger.info('支付信息', {
225
+ userId: '12345',
226
+ creditCard: '1234567890123456',
227
+ amount: 99.99
228
+ });
229
+ console.log('\n敏感信息已脱敏,保护用户隐私');
230
+ }
231
+ // #endregion
232
+ if (require.main === module) {
233
+ const examples = [
234
+ { name: '生产环境日志配置', fn: productionLoggerConfig },
235
+ { name: 'HTTP 请求日志中间件', fn: httpRequestLogger },
236
+ { name: '错误追踪和堆栈信息', fn: errorTracking },
237
+ { name: '子 Logger 和模块化', fn: childLoggers },
238
+ { name: '性能监控日志', fn: performanceMonitoring },
239
+ { name: '日志过滤和敏感信息脱敏', fn: logFiltering }
240
+ ];
241
+ const exampleNumber = process.argv[2] ? parseInt(process.argv[2]) : null;
242
+ if (exampleNumber && exampleNumber >= 1 && exampleNumber <= examples.length) {
243
+ examples[exampleNumber - 1].fn();
244
+ }
245
+ else {
246
+ console.log('Winston 实战案例示例\n');
247
+ console.log('使用方法: ts-node 04-实战案例.ts [示例编号]\n');
248
+ examples.forEach((example, index) => {
249
+ console.log(`${index + 1}. ${example.name}`);
250
+ });
251
+ console.log('\n运行所有示例:');
252
+ examples.forEach(example => example.fn());
253
+ }
254
+ }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.1.19",
6
+ "version": "1.1.21",
7
7
  "description": "ts test",
8
8
  "bin": {
9
9
  "nlearn": "dist/src/cli/index.js",
@@ -27,6 +27,7 @@
27
27
  "inquirer": "^9.3.8",
28
28
  "isomorphic-git": "^1.36.3",
29
29
  "prompts": "^2.4.2",
30
+ "winston": "^3.11.0",
30
31
  "yargs": "^18.0.0"
31
32
  },
32
33
  "engines": {