Repository: nodejs/node
Pull request: http: add diagnostic channel `http.client.request.created`

Fixes: https://github.com/nodejs/node/issues/55352

Changed files:
filename: doc/api/diagnostics_channel.md
patch: @@ -1123,6 +1123,13 @@ independently.
 
 #### HTTP
 
+`http.client.request.created`
+
+* `request` {http.ClientRequest}
+
+Emitted when client creates a request object.
+Unlike `http.client.request.start`, this event is emitted before the request has been sent.
+
 `http.client.request.start`
 
 * `request` {http.ClientRequest}

filename: lib/_http_client.js
patch: @@ -89,6 +89,7 @@ const {
 const kClientRequestStatistics = Symbol('ClientRequestStatistics');
 
 const dc = require('diagnostics_channel');
+const onClientRequestCreatedChannel = dc.channel('http.client.request.created');
 const onClientRequestStartChannel = dc.channel('http.client.request.start');
 const onClientRequestErrorChannel = dc.channel('http.client.request.error');
 const onClientResponseFinishChannel = dc.channel('http.client.response.finish');
@@ -373,6 +374,11 @@ function ClientRequest(input, options, cb) {
       this.onSocket(net.createConnection(opts));
     }
   }
+  if (onClientRequestCreatedChannel.hasSubscribers) {
+    onClientRequestCreatedChannel.publish({
+      request: this,
+    });
+  }
 }
 ObjectSetPrototypeOf(ClientRequest.prototype, OutgoingMessage.prototype);
 ObjectSetPrototypeOf(ClientRequest, OutgoingMessage);

filename: test/parallel/test-diagnostic-channel-http-request-created.js
patch: @@ -0,0 +1,39 @@
+'use strict';
+const common = require('../common');
+const assert = require('assert');
+const http = require('http');
+const dc = require('diagnostics_channel');
+
+const isHTTPServer = (server) => server instanceof http.Server;
+const isOutgoingMessage = (object) => object instanceof http.OutgoingMessage;
+
+dc.subscribe('http.client.request.created', common.mustCall(({ request }) => {
+  assert.strictEqual(request.getHeader('foo'), 'bar');
+  assert.strictEqual(request.getHeader('baz'), undefined);
+  assert.strictEqual(isOutgoingMessage(request), true);
+  assert.strictEqual(isHTTPServer(server), true);
+}));
+
+dc.subscribe('http.client.request.start', common.mustCall(({ request }) => {
+  assert.strictEqual(request.getHeader('foo'), 'bar');
+  assert.strictEqual(request.getHeader('baz'), 'bar');
+  assert.strictEqual(isOutgoingMessage(request), true);
+}));
+
+const server = http.createServer(common.mustCall((_, res) => {
+  res.end('done');
+}));
+
+server.listen(async () => {
+  const { port } = server.address();
+  const req = http.request({
+    port,
+    headers: {
+      'foo': 'bar',
+    }
+  }, common.mustCall(() => {
+    server.close();
+  }));
+  req.setHeader('baz', 'bar');
+  req.end();
+});

filename: test/parallel/test-diagnostics-channel-http.js
patch: @@ -53,6 +53,11 @@ dc.subscribe('http.server.response.finish', common.mustCall(({
   assert.strictEqual(isHTTPServer(server), true);
 }));
 
+dc.subscribe('http.client.request.created', common.mustCall(({ request }) => {
+  assert.strictEqual(isOutgoingMessage(request), true);
+  assert.strictEqual(isHTTPServer(server), true);
+}, 2));
+
 const server = http.createServer(common.mustCall((req, res) => {
   res.end('done');
 }));