@rife/logger 0.0.5-beta.8 → 0.0.6-beta.1

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/env.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const isProd: () => boolean;
2
+ export declare const isDev: () => boolean;
package/dist/env.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ isDev: function() {
13
+ return isDev;
14
+ },
15
+ isProd: function() {
16
+ return isProd;
17
+ }
18
+ });
19
+ const isProd = ()=>process.env.NODE_ENV === 'production';
20
+ const isDev = ()=>!isProd();
21
+
22
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/env.ts"],"sourcesContent":["export const isProd = () => process.env.NODE_ENV === 'production';\n\nexport const isDev = () => !isProd();\n"],"names":["isDev","isProd","process","env","NODE_ENV"],"mappings":";;;;;;;;;;;IAEaA,KAAK;eAALA;;IAFAC,MAAM;eAANA;;;AAAN,MAAMA,SAAS,IAAMC,QAAQC,GAAG,CAACC,QAAQ,KAAK;AAE9C,MAAMJ,QAAQ,IAAM,CAACC"}
package/dist/index.d.ts CHANGED
@@ -1,54 +1 @@
1
- import winston from 'winston';
2
- import 'winston-daily-rotate-file';
3
- export type { winston };
4
- export declare const getNewTraceId: (size?: number | undefined) => string;
5
- export declare function runInTrace<T>(fn: (...args: any[]) => T): T;
6
- export declare function getTraceId(): any;
7
- export declare namespace Logger {
8
- interface Options {
9
- /**
10
- * 输出日志到console
11
- * 默认:development环境下输出,production环境下不输出
12
- */
13
- writeToConsole?: boolean;
14
- /**
15
- * 输出日志到文件
16
- * 默认:development环境下输出,production环境下不输出
17
- */
18
- writeToFile?: boolean;
19
- /**
20
- * 输出日志的文件目录
21
- * 默认:./logs/
22
- */
23
- dirname?: string;
24
- /**
25
- * 输出日志的文件名
26
- * 默认:server
27
- */
28
- filename?: string;
29
- /**
30
- * 日志输出格式
31
- */
32
- format?: {
33
- /**
34
- * 显示时间
35
- * 默认:true
36
- */
37
- time?: boolean;
38
- /**
39
- * 显示traceId
40
- * 默认:true
41
- */
42
- traceId?: boolean;
43
- };
44
- }
45
- }
46
- export interface Logger {
47
- info: winston.LeveledLogMethod;
48
- warn: winston.LeveledLogMethod;
49
- error: winston.LeveledLogMethod;
50
- setMetaData: (data: any) => void;
51
- }
52
- export declare function createLogger(options?: Logger.Options): {
53
- logger: Logger;
54
- };
1
+ export * from './trace';
package/dist/index.js CHANGED
@@ -1,131 +1,8 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createLogger = exports.getTraceId = exports.runInTrace = exports.getNewTraceId = void 0;
4
- const tslib_1 = require("tslib");
5
- const path_1 = tslib_1.__importDefault(require("path"));
6
- const async_hooks_1 = require("async_hooks");
7
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
8
- const nanoid_1 = require("nanoid");
9
- const winston_1 = tslib_1.__importDefault(require("winston"));
10
- const safe_stable_stringify_1 = tslib_1.__importDefault(require("safe-stable-stringify"));
11
- require("winston-daily-rotate-file");
12
- const als = new async_hooks_1.AsyncLocalStorage();
13
- const isDev = () => process.env.NODE_ENV === 'development';
14
- const isProd = () => !isDev();
15
- // https://github.com/CyberAP/nanoid-dictionary/blob/master/src/nolookalikes.js
16
- exports.getNewTraceId = (0, nanoid_1.customAlphabet)('346789ABCDEFGHJKLMNPQRTUVWXYabcdefghijkmnpqrtwxyz', 5);
17
- function runInTrace(fn) {
18
- return als.run({ traceId: (0, exports.getNewTraceId)() }, fn);
19
- }
20
- exports.runInTrace = runInTrace;
21
- function getTraceId() {
22
- return als.getStore()?.traceId;
23
- }
24
- exports.getTraceId = getTraceId;
25
- const levelColor = {
26
- info: chalk_1.default.green,
27
- error: chalk_1.default.redBright,
28
- warn: chalk_1.default.yellow,
29
- };
30
- const levelSymbolMap = {
31
- info: 'INF',
32
- warn: 'WRN',
33
- error: 'ERR',
34
- };
35
- // 设置traceId
36
- // https://www.npmjs.com/package/cls-rtracer
37
- const tracerFormat = (options) => winston_1.default.format.printf(info => {
38
- let traceId = getTraceId();
39
- const color = (message, chalk) => (options.writeToFile ? message : chalk(message));
40
- const levelit = (text) => {
41
- switch (info.level) {
42
- case 'info': {
43
- return color(text, levelColor.info);
44
- }
45
- case 'warn': {
46
- return color(text, levelColor.warn);
47
- }
48
- case 'error': {
49
- return color(text, levelColor.error);
50
- }
51
- }
52
- return text;
53
- };
54
- const levelSymbol = levelSymbolMap[info.level];
55
- const level = levelSymbol ? levelit(` [${levelSymbol}]`) : '';
56
- const service = info.metadata.service ? levelit(` [${info.metadata.service}]`) : '';
57
- const timestamp = options.format.time ? color(info.timestamp, chalk_1.default.gray) : '';
58
- const trace = traceId ? color(` [${traceId}]`, chalk_1.default.gray) : '';
59
- let message = info.message || '';
60
- if (typeof info?.message !== 'string') {
61
- try {
62
- if (isDev()) {
63
- message = '\n' + (0, safe_stable_stringify_1.default)(info?.message, undefined, 4);
64
- }
65
- else {
66
- message = (0, safe_stable_stringify_1.default)(info?.message, undefined, 0);
67
- }
68
- }
69
- catch (e) {
70
- message = 'fail to stringify json';
71
- }
72
- }
73
- message = ' ' + message;
74
- const stack = info.metadata.stack ? color('\n' + info.metadata.stack + '\n', chalk_1.default.gray) : '';
75
- return `${timestamp}${trace}${level}${service}${message}${stack}`;
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
76
4
  });
