logxpert 1.0.4-0 → 2.0.0
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/CHANGELOG.md +14 -0
- package/LICENSE +674 -21
- package/README.md +97 -113
- package/index.d.ts +57 -0
- package/main.js +188 -185
- package/main.mjs +14 -0
- package/package.json +51 -17
- package/CODE_OF_CONDUCT.md +0 -128
- package/PATCHNOTE.fr.md +0 -36
- package/PATCHNOTE.md +0 -36
- package/README.fr.md +0 -113
package/README.md
CHANGED
|
@@ -1,113 +1,97 @@
|
|
|
1
|
-
# LogXpert
|
|
2
|
-
|
|
3
|
-
LogXpert is a powerful logging library for Node.js that provides easy-to-use logging methods with colorful formatted output and optional file logging support
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
```js
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
log.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- **log.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
- **log.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
**Files Options:**
|
|
100
|
-
- `folder` (string): Directory where log files will be stored (default: `'logs'`).
|
|
101
|
-
- `filesName` (string): Date pattern for the log file name (default: `'YYYY-MM-DD'`).
|
|
102
|
-
- `maxFile` (string): Maximum file retention (default: `'14d'`).
|
|
103
|
-
- `maxSize` (string): Maximum size per log file (default: `'20m'`).
|
|
104
|
-
- `zippedArchive` (boolean): Archive logs in zip format (default: `false`).
|
|
105
|
-
|
|
106
|
-
## Additional Information
|
|
107
|
-
|
|
108
|
-
- [French Version](./README.fr.md)
|
|
109
|
-
- [Patch Notes](./PATCHNOTE.md)
|
|
110
|
-
|
|
111
|
-
## License
|
|
112
|
-
|
|
113
|
-
This project is licensed under the MIT License.
|
|
1
|
+
# LogXpert
|
|
2
|
+
|
|
3
|
+
LogXpert is a powerful logging library for Node.js that provides easy-to-use logging methods with colorful formatted output and optional file logging support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install logxpert
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
CommonJS:
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const log = require('logxpert');
|
|
17
|
+
|
|
18
|
+
log('general message');
|
|
19
|
+
log.error('error message');
|
|
20
|
+
log.warn('warn message');
|
|
21
|
+
log.info('info with meta', { user: 1 });
|
|
22
|
+
log.debug({ structured: 'object' });
|
|
23
|
+
log.error(new Error('boom'));
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
ESM:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
import log from 'logxpert';
|
|
30
|
+
|
|
31
|
+
log.info('hello');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Set level (`LOG_LEVEL` env also respected):
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
log.setLevel('info');
|
|
38
|
+
console.log(log.getLevel());
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Isolated instances and child loggers:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
const { createLogger } = require('logxpert');
|
|
45
|
+
const apiLog = createLogger({ level: 'info' });
|
|
46
|
+
apiLog.info('isolated');
|
|
47
|
+
|
|
48
|
+
const child = log.child({ service: 'api' });
|
|
49
|
+
child.info('child message');
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### File output & console timestamp
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
log.settings({
|
|
56
|
+
level: 'debug',
|
|
57
|
+
console: {
|
|
58
|
+
enableTimestamp: true,
|
|
59
|
+
timestampFormat: 'YYYY-MM-DD HH:mm:ss',
|
|
60
|
+
timestampPrefix: '',
|
|
61
|
+
timestampSuffix: '',
|
|
62
|
+
colorize: true
|
|
63
|
+
},
|
|
64
|
+
files: {
|
|
65
|
+
folder: 'logs',
|
|
66
|
+
filename: 'application-%DATE%.log',
|
|
67
|
+
filesName: 'YYYY-MM-DD',
|
|
68
|
+
maxFile: '14d',
|
|
69
|
+
maxSize: '20m',
|
|
70
|
+
zippedArchive: false
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Close file transports on shutdown:
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
log.close();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API Reference
|
|
82
|
+
|
|
83
|
+
- **log(message, ...meta):** info level.
|
|
84
|
+
- **log.error/warn/info/debug/http/verbose/silly(message, ...meta)**
|
|
85
|
+
- **log.log(level, message, ...meta)**
|
|
86
|
+
- **log.settings({ console, files, level })**
|
|
87
|
+
- **log.setLevel(level) / log.getLevel()**
|
|
88
|
+
- **log.createLogger(options):** independent instance.
|
|
89
|
+
- **log.child(meta):** child logger with bound context.
|
|
90
|
+
- **log.close():** remove file transport.
|
|
91
|
+
|
|
92
|
+
Console options: `enableTimestamp`, `timestampFormat`, `timestampPrefix`, `timestampSuffix`, `colorize`, `level`.
|
|
93
|
+
Files options: `folder`, `filename`, `filesName`/`datePattern`, `maxFile`/`maxFiles`, `maxSize`, `zippedArchive`, `level`.
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
GPL-3.0-only. See [LICENSE](LICENSE).
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export type LogLevel = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
|
|
2
|
+
|
|
3
|
+
export interface ConsoleOptions {
|
|
4
|
+
enableTimestamp?: boolean;
|
|
5
|
+
timestampFormat?: string;
|
|
6
|
+
timestampPrefix?: string;
|
|
7
|
+
timestampSuffix?: string;
|
|
8
|
+
colorize?: boolean;
|
|
9
|
+
level?: LogLevel;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface FilesOptions {
|
|
13
|
+
folder?: string;
|
|
14
|
+
filesName?: string;
|
|
15
|
+
datePattern?: string;
|
|
16
|
+
filename?: string;
|
|
17
|
+
maxFile?: string;
|
|
18
|
+
maxFiles?: string;
|
|
19
|
+
maxSize?: string;
|
|
20
|
+
zippedArchive?: boolean;
|
|
21
|
+
level?: LogLevel;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface LogSettingsOptions {
|
|
25
|
+
console?: ConsoleOptions;
|
|
26
|
+
files?: FilesOptions;
|
|
27
|
+
level?: LogLevel;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ChildLogger {
|
|
31
|
+
error(message: unknown, ...meta: unknown[]): void;
|
|
32
|
+
warn(message: unknown, ...meta: unknown[]): void;
|
|
33
|
+
info(message: unknown, ...meta: unknown[]): void;
|
|
34
|
+
debug(message: unknown, ...meta: unknown[]): void;
|
|
35
|
+
log(level: LogLevel, message: unknown, ...meta: unknown[]): void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface LogXpert {
|
|
39
|
+
(message: unknown, ...meta: unknown[]): void;
|
|
40
|
+
error(message: unknown, ...meta: unknown[]): void;
|
|
41
|
+
warn(message: unknown, ...meta: unknown[]): void;
|
|
42
|
+
info(message: unknown, ...meta: unknown[]): void;
|
|
43
|
+
debug(message: unknown, ...meta: unknown[]): void;
|
|
44
|
+
http(message: unknown, ...meta: unknown[]): void;
|
|
45
|
+
verbose(message: unknown, ...meta: unknown[]): void;
|
|
46
|
+
silly(message: unknown, ...meta: unknown[]): void;
|
|
47
|
+
log(level: LogLevel, message: unknown, ...meta: unknown[]): void;
|
|
48
|
+
settings(options?: LogSettingsOptions): void;
|
|
49
|
+
setLevel(level: LogLevel): void;
|
|
50
|
+
getLevel(): string;
|
|
51
|
+
child(meta?: Record<string, unknown>): ChildLogger;
|
|
52
|
+
close(): void;
|
|
53
|
+
createLogger(options?: LogSettingsOptions): LogXpert;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
declare const log: LogXpert;
|
|
57
|
+
export default log;
|
package/main.js
CHANGED
|
@@ -1,185 +1,188 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
require('winston
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (options.files) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const dayjs = require('dayjs');
|
|
4
|
+
const { createLogger, format, transports } = require('winston');
|
|
5
|
+
require('winston-daily-rotate-file');
|
|
6
|
+
|
|
7
|
+
const VALID_LEVELS = ['error', 'warn', 'info', 'http', 'verbose', 'debug', 'silly'];
|
|
8
|
+
const DEFAULT_CONSOLE_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
|
9
|
+
|
|
10
|
+
function formatCustomTimestamp(fmt) {
|
|
11
|
+
if (typeof fmt !== 'string' || !fmt) return dayjs().format(DEFAULT_CONSOLE_FORMAT);
|
|
12
|
+
if (fmt.includes('[') && fmt.includes(']')) {
|
|
13
|
+
return fmt.split(/(\[[^\]]*\])/).map((part) => {
|
|
14
|
+
if (part.startsWith('[') && part.endsWith(']')) {
|
|
15
|
+
const inner = part.slice(1, -1);
|
|
16
|
+
return '[' + (inner ? dayjs().format(inner) : '') + ']';
|
|
17
|
+
}
|
|
18
|
+
return part;
|
|
19
|
+
}).join('');
|
|
20
|
+
}
|
|
21
|
+
return dayjs().format(fmt);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function formatExtra(meta) {
|
|
25
|
+
const keys = Object.keys(meta).filter((k) => k !== 'splat' && k !== 'ms');
|
|
26
|
+
if (!keys.length) return '';
|
|
27
|
+
try {
|
|
28
|
+
const picked = {};
|
|
29
|
+
for (const k of keys) picked[k] = meta[k];
|
|
30
|
+
return JSON.stringify(picked);
|
|
31
|
+
} catch {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const prettyFormat = format.printf(({ timestamp, level, message, ...meta }) => {
|
|
37
|
+
const msg = typeof message === 'string' ? message : message == null ? '' : JSON.stringify(message);
|
|
38
|
+
const extra = formatExtra(meta);
|
|
39
|
+
const body = [msg, extra].filter(Boolean).join(' ');
|
|
40
|
+
return timestamp ? `${timestamp} [${level}]: ${body}` : `[${level}]: ${body}`;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
function assertLevel(level) {
|
|
44
|
+
if (!VALID_LEVELS.includes(level)) throw new Error(`Invalid log level "${level}". Use one of: ${VALID_LEVELS.join(', ')}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function normalizeFilesOptions(files = {}) {
|
|
48
|
+
const folder = files.folder ?? 'logs';
|
|
49
|
+
if (typeof folder !== 'string' || !folder.trim() || folder.includes('\0')) {
|
|
50
|
+
throw new Error('files.folder must be a non-empty string');
|
|
51
|
+
}
|
|
52
|
+
const datePattern = files.filesName ?? files.datePattern ?? 'YYYY-MM-DD';
|
|
53
|
+
if (typeof datePattern !== 'string' || !datePattern.trim()) {
|
|
54
|
+
throw new Error('files.filesName/datePattern must be a non-empty string');
|
|
55
|
+
}
|
|
56
|
+
let filename = files.filename ?? `application-%DATE%.log`;
|
|
57
|
+
if (typeof filename !== 'string' || !filename.trim()) {
|
|
58
|
+
throw new Error('files.filename must be a non-empty string');
|
|
59
|
+
}
|
|
60
|
+
if (!filename.includes('%DATE%')) {
|
|
61
|
+
const ext = path.extname(filename) || '.log';
|
|
62
|
+
const base = path.basename(filename, ext);
|
|
63
|
+
filename = `${base}-%DATE%${ext}`;
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
folder: path.normalize(folder),
|
|
67
|
+
datePattern,
|
|
68
|
+
filename,
|
|
69
|
+
maxFiles: files.maxFile ?? files.maxFiles ?? '14d',
|
|
70
|
+
maxSize: files.maxSize ?? '20m',
|
|
71
|
+
zippedArchive: files.zippedArchive ?? false,
|
|
72
|
+
level: files.level,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function buildConsoleTransport({ enableTimestamp = true, timestampFormat = DEFAULT_CONSOLE_FORMAT, timestampPrefix = '', timestampSuffix = '', colorize = true, level } = {}) {
|
|
77
|
+
const parts = [];
|
|
78
|
+
if (colorize) parts.push(format.colorize());
|
|
79
|
+
if (enableTimestamp) {
|
|
80
|
+
parts.push(format.timestamp({ format: () => `${timestampPrefix}${formatCustomTimestamp(timestampFormat)}${timestampSuffix}` }));
|
|
81
|
+
} else {
|
|
82
|
+
parts.push(format((info) => { delete info.timestamp; return info; })());
|
|
83
|
+
}
|
|
84
|
+
parts.push(format.errors({ stack: true }), format.splat(), prettyFormat);
|
|
85
|
+
return new transports.Console({ format: format.combine(...parts), level });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function buildFileTransport({ folder, datePattern, filename, maxFiles, maxSize, zippedArchive, level }) {
|
|
89
|
+
if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
|
|
90
|
+
return new transports.DailyRotateFile({
|
|
91
|
+
filename: path.join(folder, filename),
|
|
92
|
+
datePattern,
|
|
93
|
+
zippedArchive,
|
|
94
|
+
maxSize,
|
|
95
|
+
maxFiles,
|
|
96
|
+
level,
|
|
97
|
+
format: format.combine(format.errors({ stack: true }), format.splat(), format.timestamp(), prettyFormat),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function createLoggerInstance(initial = {}) {
|
|
102
|
+
const globalLevel = process.env.LOG_LEVEL || initial.level || 'debug';
|
|
103
|
+
assertLevel(globalLevel);
|
|
104
|
+
|
|
105
|
+
const logger = createLogger({
|
|
106
|
+
level: globalLevel,
|
|
107
|
+
format: format.combine(format.errors({ stack: true }), format.splat()),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
let consoleTransport = buildConsoleTransport(initial.console);
|
|
111
|
+
consoleTransport.level = initial.console?.level;
|
|
112
|
+
logger.add(consoleTransport);
|
|
113
|
+
|
|
114
|
+
let fileTransport = null;
|
|
115
|
+
let consoleOpts = { ...(initial.console || {}) };
|
|
116
|
+
let filesOpts = null;
|
|
117
|
+
|
|
118
|
+
function applySettings(options = {}) {
|
|
119
|
+
if (options.level !== undefined) {
|
|
120
|
+
assertLevel(options.level);
|
|
121
|
+
logger.level = options.level;
|
|
122
|
+
}
|
|
123
|
+
if (options.console) {
|
|
124
|
+
if (options.console.level !== undefined && options.console.level !== null) assertLevel(options.console.level);
|
|
125
|
+
consoleOpts = { ...consoleOpts, ...options.console };
|
|
126
|
+
logger.remove(consoleTransport);
|
|
127
|
+
consoleTransport = buildConsoleTransport(consoleOpts);
|
|
128
|
+
consoleTransport.level = consoleOpts.level;
|
|
129
|
+
logger.add(consoleTransport);
|
|
130
|
+
}
|
|
131
|
+
if (options.files) {
|
|
132
|
+
const normalized = normalizeFilesOptions(options.files);
|
|
133
|
+
if (normalized.level !== undefined && normalized.level !== null) assertLevel(normalized.level);
|
|
134
|
+
filesOpts = normalized;
|
|
135
|
+
if (fileTransport) logger.remove(fileTransport);
|
|
136
|
+
fileTransport = buildFileTransport(normalized);
|
|
137
|
+
logger.add(fileTransport);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function write(level, message, ...meta) {
|
|
142
|
+
if (message instanceof Error) {
|
|
143
|
+
logger.log(level, message.message, { stack: message.stack, ...meta[0] });
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
logger.log(level, message, ...meta);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function callable(message, ...meta) {
|
|
150
|
+
write('info', message, ...meta);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
callable.error = (m, ...a) => write('error', m, ...a);
|
|
154
|
+
callable.warn = (m, ...a) => write('warn', m, ...a);
|
|
155
|
+
callable.info = (m, ...a) => write('info', m, ...a);
|
|
156
|
+
callable.debug = (m, ...a) => write('debug', m, ...a);
|
|
157
|
+
callable.http = (m, ...a) => write('http', m, ...a);
|
|
158
|
+
callable.verbose = (m, ...a) => write('verbose', m, ...a);
|
|
159
|
+
callable.silly = (m, ...a) => write('silly', m, ...a);
|
|
160
|
+
callable.log = (level, m, ...a) => { assertLevel(level); write(level, m, ...a); };
|
|
161
|
+
|
|
162
|
+
callable.settings = applySettings;
|
|
163
|
+
callable.setLevel = (level) => { assertLevel(level); logger.level = level; };
|
|
164
|
+
callable.getLevel = () => logger.level;
|
|
165
|
+
callable.child = (meta = {}) => {
|
|
166
|
+
const child = logger.child(meta);
|
|
167
|
+
return {
|
|
168
|
+
error: (m, ...a) => child.error(m, ...a),
|
|
169
|
+
warn: (m, ...a) => child.warn(m, ...a),
|
|
170
|
+
info: (m, ...a) => child.info(m, ...a),
|
|
171
|
+
debug: (m, ...a) => child.debug(m, ...a),
|
|
172
|
+
log: child.log.bind(child),
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
callable.close = () => {
|
|
176
|
+
if (fileTransport) { logger.remove(fileTransport); try { fileTransport.close?.(); } catch {} fileTransport = null; }
|
|
177
|
+
};
|
|
178
|
+
callable.createLogger = (opts = {}) => createLoggerInstance(opts);
|
|
179
|
+
callable._winston = logger;
|
|
180
|
+
|
|
181
|
+
if (initial.files) applySettings({ files: initial.files });
|
|
182
|
+
if (initial.console || initial.level) applySettings({ console: initial.console, level: initial.level });
|
|
183
|
+
|
|
184
|
+
return callable;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = createLoggerInstance();
|
|
188
|
+
module.exports.createLogger = createLoggerInstance;
|