@jeffchi/logger 1.0.3 → 1.0.5
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/lib/cache.d.ts +19 -0
- package/lib/cache.js +84 -0
- package/lib/index.js +19 -19
- package/lib/interface.d.ts +36 -2
- package/lib/utils/buildLogPreffix.js +9 -4
- package/lib/utils/checkPlateform.d.ts +2 -2
- package/lib/utils/checkPlateform.js +11 -5
- package/package.json +7 -2
package/lib/cache.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/// <reference types="lodash" />
|
|
2
|
+
export interface LogContent {
|
|
3
|
+
prefix?: string[];
|
|
4
|
+
data: any[];
|
|
5
|
+
timestamp: number;
|
|
6
|
+
}
|
|
7
|
+
/** 单例模式的缓存对像 */
|
|
8
|
+
export declare class LogCache {
|
|
9
|
+
#private;
|
|
10
|
+
lastWrite: number;
|
|
11
|
+
static get cache(): LogCache;
|
|
12
|
+
get defaultLogFile(): string;
|
|
13
|
+
private constructor();
|
|
14
|
+
push(data: LogContent, file?: string): void;
|
|
15
|
+
/** 立即写入并清空缓存 */
|
|
16
|
+
flush(file?: string): void;
|
|
17
|
+
/** 延迟写入并清空缓存 */
|
|
18
|
+
write: import("lodash").DebouncedFunc<(file: any) => void>;
|
|
19
|
+
}
|
package/lib/cache.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
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.LogCache = void 0;
|
|
7
|
+
const checkPlateform_1 = require("./utils/checkPlateform");
|
|
8
|
+
const date_fns_1 = require("date-fns");
|
|
9
|
+
const lodash_1 = require("lodash");
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const noop_1 = __importDefault(require("./utils/noop"));
|
|
12
|
+
const type_1 = require("./utils/type");
|
|
13
|
+
/** 单例模式的缓存对像 */
|
|
14
|
+
class LogCache {
|
|
15
|
+
static #cache = new LogCache();
|
|
16
|
+
lastWrite = Date.now();
|
|
17
|
+
#map;
|
|
18
|
+
#fs;
|
|
19
|
+
static get cache() {
|
|
20
|
+
return LogCache.#cache;
|
|
21
|
+
}
|
|
22
|
+
get defaultLogFile() {
|
|
23
|
+
return `logs/${(0, date_fns_1.format)(Date.now(), 'yyyy-MM-dd')}.log`;
|
|
24
|
+
}
|
|
25
|
+
constructor() {
|
|
26
|
+
this.#map = new Map();
|
|
27
|
+
(0, checkPlateform_1.checkPlatform)().then((fs) => {
|
|
28
|
+
this.#fs = fs;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
push(data, file) {
|
|
32
|
+
file = file || this.defaultLogFile;
|
|
33
|
+
let set = this.#map.get(file);
|
|
34
|
+
if (!set) {
|
|
35
|
+
set = new Set();
|
|
36
|
+
this.#map.set(file, set);
|
|
37
|
+
}
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
if (set.add(data).size > 1000 || now - this.lastWrite > 30000) {
|
|
40
|
+
this.flush(file);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
this.write(file);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** 立即写入并清空缓存 */
|
|
47
|
+
flush(file) {
|
|
48
|
+
if (!this.#fs)
|
|
49
|
+
return;
|
|
50
|
+
this.#map.forEach((set, key) => {
|
|
51
|
+
if (!set)
|
|
52
|
+
return;
|
|
53
|
+
if ((file === null && key === this.defaultLogFile) || !file || key === file) {
|
|
54
|
+
const list = Array.from(set);
|
|
55
|
+
set.clear();
|
|
56
|
+
this.#writeLogFile(key, list);
|
|
57
|
+
this.lastWrite = Date.now();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** 延迟写入并清空缓存 */
|
|
62
|
+
write = (0, lodash_1.debounce)((file) => this.flush(file), 1000);
|
|
63
|
+
/** 检查日志文件的路径,如果目录不存在,则创建,最好返回有效的日志文件,如果文件已存在,则追加日志数据 */
|
|
64
|
+
#checkFolder(output) {
|
|
65
|
+
const paths = path_1.default.dirname(output || this.defaultLogFile);
|
|
66
|
+
const { existsSync, mkdirSync } = this.#fs || {};
|
|
67
|
+
if (!existsSync?.(paths)) {
|
|
68
|
+
mkdirSync?.(paths);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
#writeLogFile(outputFile, content) {
|
|
72
|
+
if (!(0, type_1.isArray)(content)) {
|
|
73
|
+
content = [content];
|
|
74
|
+
}
|
|
75
|
+
outputFile = outputFile || this.defaultLogFile;
|
|
76
|
+
this.#checkFolder(outputFile);
|
|
77
|
+
const { writeFile } = this.#fs || {};
|
|
78
|
+
if (outputFile && writeFile) {
|
|
79
|
+
const list = content.reduce((o, { prefix = [], data }) => [...o, [...prefix, ...data.map(JSON.stringify), '\n'].join(' ')], []);
|
|
80
|
+
writeFile?.(outputFile, list.join(''), { flag: 'a' }, noop_1.default);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.LogCache = LogCache;
|
package/lib/index.js
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.loggerWithTags = void 0;
|
|
4
|
+
const cache_1 = require("./cache");
|
|
4
5
|
const defOptions_1 = require("./consts/defOptions");
|
|
5
6
|
const interface_1 = require("./interface");
|
|
6
7
|
const buildLogPreffix_1 = require("./utils/buildLogPreffix");
|
|
7
8
|
const checkLogMode_1 = require("./utils/checkLogMode");
|
|
8
|
-
const checkPlateform_1 = require("./utils/checkPlateform");
|
|
9
9
|
const type_1 = require("./utils/type");
|
|
10
|
-
const writeFile_1 = require("./utils/writeFile");
|
|
11
10
|
const loggerWithTags = (tags, options) => {
|
|
12
11
|
if (!(0, type_1.isArray)(tags)) {
|
|
13
12
|
tags = [tags];
|
|
14
13
|
}
|
|
15
|
-
const { env, ...mergedOptions } = { ...defOptions_1.defOptions, ...(options || {}) };
|
|
14
|
+
const { env, outputFile, ...mergedOptions } = { ...defOptions_1.defOptions, ...(options || {}) };
|
|
16
15
|
const debug = (...rest) => {
|
|
17
16
|
const prefix = (0, buildLogPreffix_1.buildLogPreffix)(tags, { level: interface_1.LogLevel.DEBUG, ...mergedOptions });
|
|
18
|
-
|
|
19
|
-
(
|
|
20
|
-
(0, checkPlateform_1.checkPlatform)().then((writer) => (0, writeFile_1.writeLogFile)(writer, content));
|
|
17
|
+
(0, checkLogMode_1.checkLogMode)(env || interface_1.LogMode.ALL) && console.debug([...prefix, ...rest]);
|
|
18
|
+
cache_1.LogCache.cache.push({ prefix, timestamp: Date.now(), data: [...rest] }, outputFile);
|
|
21
19
|
};
|
|
22
20
|
const info = (...rest) => {
|
|
23
21
|
const prefix = (0, buildLogPreffix_1.buildLogPreffix)(tags, { level: interface_1.LogLevel.INFO, ...mergedOptions });
|
|
24
|
-
|
|
25
|
-
(
|
|
26
|
-
(0, checkPlateform_1.checkPlatform)().then((writer) => (0, writeFile_1.writeLogFile)(writer, content));
|
|
22
|
+
(0, checkLogMode_1.checkLogMode)(env || interface_1.LogMode.ALL) && console.info([...prefix, ...rest]);
|
|
23
|
+
cache_1.LogCache.cache.push({ prefix, timestamp: Date.now(), data: [...rest] }, outputFile);
|
|
27
24
|
};
|
|
28
25
|
const log = (...rest) => {
|
|
29
26
|
const prefix = (0, buildLogPreffix_1.buildLogPreffix)(tags, mergedOptions);
|
|
30
|
-
|
|
31
|
-
(
|
|
32
|
-
(0, checkPlateform_1.checkPlatform)().then((writer) => (0, writeFile_1.writeLogFile)(writer, content));
|
|
27
|
+
(0, checkLogMode_1.checkLogMode)(env || interface_1.LogMode.ALL) && console.log([...prefix, ...rest]);
|
|
28
|
+
cache_1.LogCache.cache.push({ prefix, timestamp: Date.now(), data: [...rest] }, outputFile);
|
|
33
29
|
};
|
|
34
30
|
const warn = (...rest) => {
|
|
35
31
|
const prefix = (0, buildLogPreffix_1.buildLogPreffix)(tags, { level: interface_1.LogLevel.WARN, ...mergedOptions });
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
(0,
|
|
32
|
+
const { disableError } = mergedOptions;
|
|
33
|
+
const out = disableError ? console.debug : console.warn;
|
|
34
|
+
(0, checkLogMode_1.checkLogMode)(env || interface_1.LogMode.ALL) && out([...prefix, ...rest]);
|
|
35
|
+
cache_1.LogCache.cache.push({ prefix, timestamp: Date.now(), data: [...rest] }, outputFile);
|
|
39
36
|
};
|
|
40
37
|
const error = (msg, cause) => {
|
|
41
38
|
const prefix = (0, buildLogPreffix_1.buildLogPreffix)(tags, { level: interface_1.LogLevel.ERROR, ...mergedOptions });
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
(0,
|
|
45
|
-
|
|
39
|
+
const { ignoreThrow, disableError } = mergedOptions;
|
|
40
|
+
const out = disableError ? console.debug : console.error;
|
|
41
|
+
(0, checkLogMode_1.checkLogMode)(env || interface_1.LogMode.ALL) && out([...prefix, msg]);
|
|
42
|
+
cache_1.LogCache.cache.push({ prefix, timestamp: Date.now(), data: [msg] }, outputFile);
|
|
43
|
+
if (!ignoreThrow) {
|
|
44
|
+
throw new Error(msg, { cause });
|
|
45
|
+
}
|
|
46
46
|
};
|
|
47
47
|
return { debug, info, log, warn, error };
|
|
48
48
|
};
|
package/lib/interface.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export type PathLike = string | Buffer | URL;
|
|
1
3
|
/**
|
|
2
4
|
* 日志输出打印的模式
|
|
3
5
|
* @default LogMode.ALL
|
|
@@ -29,7 +31,7 @@ export interface ILogOptions {
|
|
|
29
31
|
* 是否支持输出时间戳及时间戳格式
|
|
30
32
|
*
|
|
31
33
|
* 字符串格式参见: https://github.com/date-fns/date-fns/blob/main/src/format/index.ts
|
|
32
|
-
* @default true
|
|
34
|
+
* @default true 开启后默认IOS格式 'yyyy-MM-ddTHH:mm:ss.SSSZ'
|
|
33
35
|
*/
|
|
34
36
|
date?: boolean | string;
|
|
35
37
|
/**
|
|
@@ -37,8 +39,40 @@ export interface ILogOptions {
|
|
|
37
39
|
* @default 'all'
|
|
38
40
|
*/
|
|
39
41
|
env?: LogMode;
|
|
42
|
+
/** 禁用warn输出,避免在测试场景下影响测试结果
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
disableWarn?: boolean;
|
|
46
|
+
/** 禁用error输出,避免在测试场景下打断正常测试流程
|
|
47
|
+
* @default false
|
|
48
|
+
*/
|
|
49
|
+
disableError?: boolean;
|
|
50
|
+
/** 调用error输出错误信息后,禁止继续抛出异常错误
|
|
51
|
+
* @description
|
|
52
|
+
* 调用error输出错误信息后,默认继续抛出异常错误,在测试环境下可以临地禁用,避免影响正常的测试流程
|
|
53
|
+
*/
|
|
54
|
+
ignoreThrow?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* 基于当前工程根目录下的日志输出文件
|
|
57
|
+
*
|
|
58
|
+
* @description
|
|
59
|
+
* 浏览器环境:自动忽略该选项;
|
|
60
|
+
*
|
|
61
|
+
* node环境下默认 logs/xxx.log
|
|
62
|
+
*/
|
|
63
|
+
outputFile?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface IFileHelper {
|
|
66
|
+
existsSync?: (path: PathLike) => boolean;
|
|
67
|
+
mkdirSync?: (path: PathLike, options?: {
|
|
68
|
+
mode?: number | string | undefined;
|
|
69
|
+
recursive: true;
|
|
70
|
+
}) => string | undefined;
|
|
71
|
+
writeFile?: CallableFunction;
|
|
72
|
+
join?: (...paths: string[]) => string;
|
|
73
|
+
sep?: '\\' | '/';
|
|
74
|
+
resolve?: (...paths: string[]) => string;
|
|
40
75
|
}
|
|
41
|
-
export type LogContent = any[];
|
|
42
76
|
export interface ILogger {
|
|
43
77
|
debug: (...rest: any[]) => void;
|
|
44
78
|
info: (...rest: any[]) => void;
|
|
@@ -6,17 +6,22 @@ const interface_1 = require("../interface");
|
|
|
6
6
|
const type_1 = require("./type");
|
|
7
7
|
const buildLogPreffix = (tags, options) => {
|
|
8
8
|
const { level = interface_1.LogLevel.LOG, date } = options;
|
|
9
|
-
const prefix = [
|
|
9
|
+
const prefix = [];
|
|
10
10
|
if (tags.length) {
|
|
11
11
|
prefix.unshift(tags.map((t) => `[${t.toUpperCase()}]`).join(' '));
|
|
12
12
|
}
|
|
13
13
|
if (date) {
|
|
14
|
-
|
|
14
|
+
const now = new Date();
|
|
15
|
+
let dtStr;
|
|
15
16
|
if ((0, type_1.isString)(date)) {
|
|
16
|
-
|
|
17
|
+
dtStr = (0, date_fns_1.format)(now, date);
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
+
else {
|
|
20
|
+
dtStr = new Date(now).toISOString();
|
|
21
|
+
}
|
|
22
|
+
prefix.unshift(dtStr);
|
|
19
23
|
}
|
|
24
|
+
prefix.unshift(`[${level}]\t`);
|
|
20
25
|
return prefix;
|
|
21
26
|
};
|
|
22
27
|
exports.buildLogPreffix = buildLogPreffix;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { IFileHelper } from '../interface';
|
|
2
2
|
/**
|
|
3
3
|
* 检查当前运行环境,node环境下返回node的fs模块,浏览器环境返回null
|
|
4
4
|
* @returns fs
|
|
5
5
|
*/
|
|
6
|
-
export declare const checkPlatform: () => Promise<
|
|
6
|
+
export declare const checkPlatform: () => Promise<IFileHelper | null>;
|
|
@@ -28,13 +28,19 @@ exports.checkPlatform = void 0;
|
|
|
28
28
|
* 检查当前运行环境,node环境下返回node的fs模块,浏览器环境返回null
|
|
29
29
|
* @returns fs
|
|
30
30
|
*/
|
|
31
|
-
const checkPlatform = () => Promise.resolve().then(() => __importStar(require('fs'))).then((fs) => {
|
|
31
|
+
const checkPlatform = () => Promise.all([Promise.resolve().then(() => __importStar(require('fs'))), Promise.resolve().then(() => __importStar(require('path')))]).then(([fs, path]) => {
|
|
32
32
|
// 如果fs为空则判定当前为浏览器环境
|
|
33
33
|
if (!fs)
|
|
34
34
|
return null;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
const { existsSync, mkdirSync, writeFile } = fs;
|
|
36
|
+
const { sep, resolve, join } = path;
|
|
37
|
+
return {
|
|
38
|
+
existsSync,
|
|
39
|
+
mkdirSync,
|
|
40
|
+
writeFile,
|
|
41
|
+
join,
|
|
42
|
+
sep,
|
|
43
|
+
resolve,
|
|
44
|
+
};
|
|
39
45
|
});
|
|
40
46
|
exports.checkPlatform = checkPlatform;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jeffchi/logger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"description": "A log print output javascript tool library that can be used at the front and back ends",
|
|
@@ -39,12 +39,17 @@
|
|
|
39
39
|
"lib/**/*"
|
|
40
40
|
],
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"date-fns": "^2.29.3"
|
|
42
|
+
"date-fns": "^2.29.3",
|
|
43
|
+
"@types/lodash": "^4.14.191",
|
|
44
|
+
"@types/node": "^18.11.18",
|
|
45
|
+
"lodash": "^4.17.21"
|
|
43
46
|
},
|
|
44
47
|
"devDependencies": {
|
|
45
48
|
"@types/jest": "^29.2.5",
|
|
49
|
+
"@types/lodash": "^4.14.191",
|
|
46
50
|
"@types/node": "^18.11.18",
|
|
47
51
|
"jest": "^29.3.1",
|
|
52
|
+
"lodash": "^4.17.21",
|
|
48
53
|
"prettier": "^2.8.2",
|
|
49
54
|
"ts-jest": "^29.0.5",
|
|
50
55
|
"tslint": "^6.1.3",
|