77
- function createLogger(options) {
78
- let transports = [];
79
- let config = {
80
- writeToConsole: options?.writeToConsole ?? isDev(),
81
- writeToFile: options?.writeToFile ?? isProd(),
82
- dirname: options?.dirname || path_1.default.join(process.cwd(), './logs/'),
83
- filename: options?.filename || 'server',
84
- format: {
85
- time: options?.format?.time ?? true,
86
- },
87
- };
88
- if (config.writeToFile) {
89
- transports.push(new winston_1.default.transports.DailyRotateFile({
90
- // https://www.npmjs.com/package/winston-daily-rotate-file
91
- filename: config.filename,
92
- dirname: config.dirname,
93
- datePattern: 'YYYY-MM-DD',
94
- maxFiles: '30d',
95
- extension: '.log',
96
- }));
97
- }
98
- if (config.writeToConsole) {
99
- transports.push(new winston_1.default.transports.Console());
100
- }
101
- const { combine, timestamp, colorize, errors, metadata, splat } = winston_1.default.format;
102
- const timeFormat = isProd() ? 'YYYY-MM-DD HH:mm:ss.SSS' : 'HH:mm:ss.SSS';
103
- let format = [
104
- errors({ stack: true }),
105
- metadata(),
106
- timestamp({ format: timeFormat }),
107
- splat(),
108
- tracerFormat(config),
109
- ];
110
- if (!config.writeToFile) {
111
- format.push(colorize());
112
- }
113
- const instance = winston_1.default.createLogger({
114
- format: combine(...format),
115
- transports,
116
- });
117
- const setMetaData = (data) => {
118
- instance.defaultMeta = {
119
- ...instance.defaultMeta,
120
- ...data,
121
- };
122
- };
123
- const logger = {
124
- info: instance.info.bind(instance),
125
- warn: instance.warn.bind(instance),
126
- error: instance.error.bind(instance),
127
- setMetaData,
128
- };
129
- return { logger };
130
- }
131
- exports.createLogger = createLogger;
5
+ const _export_star = require("@swc/helpers/_/_export_star");
6
+ _export_star._(require("./trace"), exports);
7
+
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './trace';\n"],"names":[],"mappings":";;;;;uBAAc"}
package/dist/pino.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export declare namespace ILogger {
2
+ interface Options {
3
+ }
4
+ }
5
+ export declare function createLogger(options?: ILogger.Options): {
6
+ logger: import("pino").Logger<never, boolean>;
7
+ express: () => (req: any, res: any, next: any) => void;
8
+ };
package/dist/pino.js ADDED
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "createLogger", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return createLogger;
9
+ }
10
+ });
11
+ const _interop_require_default = require("@swc/helpers/_/_interop_require_default");
12
+ const _pino = /*#__PURE__*/ _interop_require_default._(require("pino"));
13
+ const _env = require("./env");
14
+ const _trace = require("./trace");
15
+ function getPinoConfig() {
16
+ const targets = [];
17
+ if ((0, _env.isDev)()) {
18
+ targets.push({
19
+ level: 'debug',
20
+ target: 'pino-pretty',
21
+ options: {}
22
+ });
23
+ }
24
+ targets.push({
25
+ level: 'debug',
26
+ target: './rotate',
27
+ options: {
28
+ path: './.logs/'
29
+ }
30
+ });
31
+ const config = {
32
+ transport: {
33
+ targets
34
+ },
35
+ mixin (data) {
36
+ // {"level":30,"time":1726065716643,"pid":21968,"hostname":"Win-LH"}
37
+ // 基础字段不能重复 删除掉
38
+ delete data.level;
39
+ delete data.time;
40
+ delete data.pid;
41
+ delete data.hostname;
42
+ if (!data?.traceId) {
43
+ return {
44
+ traceId: (0, _trace.getTraceId)()
45
+ };
46
+ }
47
+ return {};
48
+ }
49
+ };
50
+ return config;
51
+ }
52
+ const startTime = Symbol('startTime');
53
+ function createLogger(options) {
54
+ const logger = (0, _pino.default)({
55
+ ...getPinoConfig()
56
+ });
57
+ const express = ()=>{
58
+ const { mapHttpRequest, mapHttpResponse } = require('pino-std-serializers');
59
+ return (req, res, next)=>{
60
+ const response = res;
61
+ response[startTime] = response[startTime] || Date.now();
62
+ const traceId = req.headers['trace-id'] || (0, _trace.genTraceId)();
63
+ const onComplete = ()=>{
64
+ res.removeListener('close', onComplete);
65
+ res.removeListener('finish', onComplete);
66
+ res.removeListener('error', onComplete);
67
+ const duration = Date.now() - response[startTime];
68
+ logger.info({
69
+ duration,
70
+ request: mapHttpRequest(req).req,
71
+ response: mapHttpResponse(res).res
72
+ }, 'request');
73
+ };
74
+ res.on('close', onComplete);
75
+ res.on('finish', onComplete);
76
+ res.on('error', onComplete);
77
+ (0, _trace.runInTrace)({
78
+ traceId
79
+ }, next);
80
+ };
81
+ };
82
+ return {
83
+ logger,
84
+ express
85
+ };
86
+ }
87
+
88
+ //# sourceMappingURL=pino.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pino.ts"],"sourcesContent":["import pino from 'pino';\r\n// https://github.com/pinojs/pino/blob/master/docs/api.md\r\n\r\nimport { isDev } from './env';\r\nimport { genTraceId, getTraceId, runInTrace } from './trace';\r\n\r\nexport namespace ILogger {\r\n export interface Options {}\r\n}\r\n\r\nfunction getPinoConfig() {\r\n const targets: any = [];\r\n\r\n if (isDev()) {\r\n targets.push({\r\n level: 'debug',\r\n target: 'pino-pretty', // must be installed separately,\r\n options: {},\r\n });\r\n }\r\n\r\n targets.push({\r\n level: 'debug',\r\n target: './rotate',\r\n options: { path: './.logs/' },\r\n });\r\n\r\n const config: pino.LoggerOptions = {\r\n transport: { targets },\r\n mixin(data: any) {\r\n // {\"level\":30,\"time\":1726065716643,\"pid\":21968,\"hostname\":\"Win-LH\"}\r\n // 基础字段不能重复 删除掉\r\n delete data.level;\r\n delete data.time;\r\n delete data.pid;\r\n delete data.hostname;\r\n if (!data?.traceId) {\r\n return { traceId: getTraceId() };\r\n }\r\n return {};\r\n },\r\n };\r\n\r\n return config;\r\n}\r\n\r\nconst startTime = Symbol('startTime');\r\n\r\nexport function createLogger(options?: ILogger.Options) {\r\n const logger = pino({\r\n ...getPinoConfig(),\r\n });\r\n\r\n const express = () => {\r\n const { mapHttpRequest, mapHttpResponse } = require('pino-std-serializers') as typeof import('pino-std-serializers');\r\n\r\n return (req: any, res: any, next: any) => {\r\n const response: any = res;\r\n response[startTime] = response[startTime] || Date.now();\r\n const traceId = req.headers['trace-id'] || genTraceId();\r\n\r\n const onComplete = () => {\r\n res.removeListener('close', onComplete);\r\n res.removeListener('finish', onComplete);\r\n res.removeListener('error', onComplete);\r\n const duration = Date.now() - response[startTime];\r\n\r\n logger.info({ duration, request: mapHttpRequest(req).req, response: mapHttpResponse(res).res }, 'request');\r\n };\r\n\r\n res.on('close', onComplete);\r\n res.on('finish', onComplete);\r\n res.on('error', onComplete);\r\n\r\n runInTrace({ traceId }, next);\r\n };\r\n };\r\n\r\n return { logger, express };\r\n}\r\n"],"names":["createLogger","getPinoConfig","targets","isDev","push","level","target","options","path","config","transport","mixin","data","time","pid","hostname","traceId","getTraceId","startTime","Symbol","logger","pino","express","mapHttpRequest","mapHttpResponse","require","req","res","next","response","Date","now","headers","genTraceId","onComplete","removeListener","duration","info","request","on","runInTrace"],"mappings":";;;;+BAgDgBA;;;eAAAA;;;;+DAhDC;qBAGK;uBAC6B;AAMnD,SAASC;IACL,MAAMC,UAAe,EAAE;IAEvB,IAAIC,IAAAA,UAAK,KAAI;QACTD,QAAQE,IAAI,CAAC;YACTC,OAAO;YACPC,QAAQ;YACRC,SAAS,CAAC;QACd;IACJ;IAEAL,QAAQE,IAAI,CAAC;QACTC,OAAO;QACPC,QAAQ;QACRC,SAAS;YAAEC,MAAM;QAAW;IAChC;IAEA,MAAMC,SAA6B;QAC/BC,WAAW;YAAER;QAAQ;QACrBS,OAAMC,IAAS;YACX,oEAAoE;YACpE,eAAe;YACf,OAAOA,KAAKP,KAAK;YACjB,OAAOO,KAAKC,IAAI;YAChB,OAAOD,KAAKE,GAAG;YACf,OAAOF,KAAKG,QAAQ;YACpB,IAAI,CAACH,MAAMI,SAAS;gBAChB,OAAO;oBAAEA,SAASC,IAAAA,iBAAU;gBAAG;YACnC;YACA,OAAO,CAAC;QACZ;IACJ;IAEA,OAAOR;AACX;AAEA,MAAMS,YAAYC,OAAO;AAElB,SAASnB,aAAaO,OAAyB;IAClD,MAAMa,SAASC,IAAAA,aAAI,EAAC;QAChB,GAAGpB,eAAe;IACtB;IAEA,MAAMqB,UAAU;QACZ,MAAM,EAAEC,cAAc,EAAEC,eAAe,EAAE,GAAGC,QAAQ;QAEpD,OAAO,CAACC,KAAUC,KAAUC;YACxB,MAAMC,WAAgBF;YACtBE,QAAQ,CAACX,UAAU,GAAGW,QAAQ,CAACX,UAAU,IAAIY,KAAKC,GAAG;YACrD,MAAMf,UAAUU,IAAIM,OAAO,CAAC,WAAW,IAAIC,IAAAA,iBAAU;YAErD,MAAMC,aAAa;gBACfP,IAAIQ,cAAc,CAAC,SAASD;gBAC5BP,IAAIQ,cAAc,CAAC,UAAUD;gBAC7BP,IAAIQ,cAAc,CAAC,SAASD;gBAC5B,MAAME,WAAWN,KAAKC,GAAG,KAAKF,QAAQ,CAACX,UAAU;gBAEjDE,OAAOiB,IAAI,CAAC;oBAAED;oBAAUE,SAASf,eAAeG,KAAKA,GAAG;oBAAEG,UAAUL,gBAAgBG,KAAKA,GAAG;gBAAC,GAAG;YACpG;YAEAA,IAAIY,EAAE,CAAC,SAASL;YAChBP,IAAIY,EAAE,CAAC,UAAUL;YACjBP,IAAIY,EAAE,CAAC,SAASL;YAEhBM,IAAAA,iBAAU,EAAC;gBAAExB;YAAQ,GAAGY;QAC5B;IACJ;IAEA,OAAO;QAAER;QAAQE;IAAQ;AAC7B"}
@@ -0,0 +1,6 @@
1
+ import type { Options } from 'rotating-file-stream';
2
+ export interface PinoRotatingFileStreamOptions extends Options {
3
+ path: string;
4
+ }
5
+ declare const _default: (options: PinoRotatingFileStreamOptions) => import("rotating-file-stream").RotatingFileStream;
6
+ export default _default;
package/dist/rotate.js ADDED
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _default;
9
+ }
10
+ });
11
+ const generator = (time, index)=>{
12
+ if (!time) {
13
+ return 'server.log';
14
+ }
15
+ time = new Date(time);
16
+ const month = String(time.getMonth() + 1).padStart(2, '0');
17
+ const day = String(time.getDate()).padStart(2, '0');
18
+ if (index) {
19
+ const count = String(index).padStart(3, '0');
20
+ return `server.${time.getFullYear()}${month}${day}-${count}.log`;
21
+ }
22
+ return `server.${time.getFullYear()}${month}${day}.log`;
23
+ };
24
+ const _default = (options)=>{
25
+ const { createStream } = require('rotating-file-stream');
26
+ const { path } = options;
27
+ return createStream(generator, {
28
+ size: '50M',
29
+ maxSize: '500M',
30
+ interval: '1d',
31
+ path
32
+ });
33
+ };
34
+
35
+ //# sourceMappingURL=rotate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rotate.ts"],"sourcesContent":["import type { Options } from 'rotating-file-stream';\n\nexport interface PinoRotatingFileStreamOptions extends Options {\n path: string;\n}\n\nconst generator = (time: number | Date, index?: number) => {\n if (!time) {\n return 'server.log';\n }\n time = new Date(time);\n\n const month = String(time.getMonth() + 1).padStart(2, '0');\n const day = String(time.getDate()).padStart(2, '0');\n if (index) {\n const count = String(index).padStart(3, '0');\n return `server.${time.getFullYear()}${month}${day}-${count}.log`;\n }\n return `server.${time.getFullYear()}${month}${day}.log`;\n};\n\nexport default (options: PinoRotatingFileStreamOptions) => {\n const { createStream } = require('rotating-file-stream') as typeof import('rotating-file-stream');\n\n const { path } = options;\n return createStream(generator, {\n size: '50M',\n maxSize: '500M',\n interval: '1d',\n path,\n });\n};\n"],"names":["generator","time","index","Date","month","String","getMonth","padStart","day","getDate","count","getFullYear","options","createStream","require","path","size","maxSize","interval"],"mappings":";;;;+BAqBA;;;eAAA;;;AAfA,MAAMA,YAAY,CAACC,MAAqBC;IACpC,IAAI,CAACD,MAAM;QACP,OAAO;IACX;IACAA,OAAO,IAAIE,KAAKF;IAEhB,MAAMG,QAAQC,OAAOJ,KAAKK,QAAQ,KAAK,GAAGC,QAAQ,CAAC,GAAG;IACtD,MAAMC,MAAMH,OAAOJ,KAAKQ,OAAO,IAAIF,QAAQ,CAAC,GAAG;IAC/C,IAAIL,OAAO;QACP,MAAMQ,QAAQL,OAAOH,OAAOK,QAAQ,CAAC,GAAG;QACxC,OAAO,CAAC,OAAO,EAAEN,KAAKU,WAAW,KAAKP,QAAQI,IAAI,CAAC,EAAEE,MAAM,IAAI,CAAC;IACpE;IACA,OAAO,CAAC,OAAO,EAAET,KAAKU,WAAW,KAAKP,QAAQI,IAAI,IAAI,CAAC;AAC3D;MAEA,WAAe,CAACI;IACZ,MAAM,EAAEC,YAAY,EAAE,GAAGC,QAAQ;IAEjC,MAAM,EAAEC,IAAI,EAAE,GAAGH;IACjB,OAAOC,aAAab,WAAW;QAC3BgB,MAAM;QACNC,SAAS;QACTC,UAAU;QACVH;IACJ;AACJ"}
package/dist/test.js CHANGED
@@ -1,22 +1,23 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _pino = require("./pino");
6
+ const _trace = require("./trace");
3
7
  process.env.NODE_ENV = 'development';
