urllib
Version:
Help in opening URLs (mostly HTTP) in a complex world — basic and digest authentication, redirections, cookies and more. Base undici fetch API.
132 lines • 7.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.initDiagnosticsChannel = void 0;
const tslib_1 = require("tslib");
const diagnostics_channel_1 = tslib_1.__importDefault(require("diagnostics_channel"));
const perf_hooks_1 = require("perf_hooks");
const util_1 = require("util");
const symbols_1 = tslib_1.__importDefault(require("./symbols"));
const utils_1 = require("./utils");
const debug = (0, util_1.debuglog)('urllib:DiagnosticsChannel');
let initedDiagnosticsChannel = false;
// https://undici.nodejs.org/#/docs/api/DiagnosticsChannel
// client --> server
// undici:request:create => { request }
// -> [optional] undici:client:connected => { socket } [first request will create socket]
// -> undici:client:sendHeaders => { socket, request }
// -> undici:request:bodySent => { request }
//
// server --> client
// undici:request:headers => { request, response }
// -> undici:request:trailers => { request, trailers }
function initDiagnosticsChannel() {
// makre sure init global DiagnosticsChannel once
if (initedDiagnosticsChannel)
return;
initedDiagnosticsChannel = true;
let kHandler;
// This message is published when a new outgoing request is created.
// Note: a request is only loosely completed to a given socket.
diagnostics_channel_1.default.channel('undici:request:create').subscribe((message, name) => {
var _a, _b;
const { request } = message;
if (!kHandler) {
const symbols = Object.getOwnPropertySymbols(request);
for (const symbol of symbols) {
if (symbol.description === 'handler') {
kHandler = symbol;
break;
}
}
}
const opaque = (_b = (_a = request[kHandler]) === null || _a === void 0 ? void 0 : _a.opts) === null || _b === void 0 ? void 0 : _b.opaque;
// ignore non HttpClient Request
if (!opaque || !opaque[symbols_1.default.kRequestId])
return;
debug('[%s] Request#%d %s %s, path: %s', name, opaque[symbols_1.default.kRequestId], request.method, request.origin, request.path);
if (!opaque[symbols_1.default.kEnableRequestTiming])
return;
opaque[symbols_1.default.kRequestTiming].queuing = (0, utils_1.performanceTime)(opaque[symbols_1.default.kRequestStartTime]);
});
// diagnosticsChannel.channel('undici:client:beforeConnect')
// diagnosticsChannel.channel('undici:client:connectError')
// This message is published after a connection is established.
diagnostics_channel_1.default.channel('undici:client:connected').subscribe((message, name) => {
const { socket } = message;
socket[symbols_1.default.kSocketId] = (0, utils_1.globalId)('UndiciSocket');
socket[symbols_1.default.kSocketStartTime] = perf_hooks_1.performance.now();
socket[symbols_1.default.kHandledRequests] = 0;
socket[symbols_1.default.kHandledResponses] = 0;
debug('[%s] Socket#%d connected', name, socket[symbols_1.default.kSocketId]);
});
// This message is published right before the first byte of the request is written to the socket.
diagnostics_channel_1.default.channel('undici:client:sendHeaders').subscribe((message, name) => {
var _a, _b;
const { request, socket } = message;
if (!kHandler)
return;
const opaque = (_b = (_a = request[kHandler]) === null || _a === void 0 ? void 0 : _a.opts) === null || _b === void 0 ? void 0 : _b.opaque;
if (!opaque || !opaque[symbols_1.default.kRequestId])
return;
socket[symbols_1.default.kHandledRequests]++;
// attach socket to opaque
opaque[symbols_1.default.kRequestSocket] = socket;
debug('[%s] Request#%d send headers on Socket#%d (handled %d requests)', name, opaque[symbols_1.default.kRequestId], socket[symbols_1.default.kSocketId], socket[symbols_1.default.kHandledRequests]);
if (!opaque[symbols_1.default.kEnableRequestTiming])
return;
opaque[symbols_1.default.kRequestTiming].requestHeadersSent = (0, utils_1.performanceTime)(opaque[symbols_1.default.kRequestStartTime]);
// first socket need to caculate the connected time
if (socket[symbols_1.default.kHandledRequests] === 1) {
// kSocketStartTime - kRequestStartTime = connected time
opaque[symbols_1.default.kRequestTiming].connected =
(0, utils_1.performanceTime)(opaque[symbols_1.default.kRequestStartTime], socket[symbols_1.default.kSocketStartTime]);
}
});
diagnostics_channel_1.default.channel('undici:request:bodySent').subscribe((message, name) => {
var _a, _b;
const { request } = message;
if (!kHandler)
return;
const opaque = (_b = (_a = request[kHandler]) === null || _a === void 0 ? void 0 : _a.opts) === null || _b === void 0 ? void 0 : _b.opaque;
if (!opaque || !opaque[symbols_1.default.kRequestId])
return;
debug('[%s] Request#%d send body', name, opaque[symbols_1.default.kRequestId]);
if (!opaque[symbols_1.default.kEnableRequestTiming])
return;
opaque[symbols_1.default.kRequestTiming].requestSent = (0, utils_1.performanceTime)(opaque[symbols_1.default.kRequestStartTime]);
});
// This message is published after the response headers have been received, i.e. the response has been completed.
diagnostics_channel_1.default.channel('undici:request:headers').subscribe((message, name) => {
var _a, _b;
const { request, response } = message;
if (!kHandler)
return;
const opaque = (_b = (_a = request[kHandler]) === null || _a === void 0 ? void 0 : _a.opts) === null || _b === void 0 ? void 0 : _b.opaque;
if (!opaque || !opaque[symbols_1.default.kRequestId])
return;
// get socket from opaque
const socket = opaque[symbols_1.default.kRequestSocket];
socket[symbols_1.default.kHandledResponses]++;
debug('[%s] Request#%d get %s response headers on Socket#%d (handled %d responses)', name, opaque[symbols_1.default.kRequestId], response.statusCode, socket[symbols_1.default.kSocketId], socket[symbols_1.default.kHandledResponses]);
if (!opaque[symbols_1.default.kEnableRequestTiming])
return;
opaque[symbols_1.default.kRequestTiming].waiting = (0, utils_1.performanceTime)(opaque[symbols_1.default.kRequestStartTime]);
});
// This message is published after the response body and trailers have been received, i.e. the response has been completed.
diagnostics_channel_1.default.channel('undici:request:trailers').subscribe((message, name) => {
var _a, _b;
const { request } = message;
if (!kHandler)
return;
const opaque = (_b = (_a = request[kHandler]) === null || _a === void 0 ? void 0 : _a.opts) === null || _b === void 0 ? void 0 : _b.opaque;
if (!opaque || !opaque[symbols_1.default.kRequestId])
return;
debug('[%s] Request#%d get response body and trailers', name, opaque[symbols_1.default.kRequestId]);
if (!opaque[symbols_1.default.kEnableRequestTiming])
return;
opaque[symbols_1.default.kRequestTiming].contentDownload = (0, utils_1.performanceTime)(opaque[symbols_1.default.kRequestStartTime]);
});
// diagnosticsChannel.channel('undici:request:error')
}
exports.initDiagnosticsChannel = initDiagnosticsChannel;
//# sourceMappingURL=diagnosticsChannel.js.map