@pori15/logixlysia 0.0.1 → 6.0.2
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/README.md +1 -1
- package/dist/index.d.ts +45 -14
- package/dist/index.js +7 -7
- package/package.json +13 -4
- package/src/Error/errors.ts +258 -258
- package/src/Error/type.ts +51 -51
- package/src/extensions/banner.ts +26 -26
- package/src/extensions/index.ts +28 -28
- package/src/helpers/status.ts +58 -58
- package/src/index.ts +162 -141
- package/src/interfaces.ts +138 -136
- package/src/logger/create-logger.ts +240 -246
- package/src/logger/handle-http-error.ts +60 -62
- package/src/logger/index.ts +138 -125
- package/src/output/file.ts +85 -85
- package/src/output/fs.ts +5 -5
- package/src/output/index.ts +58 -58
- package/src/output/rotation-manager.ts +122 -122
- package/src/utils/error.ts +13 -15
- package/src/utils/handle-error.ts +41 -46
- package/src/utils/rotation.ts +91 -91
package/src/logger/index.ts
CHANGED
|
@@ -1,125 +1,138 @@
|
|
|
1
|
-
import pino from 'pino'
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
1
|
+
import pino from 'pino'
|
|
2
|
+
import type {
|
|
3
|
+
LogFilter,
|
|
4
|
+
Logger,
|
|
5
|
+
LogLevel,
|
|
6
|
+
Options,
|
|
7
|
+
Pino,
|
|
8
|
+
StoreData
|
|
9
|
+
} from '../interfaces'
|
|
10
|
+
import { logToTransports } from '../output'
|
|
11
|
+
import { logToFile } from '../output/file'
|
|
12
|
+
import { formatLine } from './create-logger'
|
|
13
|
+
import { handleHttpError } from './handle-http-error'
|
|
14
|
+
|
|
15
|
+
export const createLogger = (options: Options = {}): Logger => {
|
|
16
|
+
const config = options.config
|
|
17
|
+
|
|
18
|
+
const pinoConfig = config?.pino
|
|
19
|
+
const { prettyPrint, ...pinoOptions } = pinoConfig ?? {}
|
|
20
|
+
|
|
21
|
+
const shouldPrettyPrint =
|
|
22
|
+
prettyPrint === true && pinoOptions.transport === undefined
|
|
23
|
+
|
|
24
|
+
const transport = shouldPrettyPrint
|
|
25
|
+
? pino.transport({
|
|
26
|
+
target: 'pino-pretty',
|
|
27
|
+
options: {
|
|
28
|
+
colorize: process.stdout?.isTTY === true,
|
|
29
|
+
translateTime: config?.timestamp?.translateTime,
|
|
30
|
+
messageKey: pinoOptions.messageKey,
|
|
31
|
+
errorKey: pinoOptions.errorKey
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
: pinoOptions.transport
|
|
35
|
+
|
|
36
|
+
const pinoLogger: Pino = pino({
|
|
37
|
+
...pinoOptions,
|
|
38
|
+
level: pinoOptions.level ?? 'info',
|
|
39
|
+
messageKey: pinoOptions.messageKey,
|
|
40
|
+
errorKey: pinoOptions.errorKey,
|
|
41
|
+
transport
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const shouldLog = (level: LogLevel, logFilter?: LogFilter): boolean => {
|
|
45
|
+
if (!logFilter?.level || logFilter.level.length === 0) {
|
|
46
|
+
return true
|
|
47
|
+
}
|
|
48
|
+
return logFilter.level.includes(level)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const log = (
|
|
52
|
+
level: LogLevel,
|
|
53
|
+
request: Request,
|
|
54
|
+
data: Record<string, unknown>,
|
|
55
|
+
store: StoreData
|
|
56
|
+
): void => {
|
|
57
|
+
// Check if this log level should be filtered
|
|
58
|
+
if (!shouldLog(level, config?.logFilter)) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
logToTransports({ level, request, data, store, options })
|
|
63
|
+
|
|
64
|
+
const useTransportsOnly = config?.useTransportsOnly === true
|
|
65
|
+
const disableInternalLogger = config?.disableInternalLogger === true
|
|
66
|
+
const disableFileLogging = config?.disableFileLogging === true
|
|
67
|
+
|
|
68
|
+
if (!(useTransportsOnly || disableFileLogging)) {
|
|
69
|
+
const filePath = config?.logFilePath
|
|
70
|
+
if (filePath) {
|
|
71
|
+
logToFile({ filePath, level, request, data, store, options }).catch(
|
|
72
|
+
() => {
|
|
73
|
+
// Ignore errors
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (useTransportsOnly || disableInternalLogger) {
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const message = formatLine({ level, request, data, store, options })
|
|
84
|
+
|
|
85
|
+
switch (level) {
|
|
86
|
+
case 'DEBUG': {
|
|
87
|
+
console.debug(message)
|
|
88
|
+
break
|
|
89
|
+
}
|
|
90
|
+
case 'INFO': {
|
|
91
|
+
console.info(message)
|
|
92
|
+
break
|
|
93
|
+
}
|
|
94
|
+
case 'WARNING': {
|
|
95
|
+
console.warn(message)
|
|
96
|
+
break
|
|
97
|
+
}
|
|
98
|
+
case 'ERROR': {
|
|
99
|
+
console.error(message)
|
|
100
|
+
break
|
|
101
|
+
}
|
|
102
|
+
default: {
|
|
103
|
+
console.log(message)
|
|
104
|
+
break
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const logWithContext = (
|
|
110
|
+
level: LogLevel,
|
|
111
|
+
request: Request,
|
|
112
|
+
message: string,
|
|
113
|
+
context?: Record<string, unknown>
|
|
114
|
+
): void => {
|
|
115
|
+
const store: StoreData = { beforeTime: process.hrtime.bigint() }
|
|
116
|
+
log(level, request, { message, context }, store)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
pino: pinoLogger,
|
|
121
|
+
log,
|
|
122
|
+
handleHttpError: (request, error, store) => {
|
|
123
|
+
handleHttpError(request, error, store, options)
|
|
124
|
+
},
|
|
125
|
+
debug: (request, message, context) => {
|
|
126
|
+
logWithContext('DEBUG', request, message, context)
|
|
127
|
+
},
|
|
128
|
+
info: (request, message, context) => {
|
|
129
|
+
logWithContext('INFO', request, message, context)
|
|
130
|
+
},
|
|
131
|
+
warn: (request, message, context) => {
|
|
132
|
+
logWithContext('WARNING', request, message, context)
|
|
133
|
+
},
|
|
134
|
+
error: (request, message, context) => {
|
|
135
|
+
logWithContext('ERROR', request, message, context)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
package/src/output/file.ts
CHANGED
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
import { appendFile } from 'node:fs/promises'
|
|
2
|
-
import { dirname } from 'node:path'
|
|
3
|
-
import type { LogLevel, Options, RequestInfo, StoreData } from '../interfaces'
|
|
4
|
-
import { ensureDir } from './fs'
|
|
5
|
-
import { performRotation, shouldRotate } from './rotation-manager'
|
|
6
|
-
|
|
7
|
-
interface LogToFileInput {
|
|
8
|
-
filePath: string
|
|
9
|
-
level: LogLevel
|
|
10
|
-
request: RequestInfo
|
|
11
|
-
data: Record<string, unknown>
|
|
12
|
-
store: StoreData
|
|
13
|
-
options: Options
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const logToFile = async (
|
|
17
|
-
...args:
|
|
18
|
-
| [LogToFileInput]
|
|
19
|
-
| [
|
|
20
|
-
string,
|
|
21
|
-
LogLevel,
|
|
22
|
-
RequestInfo,
|
|
23
|
-
Record<string, unknown>,
|
|
24
|
-
StoreData,
|
|
25
|
-
Options
|
|
26
|
-
]
|
|
27
|
-
): Promise<void> => {
|
|
28
|
-
const input: LogToFileInput =
|
|
29
|
-
typeof args[0] === 'string'
|
|
30
|
-
? (() => {
|
|
31
|
-
const [
|
|
32
|
-
filePathArg,
|
|
33
|
-
levelArg,
|
|
34
|
-
requestArg,
|
|
35
|
-
dataArg,
|
|
36
|
-
storeArg,
|
|
37
|
-
optionsArg
|
|
38
|
-
] = args as [
|
|
39
|
-
string,
|
|
40
|
-
LogLevel,
|
|
41
|
-
RequestInfo,
|
|
42
|
-
Record<string, unknown>,
|
|
43
|
-
StoreData,
|
|
44
|
-
Options
|
|
45
|
-
]
|
|
46
|
-
return {
|
|
47
|
-
filePath: filePathArg,
|
|
48
|
-
level: levelArg,
|
|
49
|
-
request: requestArg,
|
|
50
|
-
data: dataArg,
|
|
51
|
-
store: storeArg,
|
|
52
|
-
options: optionsArg
|
|
53
|
-
}
|
|
54
|
-
})()
|
|
55
|
-
: args[0]
|
|
56
|
-
|
|
57
|
-
const { filePath, level, request, data, store, options } = input
|
|
58
|
-
const config = options.config
|
|
59
|
-
const useTransportsOnly = config?.useTransportsOnly === true
|
|
60
|
-
const disableFileLogging = config?.disableFileLogging === true
|
|
61
|
-
if (useTransportsOnly || disableFileLogging) {
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const message = typeof data.message === 'string' ? data.message : ''
|
|
66
|
-
const durationMs =
|
|
67
|
-
store.beforeTime === BigInt(0)
|
|
68
|
-
? 0
|
|
69
|
-
: Number(process.hrtime.bigint() - store.beforeTime) / 1_000_000
|
|
70
|
-
|
|
71
|
-
const line = `${level} ${durationMs.toFixed(2)}ms ${request.method} ${new URL(request.url).pathname} ${message}\n`
|
|
72
|
-
|
|
73
|
-
await ensureDir(dirname(filePath))
|
|
74
|
-
await appendFile(filePath, line, { encoding: 'utf-8' })
|
|
75
|
-
|
|
76
|
-
const rotation = config?.logRotation
|
|
77
|
-
if (!rotation) {
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const should = await shouldRotate(filePath, rotation)
|
|
82
|
-
if (should) {
|
|
83
|
-
await performRotation(filePath, rotation)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
1
|
+
import { appendFile } from 'node:fs/promises'
|
|
2
|
+
import { dirname } from 'node:path'
|
|
3
|
+
import type { LogLevel, Options, RequestInfo, StoreData } from '../interfaces'
|
|
4
|
+
import { ensureDir } from './fs'
|
|
5
|
+
import { performRotation, shouldRotate } from './rotation-manager'
|
|
6
|
+
|
|
7
|
+
interface LogToFileInput {
|
|
8
|
+
filePath: string
|
|
9
|
+
level: LogLevel
|
|
10
|
+
request: RequestInfo
|
|
11
|
+
data: Record<string, unknown>
|
|
12
|
+
store: StoreData
|
|
13
|
+
options: Options
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const logToFile = async (
|
|
17
|
+
...args:
|
|
18
|
+
| [LogToFileInput]
|
|
19
|
+
| [
|
|
20
|
+
string,
|
|
21
|
+
LogLevel,
|
|
22
|
+
RequestInfo,
|
|
23
|
+
Record<string, unknown>,
|
|
24
|
+
StoreData,
|
|
25
|
+
Options
|
|
26
|
+
]
|
|
27
|
+
): Promise<void> => {
|
|
28
|
+
const input: LogToFileInput =
|
|
29
|
+
typeof args[0] === 'string'
|
|
30
|
+
? (() => {
|
|
31
|
+
const [
|
|
32
|
+
filePathArg,
|
|
33
|
+
levelArg,
|
|
34
|
+
requestArg,
|
|
35
|
+
dataArg,
|
|
36
|
+
storeArg,
|
|
37
|
+
optionsArg
|
|
38
|
+
] = args as [
|
|
39
|
+
string,
|
|
40
|
+
LogLevel,
|
|
41
|
+
RequestInfo,
|
|
42
|
+
Record<string, unknown>,
|
|
43
|
+
StoreData,
|
|
44
|
+
Options
|
|
45
|
+
]
|
|
46
|
+
return {
|
|
47
|
+
filePath: filePathArg,
|
|
48
|
+
level: levelArg,
|
|
49
|
+
request: requestArg,
|
|
50
|
+
data: dataArg,
|
|
51
|
+
store: storeArg,
|
|
52
|
+
options: optionsArg
|
|
53
|
+
}
|
|
54
|
+
})()
|
|
55
|
+
: args[0]
|
|
56
|
+
|
|
57
|
+
const { filePath, level, request, data, store, options } = input
|
|
58
|
+
const config = options.config
|
|
59
|
+
const useTransportsOnly = config?.useTransportsOnly === true
|
|
60
|
+
const disableFileLogging = config?.disableFileLogging === true
|
|
61
|
+
if (useTransportsOnly || disableFileLogging) {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const message = typeof data.message === 'string' ? data.message : ''
|
|
66
|
+
const durationMs =
|
|
67
|
+
store.beforeTime === BigInt(0)
|
|
68
|
+
? 0
|
|
69
|
+
: Number(process.hrtime.bigint() - store.beforeTime) / 1_000_000
|
|
70
|
+
|
|
71
|
+
const line = `${level} ${durationMs.toFixed(2)}ms ${request.method} ${new URL(request.url).pathname} ${message}\n`
|
|
72
|
+
|
|
73
|
+
await ensureDir(dirname(filePath))
|
|
74
|
+
await appendFile(filePath, line, { encoding: 'utf-8' })
|
|
75
|
+
|
|
76
|
+
const rotation = config?.logRotation
|
|
77
|
+
if (!rotation) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const should = await shouldRotate(filePath, rotation)
|
|
82
|
+
if (should) {
|
|
83
|
+
await performRotation(filePath, rotation)
|
|
84
|
+
}
|
|
85
|
+
}
|
package/src/output/fs.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { promises as fs } from 'node:fs'
|
|
2
|
-
|
|
3
|
-
export const ensureDir = async (dirPath: string): Promise<void> => {
|
|
4
|
-
await fs.mkdir(dirPath, { recursive: true })
|
|
5
|
-
}
|
|
1
|
+
import { promises as fs } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
export const ensureDir = async (dirPath: string): Promise<void> => {
|
|
4
|
+
await fs.mkdir(dirPath, { recursive: true })
|
|
5
|
+
}
|
package/src/output/index.ts
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import type { LogLevel, Options, Request, StoreData } from '../interfaces'
|
|
2
|
-
|
|
3
|
-
interface LogToTransportsInput {
|
|
4
|
-
level: LogLevel
|
|
5
|
-
request: Request
|
|
6
|
-
data: Record<string, unknown>
|
|
7
|
-
store: StoreData
|
|
8
|
-
options: Options
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const logToTransports = (
|
|
12
|
-
...args:
|
|
13
|
-
| [LogToTransportsInput]
|
|
14
|
-
| [LogLevel, Request, Record<string, unknown>, StoreData, Options]
|
|
15
|
-
): void => {
|
|
16
|
-
const input: LogToTransportsInput =
|
|
17
|
-
typeof args[0] === 'string'
|
|
18
|
-
? {
|
|
19
|
-
level: args[0],
|
|
20
|
-
request: args[1],
|
|
21
|
-
data: args[2],
|
|
22
|
-
store: args[3],
|
|
23
|
-
options: args[4]
|
|
24
|
-
}
|
|
25
|
-
: args[0]
|
|
26
|
-
|
|
27
|
-
const { level, request, data, store, options } = input
|
|
28
|
-
const transports = options.config?.transports ?? []
|
|
29
|
-
if (transports.length === 0) {
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const message = typeof data.message === 'string' ? data.message : ''
|
|
34
|
-
const meta: Record<string, unknown> = {
|
|
35
|
-
request: {
|
|
36
|
-
method: request.method,
|
|
37
|
-
url: request.url
|
|
38
|
-
},
|
|
39
|
-
...data,
|
|
40
|
-
beforeTime: store.beforeTime
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
for (const transport of transports) {
|
|
44
|
-
try {
|
|
45
|
-
const result = transport.log(level, message, meta)
|
|
46
|
-
if (
|
|
47
|
-
result &&
|
|
48
|
-
typeof (result as { catch?: unknown }).catch === 'function'
|
|
49
|
-
) {
|
|
50
|
-
;(result as Promise<void>).catch(() => {
|
|
51
|
-
// Ignore errors
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
} catch {
|
|
55
|
-
// Transport failures must never crash application logging.
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
1
|
+
import type { LogLevel, Options, Request, StoreData } from '../interfaces'
|
|
2
|
+
|
|
3
|
+
interface LogToTransportsInput {
|
|
4
|
+
level: LogLevel
|
|
5
|
+
request: Request
|
|
6
|
+
data: Record<string, unknown>
|
|
7
|
+
store: StoreData
|
|
8
|
+
options: Options
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const logToTransports = (
|
|
12
|
+
...args:
|
|
13
|
+
| [LogToTransportsInput]
|
|
14
|
+
| [LogLevel, Request, Record<string, unknown>, StoreData, Options]
|
|
15
|
+
): void => {
|
|
16
|
+
const input: LogToTransportsInput =
|
|
17
|
+
typeof args[0] === 'string'
|
|
18
|
+
? {
|
|
19
|
+
level: args[0],
|
|
20
|
+
request: args[1],
|
|
21
|
+
data: args[2],
|
|
22
|
+
store: args[3],
|
|
23
|
+
options: args[4]
|
|
24
|
+
}
|
|
25
|
+
: args[0]
|
|
26
|
+
|
|
27
|
+
const { level, request, data, store, options } = input
|
|
28
|
+
const transports = options.config?.transports ?? []
|
|
29
|
+
if (transports.length === 0) {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const message = typeof data.message === 'string' ? data.message : ''
|
|
34
|
+
const meta: Record<string, unknown> = {
|
|
35
|
+
request: {
|
|
36
|
+
method: request.method,
|
|
37
|
+
url: request.url
|
|
38
|
+
},
|
|
39
|
+
...data,
|
|
40
|
+
beforeTime: store.beforeTime
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (const transport of transports) {
|
|
44
|
+
try {
|
|
45
|
+
const result = transport.log(level, message, meta)
|
|
46
|
+
if (
|
|
47
|
+
result &&
|
|
48
|
+
typeof (result as { catch?: unknown }).catch === 'function'
|
|
49
|
+
) {
|
|
50
|
+
;(result as Promise<void>).catch(() => {
|
|
51
|
+
// Ignore errors
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
// Transport failures must never crash application logging.
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|