4
- // process.env.NODE_ENV = 'production';
5
- const _1 = require(".");
6
- const { logger } = (0, _1.createLogger)({ writeToFile: false, writeToConsole: true, format: { time: false } });
7
- const deep = { a: { b: { c: { g: { e: { f: 1 } } } } } };
8
- logger.info('1 %s', { a: 1 });
9
- logger.info('2 %j', deep);
10
- logger.info('3 \n%j', deep);
11
- logger.info('4 %s %s', 1, 2);
12
- logger.info('5 %o', deep);
13
- logger.info(deep);
14
- logger.warn('execed');
15
- logger.error(new Error('not found'));
16
- // import { format } from 'logform';
17
- // const jsonFormat = format.json({ space: 2 });
18
- // const info = jsonFormat.transform({
19
- // level: 'info',
20
- // message: 'my message',
21
- // });
22
- // console.log(info);
8
+ const { logger } = (0, _pino.createLogger)();
9
+ logger.info({
10
+ time: 1,
11
+ level: 1,
12
+ hostname: 1,
13
+ pid: 1,
14
+ c: 2
15
+ }, '123');
16
+ const start = performance.now();
17
+ logger.info({
18
+ duration: performance.now() - start,
19
+ id: (0, _trace.genTraceId)()
20
+ });
21
+ console.log(module);
22
+
23
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/test.ts"],"sourcesContent":["process.env.NODE_ENV = 'development';\n// process.env.NODE_ENV = 'production';\n\nimport { createLogger } from './pino';\nimport { genTraceId } from './trace';\n\nconst { logger } = createLogger();\n\nlogger.info({ time: 1, level: 1, hostname: 1, pid: 1, c: 2 }, '123');\n\nconst start = performance.now();\nlogger.info({ duration: performance.now() - start, id: genTraceId() });\n\nconsole.log(module);\n"],"names":["process","env","NODE_ENV","logger","createLogger","info","time","level","hostname","pid","c","start","performance","now","duration","id","genTraceId","console","log","module"],"mappings":";;;;sBAG6B;uBACF;AAJ3BA,QAAQC,GAAG,CAACC,QAAQ,GAAG;AAMvB,MAAM,EAAEC,MAAM,EAAE,GAAGC,IAAAA,kBAAY;AAE/BD,OAAOE,IAAI,CAAC;IAAEC,MAAM;IAAGC,OAAO;IAAGC,UAAU;IAAGC,KAAK;IAAGC,GAAG;AAAE,GAAG;AAE9D,MAAMC,QAAQC,YAAYC,GAAG;AAC7BV,OAAOE,IAAI,CAAC;IAAES,UAAUF,YAAYC,GAAG,KAAKF;IAAOI,IAAIC,IAAAA,iBAAU;AAAG;AAEpEC,QAAQC,GAAG,CAACC"}
package/dist/trace.d.ts CHANGED
@@ -0,0 +1,3 @@
1
+ export declare function runInTrace<T>(data: any, fn: (...args: any[]) => T): T;
2
+ export declare function genTraceId(): `${string}-${string}-${string}-${string}-${string}`;
3
+ export declare function getTraceId(): any;
package/dist/trace.js CHANGED
@@ -1 +1,35 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ genTraceId: function() {
13
+ return genTraceId;
14
+ },
15
+ getTraceId: function() {
16
+ return getTraceId;
17
+ },
18
+ runInTrace: function() {
19
+ return runInTrace;
20
+ }
21
+ });
22
+ const _async_hooks = require("async_hooks");
23
+ const als = new _async_hooks.AsyncLocalStorage();
24
+ function runInTrace(data, fn) {
25
+ return als.run(data, fn);
26
+ }
27
+ function genTraceId() {
28
+ // crypto 680
29
+ return crypto.randomUUID();
30
+ }
31
+ function getTraceId() {
32
+ return als.getStore()?.traceId;
33
+ }
34
+
35
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/trace.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'async_hooks';\n\nconst als = new AsyncLocalStorage<{ traceId: string } & any>();\n\nexport function runInTrace<T>(data: any, fn: (...args: any[]) => T): T {\n return als.run(data, fn);\n}\n\nexport function genTraceId() {\n // crypto 680\n return crypto.randomUUID();\n}\n\nexport function getTraceId() {\n return als.getStore()?.traceId;\n}\n"],"names":["genTraceId","getTraceId","runInTrace","als","AsyncLocalStorage","data","fn","run","crypto","randomUUID","getStore","traceId"],"mappings":";;;;;;;;;;;IAQgBA,UAAU;eAAVA;;IAKAC,UAAU;eAAVA;;IATAC,UAAU;eAAVA;;;6BAJkB;AAElC,MAAMC,MAAM,IAAIC,8BAAiB;AAE1B,SAASF,WAAcG,IAAS,EAAEC,EAAyB;IAC9D,OAAOH,IAAII,GAAG,CAACF,MAAMC;AACzB;AAEO,SAASN;IACZ,aAAa;IACb,OAAOQ,OAAOC,UAAU;AAC5B;AAEO,SAASR;IACZ,OAAOE,IAAIO,QAAQ,IAAIC;AAC3B"}
package/package.json CHANGED
@@ -1,25 +1,50 @@
1
1
  {
2
2
  "name": "@rife/logger",
3
- "version": "0.0.5-beta.8",
3
+ "version": "0.0.6-beta.1",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./src/index.ts",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./dist/index.js",
10
+ "import": "./dist/index.js",
11
+ "types": "./src/index.ts"
12
+ },
13
+ "./pino": {
14
+ "require": "./dist/pino.js",
15
+ "import": "./dist/pino.js",
16
+ "types": "./src/pino.ts"
17
+ }
18
+ },
19
+ "typesVersions": {
20
+ "*": {
21
+ "pino": [
22
+ "./src/pino.ts"
23
+ ]
24
+ }
25
+ },
7
26
  "files": [
8
27
  "dist/**/*",
9
28
  "src/**/*",
10
29
  "tsconfig.json"
11
30
  ],
