From f3a1dc1f778b759762db26e1e88dd37a4beb776e Mon Sep 17 00:00:00 2001 From: theanarkh Date: Sun, 26 Jun 2022 21:23:03 +0800 Subject: [PATCH] http: add diagnostics channel for http client --- doc/api/diagnostics_channel.md | 35 +++++++++++ lib/_http_client.js | 15 +++++ .../parallel/test-diagnostics-channel-http.js | 63 +++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 test/parallel/test-diagnostics-channel-http.js diff --git a/doc/api/diagnostics_channel.md b/doc/api/diagnostics_channel.md index eff642f96743b4..75d714d933ab07 100644 --- a/doc/api/diagnostics_channel.md +++ b/doc/api/diagnostics_channel.md @@ -307,6 +307,41 @@ channel.subscribe(onMessage); channel.unsubscribe(onMessage); ``` +### Built-in Channels + +#### HTTP + +`http.client.request.start` + +* `request` {http.ClientRequest} + +Emitted when client starts a request. + +`http.client.response.finish` + +* `request` {http.ClientRequest} +* `response` {http.IncomingMessage} + +Emitted when client receives a response. + +`http.server.request.start` + +* `request` {http.IncomingMessage} +* `response` {http.ServerResponse} +* `socket` {net.Socket} +* `server` {http.Server} + +Emitted when server receives a request. + +`http.server.response.finish` + +* `request` {http.IncomingMessage} +* `response` {http.ServerResponse} +* `socket` {net.Socket} +* `server` {http.Server} + +Emitted when server sends a response. + [`'uncaughtException'`]: process.md#event-uncaughtexception [`channel.subscribe(onMessage)`]: #channelsubscribeonmessage [`diagnostics_channel.channel(name)`]: #diagnostics_channelchannelname diff --git a/lib/_http_client.js b/lib/_http_client.js index d14cdc343b6b29..98ebdfc5b77fba 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -90,6 +90,10 @@ const { const kClientRequestStatistics = Symbol('ClientRequestStatistics'); +const dc = require('diagnostics_channel'); +const onClientRequestStartChannel = dc.channel('http.client.request.start'); +const onClientResponseFinishChannel = dc.channel('http.client.response.finish'); + const { addAbortSignal, finished } = require('stream'); let debug = require('internal/util/debuglog').debuglog('http', (fn) => { @@ -367,6 +371,11 @@ ClientRequest.prototype._finish = function _finish() { }, }); } + if (onClientRequestStartChannel.hasSubscribers) { + onClientRequestStartChannel.publish({ + request: this, + }); + } }; ClientRequest.prototype._implicitHeader = function _implicitHeader() { @@ -645,6 +654,12 @@ function parserOnIncomingClient(res, shouldKeepAlive) { }, }); } + if (onClientResponseFinishChannel.hasSubscribers) { + onClientResponseFinishChannel.publish({ + request: req, + response: res, + }); + } req.res = res; res.req = req; diff --git a/test/parallel/test-diagnostics-channel-http.js b/test/parallel/test-diagnostics-channel-http.js new file mode 100644 index 00000000000000..4de08d9253c10a --- /dev/null +++ b/test/parallel/test-diagnostics-channel-http.js @@ -0,0 +1,63 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); +const net = require('net'); +const dc = require('diagnostics_channel'); + +const onClientRequestStart = dc.channel('http.client.request.start'); +const onClientResponseFinish = dc.channel('http.client.response.finish'); +const onServerRequestStart = dc.channel('http.server.request.start'); +const onServerResponseFinish = dc.channel('http.server.response.finish'); + +const isHTTPServer = (server) => server instanceof http.Server; +const isIncomingMessage = (object) => object instanceof http.IncomingMessage; +const isOutgoingMessage = (object) => object instanceof http.OutgoingMessage; +const isNetSocket = (socket) => socket instanceof net.Socket; + +onClientRequestStart.subscribe(common.mustCall(({ request }) => { + assert.strictEqual(isOutgoingMessage(request), true); +})); + +onClientResponseFinish.subscribe(common.mustCall(({ request, response }) => { + assert.strictEqual(isOutgoingMessage(request), true); + assert.strictEqual(isIncomingMessage(response), true); +})); + +onServerRequestStart.subscribe(common.mustCall(({ + request, + response, + socket, + server, +}) => { + assert.strictEqual(isIncomingMessage(request), true); + assert.strictEqual(isOutgoingMessage(response), true); + assert.strictEqual(isNetSocket(socket), true); + assert.strictEqual(isHTTPServer(server), true); +})); + +onServerResponseFinish.subscribe(common.mustCall(({ + request, + response, + socket, + server, +}) => { + assert.strictEqual(isIncomingMessage(request), true); + assert.strictEqual(isOutgoingMessage(response), true); + assert.strictEqual(isNetSocket(socket), true); + assert.strictEqual(isHTTPServer(server), true); +})); + +const server = http.createServer(common.mustCall((req, res) => { + res.end('done'); +})); + +server.listen(() => { + const { port } = server.address(); + http.get(`http://localhost:${port}`, (res) => { + res.resume(); + res.on('end', () => { + server.close(); + }); + }); +});