167 lines
7.5 KiB
JavaScript
167 lines
7.5 KiB
JavaScript
|
"use strict";
|
||
|
var __extends = (this && this.__extends) || (function () {
|
||
|
var extendStatics = Object.setPrototypeOf ||
|
||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||
|
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||
|
return function (d, b) {
|
||
|
extendStatics(d, b);
|
||
|
function __() { this.constructor = d; }
|
||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||
|
};
|
||
|
})();
|
||
|
var url = require("url");
|
||
|
var Contracts = require("../Declarations/Contracts");
|
||
|
var Util = require("../Library/Util");
|
||
|
var RequestResponseHeaders = require("../Library/RequestResponseHeaders");
|
||
|
var RequestParser = require("./RequestParser");
|
||
|
var CorrelationIdManager = require("../Library/CorrelationIdManager");
|
||
|
/**
|
||
|
* Helper class to read data from the request/response objects and convert them into the telemetry contract
|
||
|
*/
|
||
|
var HttpDependencyParser = (function (_super) {
|
||
|
__extends(HttpDependencyParser, _super);
|
||
|
function HttpDependencyParser(requestOptions, request) {
|
||
|
var _this = _super.call(this) || this;
|
||
|
if (request && request.method && requestOptions) {
|
||
|
// The ClientRequest.method property isn't documented, but is always there.
|
||
|
_this.method = request.method;
|
||
|
_this.url = HttpDependencyParser._getUrlFromRequestOptions(requestOptions, request);
|
||
|
_this.startTime = +new Date();
|
||
|
}
|
||
|
return _this;
|
||
|
}
|
||
|
/**
|
||
|
* Called when the ClientRequest emits an error event.
|
||
|
*/
|
||
|
HttpDependencyParser.prototype.onError = function (error) {
|
||
|
this._setStatus(undefined, error);
|
||
|
};
|
||
|
/**
|
||
|
* Called when the ClientRequest emits a response event.
|
||
|
*/
|
||
|
HttpDependencyParser.prototype.onResponse = function (response) {
|
||
|
this._setStatus(response.statusCode, undefined);
|
||
|
this.correlationId = Util.getCorrelationContextTarget(response, RequestResponseHeaders.requestContextTargetKey);
|
||
|
};
|
||
|
/**
|
||
|
* Gets a dependency data contract object for a completed ClientRequest.
|
||
|
*/
|
||
|
HttpDependencyParser.prototype.getDependencyTelemetry = function (baseTelemetry, dependencyId) {
|
||
|
var urlObject = url.parse(this.url);
|
||
|
urlObject.search = undefined;
|
||
|
urlObject.hash = undefined;
|
||
|
var dependencyName = this.method.toUpperCase() + " " + urlObject.pathname;
|
||
|
var remoteDependencyType = Contracts.RemoteDependencyDataConstants.TYPE_HTTP;
|
||
|
var remoteDependencyTarget = urlObject.hostname;
|
||
|
if (urlObject.port) {
|
||
|
remoteDependencyTarget += ":" + urlObject.port;
|
||
|
}
|
||
|
if (this.correlationId) {
|
||
|
remoteDependencyType = Contracts.RemoteDependencyDataConstants.TYPE_AI;
|
||
|
if (this.correlationId !== CorrelationIdManager.correlationIdPrefix) {
|
||
|
remoteDependencyTarget += " | " + this.correlationId;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
remoteDependencyType = Contracts.RemoteDependencyDataConstants.TYPE_HTTP;
|
||
|
}
|
||
|
var dependencyTelemetry = {
|
||
|
id: dependencyId,
|
||
|
name: dependencyName,
|
||
|
data: this.url,
|
||
|
duration: this.duration,
|
||
|
success: this._isSuccess(),
|
||
|
resultCode: this.statusCode ? this.statusCode.toString() : null,
|
||
|
properties: this.properties || {},
|
||
|
dependencyTypeName: remoteDependencyType,
|
||
|
target: remoteDependencyTarget
|
||
|
};
|
||
|
if (baseTelemetry && baseTelemetry.time) {
|
||
|
dependencyTelemetry.time = baseTelemetry.time;
|
||
|
}
|
||
|
else if (this.startTime) {
|
||
|
dependencyTelemetry.time = new Date(this.startTime);
|
||
|
}
|
||
|
// We should keep any parameters the user passed in
|
||
|
// Except the fields defined above in requestTelemetry, which take priority
|
||
|
// Except the properties field, where they're merged instead, with baseTelemetry taking priority
|
||
|
if (baseTelemetry) {
|
||
|
// Copy missing fields
|
||
|
for (var key in baseTelemetry) {
|
||
|
if (!dependencyTelemetry[key]) {
|
||
|
dependencyTelemetry[key] = baseTelemetry[key];
|
||
|
}
|
||
|
}
|
||
|
// Merge properties
|
||
|
if (baseTelemetry.properties) {
|
||
|
for (var key in baseTelemetry.properties) {
|
||
|
dependencyTelemetry.properties[key] = baseTelemetry.properties[key];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return dependencyTelemetry;
|
||
|
};
|
||
|
/**
|
||
|
* Builds a URL from request options, using the same logic as http.request(). This is
|
||
|
* necessary because a ClientRequest object does not expose a url property.
|
||
|
*/
|
||
|
HttpDependencyParser._getUrlFromRequestOptions = function (options, request) {
|
||
|
if (typeof options === 'string') {
|
||
|
if (options.indexOf("http://") === 0 || options.indexOf("https://") === 0) {
|
||
|
// protocol exists, parse normally
|
||
|
options = url.parse(options);
|
||
|
}
|
||
|
else {
|
||
|
// protocol not found, insert http/https where appropriate
|
||
|
var parsed = url.parse(options);
|
||
|
if (parsed.host === "443") {
|
||
|
options = url.parse("https://" + options);
|
||
|
}
|
||
|
else {
|
||
|
options = url.parse("http://" + options);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (options && typeof url.URL === 'function' && options instanceof url.URL) {
|
||
|
return url.format(options);
|
||
|
}
|
||
|
else {
|
||
|
// Avoid modifying the original options object.
|
||
|
var originalOptions_1 = options;
|
||
|
options = {};
|
||
|
if (originalOptions_1) {
|
||
|
Object.keys(originalOptions_1).forEach(function (key) {
|
||
|
options[key] = originalOptions_1[key];
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
// Oddly, url.format ignores path and only uses pathname and search,
|
||
|
// so create them from the path, if path was specified
|
||
|
if (options.path) {
|
||
|
var parsedQuery = url.parse(options.path);
|
||
|
options.pathname = parsedQuery.pathname;
|
||
|
options.search = parsedQuery.search;
|
||
|
}
|
||
|
// Similarly, url.format ignores hostname and port if host is specified,
|
||
|
// even if host doesn't have the port, but http.request does not work
|
||
|
// this way. It will use the port if one is not specified in host,
|
||
|
// effectively treating host as hostname, but will use the port specified
|
||
|
// in host if it exists.
|
||
|
if (options.host && options.port) {
|
||
|
// Force a protocol so it will parse the host as the host, not path.
|
||
|
// It is discarded and not used, so it doesn't matter if it doesn't match
|
||
|
var parsedHost = url.parse("http://" + options.host);
|
||
|
if (!parsedHost.port && options.port) {
|
||
|
options.hostname = options.host;
|
||
|
delete options.host;
|
||
|
}
|
||
|
}
|
||
|
// Mix in default values used by http.request and others
|
||
|
options.protocol = options.protocol || (request.agent && request.agent.protocol) || (request.protocol) || undefined;
|
||
|
options.hostname = options.hostname || 'localhost';
|
||
|
return url.format(options);
|
||
|
};
|
||
|
return HttpDependencyParser;
|
||
|
}(RequestParser));
|
||
|
module.exports = HttpDependencyParser;
|
||
|
//# sourceMappingURL=HttpDependencyParser.js.map
|