31
+ "keywords": [],
32
+ "author": "",
33
+ "license": "ISC",
12
34
  "dependencies": {
13
- "chalk": "4",
14
- "nanoid": "^3.3.6",
15
- "safe-stable-stringify": "^2.4.3",
16
- "winston": "^3.9.0",
17
- "winston-daily-rotate-file": "^4.7.1",
18
- "@rife/config": "0.0.5-beta.8"
35
+ "pino": "^9.6.0",
36
+ "pino-http": "^10.4.0",
37
+ "pino-pretty": "^13.0.0",
38
+ "pino-std-serializers": "^7.0.0",
39
+ "rotating-file-stream": "^3.2.5"
40
+ },
41
+ "devDependencies": {
42
+ "@rife/cli": "0.0.6-beta.1"
19
43
  },
20
44
  "scripts": {
21
- "dev": "infra dev",
22
- "build": "infra build",
23
- "prepublish": "infra build"
45
+ "dev": "rife dev",
46
+ "build": "rife build",
47
+ "lint": "eslint . --fix",
48
+ "release": "pnpm publish --registry https://registry.npmjs.org --no-git-checks"
24
49
  }
25
50
  }
package/src/env.ts ADDED
@@ -0,0 +1,3 @@
1
+ export const isProd = () => process.env.NODE_ENV === 'production';
2
+
3
+ export const isDev = () => !isProd();
package/src/index.ts CHANGED
@@ -1,194 +1 @@
1
- import path from 'path';
2
- import { AsyncLocalStorage } from 'async_hooks';
3
-
4
- import chalk from 'chalk';
5
- import { customAlphabet } from 'nanoid';
6
- import winston from 'winston';
7
- import JSONStringify from 'safe-stable-stringify';
8
- import 'winston-daily-rotate-file';
9
-
10
- export type { winston };
11
-
12
- const als = new AsyncLocalStorage<{ traceId: string } & any>();
13
-
14
- const isDev = () => process.env.NODE_ENV === 'development';
15
- const isProd = () => !isDev();
16
-
17
- // https://github.com/CyberAP/nanoid-dictionary/blob/master/src/nolookalikes.js
18
- export const getNewTraceId = customAlphabet('346789ABCDEFGHJKLMNPQRTUVWXYabcdefghijkmnpqrtwxyz', 5);
19
-
20
- export function runInTrace<T>(fn: (...args: any[]) => T): T {
21
- return als.run({ traceId: getNewTraceId() }, fn);
22
- }
23
-
24
- export function getTraceId() {
25
- return als.getStore()?.traceId;
26
- }
27
-
28
- const levelColor = {
29
- info: chalk.green,
30
- error: chalk.redBright,
31
- warn: chalk.yellow,
32
- };
33
-
34
- const levelSymbolMap = {
35
- info: 'INF',
36
- warn: 'WRN',
37
- error: 'ERR',
38
- };
39
-
40
- // 设置traceId
41
- // https://www.npmjs.com/package/cls-rtracer
42
- const tracerFormat = (options: { writeToFile: boolean; format: { time: boolean } }) =>
43
- winston.format.printf(info => {
44
- let traceId = getTraceId();
45
- const color = (message: string, chalk: chalk.Chalk) => (options.writeToFile ? message : chalk(message));
46
- const levelit = (text: string) => {
47
- switch (info.level) {
48
- case 'info': {
49
- return color(text, levelColor.info);
50
- }
51
- case 'warn': {
52
- return color(text, levelColor.warn);
53
- }
54
- case 'error': {
55
- return color(text, levelColor.error);
56
- }
57
- }
58
- return text;
59
- };
60
- const levelSymbol = levelSymbolMap[info.level as keyof typeof levelSymbolMap];
61
- const level = levelSymbol ? levelit(` [${levelSymbol}]`) : '';
62
- const service = info.metadata.service ? levelit(` [${info.metadata.service}]`) : '';
63
- const timestamp = options.format.time ? color(info.timestamp, chalk.gray) : '';
64
- const trace = traceId ? color(` [${traceId}]`, chalk.gray) : '';
65
- let message = info.message || '';
66
- if (typeof info?.message !== 'string') {
67
- try {
68
- if (isDev()) {
69
- message = '\n' + JSONStringify(info?.message, undefined, 4);
70
- } else {
71
- message = JSONStringify(info?.message, undefined, 0);
72
- }
73
- } catch (e) {
74
- message = 'fail to stringify json';
75
- }
76
- }
77
- message = ' ' + message;
78
- const stack = info.metadata.stack ? color('\n' + info.metadata.stack + '\n', chalk.gray) : '';
79
- return `${timestamp}${trace}${level}${service}${message}${stack}`;
80
- });
81
-
82
- export namespace Logger {
83
- export interface Options {
84
- /**
85
- * 输出日志到console
86
- * 默认:development环境下输出,production环境下不输出
87
- */
88
- writeToConsole?: boolean;
89
-
90
- /**
91
- * 输出日志到文件
92
- * 默认:development环境下输出,production环境下不输出
93
- */
94
- writeToFile?: boolean;
95
-
96
- /**
97
- * 输出日志的文件目录
98
- * 默认:./logs/
99
- */
100
- dirname?: string;
101
-
102
- /**
103
- * 输出日志的文件名
104
- * 默认:server
105
- */
106
- filename?: string;
107
-
108
- /**
109
- * 日志输出格式
110
- */
111
- format?: {
112
- /**
113
- * 显示时间
114
- * 默认:true
115
- */
116
- time?: boolean;
117
-
118
- /**
119
- * 显示traceId
120
- * 默认:true
121
- */
122
- traceId?: boolean;
123
- };
124
- }
125
- }
126
-
127
- export interface Logger {
128
- info: winston.LeveledLogMethod;
129
- warn: winston.LeveledLogMethod;
130
- error: winston.LeveledLogMethod;
131
- setMetaData: (data: any) => void;
132
- }
133
-
134
- export function createLogger(options?: Logger.Options) {
135
- let transports: winston.transport[] = [];
136
- let config = {
137
- writeToConsole: options?.writeToConsole ?? isDev(),
138
- writeToFile: options?.writeToFile ?? isProd(),
139
- dirname: options?.dirname || path.join(process.cwd(), './logs/'),
140
- filename: options?.filename || 'server',
141
- format: {
142
- time: options?.format?.time ?? true,
143
- },
144
- };
145
- if (config.writeToFile) {
146
- transports.push(
147
- new winston.transports.DailyRotateFile({
148
- // https://www.npmjs.com/package/winston-daily-rotate-file
149
- filename: config.filename,
150
- dirname: config.dirname,
151
- datePattern: 'YYYY-MM-DD',
152
- maxFiles: '30d',
153
- extension: '.log',
154
- }),
155
- );
156
- }
157
-
158
- if (config.writeToConsole) {
159
- transports.push(new winston.transports.Console());
160
- }
161
-
162
- const { combine, timestamp, colorize, errors, metadata, splat } = winston.format;
163
- const timeFormat = isProd() ? 'YYYY-MM-DD HH:mm:ss.SSS' : 'HH:mm:ss.SSS';
164
- let format: winston.Logform.Format[] = [
165
- errors({ stack: true }),
166
- metadata(),
167
- timestamp({ format: timeFormat }),
168
- splat(), // https://github.com/winstonjs/logform/blob/master/splat.js
169
- tracerFormat(config),
170
- ];
171
- if (!config.writeToFile) {
172
- format.push(colorize());
173
- }
174
- const instance = winston.createLogger({
175
- format: combine(...format),
176
- transports,
177
- });
178
-
179
- const setMetaData = (data: any) => {
180
- instance.defaultMeta = {
181
- ...instance.defaultMeta,
182
- ...data,
183
- };
184
- };
185
-
186
- const logger: Logger = {
187
- info: instance.info.bind(instance),
188
- warn: instance.warn.bind(instance),
189
- error: instance.error.bind(instance),
190
- setMetaData,
191
- };
192
-
193
- return { logger };
194
- }
1
+ export * from './trace';
package/src/pino.ts ADDED
@@ -0,0 +1,80 @@
1
+ import pino from 'pino';
2
+ // https://github.com/pinojs/pino/blob/master/docs/api.md
3
+
4
+ import { isDev } from './env';
5
+ import { genTraceId, getTraceId, runInTrace } from './trace';
6
+
7
+ export namespace ILogger {
8
+ export interface Options {}
9
+ }
10
+
11
+ function getPinoConfig() {
12
+ const targets: any = [];
13
+
14
+ if (isDev()) {
15
+ targets.push({
16
+ level: 'debug',
17
+ target: 'pino-pretty', // must be installed separately,
18
+ options: {},
19
+ });
20
+ }
21
+
22
+ targets.push({
23
+ level: 'debug',
24
+ target: './rotate',
25
+ options: { path: './.logs/' },
26
+ });
27
+
28
+ const config: pino.LoggerOptions = {
29
+ transport: { targets },
30
+ mixin(data: any) {
31
+ // {"level":30,"time":1726065716643,"pid":21968,"hostname":"Win-LH"}
32
+ // 基础字段不能重复 删除掉
33
+ delete data.level;
34
+ delete data.time;
35
+ delete data.pid;
36
+ delete data.hostname;
37
+ if (!data?.traceId) {
38
+ return { traceId: getTraceId() };
39
+ }
40
+ return {};
41
+ },
42
+ };
43
+
44
+ return config;
45
+ }
46
+
47
+ const startTime = Symbol('startTime');
48
+
49
+ export function createLogger(options?: ILogger.Options) {
50
+ const logger = pino({
51
+ ...getPinoConfig(),
52
+ });
53
+
54
+ const express = () => {
55
+ const { mapHttpRequest, mapHttpResponse } = require('pino-std-serializers') as typeof import('pino-std-serializers');
56
+
57
+ return (req: any, res: any, next: any) => {
58
+ const response: any = res;
59
+ response[startTime] = response[startTime] || Date.now();
60
+ const traceId = req.headers['trace-id'] || genTraceId();
61
+
62
+ const onComplete = () => {
63
+ res.removeListener('close', onComplete);
64
+ res.removeListener('finish', onComplete);
65
+ res.removeListener('error', onComplete);
66
+ const duration = Date.now() - response[startTime];
67
+
68
+ logger.info({ duration, request: mapHttpRequest(req).req, response: mapHttpResponse(res).res }, 'request');
69
+ };
70
+
71
+ res.on('close', onComplete);
72
+ res.on('finish', onComplete);
73
+ res.on('error', onComplete);
74
+
75
+ runInTrace({ traceId }, next);
76
+ };
77
+ };
78
+
79
+ return { logger, express };
80
+ }
package/src/rotate.ts ADDED
@@ -0,0 +1,32 @@
1
+ import type { Options } from 'rotating-file-stream';
2
+
3
+ export interface PinoRotatingFileStreamOptions extends Options {
4
+ path: string;
5
+ }
6
+
7
+ const generator = (time: number | Date, index?: number) => {
8
+ if (!time) {
9
+ return 'server.log';
10
+ }
11
+ time = new Date(time);
12
+
13
+ const month = String(time.getMonth() + 1).padStart(2, '0');
14
+ const day = String(time.getDate()).padStart(2, '0');
15
+ if (index) {
16
+ const count = String(index).padStart(3, '0');
17
+ return `server.${time.getFullYear()}${month}${day}-${count}.log`;
18
+ }
19
+ return `server.${time.getFullYear()}${month}${day}.log`;
20
+ };
21
+
22
+ export default (options: PinoRotatingFileStreamOptions) => {
23
+ const { createStream } = require('rotating-file-stream') as typeof import('rotating-file-stream');
24
+
25
+ const { path } = options;
26
+ return createStream(generator, {
27
+ size: '50M',
28
+ maxSize: '500M',
29
+ interval: '1d',
30
+ path,
31
+ });
32
+ };
package/src/test.ts CHANGED
@@ -1,25 +1,14 @@
1
1
  process.env.NODE_ENV = 'development';
