Skip to content

Commit

Permalink
diagnostics_channel: capture console messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Qard committed Dec 17, 2024
1 parent 2cd385e commit 07fbcd4
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 3 deletions.
37 changes: 37 additions & 0 deletions doc/api/diagnostics_channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,43 @@ While the diagnostics\_channel API is now considered stable, the built-in
channels currently available are not. Each channel must be declared stable
independently.

#### Console

`console.log`

* `args` {any[]}

Emitted when `console.log()` is called. Receives and array of the arguments
passed to `console.log()`.

`console.info`

* `args` {any[]}

Emitted when `console.info()` is called. Receives and array of the arguments
passed to `console.info()`.

`console.debug`

* `args` {any[]}

Emitted when `console.debug()` is called. Receives and array of the arguments
passed to `console.debug()`.

`console.warn`

* `args` {any[]}

Emitted when `console.warn()` is called. Receives and array of the arguments
passed to `console.warn()`.

`console.error`

* `args` {any[]}

Emitted when `console.error()` is called. Receives and array of the arguments
passed to `console.error()`.

#### HTTP

`http.client.request.created`
Expand Down
35 changes: 32 additions & 3 deletions lib/internal/console/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ const {
} = require('internal/constants');
const kCounts = Symbol('counts');
const { time, timeLog, timeEnd, kNone } = require('internal/util/debuglog');
const { channel } = require('diagnostics_channel');

const onLog = channel('console.log');
const onWarn = channel('console.warn');
const onError = channel('console.error');
const onInfo = channel('console.info');
const onDebug = channel('console.debug');

const kTraceConsoleCategory = 'node,node.console';

Expand Down Expand Up @@ -371,14 +378,39 @@ function timeLogImpl(consoleRef, label, formatted, args) {

const consoleMethods = {
log(...args) {
if (onLog.hasSubscribers) {
onLog.publish(args);
}
this[kWriteToConsole](kUseStdout, this[kFormatForStdout](args));
},

info(...args) {
if (onInfo.hasSubscribers) {
onInfo.publish(args);
}
this[kWriteToConsole](kUseStdout, this[kFormatForStdout](args));
},

debug(...args) {
if (onDebug.hasSubscribers) {
onDebug.publish(args);
}
this[kWriteToConsole](kUseStdout, this[kFormatForStdout](args));
},

warn(...args) {
if (onWarn.hasSubscribers) {
onWarn.publish(args);
}
this[kWriteToConsole](kUseStderr, this[kFormatForStderr](args));
},

error(...args) {
if (onError.hasSubscribers) {
onError.publish(args);
}
this[kWriteToConsole](kUseStderr, this[kFormatForStderr](args));
},

dir(object, options) {
this[kWriteToConsole](kUseStdout, inspect(object, {
Expand Down Expand Up @@ -614,10 +646,7 @@ function noop() {}
for (const method of ReflectOwnKeys(consoleMethods))
Console.prototype[method] = consoleMethods[method];

Console.prototype.debug = Console.prototype.log;
Console.prototype.info = Console.prototype.log;
Console.prototype.dirxml = Console.prototype.log;
Console.prototype.error = Console.prototype.warn;
Console.prototype.groupCollapsed = Console.prototype.group;

function initializeGlobalConsole(globalConsole) {
Expand Down
82 changes: 82 additions & 0 deletions test/parallel/test-console-diagnostics-channels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

const { mustCall } = require('../common');
const { deepStrictEqual, strictEqual, match, ok } = require('assert');

Check failure on line 4 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

'strictEqual' is assigned a value but never used

Check failure on line 4 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

'match' is assigned a value but never used
const { formatWithOptions } = require('util');

Check failure on line 5 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

'formatWithOptions' is assigned a value but never used

const { channel } = require('diagnostics_channel');

const {
hijackStdout,
hijackStderr,
restoreStdout,
restoreStderr
} = require('../common/hijackstdio');

const stdoutMethods = [
'log',
'info',
'debug'

Check failure on line 19 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Missing trailing comma
];

const stderrMethods = [
'warn',
'error'

Check failure on line 24 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Missing trailing comma
];

const methods = [
...stdoutMethods,
...stderrMethods

Check failure on line 29 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Missing trailing comma
];

const channels = {
log: channel('console.log'),
info: channel('console.info'),
debug: channel('console.debug'),
warn: channel('console.warn'),
error: channel('console.error')
}

Check failure on line 38 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Missing semicolon

process.stdout.isTTY = false;
process.stderr.isTTY = false;

for (const method of methods) {
let intercepted = false;
let formatted = false;

const hijack = stdoutMethods.includes(method)
? hijackStdout

Check failure on line 48 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

'?' should be placed at the end of the line
: hijackStderr;

Check failure on line 49 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

':' should be placed at the end of the line

const restore = stdoutMethods.includes(method)
? restoreStdout

Check failure on line 52 in test/parallel/test-console-diagnostics-channels.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

'?' should be placed at the end of the line
: restoreStderr;

const foo = 'string';
const bar = { key: /value/ };
const baz = [ 1, 2, 3 ];

channels[method].subscribe(mustCall((args) => {
// Should not have been formatted yet.
intercepted = true;
ok(!formatted);

// Should receive expected log message args.
deepStrictEqual(args, [foo, bar, baz]);

// Should be able to mutate message args and have it reflected in output.
bar.added = true;
}));

hijack(mustCall((output) => {
// Should have already been intercepted.
formatted = true;
ok(intercepted);

// Should produce expected formatted output with mutated message args.
deepStrictEqual(output, 'string { key: /value/, added: true } [ 1, 2, 3 ]\n');
}));

console[method](foo, bar, baz);
restore();
}

0 comments on commit 07fbcd4

Please sign in to comment.