@zwa73/utils 1.0.57 → 1.0.61
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/dist/UtilCodecs.d.ts +16 -16
- package/dist/UtilCodecs.js +16 -16
- package/dist/UtilCom.d.ts +22 -25
- package/dist/UtilCom.js +35 -38
- package/dist/UtilDecorators.d.ts +15 -8
- package/dist/UtilDecorators.js +79 -25
- package/dist/UtilFP.d.ts +46 -0
- package/dist/UtilFP.js +52 -0
- package/dist/UtilFfmpegTools.d.ts +30 -30
- package/dist/UtilFfmpegTools.js +32 -32
- package/dist/UtilFileTools.d.ts +30 -35
- package/dist/UtilFileTools.js +17 -18
- package/dist/UtilFunctions.d.ts +37 -78
- package/dist/UtilFunctions.js +27 -62
- package/dist/UtilInterfaces.d.ts +11 -11
- package/dist/UtilInterfaces.js +2 -2
- package/dist/UtilLogger.d.ts +55 -55
- package/dist/UtilLogger.js +55 -55
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/test/composeTest.d.ts +21 -0
- package/dist/test/composeTest.js +33 -0
- package/dist/test/importtest.d.ts +1 -0
- package/dist/test/importtest.js +4 -0
- package/dist/test/test.js +5 -3
- package/package.json +2 -2
- package/src/UtilClass.ts +1051 -1051
- package/src/UtilCodecs.ts +117 -117
- package/src/UtilCom.ts +171 -174
- package/src/UtilDecorators.ts +174 -116
- package/src/UtilFP.ts +98 -0
- package/src/UtilFfmpegTools.ts +271 -271
- package/src/UtilFileTools.ts +231 -236
- package/src/UtilFunctions.ts +289 -364
- package/src/UtilInterfaces.ts +137 -137
- package/src/UtilLogger.ts +386 -386
- package/src/index.ts +10 -9
- package/src/test/composeTest.ts +37 -0
- package/src/test/importtest.ts +5 -0
- package/src/test/test.ts +8 -6
- package/src/test/test2.ts +2 -3
- package/tsconfig.json +2 -7
package/src/UtilLogger.ts
CHANGED
|
@@ -1,386 +1,386 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
|
-
import * as winston from 'winston';
|
|
3
|
-
import * as DailyRotateFile from 'winston-daily-rotate-file';
|
|
4
|
-
import {inspect} from 'util';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**hrtime所产生的的记录 */
|
|
9
|
-
export type HRTimeLog = {
|
|
10
|
-
/**秒数 */
|
|
11
|
-
0:number;
|
|
12
|
-
/**纳秒数 */
|
|
13
|
-
1:number;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**log等级 undefined相当于 silly */
|
|
17
|
-
export type LogLevel = "fatal"|"error"|"warn"|"info"|"http"|"verbose"|"debug"|"silly"|undefined;
|
|
18
|
-
const logLevels = {
|
|
19
|
-
fatal: 0,
|
|
20
|
-
error: 1,
|
|
21
|
-
warn: 2,
|
|
22
|
-
info: 3,
|
|
23
|
-
http: 4,
|
|
24
|
-
verbose: 5,
|
|
25
|
-
debug: 6,
|
|
26
|
-
silly: 7
|
|
27
|
-
};
|
|
28
|
-
const colorizer = winston.format.colorize();
|
|
29
|
-
colorizer.addColors({
|
|
30
|
-
fatal: 'bold yellow redBG',
|
|
31
|
-
error: 'bold yellow',
|
|
32
|
-
warn: 'yellow',
|
|
33
|
-
info: 'white',
|
|
34
|
-
debug: 'bold cyan',
|
|
35
|
-
silly: 'bold magenta'
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export class SLogger{
|
|
40
|
-
/**获取一个Logger,如不存在则用默认参数创建
|
|
41
|
-
* @param
|
|
42
|
-
* @returns
|
|
43
|
-
*/
|
|
44
|
-
static getLogger(name:string="default"):SLogger{
|
|
45
|
-
let out = SLogger.loggerTable[name];
|
|
46
|
-
if(out==null){
|
|
47
|
-
SLogger.createLogger(name);
|
|
48
|
-
out = SLogger.loggerTable[name];
|
|
49
|
-
}
|
|
50
|
-
return out;
|
|
51
|
-
}
|
|
52
|
-
/**创建Logger
|
|
53
|
-
* @param
|
|
54
|
-
* @param
|
|
55
|
-
* @param
|
|
56
|
-
* @param
|
|
57
|
-
* @returns
|
|
58
|
-
*/
|
|
59
|
-
static createLogger(name:string="default",consoleLevel:LogLevel="info",outFloder?:string,fileLevel:LogLevel="info"):SLogger{
|
|
60
|
-
const transports:winston.transport[]=[];
|
|
61
|
-
if(outFloder!=null){
|
|
62
|
-
const fileFormat = winston.format.combine(
|
|
63
|
-
winston.format.timestamp({ format: 'HH:mm:ss' }),
|
|
64
|
-
winston.format.printf((info) => {
|
|
65
|
-
const level = info.level.toUpperCase();
|
|
66
|
-
const message = info.message as string;
|
|
67
|
-
//格式化
|
|
68
|
-
//let format = `[${info.timestamp}] [${level}]: `
|
|
69
|
-
//let space = " ".repeat(format.length);
|
|
70
|
-
let messageList = message.split("\n");
|
|
71
|
-
return `[${info.timestamp}] [${level.toUpperCase()}]: ${messageList.join("\n")}`
|
|
72
|
-
}),
|
|
73
|
-
);
|
|
74
|
-
transports.push(new DailyRotateFile({
|
|
75
|
-
filename: path.join(outFloder,'log-%DATE%.txt'),
|
|
76
|
-
datePattern: 'YYYY-MM-DD',
|
|
77
|
-
level:fileLevel,
|
|
78
|
-
format:fileFormat,
|
|
79
|
-
}));
|
|
80
|
-
}
|
|
81
|
-
const consoleFormat = winston.format.combine(
|
|
82
|
-
winston.format.timestamp({ format: 'HH:mm:ss' }),
|
|
83
|
-
winston.format.printf((info) => {
|
|
84
|
-
const level = info.level.toUpperCase();
|
|
85
|
-
const message = info.message as string;
|
|
86
|
-
const colorizedLevel = colorizer.colorize(info.level, level);
|
|
87
|
-
//格式化
|
|
88
|
-
//let format = `[${info.timestamp}] [${level}]: `
|
|
89
|
-
//let space = " ".repeat(format.length);
|
|
90
|
-
let messageList = message.split("\n");
|
|
91
|
-
messageList[0]=colorizer.colorize(info.level, messageList[0])
|
|
92
|
-
for(let i=1;i<messageList.length;i++)
|
|
93
|
-
messageList[i]=colorizer.colorize(info.level, messageList[i]);
|
|
94
|
-
return `[${info.timestamp}] [${colorizedLevel}]: ${messageList.join("\n")}`;
|
|
95
|
-
}),
|
|
96
|
-
);
|
|
97
|
-
transports.push(new winston.transports.Console({
|
|
98
|
-
level: consoleLevel,
|
|
99
|
-
format:consoleFormat,
|
|
100
|
-
}));
|
|
101
|
-
const logger = winston.createLogger({
|
|
102
|
-
levels:logLevels,
|
|
103
|
-
transports: transports,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const out = new SLogger();
|
|
107
|
-
out._logger = logger;
|
|
108
|
-
|
|
109
|
-
if(SLogger.loggerTable[name]!=null){
|
|
110
|
-
let old = SLogger.loggerTable[name];
|
|
111
|
-
old._logger.transports.forEach(tp=>{
|
|
112
|
-
if(tp.close!=null) tp.close();
|
|
113
|
-
})
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
SLogger.loggerTable[name] = out;
|
|
117
|
-
return out;
|
|
118
|
-
}
|
|
119
|
-
private constructor(){}
|
|
120
|
-
private _logger:winston.Logger = null as any as winston.Logger;
|
|
121
|
-
/**记录Logger的表 */
|
|
122
|
-
private static readonly loggerTable:Record<string,SLogger> = {};
|
|
123
|
-
/**记录Logger的表 */
|
|
124
|
-
private static readonly timeTable:Record<string,HRTimeLog> = {};
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
//———————————————————— function ——————————————————————//
|
|
129
|
-
/**产生一条对应等级的log 返回自身
|
|
130
|
-
* @param
|
|
131
|
-
* @param
|
|
132
|
-
* @returns
|
|
133
|
-
*/
|
|
134
|
-
log(level:LogLevel,...messages:Array<any>):SLogger{
|
|
135
|
-
level = level||"silly";
|
|
136
|
-
let strMessages:Array<string> = [];
|
|
137
|
-
//上一条是字符串字符串
|
|
138
|
-
let preIsString = true;
|
|
139
|
-
for(let message of messages){
|
|
140
|
-
let out:string;
|
|
141
|
-
//非string类型
|
|
142
|
-
if(typeof message!=="string"){
|
|
143
|
-
out=`<${typeof message}> ${inspect(message)}`;
|
|
144
|
-
preIsString=false;
|
|
145
|
-
}else if(!preIsString){
|
|
146
|
-
//如果上一条不是字符串则需要添加<string>类型标记
|
|
147
|
-
out = `<${typeof message}> ${inspect(message)}`;
|
|
148
|
-
preIsString=true;
|
|
149
|
-
}else{
|
|
150
|
-
out = message;
|
|
151
|
-
}
|
|
152
|
-
strMessages.push(out);
|
|
153
|
-
}
|
|
154
|
-
let outMessage = strMessages.join("\n");
|
|
155
|
-
this._logger.log(level,outMessage);
|
|
156
|
-
return this;
|
|
157
|
-
}
|
|
158
|
-
/**产生一条fatal等级的log 返回自身
|
|
159
|
-
* @param
|
|
160
|
-
* @returns
|
|
161
|
-
*/
|
|
162
|
-
fatal(...messages:Array<any>):SLogger {
|
|
163
|
-
return this.log("fatal",...messages);;
|
|
164
|
-
}
|
|
165
|
-
/**产生一条error等级的log 返回自身
|
|
166
|
-
* @param
|
|
167
|
-
* @returns
|
|
168
|
-
*/
|
|
169
|
-
error(...messages:Array<any>):SLogger {
|
|
170
|
-
return this.log("error",...messages);;
|
|
171
|
-
}
|
|
172
|
-
/**产生一条warn等级的log 返回自身
|
|
173
|
-
* @param
|
|
174
|
-
* @returns
|
|
175
|
-
*/
|
|
176
|
-
warn(...messages:Array<any>):SLogger {
|
|
177
|
-
return this.log("warn",...messages);;
|
|
178
|
-
}
|
|
179
|
-
/**产生一条info等级的log 返回自身
|
|
180
|
-
* @param
|
|
181
|
-
* @returns
|
|
182
|
-
*/
|
|
183
|
-
info(...messages:Array<any>):SLogger {
|
|
184
|
-
return this.log("info",...messages);
|
|
185
|
-
}
|
|
186
|
-
/**产生一条http等级的log 返回自身
|
|
187
|
-
* @param
|
|
188
|
-
* @returns
|
|
189
|
-
*/
|
|
190
|
-
http(...messages:Array<any>):SLogger {
|
|
191
|
-
return this.log("http",...messages);
|
|
192
|
-
}
|
|
193
|
-
/**产生一条verbose等级的log 返回自身
|
|
194
|
-
* @param
|
|
195
|
-
* @returns
|
|
196
|
-
*/
|
|
197
|
-
verbose(...messages:Array<any>):SLogger {
|
|
198
|
-
return this.log("verbose",...messages);
|
|
199
|
-
}
|
|
200
|
-
/**产生一条debug等级的log 返回自身
|
|
201
|
-
* @param
|
|
202
|
-
* @returns
|
|
203
|
-
*/
|
|
204
|
-
debug(...messages:Array<any>):SLogger {
|
|
205
|
-
return this.log("debug",...messages);
|
|
206
|
-
}
|
|
207
|
-
/**产生一条silly等级的log 返回自身
|
|
208
|
-
* @param
|
|
209
|
-
* @returns
|
|
210
|
-
*/
|
|
211
|
-
silly(...messages:Array<any>):SLogger {
|
|
212
|
-
return this.log("silly",...messages);
|
|
213
|
-
}
|
|
214
|
-
/**记录当前时间戳并存入表
|
|
215
|
-
* @param
|
|
216
|
-
* @returns
|
|
217
|
-
*/
|
|
218
|
-
time(flag:string):HRTimeLog{
|
|
219
|
-
let hrtime = process.hrtime();
|
|
220
|
-
SLogger.timeTable[flag]=hrtime;
|
|
221
|
-
return hrtime;
|
|
222
|
-
}
|
|
223
|
-
/**根据之前记录的时间戳计算经过的时间 并输出log
|
|
224
|
-
* @param
|
|
225
|
-
* @param
|
|
226
|
-
* @returns
|
|
227
|
-
*/
|
|
228
|
-
timeEnd(flag:string,level:LogLevel|null="info"):string|null{
|
|
229
|
-
let start = SLogger.timeTable[flag];
|
|
230
|
-
if(start==null){
|
|
231
|
-
this.warn("SLogger.timeEnd 错误 flag:"+flag+" 不存在");
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
const timelen = process.hrtime(start as any as [number,number]);
|
|
235
|
-
|
|
236
|
-
const totalMicroseconds = (timelen[0] * 1e9 + timelen[1]) / 1000;
|
|
237
|
-
const microseconds = totalMicroseconds % 1000;
|
|
238
|
-
const totalMilliseconds = totalMicroseconds / 1000;
|
|
239
|
-
const milliseconds = Math.floor(totalMilliseconds % 1000);
|
|
240
|
-
const totalSeconds = totalMilliseconds / 1000;
|
|
241
|
-
const seconds = Math.floor(totalSeconds % 60);
|
|
242
|
-
const totalMinutes = totalSeconds / 60;
|
|
243
|
-
const minutes = Math.floor(totalMinutes % 60);
|
|
244
|
-
const totalHours = totalMinutes / 60;
|
|
245
|
-
const hours = Math.floor(totalHours % 24);
|
|
246
|
-
const totalDay = totalHours / 24;
|
|
247
|
-
const Days = Math.floor(totalDay);
|
|
248
|
-
|
|
249
|
-
let out = '';
|
|
250
|
-
if(totalSeconds>60){
|
|
251
|
-
let result = '';
|
|
252
|
-
let format = '';
|
|
253
|
-
let acc = 0;
|
|
254
|
-
const maxAcc = 3;
|
|
255
|
-
|
|
256
|
-
let concat = function(num:number,sep:string,
|
|
257
|
-
formatText:string,resultText:string):void{
|
|
258
|
-
let hasResult = result.length>0;
|
|
259
|
-
let need = (hasResult || num>0) && (acc < maxAcc);
|
|
260
|
-
if(need){
|
|
261
|
-
if(result.length>0) result+=sep;
|
|
262
|
-
if(format.length>0) format+=sep;
|
|
263
|
-
result += resultText;
|
|
264
|
-
format += formatText;
|
|
265
|
-
acc++;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
concat(Days,':','dd',
|
|
269
|
-
`${Days.toString()}`);
|
|
270
|
-
concat(hours,':','HH',
|
|
271
|
-
`${hours.toString().padStart(2, '0')}`);
|
|
272
|
-
concat(minutes,':','mm',
|
|
273
|
-
`${minutes.toString().padStart(2, '0')}`);
|
|
274
|
-
concat(seconds,':','ss',
|
|
275
|
-
`${seconds.toString().padStart(2, '0')}`);
|
|
276
|
-
concat(milliseconds,'.','mmm',
|
|
277
|
-
`${milliseconds.toString().padStart(3, '0')}`);
|
|
278
|
-
//result = result.replace(/^(0(?![^0-9]))+/, '');
|
|
279
|
-
result = result.replace(/^0+([0-9])/,"$1");
|
|
280
|
-
out = `${result} (${format})`;
|
|
281
|
-
}else if(totalMilliseconds>1000){
|
|
282
|
-
out = `${totalSeconds.toFixed(3)}s`
|
|
283
|
-
}else{
|
|
284
|
-
out = `${totalMilliseconds.toFixed(3)}ms`
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if(level!==null)
|
|
288
|
-
this.log(level,flag+": "+out);
|
|
289
|
-
delete SLogger.timeTable[flag];
|
|
290
|
-
return out;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
//———————————————————— static ——————————————————————//
|
|
296
|
-
/**名称为default的slogger实例 */
|
|
297
|
-
private static get defaultInstance():SLogger{
|
|
298
|
-
if(SLogger.loggerTable.default==null)
|
|
299
|
-
SLogger.createLogger();
|
|
300
|
-
return SLogger.loggerTable.default;
|
|
301
|
-
}
|
|
302
|
-
/**让名称为default的logger 产生一条对应等级的log 返回自身
|
|
303
|
-
* @param
|
|
304
|
-
* @param
|
|
305
|
-
* @returns
|
|
306
|
-
*/
|
|
307
|
-
static log(level: LogLevel, ...messages:Array<any>):SLogger{
|
|
308
|
-
level = level||"silly";
|
|
309
|
-
this.defaultInstance.log(level,...messages);
|
|
310
|
-
return this.defaultInstance;
|
|
311
|
-
}
|
|
312
|
-
/**让名称为default的logger 产生一条fatal等级的log 返回自身
|
|
313
|
-
* @param
|
|
314
|
-
* @returns
|
|
315
|
-
*/
|
|
316
|
-
static fatal(...messages:Array<any>):SLogger {
|
|
317
|
-
return this.log("fatal",...messages);;
|
|
318
|
-
}
|
|
319
|
-
/**让名称为default的logger 产生一条error等级的log 返回自身
|
|
320
|
-
* @param
|
|
321
|
-
* @returns
|
|
322
|
-
*/
|
|
323
|
-
static error(...messages:Array<any>):SLogger {
|
|
324
|
-
return this.log("error",...messages);;
|
|
325
|
-
}
|
|
326
|
-
/**让名称为default的logger 产生一条warn等级的log 返回自身
|
|
327
|
-
* @param
|
|
328
|
-
* @returns
|
|
329
|
-
*/
|
|
330
|
-
static warn(...messages:Array<any>):SLogger {
|
|
331
|
-
return this.log("warn",...messages);;
|
|
332
|
-
}
|
|
333
|
-
/**让名称为default的logger 产生一条info等级的log 返回自身
|
|
334
|
-
* @param
|
|
335
|
-
* @returns
|
|
336
|
-
*/
|
|
337
|
-
static info(...messages:Array<any>):SLogger {
|
|
338
|
-
return this.log("info",...messages);
|
|
339
|
-
}
|
|
340
|
-
/**让名称为default的logger 产生一条http等级的log 返回自身
|
|
341
|
-
* @param
|
|
342
|
-
* @returns
|
|
343
|
-
*/
|
|
344
|
-
static http(...messages:Array<any>):SLogger {
|
|
345
|
-
return this.log("http",...messages);
|
|
346
|
-
}
|
|
347
|
-
/**让名称为default的logger 产生一条verbose等级的log 返回自身
|
|
348
|
-
* @param
|
|
349
|
-
* @returns
|
|
350
|
-
*/
|
|
351
|
-
static verbose(...messages:Array<any>):SLogger {
|
|
352
|
-
return this.log("verbose",...messages);
|
|
353
|
-
}
|
|
354
|
-
/**让名称为default的logger 产生一条debug等级的log 返回自身
|
|
355
|
-
* @param
|
|
356
|
-
* @returns
|
|
357
|
-
*/
|
|
358
|
-
static debug(...messages:Array<any>):SLogger {
|
|
359
|
-
return this.log("debug",...messages);
|
|
360
|
-
}
|
|
361
|
-
/**让名称为default的logger 产生一条silly等级的log 返回自身
|
|
362
|
-
* @param
|
|
363
|
-
* @returns
|
|
364
|
-
*/
|
|
365
|
-
static silly(...messages:Array<any>):SLogger {
|
|
366
|
-
return this.log("silly",...messages);
|
|
367
|
-
}
|
|
368
|
-
/**让名称为default的logger 记录当前时间戳并存入表
|
|
369
|
-
* @param
|
|
370
|
-
* @returns
|
|
371
|
-
*/
|
|
372
|
-
static time(flag:string):HRTimeLog{
|
|
373
|
-
return this.defaultInstance.time(flag);
|
|
374
|
-
}
|
|
375
|
-
/**让名称为default的logger 根据之前记录的时间戳计算经过的时间 并输出log
|
|
376
|
-
* @param
|
|
377
|
-
* @param
|
|
378
|
-
* @returns
|
|
379
|
-
*/
|
|
380
|
-
static timeEnd(flag:string,level:LogLevel="info"):void{
|
|
381
|
-
this.defaultInstance.timeEnd(flag,level);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import * as winston from 'winston';
|
|
3
|
+
import * as DailyRotateFile from 'winston-daily-rotate-file';
|
|
4
|
+
import {inspect} from 'util';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**hrtime所产生的的记录 */
|
|
9
|
+
export type HRTimeLog = {
|
|
10
|
+
/**秒数 */
|
|
11
|
+
0:number;
|
|
12
|
+
/**纳秒数 */
|
|
13
|
+
1:number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**log等级 undefined相当于 silly */
|
|
17
|
+
export type LogLevel = "fatal"|"error"|"warn"|"info"|"http"|"verbose"|"debug"|"silly"|undefined;
|
|
18
|
+
const logLevels = {
|
|
19
|
+
fatal: 0,
|
|
20
|
+
error: 1,
|
|
21
|
+
warn: 2,
|
|
22
|
+
info: 3,
|
|
23
|
+
http: 4,
|
|
24
|
+
verbose: 5,
|
|
25
|
+
debug: 6,
|
|
26
|
+
silly: 7
|
|
27
|
+
};
|
|
28
|
+
const colorizer = winston.format.colorize();
|
|
29
|
+
colorizer.addColors({
|
|
30
|
+
fatal: 'bold yellow redBG',
|
|
31
|
+
error: 'bold yellow',
|
|
32
|
+
warn: 'yellow',
|
|
33
|
+
info: 'white',
|
|
34
|
+
debug: 'bold cyan',
|
|
35
|
+
silly: 'bold magenta'
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
export class SLogger{
|
|
40
|
+
/**获取一个Logger,如不存在则用默认参数创建
|
|
41
|
+
* @param name - logger的名称 默认default
|
|
42
|
+
* @returns 获取的logger
|
|
43
|
+
*/
|
|
44
|
+
static getLogger(name:string="default"):SLogger{
|
|
45
|
+
let out = SLogger.loggerTable[name];
|
|
46
|
+
if(out==null){
|
|
47
|
+
SLogger.createLogger(name);
|
|
48
|
+
out = SLogger.loggerTable[name];
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/**创建Logger
|
|
53
|
+
* @param name - logger的名称 默认default
|
|
54
|
+
* @param consoleLevel - 输出到控制台的最低等级 默认info
|
|
55
|
+
* @param outFloder - log的输出文件夹路径 如./log/
|
|
56
|
+
* @param fileLevel - 输出到文件的最低等级 默认info
|
|
57
|
+
* @returns 创建完成的logger
|
|
58
|
+
*/
|
|
59
|
+
static createLogger(name:string="default",consoleLevel:LogLevel="info",outFloder?:string,fileLevel:LogLevel="info"):SLogger{
|
|
60
|
+
const transports:winston.transport[]=[];
|
|
61
|
+
if(outFloder!=null){
|
|
62
|
+
const fileFormat = winston.format.combine(
|
|
63
|
+
winston.format.timestamp({ format: 'HH:mm:ss' }),
|
|
64
|
+
winston.format.printf((info) => {
|
|
65
|
+
const level = info.level.toUpperCase();
|
|
66
|
+
const message = info.message as string;
|
|
67
|
+
//格式化
|
|
68
|
+
//let format = `[${info.timestamp}] [${level}]: `
|
|
69
|
+
//let space = " ".repeat(format.length);
|
|
70
|
+
let messageList = message.split("\n");
|
|
71
|
+
return `[${info.timestamp}] [${level.toUpperCase()}]: ${messageList.join("\n")}`
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
74
|
+
transports.push(new DailyRotateFile({
|
|
75
|
+
filename: path.join(outFloder,'log-%DATE%.txt'),
|
|
76
|
+
datePattern: 'YYYY-MM-DD',
|
|
77
|
+
level:fileLevel,
|
|
78
|
+
format:fileFormat,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
const consoleFormat = winston.format.combine(
|
|
82
|
+
winston.format.timestamp({ format: 'HH:mm:ss' }),
|
|
83
|
+
winston.format.printf((info) => {
|
|
84
|
+
const level = info.level.toUpperCase();
|
|
85
|
+
const message = info.message as string;
|
|
86
|
+
const colorizedLevel = colorizer.colorize(info.level, level);
|
|
87
|
+
//格式化
|
|
88
|
+
//let format = `[${info.timestamp}] [${level}]: `
|
|
89
|
+
//let space = " ".repeat(format.length);
|
|
90
|
+
let messageList = message.split("\n");
|
|
91
|
+
messageList[0]=colorizer.colorize(info.level, messageList[0])
|
|
92
|
+
for(let i=1;i<messageList.length;i++)
|
|
93
|
+
messageList[i]=colorizer.colorize(info.level, messageList[i]);
|
|
94
|
+
return `[${info.timestamp}] [${colorizedLevel}]: ${messageList.join("\n")}`;
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
transports.push(new winston.transports.Console({
|
|
98
|
+
level: consoleLevel,
|
|
99
|
+
format:consoleFormat,
|
|
100
|
+
}));
|
|
101
|
+
const logger = winston.createLogger({
|
|
102
|
+
levels:logLevels,
|
|
103
|
+
transports: transports,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const out = new SLogger();
|
|
107
|
+
out._logger = logger;
|
|
108
|
+
|
|
109
|
+
if(SLogger.loggerTable[name]!=null){
|
|
110
|
+
let old = SLogger.loggerTable[name];
|
|
111
|
+
old._logger.transports.forEach(tp=>{
|
|
112
|
+
if(tp.close!=null) tp.close();
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
SLogger.loggerTable[name] = out;
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
private constructor(){}
|
|
120
|
+
private _logger:winston.Logger = null as any as winston.Logger;
|
|
121
|
+
/**记录Logger的表 */
|
|
122
|
+
private static readonly loggerTable:Record<string,SLogger> = {};
|
|
123
|
+
/**记录Logger的表 */
|
|
124
|
+
private static readonly timeTable:Record<string,HRTimeLog> = {};
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
//———————————————————— function ——————————————————————//
|
|
129
|
+
/**产生一条对应等级的log 返回自身
|
|
130
|
+
* @param level - log等级
|
|
131
|
+
* @param messages - log消息
|
|
132
|
+
* @returns 自身
|
|
133
|
+
*/
|
|
134
|
+
log(level:LogLevel,...messages:Array<any>):SLogger{
|
|
135
|
+
level = level||"silly";
|
|
136
|
+
let strMessages:Array<string> = [];
|
|
137
|
+
//上一条是字符串字符串
|
|
138
|
+
let preIsString = true;
|
|
139
|
+
for(let message of messages){
|
|
140
|
+
let out:string;
|
|
141
|
+
//非string类型
|
|
142
|
+
if(typeof message!=="string"){
|
|
143
|
+
out=`<${typeof message}> ${inspect(message)}`;
|
|
144
|
+
preIsString=false;
|
|
145
|
+
}else if(!preIsString){
|
|
146
|
+
//如果上一条不是字符串则需要添加<string>类型标记
|
|
147
|
+
out = `<${typeof message}> ${inspect(message)}`;
|
|
148
|
+
preIsString=true;
|
|
149
|
+
}else{
|
|
150
|
+
out = message;
|
|
151
|
+
}
|
|
152
|
+
strMessages.push(out);
|
|
153
|
+
}
|
|
154
|
+
let outMessage = strMessages.join("\n");
|
|
155
|
+
this._logger.log(level,outMessage);
|
|
156
|
+
return this;
|
|
157
|
+
}
|
|
158
|
+
/**产生一条fatal等级的log 返回自身
|
|
159
|
+
* @param messages - log消息
|
|
160
|
+
* @returns 自身
|
|
161
|
+
*/
|
|
162
|
+
fatal(...messages:Array<any>):SLogger {
|
|
163
|
+
return this.log("fatal",...messages);;
|
|
164
|
+
}
|
|
165
|
+
/**产生一条error等级的log 返回自身
|
|
166
|
+
* @param messages - log消息
|
|
167
|
+
* @returns 自身
|
|
168
|
+
*/
|
|
169
|
+
error(...messages:Array<any>):SLogger {
|
|
170
|
+
return this.log("error",...messages);;
|
|
171
|
+
}
|
|
172
|
+
/**产生一条warn等级的log 返回自身
|
|
173
|
+
* @param messages - log消息
|
|
174
|
+
* @returns 自身
|
|
175
|
+
*/
|
|
176
|
+
warn(...messages:Array<any>):SLogger {
|
|
177
|
+
return this.log("warn",...messages);;
|
|
178
|
+
}
|
|
179
|
+
/**产生一条info等级的log 返回自身
|
|
180
|
+
* @param messages - log消息
|
|
181
|
+
* @returns 自身
|
|
182
|
+
*/
|
|
183
|
+
info(...messages:Array<any>):SLogger {
|
|
184
|
+
return this.log("info",...messages);
|
|
185
|
+
}
|
|
186
|
+
/**产生一条http等级的log 返回自身
|
|
187
|
+
* @param messages - log消息
|
|
188
|
+
* @returns 自身
|
|
189
|
+
*/
|
|
190
|
+
http(...messages:Array<any>):SLogger {
|
|
191
|
+
return this.log("http",...messages);
|
|
192
|
+
}
|
|
193
|
+
/**产生一条verbose等级的log 返回自身
|
|
194
|
+
* @param messages - log消息
|
|
195
|
+
* @returns 自身
|
|
196
|
+
*/
|
|
197
|
+
verbose(...messages:Array<any>):SLogger {
|
|
198
|
+
return this.log("verbose",...messages);
|
|
199
|
+
}
|
|
200
|
+
/**产生一条debug等级的log 返回自身
|
|
201
|
+
* @param messages - log消息
|
|
202
|
+
* @returns 自身
|
|
203
|
+
*/
|
|
204
|
+
debug(...messages:Array<any>):SLogger {
|
|
205
|
+
return this.log("debug",...messages);
|
|
206
|
+
}
|
|
207
|
+
/**产生一条silly等级的log 返回自身
|
|
208
|
+
* @param messages - log消息
|
|
209
|
+
* @returns 自身
|
|
210
|
+
*/
|
|
211
|
+
silly(...messages:Array<any>):SLogger {
|
|
212
|
+
return this.log("silly",...messages);
|
|
213
|
+
}
|
|
214
|
+
/**记录当前时间戳并存入表
|
|
215
|
+
* @param flag - 记录的命名
|
|
216
|
+
* @returns 记录的时间
|
|
217
|
+
*/
|
|
218
|
+
time(flag:string):HRTimeLog{
|
|
219
|
+
let hrtime = process.hrtime();
|
|
220
|
+
SLogger.timeTable[flag]=hrtime;
|
|
221
|
+
return hrtime;
|
|
222
|
+
}
|
|
223
|
+
/**根据之前记录的时间戳计算经过的时间 并输出log
|
|
224
|
+
* @param flag - 记录的命名
|
|
225
|
+
* @param level - log等级 === null时不产生log
|
|
226
|
+
* @returns 格式化的时间字符串
|
|
227
|
+
*/
|
|
228
|
+
timeEnd(flag:string,level:LogLevel|null="info"):string|null{
|
|
229
|
+
let start = SLogger.timeTable[flag];
|
|
230
|
+
if(start==null){
|
|
231
|
+
this.warn("SLogger.timeEnd 错误 flag:"+flag+" 不存在");
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
const timelen = process.hrtime(start as any as [number,number]);
|
|
235
|
+
|
|
236
|
+
const totalMicroseconds = (timelen[0] * 1e9 + timelen[1]) / 1000;
|
|
237
|
+
const microseconds = totalMicroseconds % 1000;
|
|
238
|
+
const totalMilliseconds = totalMicroseconds / 1000;
|
|
239
|
+
const milliseconds = Math.floor(totalMilliseconds % 1000);
|
|
240
|
+
const totalSeconds = totalMilliseconds / 1000;
|
|
241
|
+
const seconds = Math.floor(totalSeconds % 60);
|
|
242
|
+
const totalMinutes = totalSeconds / 60;
|
|
243
|
+
const minutes = Math.floor(totalMinutes % 60);
|
|
244
|
+
const totalHours = totalMinutes / 60;
|
|
245
|
+
const hours = Math.floor(totalHours % 24);
|
|
246
|
+
const totalDay = totalHours / 24;
|
|
247
|
+
const Days = Math.floor(totalDay);
|
|
248
|
+
|
|
249
|
+
let out = '';
|
|
250
|
+
if(totalSeconds>60){
|
|
251
|
+
let result = '';
|
|
252
|
+
let format = '';
|
|
253
|
+
let acc = 0;
|
|
254
|
+
const maxAcc = 3;
|
|
255
|
+
|
|
256
|
+
let concat = function(num:number,sep:string,
|
|
257
|
+
formatText:string,resultText:string):void{
|
|
258
|
+
let hasResult = result.length>0;
|
|
259
|
+
let need = (hasResult || num>0) && (acc < maxAcc);
|
|
260
|
+
if(need){
|
|
261
|
+
if(result.length>0) result+=sep;
|
|
262
|
+
if(format.length>0) format+=sep;
|
|
263
|
+
result += resultText;
|
|
264
|
+
format += formatText;
|
|
265
|
+
acc++;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
concat(Days,':','dd',
|
|
269
|
+
`${Days.toString()}`);
|
|
270
|
+
concat(hours,':','HH',
|
|
271
|
+
`${hours.toString().padStart(2, '0')}`);
|
|
272
|
+
concat(minutes,':','mm',
|
|
273
|
+
`${minutes.toString().padStart(2, '0')}`);
|
|
274
|
+
concat(seconds,':','ss',
|
|
275
|
+
`${seconds.toString().padStart(2, '0')}`);
|
|
276
|
+
concat(milliseconds,'.','mmm',
|
|
277
|
+
`${milliseconds.toString().padStart(3, '0')}`);
|
|
278
|
+
//result = result.replace(/^(0(?![^0-9]))+/, '');
|
|
279
|
+
result = result.replace(/^0+([0-9])/,"$1");
|
|
280
|
+
out = `${result} (${format})`;
|
|
281
|
+
}else if(totalMilliseconds>1000){
|
|
282
|
+
out = `${totalSeconds.toFixed(3)}s`
|
|
283
|
+
}else{
|
|
284
|
+
out = `${totalMilliseconds.toFixed(3)}ms`
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if(level!==null)
|
|
288
|
+
this.log(level,flag+": "+out);
|
|
289
|
+
delete SLogger.timeTable[flag];
|
|
290
|
+
return out;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
//———————————————————— static ——————————————————————//
|
|
296
|
+
/**名称为default的slogger实例 */
|
|
297
|
+
private static get defaultInstance():SLogger{
|
|
298
|
+
if(SLogger.loggerTable.default==null)
|
|
299
|
+
SLogger.createLogger();
|
|
300
|
+
return SLogger.loggerTable.default;
|
|
301
|
+
}
|
|
302
|
+
/**让名称为default的logger 产生一条对应等级的log 返回自身
|
|
303
|
+
* @param level - log等级
|
|
304
|
+
* @param messages - log消息
|
|
305
|
+
* @returns 自身
|
|
306
|
+
*/
|
|
307
|
+
static log(level: LogLevel, ...messages:Array<any>):SLogger{
|
|
308
|
+
level = level||"silly";
|
|
309
|
+
this.defaultInstance.log(level,...messages);
|
|
310
|
+
return this.defaultInstance;
|
|
311
|
+
}
|
|
312
|
+
/**让名称为default的logger 产生一条fatal等级的log 返回自身
|
|
313
|
+
* @param messages - log消息
|
|
314
|
+
* @returns 自身
|
|
315
|
+
*/
|
|
316
|
+
static fatal(...messages:Array<any>):SLogger {
|
|
317
|
+
return this.log("fatal",...messages);;
|
|
318
|
+
}
|
|
319
|
+
/**让名称为default的logger 产生一条error等级的log 返回自身
|
|
320
|
+
* @param messages - log消息
|
|
321
|
+
* @returns 自身
|
|
322
|
+
*/
|
|
323
|
+
static error(...messages:Array<any>):SLogger {
|
|
324
|
+
return this.log("error",...messages);;
|
|
325
|
+
}
|
|
326
|
+
/**让名称为default的logger 产生一条warn等级的log 返回自身
|
|
327
|
+
* @param messages - log消息
|
|
328
|
+
* @returns 自身
|
|
329
|
+
*/
|
|
330
|
+
static warn(...messages:Array<any>):SLogger {
|
|
331
|
+
return this.log("warn",...messages);;
|
|
332
|
+
}
|
|
333
|
+
/**让名称为default的logger 产生一条info等级的log 返回自身
|
|
334
|
+
* @param messages - log消息
|
|
335
|
+
* @returns 自身
|
|
336
|
+
*/
|
|
337
|
+
static info(...messages:Array<any>):SLogger {
|
|
338
|
+
return this.log("info",...messages);
|
|
339
|
+
}
|
|
340
|
+
/**让名称为default的logger 产生一条http等级的log 返回自身
|
|
341
|
+
* @param messages - log消息
|
|
342
|
+
* @returns 自身
|
|
343
|
+
*/
|
|
344
|
+
static http(...messages:Array<any>):SLogger {
|
|
345
|
+
return this.log("http",...messages);
|
|
346
|
+
}
|
|
347
|
+
/**让名称为default的logger 产生一条verbose等级的log 返回自身
|
|
348
|
+
* @param messages - log消息
|
|
349
|
+
* @returns 自身
|
|
350
|
+
*/
|
|
351
|
+
static verbose(...messages:Array<any>):SLogger {
|
|
352
|
+
return this.log("verbose",...messages);
|
|
353
|
+
}
|
|
354
|
+
/**让名称为default的logger 产生一条debug等级的log 返回自身
|
|
355
|
+
* @param messages - log消息
|
|
356
|
+
* @returns 自身
|
|
357
|
+
*/
|
|
358
|
+
static debug(...messages:Array<any>):SLogger {
|
|
359
|
+
return this.log("debug",...messages);
|
|
360
|
+
}
|
|
361
|
+
/**让名称为default的logger 产生一条silly等级的log 返回自身
|
|
362
|
+
* @param messages - log消息
|
|
363
|
+
* @returns 自身
|
|
364
|
+
*/
|
|
365
|
+
static silly(...messages:Array<any>):SLogger {
|
|
366
|
+
return this.log("silly",...messages);
|
|
367
|
+
}
|
|
368
|
+
/**让名称为default的logger 记录当前时间戳并存入表
|
|
369
|
+
* @param flag - 记录的命名
|
|
370
|
+
* @returns 记录的时间
|
|
371
|
+
*/
|
|
372
|
+
static time(flag:string):HRTimeLog{
|
|
373
|
+
return this.defaultInstance.time(flag);
|
|
374
|
+
}
|
|
375
|
+
/**让名称为default的logger 根据之前记录的时间戳计算经过的时间 并输出log
|
|
376
|
+
* @param flag - 记录的命名
|
|
377
|
+
* @param level - log等级
|
|
378
|
+
* @returns
|
|
379
|
+
*/
|
|
380
|
+
static timeEnd(flag:string,level:LogLevel="info"):void{
|
|
381
|
+
this.defaultInstance.timeEnd(flag,level);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
|