2
2
  // process.env.NODE_ENV = 'production';
3
3
 
4
- import { createLogger } from '.';
4
+ import { createLogger } from './pino';
5
+ import { genTraceId } from './trace';
5
6
 
6
- const { logger } = createLogger({ writeToFile: false, writeToConsole: true, format: { time: false } });
7
+ const { logger } = createLogger();
7
8
 
8
- const deep = { a: { b: { c: { g: { e: { f: 1 } } } } } };
9
- logger.info('1 %s', { a: 1 });
10
- logger.info('2 %j', deep);
11
- logger.info('3 \n%j', deep);
12
- logger.info('4 %s %s', 1, 2);
13
- logger.info('5 %o', deep);
14
- logger.info(deep);
15
- logger.warn('execed');
16
- logger.error(new Error('not found'));
9
+ logger.info({ time: 1, level: 1, hostname: 1, pid: 1, c: 2 }, '123');
17
10
 
18
- // import { format } from 'logform';
11
+ const start = performance.now();
12
+ logger.info({ duration: performance.now() - start, id: genTraceId() });
19
13
 
20
- // const jsonFormat = format.json({ space: 2 });
21
- // const info = jsonFormat.transform({
22
- // level: 'info',
23
- // message: 'my message',
24
- // });
25
- // console.log(info);
14
+ console.log(module);
package/src/trace.ts CHANGED
@@ -0,0 +1,16 @@
1
+ import { AsyncLocalStorage } from 'async_hooks';
2
+
3
+ const als = new AsyncLocalStorage<{ traceId: string } & any>();
4
+
5
+ export function runInTrace<T>(data: any, fn: (...args: any[]) => T): T {
6
+ return als.run(data, fn);
7
+ }
8
+
9
+ export function genTraceId() {
10
+ // crypto 680
11
+ return crypto.randomUUID();
12
+ }
13
+
14
+ export function getTraceId() {
15
+ return als.getStore()?.traceId;
16
+ }
package/tsconfig.json CHANGED
@@ -1,12 +1,12 @@
1
- {
2
- "extends": "@rife/config/tsconfig.json", // 继承 packages 目录下通用配置
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "declaration": true,
6
- "baseUrl": ".",
7
- "paths": {
8
- "@/*": ["./src/*"]
9
- }
10
- },
11
- "include": ["./src/**/*"]
12
- }
1
+ {
2
+ "extends": "@rife/config/tsconfig.json", // 继承 packages 目录下通用配置
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "declaration": true,
6
+ "baseUrl": ".",
7
+ "paths": {
8
+ "@/*": ["./src/*"]
9
+ }
10
+ },
11
+ "include": ["./src/**/*"]
12
+ }