@@ -43,6 +43,17 @@ import {
4343 CacheError ,
4444 AbortError ,
4545} from './errors.js' ;
46+ import {
47+ type RequestId ,
48+ generateRequestId ,
49+ publishRequestCreate ,
50+ publishRequestStart ,
51+ publishResponseStart ,
52+ publishResponseEnd ,
53+ publishRetry ,
54+ publishError ,
55+ publishRedirect ,
56+ } from './diagnostics-channel.js' ;
4657
4758type Error = NodeJS . ErrnoException ;
4859
@@ -200,6 +211,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
200211 private _aborted : boolean ;
201212 private _expectedContentLength ?: number ;
202213 private _byteCounter ?: ByteCounter ;
214+ private readonly _requestId : RequestId ;
203215
204216 // We need this because `this._request` if `undefined` when using cache
205217 private _requestInitialized : boolean ;
@@ -229,6 +241,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
229241 this . retryCount = 0 ;
230242
231243 this . _stopRetry = noop ;
244+ this . _requestId = generateRequestId ( ) ;
232245
233246 this . on ( 'pipe' , ( source : any ) => {
234247 if ( source ?. headers ) {
@@ -254,6 +267,13 @@ export default class Request extends Duplex implements RequestEvents<Request> {
254267 }
255268
256269 this . requestUrl = this . options . url as URL ;
270+
271+ // Publish request creation event
272+ publishRequestCreate ( {
273+ requestId : this . _requestId ,
274+ url : this . options . url ?. toString ( ) ?? '' ,
275+ method : this . options . method ,
276+ } ) ;
257277 } catch ( error : any ) {
258278 const { options} = error as OptionsError ;
259279 if ( options ) {
@@ -509,6 +529,14 @@ export default class Request extends Duplex implements RequestEvents<Request> {
509529 // and will detect it's a consumed stream, which is the correct behavior.
510530 }
511531
532+ // Publish retry event
533+ publishRetry ( {
534+ requestId : this . _requestId ,
535+ retryCount : this . retryCount + 1 ,
536+ error : typedError ,
537+ delay : backoff ,
538+ } ) ;
539+
512540 this . emit ( 'retry' , this . retryCount + 1 , error , ( updatedOptions ?: OptionsInit ) => {
513541 const request = new Request ( options . url , updatedOptions , options ) ;
514542 request . retryCount = this . retryCount + 1 ;
@@ -823,6 +851,15 @@ export default class Request extends Duplex implements RequestEvents<Request> {
823851
824852 this . response = typedResponse ;
825853
854+ // Publish response start event
855+ publishResponseStart ( {
856+ requestId : this . _requestId ,
857+ url : typedResponse . url ,
858+ statusCode,
859+ headers : response . headers ,
860+ isFromCache : typedResponse . isFromCache ,
861+ } ) ;
862+
826863 // Workaround for http-timer bug: when connecting to an IP address (no DNS lookup),
827864 // http-timer sets lookup = connect instead of lookup = socket, resulting in
828865 // dns = lookup - socket being a small positive number instead of 0.
@@ -978,6 +1015,14 @@ export default class Request extends Duplex implements RequestEvents<Request> {
9781015 await hook ( updatedOptions as NormalizedOptions , typedResponse ) ;
9791016 }
9801017
1018+ // Publish redirect event
1019+ publishRedirect ( {
1020+ requestId : this . _requestId ,
1021+ fromUrl : url ! . toString ( ) ,
1022+ toUrl : redirectUrl . toString ( ) ,
1023+ statusCode,
1024+ } ) ;
1025+
9811026 this . emit ( 'redirect' , updatedOptions , typedResponse ) ;
9821027
9831028 this . options = updatedOptions ;
@@ -1027,6 +1072,16 @@ export default class Request extends Duplex implements RequestEvents<Request> {
10271072
10281073 this . _responseSize = this . _downloadedSize ;
10291074 this . emit ( 'downloadProgress' , this . downloadProgress ) ;
1075+
1076+ // Publish response end event
1077+ publishResponseEnd ( {
1078+ requestId : this . _requestId ,
1079+ url : typedResponse . url ,
1080+ statusCode,
1081+ bodySize : this . _downloadedSize ,
1082+ timings : this . timings ,
1083+ } ) ;
1084+
10301085 this . push ( null ) ;
10311086 } ) ;
10321087
@@ -1124,6 +1179,14 @@ export default class Request extends Duplex implements RequestEvents<Request> {
11241179 const { options} = this ;
11251180 const { timeout, url} = options ;
11261181
1182+ // Publish request start event
1183+ publishRequestStart ( {
1184+ requestId : this . _requestId ,
1185+ url : url ?. toString ( ) ?? '' ,
1186+ method : options . method ,
1187+ headers : options . headers ,
1188+ } ) ;
1189+
11271190 timer ( request ) ;
11281191
11291192 this . _cancelTimeouts = timedOut ( request , timeout , url as URL ) ;
@@ -1531,6 +1594,14 @@ export default class Request extends Duplex implements RequestEvents<Request> {
15311594 error = new RequestError ( error_ . message , error_ , this ) ;
15321595 }
15331596
1597+ // Publish error event
1598+ publishError ( {
1599+ requestId : this . _requestId ,
1600+ url : this . options ?. url ?. toString ( ) ?? '' ,
1601+ error,
1602+ timings : this . timings ,
1603+ } ) ;
1604+
15341605 this . destroy ( error ) ;
15351606
15361607 // Manually emit error for Promise API to ensure it receives it.
0 commit comments