Skip to content

Commit 247cb11

Browse files
committed
http: add diagnostics channel for http client
1 parent 42ad967 commit 247cb11

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

doc/api/diagnostics_channel.md

+69
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,75 @@ channel.subscribe(onMessage);
307307
channel.unsubscribe(onMessage);
308308
```
309309

310+
### Built-in Channel
311+
312+
* `http.client.request.start`: Emited when start a request.
313+
* `http.client.response.finish`: Emited when receive a Response.
314+
* `http.server.request.start`: Emited when server receive a Request.
315+
* `http.server.response.finish`: Emited when server send a Response.
316+
317+
## Example
318+
319+
```mjs
320+
import http from 'node:http';
321+
import dc from 'node:diagnostics_channel';
322+
323+
const onClientRequestStart = dc.channel('http.client.request.start');
324+
const onClientResponseFinish = dc.channel('http.client.response.finish');
325+
326+
onClientRequestStart.subscribe(({ request }) => {
327+
328+
});
329+
330+
onClientResponseFinish.subscribe(({ request, response }) => {
331+
332+
});
333+
334+
const server = http.createServer((req, res) => {
335+
res.end('done');
336+
});
337+
338+
server.listen(() => {
339+
const { port } = server.address();
340+
http.get(`http://localhost:${port}`, (res) => {
341+
res.resume();
342+
res.on('end', () => {
343+
server.close();
344+
});
345+
});
346+
});
347+
```
348+
349+
```cjs
350+
const http = require('http');
351+
const dc = require('diagnostics_channel');
352+
353+
const onClientRequestStart = dc.channel('http.client.request.start');
354+
const onClientResponseFinish = dc.channel('http.client.response.finish');
355+
356+
onClientRequestStart.subscribe(({ request }) => {
357+
358+
});
359+
360+
onClientResponseFinish.subscribe(({ request, response }) => {
361+
362+
});
363+
364+
const server = http.createServer((req, res) => {
365+
res.end('done');
366+
});
367+
368+
server.listen(() => {
369+
const { port } = server.address();
370+
http.get(`http://localhost:${port}`, (res) => {
371+
res.resume();
372+
res.on('end', () => {
373+
server.close();
374+
});
375+
});
376+
});
377+
```
378+
310379
[`'uncaughtException'`]: process.md#event-uncaughtexception
311380
[`channel.subscribe(onMessage)`]: #channelsubscribeonmessage
312381
[`diagnostics_channel.channel(name)`]: #diagnostics_channelchannelname

lib/_http_client.js

+15
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ const {
9090

9191
const kClientRequestStatistics = Symbol('ClientRequestStatistics');
9292

93+
const dc = require('diagnostics_channel');
94+
const onClientRequestStartChannel = dc.channel('http.client.request.start');
95+
const onClientResponseFinishChannel = dc.channel('http.client.response.finish');
96+
9397
const { addAbortSignal, finished } = require('stream');
9498

9599
let debug = require('internal/util/debuglog').debuglog('http', (fn) => {
@@ -367,6 +371,11 @@ ClientRequest.prototype._finish = function _finish() {
367371
},
368372
});
369373
}
374+
if (onClientRequestStartChannel.hasSubscribers) {
375+
onClientRequestStartChannel.publish({
376+
request: this,
377+
});
378+
}
370379
};
371380

372381
ClientRequest.prototype._implicitHeader = function _implicitHeader() {
@@ -645,6 +654,12 @@ function parserOnIncomingClient(res, shouldKeepAlive) {
645654
},
646655
});
647656
}
657+
if (onClientResponseFinishChannel.hasSubscribers) {
658+
onClientResponseFinishChannel.publish({
659+
request: req,
660+
response: res,
661+
});
662+
}
648663
req.res = res;
649664
res.req = req;
650665

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const http = require('http');
5+
const net = require('net');
6+
const dc = require('diagnostics_channel');
7+
8+
const onClientRequestStart = dc.channel('http.client.request.start');
9+
const onClientResponseFinish = dc.channel('http.client.response.finish');
10+
const onServerRequestStart = dc.channel('http.server.request.start');
11+
const onServerResponseFinish = dc.channel('http.server.response.finish');
12+
13+
const isHTTPServer = (server) => server instanceof http.Server;
14+
const isIncomingMessage = (object) => object instanceof http.IncomingMessage;
15+
const isOutgoingMessage = (object) => object instanceof http.OutgoingMessage;
16+
const isNetSocket = (socket) => socket instanceof net.Socket;
17+
18+
onClientRequestStart.subscribe(common.mustCall(({ request }) => {
19+
assert.strictEqual(isOutgoingMessage(request), true);
20+
}));
21+
22+
onClientResponseFinish.subscribe(common.mustCall(({ request, response }) => {
23+
assert.strictEqual(isOutgoingMessage(request), true);
24+
assert.strictEqual(isIncomingMessage(response), true);
25+
}));
26+
27+
onServerRequestStart.subscribe(common.mustCall(({
28+
request,
29+
response,
30+
socket,
31+
server,
32+
}) => {
33+
assert.strictEqual(isIncomingMessage(request), true);
34+
assert.strictEqual(isOutgoingMessage(response), true);
35+
assert.strictEqual(isNetSocket(socket), true);
36+
assert.strictEqual(isHTTPServer(server), true);
37+
}));
38+
39+
onServerResponseFinish.subscribe(common.mustCall(({
40+
request,
41+
response,
42+
socket,
43+
server,
44+
}) => {
45+
assert.strictEqual(isIncomingMessage(request), true);
46+
assert.strictEqual(isOutgoingMessage(response), true);
47+
assert.strictEqual(isNetSocket(socket), true);
48+
assert.strictEqual(isHTTPServer(server), true);
49+
}));
50+
51+
const server = http.createServer(common.mustCall((req, res) => {
52+
res.end('done');
53+
}));
54+
55+
server.listen(() => {
56+
const { port } = server.address();
57+
http.get(`http://localhost:${port}`, (res) => {
58+
res.resume();
59+
res.on('end', () => {
60+
server.close();
61+
});
62+
});
63+
});

0 commit comments

Comments
 (0)