-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/w/8.0/improvement/WRLGS-11-stder…
…r-timestamp' into w/8.1/improvement/WRLGS-11-stderr-timestamp
- Loading branch information
Showing
7 changed files
with
533 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/** | ||
* @returns {string} a timestamp in ISO format YYYY-MM-DDThh:mm:ss.sssZ | ||
*/ | ||
const defaultTimestamp = () => new Date().toISOString(); | ||
|
||
/** | ||
* Prints on stderr a timestamp, the origin and the error | ||
* | ||
* If no other instructions are needed on uncaughtException, | ||
* consider using `catchAndTimestampStderr` directly. | ||
* | ||
* @example | ||
* process.on('uncaughtException', (err, origin) => { | ||
* printErrorWithTimestamp(err, origin); | ||
* // server.close(); | ||
* // file.close(); | ||
* process.nextTick(() => process.exit(1)); | ||
* }); | ||
* // Don't forget to timestamp warning | ||
* catchAndTimestampWarning(); | ||
* @param {Error} err see process event uncaughtException | ||
* @param {uncaughtException|unhandledRejection} origin see process event | ||
* @param {string} [date=`defaultTimestamp()`] Date to print | ||
* @returns {boolean} see process.stderr.write | ||
*/ | ||
function printErrorWithTimestamp( | ||
err, origin, date = defaultTimestamp(), | ||
) { | ||
return process.stderr.write(`${date}: ${origin}:\n${err.stack}\n`); | ||
} | ||
|
||
/** | ||
* Prefer using `catchAndTimestampStderr` instead of this function. | ||
* | ||
* Adds listener for uncaughtException to print with timestamp. | ||
* | ||
* If you want to manage the end of the process, you can set exitCode to null. | ||
* Or use `printErrorWithTimestamp` in your own uncaughtException listener. | ||
* | ||
* @param {Function} [dateFct=`defaultTimestamp`] Fct returning a formatted date | ||
* @param {*} [exitCode=1] On uncaughtException, if not null, `process.exit` | ||
* will be called with this value | ||
* @returns {undefined} | ||
*/ | ||
function catchAndTimestampUncaughtException( | ||
dateFct = defaultTimestamp, exitCode = 1, | ||
) { | ||
process.on('uncaughtException', (err, origin) => { | ||
printErrorWithTimestamp(err, origin, dateFct()); | ||
if (exitCode !== null) { | ||
process.nextTick(() => process.exit(exitCode)); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Forces the use of `--trace-warnings` and adds a date in warning.detail | ||
* The warning will be printed by the default `onWarning` | ||
* | ||
* @param {string} [dateFct=`defaultTimestamp`] Fct returning a formatted date | ||
* @returns {undefined} | ||
*/ | ||
function catchAndTimestampWarning(dateFct = defaultTimestamp) { | ||
process.traceProcessWarnings = true; | ||
// must be executed first, before the default `onWarning` | ||
process.prependListener('warning', warning => { | ||
if (warning.detail) { | ||
// eslint-disable-next-line no-param-reassign | ||
warning.detail += `\nAbove Warning Date: ${dateFct()}`; | ||
} else { | ||
// eslint-disable-next-line no-param-reassign | ||
warning.detail = `Above Warning Date: ${dateFct()}`; | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Adds listener for uncaughtException and warning to print them with timestamp. | ||
* | ||
* If you want to manage the end of the process, you can set exitCode to null. | ||
* Or use `printErrorWithTimestamp` in your own uncaughtException listener. | ||
* | ||
* @example | ||
* const { stderrUtils } = require('werelogs'); | ||
* // first instruction in your index.js or entrypoint | ||
* stderrUtils.catchAndTimestampStderr(); | ||
* | ||
* @param {Function} [dateFct=`defaultTimestamp`] Fct returning a formatted date | ||
* @param {*} [exitCode=1] On uncaughtException, if not null, `process.exit` | ||
* will be called with this value | ||
* @returns {undefined} | ||
*/ | ||
function catchAndTimestampStderr( | ||
dateFct = defaultTimestamp, exitCode = 1, | ||
) { | ||
catchAndTimestampUncaughtException(dateFct, exitCode); | ||
catchAndTimestampWarning(dateFct); | ||
} | ||
|
||
module.exports = { | ||
defaultTimestamp, | ||
printErrorWithTimestamp, | ||
catchAndTimestampUncaughtException, | ||
catchAndTimestampWarning, | ||
catchAndTimestampStderr, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#!/usr/bin/env node | ||
// Convert string args into primitive value | ||
const fromStr = (str, primitive) => (str === `${primitive}` ? primitive : str); | ||
const date = fromStr(process.argv[2], undefined); | ||
const exitCode = fromStr(fromStr(process.argv[3], null), undefined); | ||
|
||
const { stderrUtils } = require('../../../../index'); | ||
|
||
stderrUtils.catchAndTimestampStderr( | ||
date ? () => date : undefined, | ||
exitCode, | ||
); | ||
|
||
process.emitWarning('TestWarningMessage'); | ||
// This will print warning after printing error before exit | ||
throw new Error('TestingError'); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#!/usr/bin/env node | ||
// Convert string args into primitive value | ||
const fromStr = (str, primitive) => (str === `${primitive}` ? primitive : str); | ||
const date = fromStr(process.argv[2], undefined); | ||
const exitCode = fromStr(fromStr(process.argv[3], null), undefined); | ||
const promise = fromStr(process.argv[4], true); | ||
|
||
const { stderrUtils } = require('../../../../index'); | ||
|
||
stderrUtils.catchAndTimestampUncaughtException( | ||
date ? () => date : undefined, | ||
exitCode, | ||
); | ||
|
||
// Executed if process does not exit, process is in undefined behavior (bad) | ||
// eslint-disable-next-line no-console | ||
setTimeout(() => console.log('EXECUTED AFTER UNCAUGHT EXCEPTION'), 1); | ||
|
||
if (promise === true) { | ||
Promise.reject(); | ||
} else { | ||
throw new Error('TestingError'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#!/usr/bin/env node | ||
// Convert string args into primitive value | ||
const fromStr = (str, primitive) => (str === `${primitive}` ? primitive : str); | ||
const date = fromStr(process.argv[2], undefined); | ||
const name = fromStr(process.argv[3], undefined); | ||
const code = fromStr(process.argv[4], undefined); | ||
const detail = fromStr(process.argv[5], undefined); | ||
|
||
const { stderrUtils } = require('../../../../index'); | ||
|
||
stderrUtils.catchAndTimestampWarning( | ||
date ? () => date : undefined, | ||
); | ||
|
||
const warning = new Error('TestWarningMessage'); | ||
|
||
if (name) warning.name = name; | ||
if (code) warning.code = code; | ||
if (detail) warning.detail = detail; | ||
|
||
process.emitWarning(warning); | ||
|
||
/* | ||
Examples: | ||
(node:203831) Error: TestWarningMessage | ||
at Object.<anonymous> (catchWarning.js:15:17) | ||
... | ||
at node:internal/main/run_main_module:22:47 | ||
Above Warning Date: 2024-06-26T16:32:55.505Z | ||
(node:205151) [TEST01] CUSTOM: TestWarningMessage | ||
at Object.<anonymous> (catchWarning.js:15:17) | ||
... | ||
at node:internal/main/run_main_module:22:47 | ||
Some additional detail | ||
Above Warning Date: Tue, 31 Dec 2024 10:20:30 GMT | ||
*/ |
Oops, something went wrong.