@darksheep/logger 1.1.0 → 1.3.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 +21 -0
- package/README.md +41 -1
- package/package.json +3 -3
- package/src/formatters/formatter-console/stack.js +183 -0
- package/src/formatters/formatter-console.js +4 -121
- package/src/logger.js +9 -0
- package/src/utilities/colour.js +2 -2
- package/src/utilities/environment.js +20 -12
- package/src/utilities/resource-usage.js +42 -0
- package/src/utilities/stacktrace.js +4 -6
- package/types/formatters/formatter-console/stack.d.ts +18 -0
- package/types/formatters/formatter-console.d.ts +1 -4
- package/types/utilities/colour.d.ts +2 -2
- package/types/utilities/environment.d.ts +9 -3
- package/types/utilities/resource-usage.d.ts +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.0](https://github.com/DarkSheepSoftware/node-packages/compare/logger-v1.2.0...logger-v1.3.0) (2025-10-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### 🌟 Features
|
|
7
|
+
|
|
8
|
+
* Support node 24 ([#761](https://github.com/DarkSheepSoftware/node-packages/issues/761)) ([f13caae](https://github.com/DarkSheepSoftware/node-packages/commit/f13caaef978c7a657e4599f775e0a62d1738f475))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @darksheep/environment bumped from 3.1.0 to 3.2.0
|
|
16
|
+
|
|
17
|
+
## [1.2.0](https://github.com/DarkSheepSoftware/node-packages/compare/logger-v1.1.0...logger-v1.2.0) (2025-04-19)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### 🌟 Features
|
|
21
|
+
|
|
22
|
+
* Improve stacktrace rendering and add resource usage options ([#621](https://github.com/DarkSheepSoftware/node-packages/issues/621)) ([2998c6d](https://github.com/DarkSheepSoftware/node-packages/commit/2998c6da2271673120e0673c6350555e2cfa7817))
|
|
23
|
+
|
|
3
24
|
## [1.1.0](https://github.com/DarkSheepSoftware/node-packages/compare/logger-v1.0.10...logger-v1.1.0) (2025-03-25)
|
|
4
25
|
|
|
5
26
|
|
package/README.md
CHANGED
|
@@ -188,4 +188,44 @@ const output = {
|
|
|
188
188
|
|
|
189
189
|
#### `LOG_CALLSITES`
|
|
190
190
|
|
|
191
|
-
This is
|
|
191
|
+
This is a boolean to indicate whether or not the location of the place calling the log should be added to the context. (Caution may not work if you're using a bundler).
|
|
192
|
+
|
|
193
|
+
This is added to the context in the `source` property and has the form:
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
{
|
|
197
|
+
file: 'logger/example.js',
|
|
198
|
+
methodName: '<unknown>',
|
|
199
|
+
line: 54,
|
|
200
|
+
column: 4
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### `LOG_CPU`, `LOG_MEMORY`
|
|
205
|
+
|
|
206
|
+
These are booleans to indicate whether to log current [memory usage](https://nodejs.org/api/process.html#processmemoryusage) and [cpu usage](https://nodejs.org/api/process.html#processcpuusagepreviousvalue).
|
|
207
|
+
|
|
208
|
+
Cpu usage is added to the context in the `cpuUsage` property and has the following form:
|
|
209
|
+
```js
|
|
210
|
+
{
|
|
211
|
+
// Time between `cpuUsage` calls (microseconds)
|
|
212
|
+
elapsed: 735,
|
|
213
|
+
// Time spent in both `system` and `user` code (microseconds)
|
|
214
|
+
total: 237099,
|
|
215
|
+
// Time spent in `system` code (microseconds)
|
|
216
|
+
system: 37937,
|
|
217
|
+
// Time spent in `user` code (microseconds)
|
|
218
|
+
user: 199162
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Memory usage is added to the context in the `memoryUsage` property and has the following form, please see the [nodejs documentation (process.memoryUsage())](https://nodejs.org/api/process.html#processmemoryusage) for more information on properties
|
|
223
|
+
```js
|
|
224
|
+
{
|
|
225
|
+
arrayBuffers: 0.104148,
|
|
226
|
+
external: 3.523992,
|
|
227
|
+
heapTotal: 19.533824,
|
|
228
|
+
heapUsed: 11.618472,
|
|
229
|
+
rss: 79.192064
|
|
230
|
+
}
|
|
231
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@darksheep/logger",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Logging your stuff to where ever you want it",
|
|
5
5
|
"license": "UNLICENCED",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"test:watch": "node --watch --test src/**/*.test.js"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@darksheep/environment": "3.
|
|
24
|
+
"@darksheep/environment": "3.2.0",
|
|
25
25
|
"deepmerge-ts": "7.1.5",
|
|
26
26
|
"stacktrace-parser": "0.1.11",
|
|
27
27
|
"traverse": "0.6.11"
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
"nock": "~14.0.0"
|
|
32
32
|
},
|
|
33
33
|
"engines": {
|
|
34
|
-
"node": "^20.13.1 ||
|
|
34
|
+
"node": "^20.13.1 || >=22.2.0"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { ColourOptions } from '../../utilities/colour.js';
|
|
3
|
+
* @import { Callsite } from '../../utilities/log-types.js';
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { colourString } from '../../utilities/colour.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {{ hide?: boolean }} HideOption
|
|
10
|
+
* @typedef {(
|
|
11
|
+
* & HideOption
|
|
12
|
+
* & {
|
|
13
|
+
* Line?: Omit<ColourOptions, 'reset'>;
|
|
14
|
+
* FunctionName?: Omit<ColourOptions, 'reset'> & HideOption;
|
|
15
|
+
* FilePath?: Omit<ColourOptions, 'reset'>;
|
|
16
|
+
* LineNumber?: Omit<ColourOptions, 'reset'> & HideOption;
|
|
17
|
+
* ColumnNumber?: Omit<ColourOptions, 'reset'> & HideOption;
|
|
18
|
+
* }
|
|
19
|
+
* )} LineOptions
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* @type {{
|
|
23
|
+
* moduleName?: Omit<ColourOptions, 'reset'>;
|
|
24
|
+
* internalName?: Omit<ColourOptions, 'reset'>;
|
|
25
|
+
* app?: LineOptions;
|
|
26
|
+
* module?: LineOptions;
|
|
27
|
+
* internal?: LineOptions;
|
|
28
|
+
* }}
|
|
29
|
+
*/
|
|
30
|
+
const Colours = {
|
|
31
|
+
moduleName: { effects: [ 'bold', 'underline' ] },
|
|
32
|
+
|
|
33
|
+
app: {
|
|
34
|
+
FunctionName: { foreground: 'white' },
|
|
35
|
+
FilePath: { foreground: 'blue', foregroundMode: 'bright' },
|
|
36
|
+
ColumnNumber: { hide: true },
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
module: {
|
|
40
|
+
Line: { foreground: 'yellow' },
|
|
41
|
+
FunctionName: { foreground: 'yellow', effects: [ 'bold' ] },
|
|
42
|
+
ColumnNumber: { hide: true },
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
internal: {
|
|
46
|
+
// hide: true,
|
|
47
|
+
Line: { foreground: 'black', foregroundMode: 'bright' },
|
|
48
|
+
ColumnNumber: { hide: true },
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const internalNameMatch = /(?<=^(?:node:)?internal\/)[^/]+/gu;
|
|
53
|
+
const nodeNameMatch = /(?<=^\w+:)[a-z]\w+$/gu;
|
|
54
|
+
const moduleNameMatch = /(?<=node_modules\/)(?:@[-0-9a-z~][-.0-9_a-z~]*\/)?[-0-9a-z~][-.0-9_a-z~]*(?=\/|$)/gu;
|
|
55
|
+
const modulePnpmMatch = /(?<=node_modules\/\.store\/)(?:@[-0-9a-z~][-.0-9_a-z~]*\/)?[-0-9a-z~][-.0-9_a-z~]*(?=-\w+-\d+\.\d+\.\d+-[0-9a-f]+\/)/gu;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {Callsite} callsite - The callsite to underline.
|
|
59
|
+
* @param {ColourOptions} [lineColour] - The colour of the main string.
|
|
60
|
+
* @returns {string}
|
|
61
|
+
*/
|
|
62
|
+
function highlightFilePath(callsite, lineColour) {
|
|
63
|
+
const reset = lineColour ?? true;
|
|
64
|
+
|
|
65
|
+
const moduleOptions = { ...Colours.moduleName, reset };
|
|
66
|
+
const internalOptions = { ...Colours.moduleName, ...Colours.internalName, reset };
|
|
67
|
+
|
|
68
|
+
const file = callsite.file
|
|
69
|
+
.replaceAll(internalNameMatch, (string) => colourString(string, internalOptions))
|
|
70
|
+
.replaceAll(nodeNameMatch, (string) => colourString(string, internalOptions))
|
|
71
|
+
.replaceAll(moduleNameMatch, (string) => colourString(string, moduleOptions))
|
|
72
|
+
.replaceAll(modulePnpmMatch, (string) => colourString(string, moduleOptions));
|
|
73
|
+
|
|
74
|
+
return colourString(file, lineColour);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {number | undefined} [number] - The line or column number.
|
|
79
|
+
* @param {(ColourOptions & HideOption) | undefined} [options] - The formatting options.
|
|
80
|
+
* @param {string | undefined} [colon] - The formatting options.
|
|
81
|
+
* @returns {string}
|
|
82
|
+
*/
|
|
83
|
+
function highlightNumber(number, options, colon = ':') {
|
|
84
|
+
if (number == null || options?.hide === true) {
|
|
85
|
+
return '';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return `${colon}${colourString(`${number}`, options)}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {Callsite} callsite - The callsite to format.
|
|
93
|
+
* @param {LineOptions | undefined} options - The options and colours to use in the formatting.
|
|
94
|
+
* @returns {string | null}
|
|
95
|
+
*/
|
|
96
|
+
function formatStackLine(callsite, options) {
|
|
97
|
+
if (options?.hide === true) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const colon = colourString(':', options?.Line);
|
|
102
|
+
|
|
103
|
+
const filePath = highlightFilePath(callsite, options?.FilePath ?? options?.Line);
|
|
104
|
+
const line = highlightNumber(
|
|
105
|
+
callsite.line,
|
|
106
|
+
options?.LineNumber ??
|
|
107
|
+
options?.FilePath ??
|
|
108
|
+
options?.Line,
|
|
109
|
+
colon,
|
|
110
|
+
);
|
|
111
|
+
const column = highlightNumber(
|
|
112
|
+
callsite.column,
|
|
113
|
+
options?.ColumnNumber ??
|
|
114
|
+
options?.LineNumber ??
|
|
115
|
+
options?.FilePath ??
|
|
116
|
+
options?.Line,
|
|
117
|
+
colon,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const at = colourString('at', options?.Line);
|
|
121
|
+
|
|
122
|
+
if (
|
|
123
|
+
options?.FunctionName?.hide === true ||
|
|
124
|
+
callsite.methodName == null
|
|
125
|
+
) {
|
|
126
|
+
return `${at} ${filePath}${line}${column}`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const ob = colourString('(', options?.Line);
|
|
130
|
+
const cb = colourString(')', options?.Line);
|
|
131
|
+
|
|
132
|
+
const methodName = colourString(callsite.methodName, options?.FunctionName ?? options?.Line);
|
|
133
|
+
return `${at} ${methodName} ${ob}${filePath}${line}${column}${cb}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @param {Callsite} callsite - The callsite to format.
|
|
138
|
+
* @returns {string | null}
|
|
139
|
+
*/
|
|
140
|
+
function stackLine(callsite) {
|
|
141
|
+
if (
|
|
142
|
+
callsite.file === '<anonymous>' ||
|
|
143
|
+
callsite.file.startsWith('node:') ||
|
|
144
|
+
callsite.file.startsWith('internal')
|
|
145
|
+
) {
|
|
146
|
+
return formatStackLine(callsite, Colours.internal);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (callsite.file.includes('node_modules')) {
|
|
150
|
+
return formatStackLine(callsite, Colours.module);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return formatStackLine(callsite, Colours.app);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @param {unknown} input - The possible string.
|
|
158
|
+
* @returns {input is string}
|
|
159
|
+
*/
|
|
160
|
+
function isString(input) {
|
|
161
|
+
return typeof input === 'string';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @param {Callsite[] | string | undefined} stack - The stack trace to format.
|
|
166
|
+
* @param {number} indent - The indent to render from.
|
|
167
|
+
* @returns {string}
|
|
168
|
+
*/
|
|
169
|
+
export function formatStack(stack, indent) {
|
|
170
|
+
const pad = ' '.repeat(indent + 2);
|
|
171
|
+
if (Array.isArray(stack)) {
|
|
172
|
+
return stack
|
|
173
|
+
.map(stackLine)
|
|
174
|
+
.filter(isString)
|
|
175
|
+
.map((line) => `${pad}${line.trim()}`)
|
|
176
|
+
.join('\n');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return (stack ?? '')
|
|
180
|
+
.split(/\r?\n|\r/u)
|
|
181
|
+
.map((line) => `${pad}${line.trim()}`)
|
|
182
|
+
.join('\n');
|
|
183
|
+
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { LogContext, LogEntry, LogLevel } from '../utilities/log-types.js';
|
|
3
|
+
*/
|
|
1
4
|
import { inspect } from 'node:util';
|
|
2
5
|
|
|
3
6
|
import { colourString, shouldColour } from '../utilities/colour.js';
|
|
4
7
|
import { LogNames } from '../utilities/log-types.js';
|
|
5
|
-
|
|
6
|
-
/** @typedef {import('../utilities/log-types.js').LogContext} LogContext */
|
|
7
|
-
/** @typedef {import('../utilities/log-types.js').LogEntry} LogEntry */
|
|
8
|
-
/** @typedef {import('../utilities/log-types.js').LogLevel} LogLevel */
|
|
9
|
-
/** @typedef {import('../utilities/log-types.js').Callsite} Callsite */
|
|
8
|
+
import { formatStack } from './formatter-console/stack.js';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* @param {string} [channel] - The channel string.
|
|
@@ -37,102 +36,6 @@ function flattenChannelLevel(channel, level) {
|
|
|
37
36
|
return output;
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
/**
|
|
41
|
-
* @param {string} _match - The whole match.
|
|
42
|
-
* @param {string} type - The module type.
|
|
43
|
-
* @param {string} name - The module name.
|
|
44
|
-
* @returns {string}
|
|
45
|
-
*/
|
|
46
|
-
function underlineName(_match, type, name) {
|
|
47
|
-
const moduleName = colourString(name, { effects: [ 'underline' ] });
|
|
48
|
-
|
|
49
|
-
return `${type}${moduleName}`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @param {Callsite} callsite - The callsite to underline.
|
|
54
|
-
* @returns {string}
|
|
55
|
-
*/
|
|
56
|
-
function formatFileSegment(callsite) {
|
|
57
|
-
let { file } = callsite;
|
|
58
|
-
|
|
59
|
-
file = file
|
|
60
|
-
.replaceAll(/^(?:node:)?internal\/[^/]+/gu, underlineName)
|
|
61
|
-
.replaceAll(/^\w+:[a-z]\w+$/gu, underlineName)
|
|
62
|
-
.replaceAll(/node_modules\/(?:@[^/]+\/[^/]+|[^/]+)/gu, underlineName);
|
|
63
|
-
|
|
64
|
-
if (typeof callsite.line === 'number') {
|
|
65
|
-
file += `:${callsite.line}`;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (typeof callsite.column === 'number') {
|
|
69
|
-
file += `:${callsite.column}`;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return file;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* @param {Callsite} callsite - The node module callsite to format.
|
|
77
|
-
* @returns {string}
|
|
78
|
-
*/
|
|
79
|
-
function stackLineModule(callsite) {
|
|
80
|
-
const file = colourString(
|
|
81
|
-
formatFileSegment(callsite),
|
|
82
|
-
{ effects: [ 'faint' ] },
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
return colourString(
|
|
86
|
-
`at ${callsite.methodName} (${file})`,
|
|
87
|
-
{ foreground: 'yellow' },
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @param {Callsite} callsite - The internal callsite to format.
|
|
93
|
-
* @returns {string}
|
|
94
|
-
*/
|
|
95
|
-
function stackLineInternal(callsite) {
|
|
96
|
-
const file = formatFileSegment(callsite);
|
|
97
|
-
return colourString(
|
|
98
|
-
`at ${callsite.methodName} (${file})`,
|
|
99
|
-
{ foreground: 'black', foregroundMode: 'bright' },
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* @param {Callsite} callsite - The callsite to format.
|
|
105
|
-
* @returns {string}
|
|
106
|
-
*/
|
|
107
|
-
function stackLine(callsite) {
|
|
108
|
-
if (callsite.file.startsWith('node_modules')) {
|
|
109
|
-
return stackLineModule(callsite);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
callsite.file === '<anonymous>' ||
|
|
114
|
-
callsite.file.startsWith('node:') ||
|
|
115
|
-
callsite.file.startsWith('internal')
|
|
116
|
-
) {
|
|
117
|
-
return stackLineInternal(callsite);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
let file = colourString(callsite.file, {
|
|
121
|
-
foreground: 'green',
|
|
122
|
-
foregroundMode: 'bright',
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
file += `:${callsite.line}`;
|
|
126
|
-
if (typeof callsite.column === 'number') {
|
|
127
|
-
file += colourString(
|
|
128
|
-
`:${callsite.column}`,
|
|
129
|
-
{ foreground: 'black', foregroundMode: 'bright' },
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return `at ${callsite.methodName} (${file})`;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
39
|
const fixEmpties = /^\{\s*\}$/u;
|
|
137
40
|
|
|
138
41
|
/**
|
|
@@ -159,26 +62,6 @@ function splatify(entry) {
|
|
|
159
62
|
.trim();
|
|
160
63
|
}
|
|
161
64
|
|
|
162
|
-
/**
|
|
163
|
-
* @param {Callsite[] | string | undefined} stack - The stack trace to format.
|
|
164
|
-
* @param {number} indent - The indent to render from.
|
|
165
|
-
* @returns {string}
|
|
166
|
-
*/
|
|
167
|
-
function formatStack(stack, indent) {
|
|
168
|
-
const pad = ' '.repeat(indent + 2);
|
|
169
|
-
if (Array.isArray(stack)) {
|
|
170
|
-
return stack
|
|
171
|
-
.map(stackLine)
|
|
172
|
-
.map((line) => `${pad}${line.trim()}`)
|
|
173
|
-
.join('\n');
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return (stack ?? '')
|
|
177
|
-
.split(/\r?\n|\r/u)
|
|
178
|
-
.map((line) => `${pad}${line.trim()}`)
|
|
179
|
-
.join('\n');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
65
|
/**
|
|
183
66
|
* @param {Error} error - The error to render.
|
|
184
67
|
* @param {number} [indent] - The indent to render from.
|
package/src/logger.js
CHANGED
|
@@ -8,6 +8,7 @@ import { ErrorReplacer } from './replacers/error.js';
|
|
|
8
8
|
import { stdoutWrite } from './stdout-write.js';
|
|
9
9
|
import { environment } from './utilities/environment.js';
|
|
10
10
|
import { getLastCallsite } from './utilities/last-callsite.js';
|
|
11
|
+
import { getMemoryUsage, getCPUUsage } from './utilities/resource-usage.js';
|
|
11
12
|
import { checkLogFilters, checkLogLevel } from './utilities/log-filters.js';
|
|
12
13
|
import { LogLevels } from './utilities/log-types.js';
|
|
13
14
|
|
|
@@ -364,6 +365,14 @@ export class Logger {
|
|
|
364
365
|
entry.source = getLastCallsite();
|
|
365
366
|
}
|
|
366
367
|
|
|
368
|
+
if (environment.includeMemoryUsage === true) {
|
|
369
|
+
entry.memoryUsage = getMemoryUsage();
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (environment.includeCpuUsage === true) {
|
|
373
|
+
entry.cpuUsage = getCPUUsage();
|
|
374
|
+
}
|
|
375
|
+
|
|
367
376
|
const normalised =
|
|
368
377
|
/** @type {import('./utilities/log-types.js').LogEntry} */
|
|
369
378
|
(this.#replace(entry, this.replacers));
|
package/src/utilities/colour.js
CHANGED
|
@@ -126,11 +126,11 @@ export function shouldColour() {
|
|
|
126
126
|
/**
|
|
127
127
|
* Colour a string.
|
|
128
128
|
* @param {string} string - The string to colour.
|
|
129
|
-
* @param {ColourOptions} options - The options to use to colour the string.
|
|
129
|
+
* @param {ColourOptions | undefined} [options] - The options to use to colour the string.
|
|
130
130
|
* @returns {string}
|
|
131
131
|
*/
|
|
132
132
|
export function colourString(string, options) {
|
|
133
|
-
if (shouldColour() === false) {
|
|
133
|
+
if (shouldColour() === false || options == null) {
|
|
134
134
|
return string;
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -4,29 +4,37 @@ import { parseFilters } from './parse-filters.js';
|
|
|
4
4
|
import { parseLogLevel } from './parse-log-level.js';
|
|
5
5
|
|
|
6
6
|
const {
|
|
7
|
-
NODE_ENV = 'production',
|
|
8
|
-
LOG_LEVEL,
|
|
9
|
-
LOG_FILTERS,
|
|
10
|
-
LOG_SECRETS,
|
|
11
7
|
LOG_CALLSITES = false,
|
|
8
|
+
LOG_CPU = false,
|
|
9
|
+
LOG_FILTERS,
|
|
10
|
+
LOG_LEVEL,
|
|
12
11
|
LOG_MAX_LENGTH = 1024,
|
|
12
|
+
LOG_MEMORY = false,
|
|
13
|
+
LOG_SECRETS,
|
|
14
|
+
LOG_RELATIVE_TO,
|
|
15
|
+
NODE_ENV = 'production',
|
|
13
16
|
} = getTypedEnv({
|
|
14
|
-
NODE_ENV: '?string',
|
|
15
|
-
LOG_LEVEL: '?string',
|
|
16
|
-
LOG_FILTERS: '?string',
|
|
17
|
-
LOG_SECRETS: '?string',
|
|
18
17
|
LOG_CALLSITES: '?boolean',
|
|
18
|
+
LOG_CPU: '?boolean',
|
|
19
|
+
LOG_FILTERS: '?string',
|
|
20
|
+
LOG_LEVEL: '?string',
|
|
19
21
|
LOG_MAX_LENGTH: '?number',
|
|
22
|
+
LOG_MEMORY: '?boolean',
|
|
23
|
+
LOG_SECRETS: '?string',
|
|
24
|
+
LOG_RELATIVE_TO: '?string',
|
|
25
|
+
NODE_ENV: '?string',
|
|
20
26
|
});
|
|
21
27
|
|
|
22
28
|
export const environment = {
|
|
29
|
+
includeCallsite: LOG_CALLSITES,
|
|
30
|
+
includeCpuUsage: LOG_CPU,
|
|
31
|
+
includeMemoryUsage: LOG_MEMORY,
|
|
23
32
|
isDevelopment: NODE_ENV === 'development',
|
|
24
|
-
isTesting: NODE_ENV === 'test',
|
|
25
33
|
isProduction: NODE_ENV === 'production',
|
|
26
|
-
|
|
27
|
-
logLevel: parseLogLevel(LOG_LEVEL, NODE_ENV),
|
|
34
|
+
isTesting: NODE_ENV === 'test',
|
|
28
35
|
logFilters: parseFilters(LOG_FILTERS, [ /.*/u ]),
|
|
36
|
+
logLevel: parseLogLevel(LOG_LEVEL, NODE_ENV),
|
|
29
37
|
secretFilters: parseFilters(LOG_SECRETS),
|
|
30
|
-
|
|
38
|
+
relativeTo: LOG_RELATIVE_TO,
|
|
31
39
|
stringMaxLength: LOG_MAX_LENGTH,
|
|
32
40
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the current memory consumption.
|
|
3
|
+
* @returns {NodeJS.MemoryUsage}
|
|
4
|
+
*/
|
|
5
|
+
export function getMemoryUsage() {
|
|
6
|
+
const usage = process.memoryUsage();
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
arrayBuffers: usage.arrayBuffers / 1_000_000,
|
|
10
|
+
external: usage.external / 1_000_000,
|
|
11
|
+
heapTotal: usage.heapTotal / 1_000_000,
|
|
12
|
+
heapUsed: usage.heapUsed / 1_000_000,
|
|
13
|
+
rss: usage.rss / 1_000_000,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let lastCalled = performance.now();
|
|
18
|
+
let lastValue = process.cpuUsage();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get the callsite that we think is outside the package.
|
|
22
|
+
* @returns {Record<'elapsed'|'total'|'system'|'user', number> | void}
|
|
23
|
+
*/
|
|
24
|
+
export function getCPUUsage() {
|
|
25
|
+
/**
|
|
26
|
+
* Time since start in milliseconds with microseconds precision.
|
|
27
|
+
*/
|
|
28
|
+
const currentCalled = performance.now();
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Time difference in microseconds.
|
|
32
|
+
*/
|
|
33
|
+
const elapsed = Math.floor(1000 * (currentCalled - lastCalled));
|
|
34
|
+
|
|
35
|
+
lastCalled = currentCalled;
|
|
36
|
+
lastValue = process.cpuUsage(lastValue);
|
|
37
|
+
|
|
38
|
+
const { system, user } = lastValue;
|
|
39
|
+
const total = system + user;
|
|
40
|
+
|
|
41
|
+
return { elapsed, total, system, user };
|
|
42
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { relative, resolve } from 'node:path';
|
|
2
2
|
|
|
3
3
|
import { parse } from 'stacktrace-parser';
|
|
4
|
+
import { environment } from './environment.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @typedef {Object} Callsite
|
|
@@ -43,12 +44,9 @@ export function parseStack(stack) {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
if (site.file.startsWith('/')) {
|
|
46
|
-
site.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
site.file = site.relativePath[0] === '.'
|
|
50
|
-
? site.absolutePath
|
|
51
|
-
: site.relativePath;
|
|
47
|
+
site.file = typeof environment.relativeTo === 'string'
|
|
48
|
+
? relative(resolve(environment.relativeTo), site.file)
|
|
49
|
+
: resolve(site.file);
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
callsites.push(site);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {Callsite[] | string | undefined} stack - The stack trace to format.
|
|
3
|
+
* @param {number} indent - The indent to render from.
|
|
4
|
+
* @returns {string}
|
|
5
|
+
*/
|
|
6
|
+
export function formatStack(stack: Callsite[] | string | undefined, indent: number): string;
|
|
7
|
+
export type HideOption = {
|
|
8
|
+
hide?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type LineOptions = (HideOption & {
|
|
11
|
+
Line?: Omit<ColourOptions, "reset">;
|
|
12
|
+
FunctionName?: Omit<ColourOptions, "reset"> & HideOption;
|
|
13
|
+
FilePath?: Omit<ColourOptions, "reset">;
|
|
14
|
+
LineNumber?: Omit<ColourOptions, "reset"> & HideOption;
|
|
15
|
+
ColumnNumber?: Omit<ColourOptions, "reset"> & HideOption;
|
|
16
|
+
});
|
|
17
|
+
import type { Callsite } from '../../utilities/log-types.js';
|
|
18
|
+
import type { ColourOptions } from '../../utilities/colour.js';
|
|
@@ -3,7 +3,4 @@
|
|
|
3
3
|
* @returns {string}
|
|
4
4
|
*/
|
|
5
5
|
export function formatterConsole(logEntry: LogEntry): string;
|
|
6
|
-
|
|
7
|
-
export type LogEntry = import("../utilities/log-types.js").LogEntry;
|
|
8
|
-
export type LogLevel = import("../utilities/log-types.js").LogLevel;
|
|
9
|
-
export type Callsite = import("../utilities/log-types.js").Callsite;
|
|
6
|
+
import type { LogEntry } from '../utilities/log-types.js';
|
|
@@ -6,10 +6,10 @@ export function shouldColour(): boolean;
|
|
|
6
6
|
/**
|
|
7
7
|
* Colour a string.
|
|
8
8
|
* @param {string} string - The string to colour.
|
|
9
|
-
* @param {ColourOptions} options - The options to use to colour the string.
|
|
9
|
+
* @param {ColourOptions | undefined} [options] - The options to use to colour the string.
|
|
10
10
|
* @returns {string}
|
|
11
11
|
*/
|
|
12
|
-
export function colourString(string: string, options
|
|
12
|
+
export function colourString(string: string, options?: ColourOptions | undefined): string;
|
|
13
13
|
export type ColourNames = keyof typeof colours;
|
|
14
14
|
export type ColourMode = "bright" | "dim";
|
|
15
15
|
export type ColourEffects = keyof typeof effects;
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
export namespace environment {
|
|
2
|
+
export { LOG_CALLSITES as includeCallsite };
|
|
3
|
+
export { LOG_CPU as includeCpuUsage };
|
|
4
|
+
export { LOG_MEMORY as includeMemoryUsage };
|
|
2
5
|
export let isDevelopment: boolean;
|
|
3
|
-
export let isTesting: boolean;
|
|
4
6
|
export let isProduction: boolean;
|
|
5
|
-
export let
|
|
7
|
+
export let isTesting: boolean;
|
|
6
8
|
export let logFilters: {
|
|
7
9
|
allowed: RegExp[];
|
|
8
10
|
blocked: RegExp[];
|
|
9
11
|
};
|
|
12
|
+
export let logLevel: import("./log-types.js").LogLevel;
|
|
10
13
|
export let secretFilters: {
|
|
11
14
|
allowed: RegExp[];
|
|
12
15
|
blocked: RegExp[];
|
|
13
16
|
};
|
|
14
|
-
export {
|
|
17
|
+
export { LOG_RELATIVE_TO as relativeTo };
|
|
15
18
|
export { LOG_MAX_LENGTH as stringMaxLength };
|
|
16
19
|
}
|
|
17
20
|
declare const LOG_CALLSITES: boolean;
|
|
21
|
+
declare const LOG_CPU: boolean;
|
|
22
|
+
declare const LOG_MEMORY: boolean;
|
|
23
|
+
declare const LOG_RELATIVE_TO: string | undefined;
|
|
18
24
|
declare const LOG_MAX_LENGTH: number;
|
|
19
25
|
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the current memory consumption.
|
|
3
|
+
* @returns {NodeJS.MemoryUsage}
|
|
4
|
+
*/
|
|
5
|
+
export function getMemoryUsage(): NodeJS.MemoryUsage;
|
|
6
|
+
/**
|
|
7
|
+
* Get the callsite that we think is outside the package.
|
|
8
|
+
* @returns {Record<'elapsed'|'total'|'system'|'user', number> | void}
|
|
9
|
+
*/
|
|
10
|
+
export function getCPUUsage(): Record<"elapsed" | "total" | "system" | "user", number> | void;
|