@navios/core 0.1.0 → 0.1.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/index.d.mts +432 -11
- package/dist/index.d.ts +432 -11
- package/dist/index.js +798 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +771 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.mts +1 -0
- package/src/logger/README.md +3 -0
- package/src/logger/console-logger.service.mts +588 -0
- package/src/logger/index.mts +7 -0
- package/src/logger/log-levels.mts +12 -0
- package/src/logger/logger-service.interface.mts +42 -0
- package/src/logger/logger.factory.mts +37 -0
- package/src/logger/logger.service.mts +214 -0
- package/src/logger/pino-wrapper.mts +63 -0
- package/src/logger/utils/cli-colors.util.mts +17 -0
- package/src/logger/utils/filter-log-levelts.util.mts +29 -0
- package/src/logger/utils/index.mts +5 -0
- package/src/logger/utils/is-log-level-enabled.mts +33 -0
- package/src/logger/utils/is-log-level.util.mts +10 -0
- package/src/logger/utils/shared.utils.mts +51 -0
- package/src/navios.application.mts +71 -18
- package/src/navios.factory.mts +18 -1
- package/src/service-locator/inject.mts +6 -1
- package/src/service-locator/injection-token.mts +11 -6
- package/src/service-locator/service-locator.mts +44 -15
- package/src/service-locator/sync-injector.mts +6 -1
- package/src/services/controller-adapter.service.mts +8 -0
- package/src/services/module-loader.service.mts +6 -1
package/package.json
CHANGED
package/src/index.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './decorators/index.mjs'
|
|
2
2
|
export * from './exceptions/index.mjs'
|
|
3
3
|
export * from './interfaces/index.mjs'
|
|
4
|
+
export * from './logger/index.mjs'
|
|
4
5
|
export * from './metadata/index.mjs'
|
|
5
6
|
export * from './service-locator/index.mjs'
|
|
6
7
|
export * from './services/index.mjs'
|
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
import type { InspectOptions } from 'util'
|
|
2
|
+
|
|
3
|
+
import { inspect } from 'util'
|
|
4
|
+
|
|
5
|
+
import type { LogLevel } from './log-levels.mjs'
|
|
6
|
+
import type { LoggerService } from './logger-service.interface.mjs'
|
|
7
|
+
|
|
8
|
+
import { Injectable } from '../service-locator/index.mjs'
|
|
9
|
+
import {
|
|
10
|
+
clc,
|
|
11
|
+
isFunction,
|
|
12
|
+
isLogLevelEnabled,
|
|
13
|
+
isPlainObject,
|
|
14
|
+
isString,
|
|
15
|
+
isUndefined,
|
|
16
|
+
yellow,
|
|
17
|
+
} from './utils/index.mjs'
|
|
18
|
+
|
|
19
|
+
const DEFAULT_DEPTH = 5
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @publicApi
|
|
23
|
+
*/
|
|
24
|
+
export interface ConsoleLoggerOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Enabled log levels.
|
|
27
|
+
*/
|
|
28
|
+
logLevels?: LogLevel[]
|
|
29
|
+
/**
|
|
30
|
+
* If enabled, will print timestamp (time difference) between current and previous log message.
|
|
31
|
+
* Note: This option is not used when `json` is enabled.
|
|
32
|
+
*/
|
|
33
|
+
timestamp?: boolean
|
|
34
|
+
/**
|
|
35
|
+
* A prefix to be used for each log message.
|
|
36
|
+
* Note: This option is not used when `json` is enabled.
|
|
37
|
+
*/
|
|
38
|
+
prefix?: string
|
|
39
|
+
/**
|
|
40
|
+
* If enabled, will print the log message in JSON format.
|
|
41
|
+
*/
|
|
42
|
+
json?: boolean
|
|
43
|
+
/**
|
|
44
|
+
* If enabled, will print the log message in color.
|
|
45
|
+
* Default true if json is disabled, false otherwise
|
|
46
|
+
*/
|
|
47
|
+
colors?: boolean
|
|
48
|
+
/**
|
|
49
|
+
* The context of the logger.
|
|
50
|
+
*/
|
|
51
|
+
context?: string
|
|
52
|
+
/**
|
|
53
|
+
* If enabled, will print the log message in a single line, even if it is an object with multiple properties.
|
|
54
|
+
* If set to a number, the most n inner elements are united on a single line as long as all properties fit into breakLength. Short array elements are also grouped together.
|
|
55
|
+
* Default true when `json` is enabled, false otherwise.
|
|
56
|
+
*/
|
|
57
|
+
compact?: boolean | number
|
|
58
|
+
/**
|
|
59
|
+
* Specifies the maximum number of Array, TypedArray, Map, Set, WeakMap, and WeakSet elements to include when formatting.
|
|
60
|
+
* Set to null or Infinity to show all elements. Set to 0 or negative to show no elements.
|
|
61
|
+
* Ignored when `json` is enabled, colors are disabled, and `compact` is set to true as it produces a parseable JSON output.
|
|
62
|
+
* @default 100
|
|
63
|
+
*/
|
|
64
|
+
maxArrayLength?: number
|
|
65
|
+
/**
|
|
66
|
+
* Specifies the maximum number of characters to include when formatting.
|
|
67
|
+
* Set to null or Infinity to show all elements. Set to 0 or negative to show no characters.
|
|
68
|
+
* Ignored when `json` is enabled, colors are disabled, and `compact` is set to true as it produces a parseable JSON output.
|
|
69
|
+
* @default 10000.
|
|
70
|
+
*/
|
|
71
|
+
maxStringLength?: number
|
|
72
|
+
/**
|
|
73
|
+
* If enabled, will sort keys while formatting objects.
|
|
74
|
+
* Can also be a custom sorting function.
|
|
75
|
+
* Ignored when `json` is enabled, colors are disabled, and `compact` is set to true as it produces a parseable JSON output.
|
|
76
|
+
* @default false
|
|
77
|
+
*/
|
|
78
|
+
sorted?: boolean | ((a: string, b: string) => number)
|
|
79
|
+
/**
|
|
80
|
+
* Specifies the number of times to recurse while formatting object. T
|
|
81
|
+
* This is useful for inspecting large objects. To recurse up to the maximum call stack size pass Infinity or null.
|
|
82
|
+
* Ignored when `json` is enabled, colors are disabled, and `compact` is set to true as it produces a parseable JSON output.
|
|
83
|
+
* @default 5
|
|
84
|
+
*/
|
|
85
|
+
depth?: number
|
|
86
|
+
/**
|
|
87
|
+
* If true, object's non-enumerable symbols and properties are included in the formatted result.
|
|
88
|
+
* WeakMap and WeakSet entries are also included as well as user defined prototype properties
|
|
89
|
+
* @default false
|
|
90
|
+
*/
|
|
91
|
+
showHidden?: boolean
|
|
92
|
+
/**
|
|
93
|
+
* The length at which input values are split across multiple lines. Set to Infinity to format the input as a single line (in combination with "compact" set to true).
|
|
94
|
+
* Default Infinity when "compact" is true, 80 otherwise.
|
|
95
|
+
* Ignored when `json` is enabled, colors are disabled, and `compact` is set to true as it produces a parseable JSON output.
|
|
96
|
+
*/
|
|
97
|
+
breakLength?: number
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const DEFAULT_LOG_LEVELS: LogLevel[] = [
|
|
101
|
+
'log',
|
|
102
|
+
'error',
|
|
103
|
+
'warn',
|
|
104
|
+
'debug',
|
|
105
|
+
'verbose',
|
|
106
|
+
'fatal',
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
const dateTimeFormatter = new Intl.DateTimeFormat(undefined, {
|
|
110
|
+
year: 'numeric',
|
|
111
|
+
hour: 'numeric',
|
|
112
|
+
minute: 'numeric',
|
|
113
|
+
second: 'numeric',
|
|
114
|
+
day: '2-digit',
|
|
115
|
+
month: '2-digit',
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @publicApi
|
|
120
|
+
*/
|
|
121
|
+
@Injectable()
|
|
122
|
+
export class ConsoleLogger implements LoggerService {
|
|
123
|
+
/**
|
|
124
|
+
* The options of the logger.
|
|
125
|
+
*/
|
|
126
|
+
protected options: ConsoleLoggerOptions
|
|
127
|
+
/**
|
|
128
|
+
* The context of the logger (can be set manually or automatically inferred).
|
|
129
|
+
*/
|
|
130
|
+
protected context?: string
|
|
131
|
+
/**
|
|
132
|
+
* The original context of the logger (set in the constructor).
|
|
133
|
+
*/
|
|
134
|
+
protected originalContext?: string
|
|
135
|
+
/**
|
|
136
|
+
* The options used for the "inspect" method.
|
|
137
|
+
*/
|
|
138
|
+
protected inspectOptions: InspectOptions
|
|
139
|
+
/**
|
|
140
|
+
* The last timestamp at which the log message was printed.
|
|
141
|
+
*/
|
|
142
|
+
protected static lastTimestampAt?: number
|
|
143
|
+
|
|
144
|
+
constructor()
|
|
145
|
+
constructor(context: string)
|
|
146
|
+
constructor(options: ConsoleLoggerOptions)
|
|
147
|
+
constructor(context: string, options: ConsoleLoggerOptions)
|
|
148
|
+
constructor(
|
|
149
|
+
contextOrOptions?: string | ConsoleLoggerOptions,
|
|
150
|
+
options?: ConsoleLoggerOptions,
|
|
151
|
+
) {
|
|
152
|
+
// eslint-disable-next-line prefer-const
|
|
153
|
+
let [context, opts] = isString(contextOrOptions)
|
|
154
|
+
? [contextOrOptions, options]
|
|
155
|
+
: options
|
|
156
|
+
? [undefined, options]
|
|
157
|
+
: [contextOrOptions?.context, contextOrOptions]
|
|
158
|
+
|
|
159
|
+
opts = opts ?? {}
|
|
160
|
+
opts.logLevels ??= DEFAULT_LOG_LEVELS
|
|
161
|
+
opts.colors ??= opts.colors ?? (opts.json ? false : true)
|
|
162
|
+
opts.prefix ??= 'Navios'
|
|
163
|
+
|
|
164
|
+
this.options = opts
|
|
165
|
+
this.inspectOptions = this.getInspectOptions()
|
|
166
|
+
|
|
167
|
+
if (context) {
|
|
168
|
+
this.context = context
|
|
169
|
+
this.originalContext = context
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Write a 'log' level log, if the configured level allows for it.
|
|
175
|
+
* Prints to `stdout` with newline.
|
|
176
|
+
*/
|
|
177
|
+
log(message: any, context?: string): void
|
|
178
|
+
log(message: any, ...optionalParams: [...any, string?]): void
|
|
179
|
+
log(message: any, ...optionalParams: any[]) {
|
|
180
|
+
if (!this.isLevelEnabled('log')) {
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
const { messages, context } = this.getContextAndMessagesToPrint([
|
|
184
|
+
message,
|
|
185
|
+
...optionalParams,
|
|
186
|
+
])
|
|
187
|
+
this.printMessages(messages, context, 'log')
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Write an 'error' level log, if the configured level allows for it.
|
|
192
|
+
* Prints to `stderr` with newline.
|
|
193
|
+
*/
|
|
194
|
+
error(message: any, stackOrContext?: string): void
|
|
195
|
+
error(message: any, stack?: string, context?: string): void
|
|
196
|
+
error(message: any, ...optionalParams: [...any, string?, string?]): void
|
|
197
|
+
error(message: any, ...optionalParams: any[]) {
|
|
198
|
+
if (!this.isLevelEnabled('error')) {
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
const { messages, context, stack } =
|
|
202
|
+
this.getContextAndStackAndMessagesToPrint([message, ...optionalParams])
|
|
203
|
+
|
|
204
|
+
this.printMessages(messages, context, 'error', 'stderr', stack)
|
|
205
|
+
this.printStackTrace(stack!)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Write a 'warn' level log, if the configured level allows for it.
|
|
210
|
+
* Prints to `stdout` with newline.
|
|
211
|
+
*/
|
|
212
|
+
warn(message: any, context?: string): void
|
|
213
|
+
warn(message: any, ...optionalParams: [...any, string?]): void
|
|
214
|
+
warn(message: any, ...optionalParams: any[]) {
|
|
215
|
+
if (!this.isLevelEnabled('warn')) {
|
|
216
|
+
return
|
|
217
|
+
}
|
|
218
|
+
const { messages, context } = this.getContextAndMessagesToPrint([
|
|
219
|
+
message,
|
|
220
|
+
...optionalParams,
|
|
221
|
+
])
|
|
222
|
+
this.printMessages(messages, context, 'warn')
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Write a 'debug' level log, if the configured level allows for it.
|
|
227
|
+
* Prints to `stdout` with newline.
|
|
228
|
+
*/
|
|
229
|
+
debug(message: any, context?: string): void
|
|
230
|
+
debug(message: any, ...optionalParams: [...any, string?]): void
|
|
231
|
+
debug(message: any, ...optionalParams: any[]) {
|
|
232
|
+
if (!this.isLevelEnabled('debug')) {
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
const { messages, context } = this.getContextAndMessagesToPrint([
|
|
236
|
+
message,
|
|
237
|
+
...optionalParams,
|
|
238
|
+
])
|
|
239
|
+
this.printMessages(messages, context, 'debug')
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Write a 'verbose' level log, if the configured level allows for it.
|
|
244
|
+
* Prints to `stdout` with newline.
|
|
245
|
+
*/
|
|
246
|
+
verbose(message: any, context?: string): void
|
|
247
|
+
verbose(message: any, ...optionalParams: [...any, string?]): void
|
|
248
|
+
verbose(message: any, ...optionalParams: any[]) {
|
|
249
|
+
if (!this.isLevelEnabled('verbose')) {
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
const { messages, context } = this.getContextAndMessagesToPrint([
|
|
253
|
+
message,
|
|
254
|
+
...optionalParams,
|
|
255
|
+
])
|
|
256
|
+
this.printMessages(messages, context, 'verbose')
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Write a 'fatal' level log, if the configured level allows for it.
|
|
261
|
+
* Prints to `stdout` with newline.
|
|
262
|
+
*/
|
|
263
|
+
fatal(message: any, context?: string): void
|
|
264
|
+
fatal(message: any, ...optionalParams: [...any, string?]): void
|
|
265
|
+
fatal(message: any, ...optionalParams: any[]) {
|
|
266
|
+
if (!this.isLevelEnabled('fatal')) {
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
const { messages, context } = this.getContextAndMessagesToPrint([
|
|
270
|
+
message,
|
|
271
|
+
...optionalParams,
|
|
272
|
+
])
|
|
273
|
+
this.printMessages(messages, context, 'fatal')
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Set log levels
|
|
278
|
+
* @param levels log levels
|
|
279
|
+
*/
|
|
280
|
+
setLogLevels(levels: LogLevel[]) {
|
|
281
|
+
if (!this.options) {
|
|
282
|
+
this.options = {}
|
|
283
|
+
}
|
|
284
|
+
this.options.logLevels = levels
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Set logger context
|
|
289
|
+
* @param context context
|
|
290
|
+
*/
|
|
291
|
+
setContext(context: string) {
|
|
292
|
+
this.context = context
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Resets the logger context to the value that was passed in the constructor.
|
|
297
|
+
*/
|
|
298
|
+
resetContext() {
|
|
299
|
+
this.context = this.originalContext
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
isLevelEnabled(level: LogLevel): boolean {
|
|
303
|
+
const logLevels = this.options?.logLevels
|
|
304
|
+
return isLogLevelEnabled(level, logLevels)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
protected getTimestamp(): string {
|
|
308
|
+
return dateTimeFormatter.format(Date.now())
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
protected printMessages(
|
|
312
|
+
messages: unknown[],
|
|
313
|
+
context = '',
|
|
314
|
+
logLevel: LogLevel = 'log',
|
|
315
|
+
writeStreamType?: 'stdout' | 'stderr',
|
|
316
|
+
errorStack?: unknown,
|
|
317
|
+
) {
|
|
318
|
+
messages.forEach((message) => {
|
|
319
|
+
if (this.options.json) {
|
|
320
|
+
this.printAsJson(message, {
|
|
321
|
+
context,
|
|
322
|
+
logLevel,
|
|
323
|
+
writeStreamType,
|
|
324
|
+
errorStack,
|
|
325
|
+
})
|
|
326
|
+
return
|
|
327
|
+
}
|
|
328
|
+
const pidMessage = this.formatPid(process.pid)
|
|
329
|
+
const contextMessage = this.formatContext(context)
|
|
330
|
+
const timestampDiff = this.updateAndGetTimestampDiff()
|
|
331
|
+
const formattedLogLevel = logLevel.toUpperCase().padStart(7, ' ')
|
|
332
|
+
const formattedMessage = this.formatMessage(
|
|
333
|
+
logLevel,
|
|
334
|
+
message,
|
|
335
|
+
pidMessage,
|
|
336
|
+
formattedLogLevel,
|
|
337
|
+
contextMessage,
|
|
338
|
+
timestampDiff,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
process[writeStreamType ?? 'stdout'].write(formattedMessage)
|
|
342
|
+
})
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
protected printAsJson(
|
|
346
|
+
message: unknown,
|
|
347
|
+
options: {
|
|
348
|
+
context: string
|
|
349
|
+
logLevel: LogLevel
|
|
350
|
+
writeStreamType?: 'stdout' | 'stderr'
|
|
351
|
+
errorStack?: unknown
|
|
352
|
+
},
|
|
353
|
+
) {
|
|
354
|
+
type JsonLogObject = {
|
|
355
|
+
level: LogLevel
|
|
356
|
+
pid: number
|
|
357
|
+
timestamp: number
|
|
358
|
+
message: unknown
|
|
359
|
+
context?: string
|
|
360
|
+
stack?: unknown
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const logObject: JsonLogObject = {
|
|
364
|
+
level: options.logLevel,
|
|
365
|
+
pid: process.pid,
|
|
366
|
+
timestamp: Date.now(),
|
|
367
|
+
message,
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (options.context) {
|
|
371
|
+
logObject.context = options.context
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (options.errorStack) {
|
|
375
|
+
logObject.stack = options.errorStack
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const formattedMessage =
|
|
379
|
+
!this.options.colors && this.inspectOptions.compact === true
|
|
380
|
+
? JSON.stringify(logObject, this.stringifyReplacer)
|
|
381
|
+
: inspect(logObject, this.inspectOptions)
|
|
382
|
+
process[options.writeStreamType ?? 'stdout'].write(`${formattedMessage}\n`)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
protected formatPid(pid: number) {
|
|
386
|
+
return `[${this.options.prefix}] ${pid} - `
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
protected formatContext(context: string): string {
|
|
390
|
+
if (!context) {
|
|
391
|
+
return ''
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
context = `[${context}] `
|
|
395
|
+
return this.options.colors ? yellow(context) : context
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
protected formatMessage(
|
|
399
|
+
logLevel: LogLevel,
|
|
400
|
+
message: unknown,
|
|
401
|
+
pidMessage: string,
|
|
402
|
+
formattedLogLevel: string,
|
|
403
|
+
contextMessage: string,
|
|
404
|
+
timestampDiff: string,
|
|
405
|
+
) {
|
|
406
|
+
const output = this.stringifyMessage(message, logLevel)
|
|
407
|
+
pidMessage = this.colorize(pidMessage, logLevel)
|
|
408
|
+
formattedLogLevel = this.colorize(formattedLogLevel, logLevel)
|
|
409
|
+
return `${pidMessage}${this.getTimestamp()} ${formattedLogLevel} ${contextMessage}${output}${timestampDiff}\n`
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
protected stringifyMessage(message: unknown, logLevel: LogLevel): string {
|
|
413
|
+
if (isFunction(message)) {
|
|
414
|
+
const messageAsStr = Function.prototype.toString.call(message)
|
|
415
|
+
const isClass = messageAsStr.startsWith('class ')
|
|
416
|
+
if (isClass) {
|
|
417
|
+
// If the message is a class, we will display the class name.
|
|
418
|
+
return this.stringifyMessage(message.name, logLevel)
|
|
419
|
+
}
|
|
420
|
+
// If the message is a non-class function, call it and re-resolve its value.
|
|
421
|
+
return this.stringifyMessage(message(), logLevel)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (typeof message === 'string') {
|
|
425
|
+
return this.colorize(message, logLevel)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const outputText = inspect(message, this.inspectOptions)
|
|
429
|
+
if (isPlainObject(message)) {
|
|
430
|
+
return `Object(${Object.keys(message).length}) ${outputText}`
|
|
431
|
+
}
|
|
432
|
+
if (Array.isArray(message)) {
|
|
433
|
+
return `Array(${message.length}) ${outputText}`
|
|
434
|
+
}
|
|
435
|
+
return outputText
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
protected colorize(message: string, logLevel: LogLevel) {
|
|
439
|
+
if (!this.options.colors || this.options.json) {
|
|
440
|
+
return message
|
|
441
|
+
}
|
|
442
|
+
const color = this.getColorByLogLevel(logLevel)
|
|
443
|
+
return color(message)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
protected printStackTrace(stack: string) {
|
|
447
|
+
if (!stack || this.options.json) {
|
|
448
|
+
return
|
|
449
|
+
}
|
|
450
|
+
process.stderr.write(`${stack}\n`)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
protected updateAndGetTimestampDiff(): string {
|
|
454
|
+
const includeTimestamp =
|
|
455
|
+
ConsoleLogger.lastTimestampAt && this.options?.timestamp
|
|
456
|
+
const result = includeTimestamp
|
|
457
|
+
? this.formatTimestampDiff(Date.now() - ConsoleLogger.lastTimestampAt!)
|
|
458
|
+
: ''
|
|
459
|
+
ConsoleLogger.lastTimestampAt = Date.now()
|
|
460
|
+
return result
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
protected formatTimestampDiff(timestampDiff: number) {
|
|
464
|
+
const formattedDiff = ` +${timestampDiff}ms`
|
|
465
|
+
return this.options.colors ? yellow(formattedDiff) : formattedDiff
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
protected getInspectOptions() {
|
|
469
|
+
let breakLength = this.options.breakLength
|
|
470
|
+
if (typeof breakLength === 'undefined') {
|
|
471
|
+
breakLength = this.options.colors
|
|
472
|
+
? this.options.compact
|
|
473
|
+
? Infinity
|
|
474
|
+
: undefined
|
|
475
|
+
: this.options.compact === false
|
|
476
|
+
? undefined
|
|
477
|
+
: Infinity // default breakLength to Infinity if inline is not set and colors is false
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const inspectOptions: InspectOptions = {
|
|
481
|
+
depth: this.options.depth ?? DEFAULT_DEPTH,
|
|
482
|
+
sorted: this.options.sorted,
|
|
483
|
+
showHidden: this.options.showHidden,
|
|
484
|
+
compact: this.options.compact ?? (this.options.json ? true : false),
|
|
485
|
+
colors: this.options.colors,
|
|
486
|
+
breakLength,
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (this.options.maxArrayLength) {
|
|
490
|
+
inspectOptions.maxArrayLength = this.options.maxArrayLength
|
|
491
|
+
}
|
|
492
|
+
if (this.options.maxStringLength) {
|
|
493
|
+
inspectOptions.maxStringLength = this.options.maxStringLength
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return inspectOptions
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
protected stringifyReplacer(key: string, value: unknown) {
|
|
500
|
+
// Mimic util.inspect behavior for JSON logger with compact on and colors off
|
|
501
|
+
if (typeof value === 'bigint') {
|
|
502
|
+
return value.toString()
|
|
503
|
+
}
|
|
504
|
+
if (typeof value === 'symbol') {
|
|
505
|
+
return value.toString()
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (
|
|
509
|
+
value instanceof Map ||
|
|
510
|
+
value instanceof Set ||
|
|
511
|
+
value instanceof Error
|
|
512
|
+
) {
|
|
513
|
+
return `${inspect(value, this.inspectOptions)}`
|
|
514
|
+
}
|
|
515
|
+
return value
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
private getContextAndMessagesToPrint(args: unknown[]) {
|
|
519
|
+
if (args?.length <= 1) {
|
|
520
|
+
return { messages: args, context: this.context }
|
|
521
|
+
}
|
|
522
|
+
const lastElement = args[args.length - 1]
|
|
523
|
+
const isContext = isString(lastElement)
|
|
524
|
+
if (!isContext) {
|
|
525
|
+
return { messages: args, context: this.context }
|
|
526
|
+
}
|
|
527
|
+
return {
|
|
528
|
+
context: lastElement,
|
|
529
|
+
messages: args.slice(0, args.length - 1),
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
private getContextAndStackAndMessagesToPrint(args: unknown[]) {
|
|
534
|
+
if (args.length === 2) {
|
|
535
|
+
return this.isStackFormat(args[1])
|
|
536
|
+
? {
|
|
537
|
+
messages: [args[0]],
|
|
538
|
+
stack: args[1] as string,
|
|
539
|
+
context: this.context,
|
|
540
|
+
}
|
|
541
|
+
: {
|
|
542
|
+
messages: [args[0]],
|
|
543
|
+
context: args[1] as string,
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
const { messages, context } = this.getContextAndMessagesToPrint(args)
|
|
548
|
+
if (messages?.length <= 1) {
|
|
549
|
+
return { messages, context }
|
|
550
|
+
}
|
|
551
|
+
const lastElement = messages[messages.length - 1]
|
|
552
|
+
const isStack = isString(lastElement)
|
|
553
|
+
// https://github.com/nestjs/nest/issues/11074#issuecomment-1421680060
|
|
554
|
+
if (!isStack && !isUndefined(lastElement)) {
|
|
555
|
+
return { messages, context }
|
|
556
|
+
}
|
|
557
|
+
return {
|
|
558
|
+
stack: lastElement,
|
|
559
|
+
messages: messages.slice(0, messages.length - 1),
|
|
560
|
+
context,
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
private isStackFormat(stack: unknown) {
|
|
565
|
+
if (!isString(stack) && !isUndefined(stack)) {
|
|
566
|
+
return false
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return /^(.)+\n\s+at .+:\d+:\d+/.test(stack!)
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
private getColorByLogLevel(level: LogLevel) {
|
|
573
|
+
switch (level) {
|
|
574
|
+
case 'debug':
|
|
575
|
+
return clc.magentaBright
|
|
576
|
+
case 'warn':
|
|
577
|
+
return clc.yellow
|
|
578
|
+
case 'error':
|
|
579
|
+
return clc.red
|
|
580
|
+
case 'verbose':
|
|
581
|
+
return clc.cyanBright
|
|
582
|
+
case 'fatal':
|
|
583
|
+
return clc.bold
|
|
584
|
+
default:
|
|
585
|
+
return clc.green
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './utils/index.mjs'
|
|
2
|
+
export * from './console-logger.service.mjs'
|
|
3
|
+
export * from './log-levels.mjs'
|
|
4
|
+
export * from './logger.factory.mjs'
|
|
5
|
+
export * from './logger.service.mjs'
|
|
6
|
+
export * from './logger-service.interface.mjs'
|
|
7
|
+
export * from './pino-wrapper.mjs'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { LogLevel } from './log-levels.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @publicApi
|
|
5
|
+
*/
|
|
6
|
+
export interface LoggerService {
|
|
7
|
+
/**
|
|
8
|
+
* Write a 'log' level log.
|
|
9
|
+
*/
|
|
10
|
+
log(message: any, ...optionalParams: any[]): any
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Write an 'error' level log.
|
|
14
|
+
*/
|
|
15
|
+
error(message: any, ...optionalParams: any[]): any
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Write a 'warn' level log.
|
|
19
|
+
*/
|
|
20
|
+
warn(message: any, ...optionalParams: any[]): any
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Write a 'debug' level log.
|
|
24
|
+
*/
|
|
25
|
+
debug?(message: any, ...optionalParams: any[]): any
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Write a 'verbose' level log.
|
|
29
|
+
*/
|
|
30
|
+
verbose?(message: any, ...optionalParams: any[]): any
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Write a 'fatal' level log.
|
|
34
|
+
*/
|
|
35
|
+
fatal?(message: any, ...optionalParams: any[]): any
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Set log levels.
|
|
39
|
+
* @param levels log levels
|
|
40
|
+
*/
|
|
41
|
+
setLogLevels?(levels: LogLevel[]): any
|
|
42
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Injectable,
|
|
5
|
+
InjectableType,
|
|
6
|
+
InjectionToken,
|
|
7
|
+
} from '../service-locator/index.mjs'
|
|
8
|
+
import { LoggerInstance } from './logger.service.mjs'
|
|
9
|
+
|
|
10
|
+
export const LoggerInjectionToken = 'LoggerInjectionToken'
|
|
11
|
+
|
|
12
|
+
export const LoggerOptions = z
|
|
13
|
+
.object({
|
|
14
|
+
context: z.string().optional(),
|
|
15
|
+
options: z
|
|
16
|
+
.object({
|
|
17
|
+
timestamp: z.boolean().optional(),
|
|
18
|
+
})
|
|
19
|
+
.optional(),
|
|
20
|
+
})
|
|
21
|
+
.optional()
|
|
22
|
+
|
|
23
|
+
export const Logger = InjectionToken.create<
|
|
24
|
+
LoggerInstance,
|
|
25
|
+
typeof LoggerOptions
|
|
26
|
+
>(LoggerInjectionToken, LoggerOptions)
|
|
27
|
+
|
|
28
|
+
@Injectable({
|
|
29
|
+
type: InjectableType.Factory,
|
|
30
|
+
token: Logger,
|
|
31
|
+
})
|
|
32
|
+
export class LoggerFactory {
|
|
33
|
+
create(ctx: any, args: z.infer<typeof LoggerOptions>) {
|
|
34
|
+
// @ts-expect-error We don't need to support this in the current version
|
|
35
|
+
return new LoggerInstance(args?.context, args?.options)
|
|
36
|
+
}
|
|
37
|
+
}
|