Skip to content

Commit

Permalink
http: add diagnostics channel for http client
Browse files Browse the repository at this point in the history
  • Loading branch information
theanarkh committed Jun 27, 2022
1 parent 42ad967 commit 4eebddb
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 0 deletions.
69 changes: 69 additions & 0 deletions doc/api/diagnostics_channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,75 @@ channel.subscribe(onMessage);
channel.unsubscribe(onMessage);
```

### Built-in Channel

* `http.client.request.start`: Emited when start a request.
* `http.client.response.finish`: Emited when receive a Response.
* `http.server.request.start`: Emited when Server receive a Request.
* `http.server.response.finish`: Emited when Server send a Response.

## Example

```mjs
import http from 'node:http';
import dc from 'node:diagnostics_channel';

const onClientRequestStart = dc.channel('http.client.request.start');
const onClientResponseFinish = dc.channel('http.client.response.finish');

onClientRequestStart.subscribe(({ request }) => {

});

onClientResponseFinish.subscribe(({ request, response }) => {

});

const server = http.createServer((req, res) => {
res.end('done');
});

server.listen(() => {
const { port } = server.address();
http.get(`http://localhost:${port}`, (res) => {
res.resume();
res.on('end', () => {
server.close();
});
});
});
```

```cjs
const http = require('http');
const dc = require('diagnostics_channel');

const onClientRequestStart = dc.channel('http.client.request.start');
const onClientResponseFinish = dc.channel('http.client.response.finish');

onClientRequestStart.subscribe(({ request }) => {

});

onClientResponseFinish.subscribe(({ request, response }) => {

});

const server = http.createServer((req, res) => {
res.end('done');
});

server.listen(() => {
const { port } = server.address();
http.get(`http://localhost:${port}`, (res) => {
res.resume();
res.on('end', () => {
server.close();
});
});
});
```

[`'uncaughtException'`]: process.md#event-uncaughtexception
[`channel.subscribe(onMessage)`]: #channelsubscribeonmessage
[`diagnostics_channel.channel(name)`]: #diagnostics_channelchannelname
15 changes: 15 additions & 0 deletions lib/_http_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -367,6 +371,11 @@ ClientRequest.prototype._finish = function _finish() {
},
});
}
if (onClientRequestStartChannel.hasSubscribers) {
onClientRequestStartChannel.publish({
request: this,
});
}
};

ClientRequest.prototype._implicitHeader = function _implicitHeader() {
Expand Down Expand Up @@ -645,6 +654,12 @@ function parserOnIncomingClient(res, shouldKeepAlive) {
},
});
}
if (onClientResponseFinishChannel.hasSubscribers) {
onClientResponseFinishChannel.publish({
request: req,
response: res,
});
}
req.res = res;
res.req = req;

Expand Down
63 changes: 63 additions & 0 deletions test/parallel/test-diagnostics-channel-http.js
Original file line number Diff line number Diff line change
@@ -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();
});
});
});

0 comments on commit 4eebddb

Please sign in to comment.