first commit

This commit is contained in:
Stefan Hacker
2026-04-03 09:38:48 +02:00
commit 37ad745546
47450 changed files with 3120798 additions and 0 deletions
@@ -0,0 +1,72 @@
/**
* Type of span. Can be used to specify additional relationships between spans
* in addition to a parent/child relationship.
*/
export declare enum SpanKind {
/** Default value. Indicates that the span is used internally. */
INTERNAL = 0,
/**
* Indicates that the span covers server-side handling of an RPC or other
* remote request.
*/
SERVER = 1,
/**
* Indicates that the span covers the client-side wrapper around an RPC or
* other remote request.
*/
CLIENT = 2,
/**
* Indicates that the span describes producer sending a message to a
* broker. Unlike client and server, there is no direct critical path latency
* relationship between producer and consumer spans.
*/
PRODUCER = 3,
/**
* Indicates that the span describes consumer receiving a message from a
* broker. Unlike client and server, there is no direct critical path latency
* relationship between producer and consumer spans.
*/
CONSUMER = 4,
}
export declare type LinkContext = Pick<SpanContext, 'traceId' | 'spanId'>;
export interface Attributes {
[attributeKey: string]: AttributeValue | undefined;
}
export declare type AttributeValue = string | number | boolean | Array<null | undefined | string> | Array<null | undefined | number> | Array<null | undefined | boolean>;
export interface Link {
/** The {@link SpanContext} of a linked span. */
context: LinkContext;
/** A set of {@link Attributes} on the link. */
attributes?: Attributes;
}
export interface SpanContext {
traceId: string;
spanId: string;
traceFlags?: {
toString: () => string;
};
tracestate?: string;
}
export interface Span {
_duration: [number, number];
name: string;
parentSpanId?: string;
status: {
code: number;
message?: string;
};
attributes: Record<string, string>;
kind: SpanKind;
links: Link[];
context: () => SpanContext;
}
export declare class OpenTelemetryScopeManagerWrapper {
private _activeSymbol;
active(): any;
with(span: Span, fn: () => any): any;
bind<T>(target: T): T;
enable(): this;
disable(): this;
private static _spanToContext(span, parentSpanId?, name?);
}
export declare const AsyncScopeManager: OpenTelemetryScopeManagerWrapper;
@@ -0,0 +1,95 @@
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var CorrelationContextManager_1 = require("./CorrelationContextManager");
var events_1 = require("events");
/**
* Type of span. Can be used to specify additional relationships between spans
* in addition to a parent/child relationship.
*/
var SpanKind;
(function (SpanKind) {
/** Default value. Indicates that the span is used internally. */
SpanKind[SpanKind["INTERNAL"] = 0] = "INTERNAL";
/**
* Indicates that the span covers server-side handling of an RPC or other
* remote request.
*/
SpanKind[SpanKind["SERVER"] = 1] = "SERVER";
/**
* Indicates that the span covers the client-side wrapper around an RPC or
* other remote request.
*/
SpanKind[SpanKind["CLIENT"] = 2] = "CLIENT";
/**
* Indicates that the span describes producer sending a message to a
* broker. Unlike client and server, there is no direct critical path latency
* relationship between producer and consumer spans.
*/
SpanKind[SpanKind["PRODUCER"] = 3] = "PRODUCER";
/**
* Indicates that the span describes consumer receiving a message from a
* broker. Unlike client and server, there is no direct critical path latency
* relationship between producer and consumer spans.
*/
SpanKind[SpanKind["CONSUMER"] = 4] = "CONSUMER";
})(SpanKind = exports.SpanKind || (exports.SpanKind = {}));
var OpenTelemetryScopeManagerWrapper = (function () {
function OpenTelemetryScopeManagerWrapper() {
}
OpenTelemetryScopeManagerWrapper.prototype.active = function () {
var _this = this;
var context = CorrelationContextManager_1.CorrelationContextManager.getCurrentContext();
return __assign({}, context, { getValue: function (key) {
// todo: lazy import activeSymbol from opentelemetry/api
if (!_this._activeSymbol) {
_this._activeSymbol = key;
return context;
}
if (key === _this._activeSymbol) {
return context;
}
return false;
}, setValue: function () { } });
};
OpenTelemetryScopeManagerWrapper.prototype.with = function (span, fn) {
var parentSpanId = span.parentSpanId;
var name = span.name;
var correlationContext = OpenTelemetryScopeManagerWrapper._spanToContext(span, parentSpanId, name);
return CorrelationContextManager_1.CorrelationContextManager.runWithContext(correlationContext, fn)();
};
OpenTelemetryScopeManagerWrapper.prototype.bind = function (target) {
if (typeof target === "function") {
return CorrelationContextManager_1.CorrelationContextManager.wrapCallback(target);
}
else if (target instanceof events_1.EventEmitter) {
CorrelationContextManager_1.CorrelationContextManager.wrapEmitter(target);
}
return target;
};
OpenTelemetryScopeManagerWrapper.prototype.enable = function () {
CorrelationContextManager_1.CorrelationContextManager.enable();
return this;
};
OpenTelemetryScopeManagerWrapper.prototype.disable = function () {
CorrelationContextManager_1.CorrelationContextManager.disable();
return this;
};
OpenTelemetryScopeManagerWrapper._spanToContext = function (span, parentSpanId, name) {
var _parentId = parentSpanId ? "|" + span.context().traceId + "." + parentSpanId + "." : span.context().traceId;
var context = __assign({}, span.context(), { traceFlags: span.context().traceFlags.toString() });
var correlationContext = CorrelationContextManager_1.CorrelationContextManager.spanToContextObject(context, _parentId, name);
return correlationContext;
};
return OpenTelemetryScopeManagerWrapper;
}());
exports.OpenTelemetryScopeManagerWrapper = OpenTelemetryScopeManagerWrapper;
exports.AsyncScopeManager = new OpenTelemetryScopeManagerWrapper();
//# sourceMappingURL=AsyncHooksScopeManager.js.map
File diff suppressed because one or more lines are too long
+15
View File
@@ -0,0 +1,15 @@
import TelemetryClient = require("../Library/TelemetryClient");
declare class AutoCollectConsole {
static originalMethods: {
[name: string]: (message?: any, ...optionalParams: any[]) => void;
};
static INSTANCE: AutoCollectConsole;
private static _methodNames;
private _client;
private _isInitialized;
constructor(client: TelemetryClient);
enable(isEnabled: boolean, collectConsoleLog: boolean): void;
isInitialized(): boolean;
dispose(): void;
}
export = AutoCollectConsole;
+29
View File
@@ -0,0 +1,29 @@
"use strict";
var DiagChannel = require("./diagnostic-channel/initialization");
var AutoCollectConsole = (function () {
function AutoCollectConsole(client) {
if (!!AutoCollectConsole.INSTANCE) {
throw new Error("Console logging adapter tracking should be configured from the applicationInsights object");
}
this._client = client;
AutoCollectConsole.INSTANCE = this;
}
AutoCollectConsole.prototype.enable = function (isEnabled, collectConsoleLog) {
if (DiagChannel.IsInitialized) {
require("./diagnostic-channel/console.sub").enable(isEnabled && collectConsoleLog, this._client);
require("./diagnostic-channel/bunyan.sub").enable(isEnabled, this._client);
require("./diagnostic-channel/winston.sub").enable(isEnabled, this._client);
}
};
AutoCollectConsole.prototype.isInitialized = function () {
return this._isInitialized;
};
AutoCollectConsole.prototype.dispose = function () {
AutoCollectConsole.INSTANCE = null;
this.enable(false, false);
};
AutoCollectConsole._methodNames = ["debug", "info", "log", "warn", "error"];
return AutoCollectConsole;
}());
module.exports = AutoCollectConsole;
//# sourceMappingURL=Console.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"Console.js","sourceRoot":"","sources":["../../AutoCollection/Console.ts"],"names":[],"mappings":";AAGA,iEAAmE;AAEnE;IASI,4BAAY,MAAuB;QAC/B,EAAE,CAAA,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,2FAA2F,CAAC,CAAC;QACjH,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,kBAAkB,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvC,CAAC;IAEM,mCAAM,GAAb,UAAc,SAAkB,EAAE,iBAA0B;QACxD,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;YAC5B,OAAO,CAAC,kCAAkC,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACjG,OAAO,CAAC,iCAAiC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3E,OAAO,CAAC,kCAAkC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAChF,CAAC;IACL,CAAC;IAEM,0CAAa,GAApB;QACI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC;IAC/B,CAAC;IAEM,oCAAO,GAAd;QACI,kBAAkB,CAAC,QAAQ,GAAG,IAAI,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IA7Bc,+BAAY,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IA8B5E,yBAAC;CAAA,AAlCD,IAkCC;AAED,iBAAS,kBAAkB,CAAC","sourcesContent":["import TelemetryClient = require(\"../Library/TelemetryClient\");\r\nimport Logging = require(\"../Library/Logging\");\r\n\r\nimport * as DiagChannel from \"./diagnostic-channel/initialization\";\r\n\r\nclass AutoCollectConsole {\r\n public static originalMethods: {[name: string]: (message?: any, ...optionalParams: any[]) => void};\r\n\r\n public static INSTANCE: AutoCollectConsole;\r\n private static _methodNames = [\"debug\", \"info\", \"log\", \"warn\", \"error\"];\r\n\r\n private _client: TelemetryClient;\r\n private _isInitialized: boolean;\r\n\r\n constructor(client: TelemetryClient) {\r\n if(!!AutoCollectConsole.INSTANCE) {\r\n throw new Error(\"Console logging adapter tracking should be configured from the applicationInsights object\");\r\n }\r\n\r\n this._client = client;\r\n AutoCollectConsole.INSTANCE = this;\r\n }\r\n\r\n public enable(isEnabled: boolean, collectConsoleLog: boolean) {\r\n if (DiagChannel.IsInitialized) {\r\n require(\"./diagnostic-channel/console.sub\").enable(isEnabled && collectConsoleLog, this._client);\r\n require(\"./diagnostic-channel/bunyan.sub\").enable(isEnabled, this._client);\r\n require(\"./diagnostic-channel/winston.sub\").enable(isEnabled, this._client);\r\n }\r\n }\r\n\r\n public isInitialized() {\r\n return this._isInitialized;\r\n }\r\n\r\n public dispose() {\r\n AutoCollectConsole.INSTANCE = null;\r\n this.enable(false, false);\r\n }\r\n}\r\n\r\nexport = AutoCollectConsole;\r\n"]}
@@ -0,0 +1,101 @@
/// <reference types="node" />
import events = require("events");
import * as azureFunctionsTypes from "../Library/Functions";
import * as http from "http";
import Traceparent = require("../Library/Traceparent");
import Tracestate = require("../Library/Tracestate");
import { ISpanContext } from "diagnostic-channel";
export interface CustomProperties {
/**
* Get a custom property from the correlation context
*/
getProperty(key: string): string;
/**
* Store a custom property in the correlation context.
* Do not store sensitive information here.
* Properties stored here are exposed via outgoing HTTP headers for correlating data cross-component.
* The characters ',' and '=' are disallowed within keys or values.
*/
setProperty(key: string, value: string): void;
}
export interface PrivateCustomProperties extends CustomProperties {
addHeaderData(header: string): void;
serializeToHeader(): string;
}
export interface CorrelationContext {
operation: {
name: string;
id: string;
parentId: string;
traceparent?: Traceparent;
tracestate?: Tracestate;
};
/** Do not store sensitive information here.
* Properties here are exposed via outgoing HTTP headers for correlating data cross-component.
*/
customProperties: CustomProperties;
}
export declare class CorrelationContextManager {
private static enabled;
private static hasEverEnabled;
private static forceClsHooked;
private static session;
private static cls;
private static CONTEXT_NAME;
/**
* Provides the current Context.
* The context is the most recent one entered into for the current
* logical chain of execution, including across asynchronous calls.
*/
static getCurrentContext(): CorrelationContext | null;
/**
* A helper to generate objects conforming to the CorrelationContext interface
*/
static generateContextObject(operationId: string, parentId?: string, operationName?: string, correlationContextHeader?: string, traceparent?: Traceparent, tracestate?: Tracestate): CorrelationContext;
static spanToContextObject(spanContext: ISpanContext, parentId?: string, name?: string): CorrelationContext;
/**
* Runs a function inside a given Context.
* All logical children of the execution path that entered this Context
* will receive this Context object on calls to GetCurrentContext.
*/
static runWithContext(context: CorrelationContext, fn: () => any): any;
/**
* Wrapper for cls-hooked bindEmitter method
*/
static wrapEmitter(emitter: events.EventEmitter): void;
/**
* Patches a callback to restore the correct Context when getCurrentContext
* is run within it. This is necessary if automatic correlation fails to work
* with user-included libraries.
*
* The supplied callback will be given the same context that was present for
* the call to wrapCallback. */
static wrapCallback<T extends Function>(fn: T, context?: CorrelationContext): T;
/**
* Enables the CorrelationContextManager.
*/
static enable(forceClsHooked?: boolean): void;
static startOperation(context: azureFunctionsTypes.Context | (http.IncomingMessage | azureFunctionsTypes.HttpRequest) | ISpanContext, request?: azureFunctionsTypes.HttpRequest | string): CorrelationContext | null;
/**
* Disables the CorrelationContextManager.
*/
static disable(): void;
/**
* Reset the namespace
*/
static reset(): void;
/**
* Reports if CorrelationContextManager is able to run in this environment
*/
static isNodeVersionCompatible(): boolean;
/**
* We only want to use cls-hooked when it uses async_hooks api (8.2+), else
* use async-listener (plain -cls)
*/
static shouldUseClsHooked(): boolean;
/**
* A TypeError is triggered by cls-hooked for node [8.0, 8.2)
* @internal Used in tests only
*/
static canUseClsHooked(): boolean;
}
@@ -0,0 +1,249 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Logging = require("../Library/Logging");
var DiagChannel = require("./diagnostic-channel/initialization");
var Traceparent = require("../Library/Traceparent");
var Tracestate = require("../Library/Tracestate");
var HttpRequestParser = require("./HttpRequestParser");
var CorrelationContextManager = (function () {
function CorrelationContextManager() {
}
/**
* Provides the current Context.
* The context is the most recent one entered into for the current
* logical chain of execution, including across asynchronous calls.
*/
CorrelationContextManager.getCurrentContext = function () {
if (!CorrelationContextManager.enabled) {
return null;
}
var context = CorrelationContextManager.session.get(CorrelationContextManager.CONTEXT_NAME);
if (context === undefined) {
return null;
}
return context;
};
/**
* A helper to generate objects conforming to the CorrelationContext interface
*/
CorrelationContextManager.generateContextObject = function (operationId, parentId, operationName, correlationContextHeader, traceparent, tracestate) {
parentId = parentId || operationId;
if (this.enabled) {
return {
operation: {
name: operationName,
id: operationId,
parentId: parentId,
traceparent: traceparent,
tracestate: tracestate
},
customProperties: new CustomPropertiesImpl(correlationContextHeader)
};
}
return null;
};
CorrelationContextManager.spanToContextObject = function (spanContext, parentId, name) {
var traceContext = new Traceparent();
traceContext.traceId = spanContext.traceId;
traceContext.spanId = spanContext.spanId;
traceContext.traceFlag = spanContext.traceFlags || Traceparent.DEFAULT_TRACE_FLAG;
traceContext.parentId = parentId;
return CorrelationContextManager.generateContextObject(traceContext.traceId, traceContext.parentId, name, null, traceContext);
};
/**
* Runs a function inside a given Context.
* All logical children of the execution path that entered this Context
* will receive this Context object on calls to GetCurrentContext.
*/
CorrelationContextManager.runWithContext = function (context, fn) {
if (CorrelationContextManager.enabled) {
return CorrelationContextManager.session.bind(fn, (_a = {}, _a[CorrelationContextManager.CONTEXT_NAME] = context, _a))();
}
else {
return fn();
}
var _a;
};
/**
* Wrapper for cls-hooked bindEmitter method
*/
CorrelationContextManager.wrapEmitter = function (emitter) {
if (CorrelationContextManager.enabled) {
CorrelationContextManager.session.bindEmitter(emitter);
}
};
/**
* Patches a callback to restore the correct Context when getCurrentContext
* is run within it. This is necessary if automatic correlation fails to work
* with user-included libraries.
*
* The supplied callback will be given the same context that was present for
* the call to wrapCallback. */
CorrelationContextManager.wrapCallback = function (fn, context) {
if (CorrelationContextManager.enabled) {
return CorrelationContextManager.session.bind(fn, context ? (_a = {},
_a[CorrelationContextManager.CONTEXT_NAME] = context,
_a) : undefined);
}
return fn;
var _a;
};
/**
* Enables the CorrelationContextManager.
*/
CorrelationContextManager.enable = function (forceClsHooked) {
if (this.enabled) {
return;
}
if (!this.isNodeVersionCompatible()) {
this.enabled = false;
return;
}
if (!CorrelationContextManager.hasEverEnabled) {
this.forceClsHooked = forceClsHooked;
this.hasEverEnabled = true;
if (typeof this.cls === "undefined") {
if ((CorrelationContextManager.forceClsHooked === true) || (CorrelationContextManager.forceClsHooked === undefined && CorrelationContextManager.shouldUseClsHooked())) {
this.cls = require('cls-hooked');
}
else {
this.cls = require('continuation-local-storage');
}
}
CorrelationContextManager.session = this.cls.createNamespace("AI-CLS-Session");
DiagChannel.registerContextPreservation(function (cb) {
return CorrelationContextManager.session.bind(cb);
});
}
this.enabled = true;
};
CorrelationContextManager.startOperation = function (context, request) {
var traceContext = context && context.traceContext || null;
var spanContext = context && context.traceId
? context
: null;
var headers = context && context.headers;
if (spanContext) {
var traceparent = new Traceparent("00-" + spanContext.traceId + "-" + spanContext.spanId + "-01");
var tracestate = new Tracestate(spanContext.tracestate);
var correlationContext = CorrelationContextManager.generateContextObject(spanContext.traceId, "|" + spanContext.traceId + "." + spanContext.spanId + ".", typeof request === "string" ? request : "", undefined, traceparent, tracestate);
return correlationContext;
}
// AzFunction TraceContext available
if (traceContext) {
var traceparent = new Traceparent(traceContext.traceparent);
var tracestate = new Tracestate(traceContext.tracestate);
var parser = typeof request === "object"
? new HttpRequestParser(request)
: null;
var correlationContext = CorrelationContextManager.generateContextObject(traceparent.traceId, traceparent.parentId, typeof request === "string"
? request
: parser.getOperationName({}), parser && parser.getCorrelationContextHeader() || undefined, traceparent, tracestate);
return correlationContext;
}
// No TraceContext available, parse as http.IncomingMessage
if (headers) {
var traceparent = new Traceparent(headers.traceparent);
var tracestate = new Tracestate(headers.tracestate);
var parser = new HttpRequestParser(context);
var correlationContext = CorrelationContextManager.generateContextObject(traceparent.traceId, traceparent.parentId, parser.getOperationName({}), parser.getCorrelationContextHeader(), traceparent, tracestate);
return correlationContext;
}
Logging.warn("startOperation was called with invalid arguments", arguments);
return null;
};
/**
* Disables the CorrelationContextManager.
*/
CorrelationContextManager.disable = function () {
this.enabled = false;
};
/**
* Reset the namespace
*/
CorrelationContextManager.reset = function () {
if (CorrelationContextManager.hasEverEnabled) {
CorrelationContextManager.session = null;
CorrelationContextManager.session = this.cls.createNamespace('AI-CLS-Session');
}
};
/**
* Reports if CorrelationContextManager is able to run in this environment
*/
CorrelationContextManager.isNodeVersionCompatible = function () {
var nodeVer = process.versions.node.split(".");
return parseInt(nodeVer[0]) > 3 || (parseInt(nodeVer[0]) > 2 && parseInt(nodeVer[1]) > 2);
};
/**
* We only want to use cls-hooked when it uses async_hooks api (8.2+), else
* use async-listener (plain -cls)
*/
CorrelationContextManager.shouldUseClsHooked = function () {
var nodeVer = process.versions.node.split(".");
return (parseInt(nodeVer[0]) > 8) || (parseInt(nodeVer[0]) >= 8 && parseInt(nodeVer[1]) >= 2);
};
/**
* A TypeError is triggered by cls-hooked for node [8.0, 8.2)
* @internal Used in tests only
*/
CorrelationContextManager.canUseClsHooked = function () {
var nodeVer = process.versions.node.split(".");
var greater800 = (parseInt(nodeVer[0]) > 8) || (parseInt(nodeVer[0]) >= 8 && parseInt(nodeVer[1]) >= 0);
var less820 = (parseInt(nodeVer[0]) < 8) || (parseInt(nodeVer[0]) <= 8 && parseInt(nodeVer[1]) < 2);
var greater470 = parseInt(nodeVer[0]) > 4 || (parseInt(nodeVer[0]) >= 4 && parseInt(nodeVer[1]) >= 7); // cls-hooked requires node 4.7+
return !(greater800 && less820) && greater470;
};
CorrelationContextManager.enabled = false;
CorrelationContextManager.hasEverEnabled = false;
CorrelationContextManager.forceClsHooked = undefined; // true: use cls-hooked, false: use cls, undefined: choose based on node version
CorrelationContextManager.CONTEXT_NAME = "ApplicationInsights-Context";
return CorrelationContextManager;
}());
exports.CorrelationContextManager = CorrelationContextManager;
var CustomPropertiesImpl = (function () {
function CustomPropertiesImpl(header) {
this.props = [];
this.addHeaderData(header);
}
CustomPropertiesImpl.prototype.addHeaderData = function (header) {
var keyvals = header ? header.split(", ") : [];
this.props = keyvals.map(function (keyval) {
var parts = keyval.split("=");
return { key: parts[0], value: parts[1] };
}).concat(this.props);
};
CustomPropertiesImpl.prototype.serializeToHeader = function () {
return this.props.map(function (keyval) {
return keyval.key + "=" + keyval.value;
}).join(", ");
};
CustomPropertiesImpl.prototype.getProperty = function (prop) {
for (var i = 0; i < this.props.length; ++i) {
var keyval = this.props[i];
if (keyval.key === prop) {
return keyval.value;
}
}
return;
};
// TODO: Strictly according to the spec, properties which are recieved from
// an incoming request should be left untouched, while we may add our own new
// properties. The logic here will need to change to track that.
CustomPropertiesImpl.prototype.setProperty = function (prop, val) {
if (CustomPropertiesImpl.bannedCharacters.test(prop) || CustomPropertiesImpl.bannedCharacters.test(val)) {
Logging.warn("Correlation context property keys and values must not contain ',' or '='. setProperty was called with key: " + prop + " and value: " + val);
return;
}
for (var i = 0; i < this.props.length; ++i) {
var keyval = this.props[i];
if (keyval.key === prop) {
keyval.value = val;
return;
}
}
this.props.push({ key: prop, value: val });
};
CustomPropertiesImpl.bannedCharacters = /[,=]/;
return CustomPropertiesImpl;
}());
//# sourceMappingURL=CorrelationContextManager.js.map
File diff suppressed because one or more lines are too long
+19
View File
@@ -0,0 +1,19 @@
import TelemetryClient = require("../Library/TelemetryClient");
declare class AutoCollectExceptions {
static INSTANCE: AutoCollectExceptions;
static UNCAUGHT_EXCEPTION_MONITOR_HANDLER_NAME: string;
static UNCAUGHT_EXCEPTION_HANDLER_NAME: string;
static UNHANDLED_REJECTION_HANDLER_NAME: string;
private static _RETHROW_EXIT_MESSAGE;
private static _FALLBACK_ERROR_MESSAGE;
private static _canUseUncaughtExceptionMonitor;
private _exceptionListenerHandle;
private _rejectionListenerHandle;
private _client;
private _isInitialized;
constructor(client: TelemetryClient);
isInitialized(): boolean;
enable(isEnabled: boolean): void;
dispose(): void;
}
export = AutoCollectExceptions;
+78
View File
@@ -0,0 +1,78 @@
"use strict";
var AutoCollectExceptions = (function () {
function AutoCollectExceptions(client) {
if (!!AutoCollectExceptions.INSTANCE) {
throw new Error("Exception tracking should be configured from the applicationInsights object");
}
AutoCollectExceptions.INSTANCE = this;
this._client = client;
// Only use for 13.7.0+
var nodeVer = process.versions.node.split(".");
AutoCollectExceptions._canUseUncaughtExceptionMonitor = parseInt(nodeVer[0]) > 13 || (parseInt(nodeVer[0]) === 13 && parseInt(nodeVer[1]) >= 7);
}
AutoCollectExceptions.prototype.isInitialized = function () {
return this._isInitialized;
};
AutoCollectExceptions.prototype.enable = function (isEnabled) {
var _this = this;
if (isEnabled) {
this._isInitialized = true;
var self = this;
if (!this._exceptionListenerHandle) {
// For scenarios like Promise.reject(), an error won't be passed to the handle. Create a placeholder
// error for these scenarios.
var handle = function (reThrow, name, error) {
if (error === void 0) { error = new Error(AutoCollectExceptions._FALLBACK_ERROR_MESSAGE); }
_this._client.trackException({ exception: error });
_this._client.flush({ isAppCrashing: true });
// only rethrow when we are the only listener
if (reThrow && name && process.listeners(name).length === 1) {
console.error(error);
process.exit(1);
}
};
if (AutoCollectExceptions._canUseUncaughtExceptionMonitor) {
// Node.js >= 13.7.0, use uncaughtExceptionMonitor. It handles both promises and exceptions
this._exceptionListenerHandle = handle.bind(this, false, undefined); // never rethrows
process.on(AutoCollectExceptions.UNCAUGHT_EXCEPTION_MONITOR_HANDLER_NAME, this._exceptionListenerHandle);
}
else {
this._exceptionListenerHandle = handle.bind(this, true, AutoCollectExceptions.UNCAUGHT_EXCEPTION_HANDLER_NAME);
this._rejectionListenerHandle = handle.bind(this, false, undefined); // never rethrows
process.on(AutoCollectExceptions.UNCAUGHT_EXCEPTION_HANDLER_NAME, this._exceptionListenerHandle);
process.on(AutoCollectExceptions.UNHANDLED_REJECTION_HANDLER_NAME, this._rejectionListenerHandle);
}
}
}
else {
if (this._exceptionListenerHandle) {
if (AutoCollectExceptions._canUseUncaughtExceptionMonitor) {
process.removeListener(AutoCollectExceptions.UNCAUGHT_EXCEPTION_MONITOR_HANDLER_NAME, this._exceptionListenerHandle);
}
else {
process.removeListener(AutoCollectExceptions.UNCAUGHT_EXCEPTION_HANDLER_NAME, this._exceptionListenerHandle);
process.removeListener(AutoCollectExceptions.UNHANDLED_REJECTION_HANDLER_NAME, this._rejectionListenerHandle);
}
this._exceptionListenerHandle = undefined;
this._rejectionListenerHandle = undefined;
delete this._exceptionListenerHandle;
delete this._rejectionListenerHandle;
}
}
};
AutoCollectExceptions.prototype.dispose = function () {
AutoCollectExceptions.INSTANCE = null;
this.enable(false);
this._isInitialized = false;
};
AutoCollectExceptions.INSTANCE = null;
AutoCollectExceptions.UNCAUGHT_EXCEPTION_MONITOR_HANDLER_NAME = "uncaughtExceptionMonitor";
AutoCollectExceptions.UNCAUGHT_EXCEPTION_HANDLER_NAME = "uncaughtException";
AutoCollectExceptions.UNHANDLED_REJECTION_HANDLER_NAME = "unhandledRejection";
AutoCollectExceptions._RETHROW_EXIT_MESSAGE = "Application Insights Rethrow Exception Handler";
AutoCollectExceptions._FALLBACK_ERROR_MESSAGE = "A promise was rejected without providing an error. Application Insights generated this error stack for you.";
AutoCollectExceptions._canUseUncaughtExceptionMonitor = false;
return AutoCollectExceptions;
}());
module.exports = AutoCollectExceptions;
//# sourceMappingURL=Exceptions.js.map
File diff suppressed because one or more lines are too long
+24
View File
@@ -0,0 +1,24 @@
import TelemetryClient = require("../Library/TelemetryClient");
import Config = require("../Library/Config");
declare class HeartBeat {
static INSTANCE: HeartBeat;
private _collectionInterval;
private _client;
private _handle;
private _isEnabled;
private _isInitialized;
private _isVM;
private _vmData;
private _azInst_vmId;
private _azInst_subscriptionId;
private _azInst_osType;
constructor(client: TelemetryClient);
enable(isEnabled: boolean, config?: Config): void;
isInitialized(): boolean;
static isEnabled(): boolean;
trackHeartBeat(config: Config, callback: () => void): void;
dispose(): void;
private _getAzureComputeMetadata(config, callback);
private _isJSON(str);
}
export = HeartBeat;
+150
View File
@@ -0,0 +1,150 @@
"use strict";
var os = require("os");
var Constants = require("../Declarations/Constants");
var Util = require("../Library/Util");
var Context = require("../Library/Context");
var AutoCollectHttpDependencies = require("../AutoCollection/HttpDependencies");
var AIMS_URI = "http://169.254.169.254/metadata/instance/compute";
var AIMS_API_VERSION = "api-version=2017-12-01";
var AIMS_FORMAT = "format=json";
var ConnectionErrorMessage = "ENETUNREACH";
var HeartBeat = (function () {
function HeartBeat(client) {
this._collectionInterval = 900000;
this._vmData = {};
this._azInst_vmId = "";
this._azInst_subscriptionId = "";
this._azInst_osType = "";
if (!HeartBeat.INSTANCE) {
HeartBeat.INSTANCE = this;
}
this._isInitialized = false;
this._client = client;
}
HeartBeat.prototype.enable = function (isEnabled, config) {
var _this = this;
this._isEnabled = isEnabled;
if (this._isEnabled && !this._isInitialized) {
this._isInitialized = true;
}
if (isEnabled) {
if (!this._handle) {
this._handle = setInterval(function () { return _this.trackHeartBeat(config, function () { }); }, this._collectionInterval);
this._handle.unref(); // Allow the app to terminate even while this loop is going on
}
}
else {
if (this._handle) {
clearInterval(this._handle);
this._handle = null;
}
}
};
HeartBeat.prototype.isInitialized = function () {
return this._isInitialized;
};
HeartBeat.isEnabled = function () {
return HeartBeat.INSTANCE && HeartBeat.INSTANCE._isEnabled;
};
HeartBeat.prototype.trackHeartBeat = function (config, callback) {
var _this = this;
var waiting = false;
var properties = {};
var sdkVersion = Context.sdkVersion; // "node" or "node-nativeperf"
properties["sdk"] = sdkVersion;
properties["osType"] = os.type();
if (process.env.WEBSITE_SITE_NAME) {
properties["appSrv_SiteName"] = process.env.WEBSITE_SITE_NAME || "";
properties["appSrv_wsStamp"] = process.env.WEBSITE_HOME_STAMPNAME || "";
properties["appSrv_wsHost"] = process.env.WEBSITE_HOSTNAME || "";
}
else if (process.env.FUNCTIONS_WORKER_RUNTIME) {
properties["azfunction_appId"] = process.env.WEBSITE_HOSTNAME;
}
else if (config) {
if (this._isVM === undefined) {
waiting = true;
this._getAzureComputeMetadata(config, function () {
if (_this._isVM && Object.keys(_this._vmData).length > 0) {
properties["azInst_vmId"] = _this._vmData["vmId"] || "";
properties["azInst_subscriptionId"] = _this._vmData["subscriptionId"] || "";
properties["azInst_osType"] = _this._vmData["osType"] || "";
_this._azInst_vmId = _this._vmData["vmId"] || "";
_this._azInst_subscriptionId = _this._vmData["subscriptionId"] || "";
_this._azInst_osType = _this._vmData["osType"] || "";
}
_this._client.trackMetric({ name: Constants.HeartBeatMetricName, value: 0, properties: properties });
callback();
});
}
else if (this._isVM) {
properties["azInst_vmId"] = this._azInst_vmId;
properties["azInst_subscriptionId"] = this._azInst_subscriptionId;
properties["azInst_osType"] = this._azInst_osType;
}
}
if (!waiting) {
this._client.trackMetric({ name: Constants.HeartBeatMetricName, value: 0, properties: properties });
callback();
}
};
HeartBeat.prototype.dispose = function () {
HeartBeat.INSTANCE = null;
this.enable(false);
this._isInitialized = false;
};
HeartBeat.prototype._getAzureComputeMetadata = function (config, callback) {
var _this = this;
var metadataRequestUrl = AIMS_URI + "?" + AIMS_API_VERSION + "&" + AIMS_FORMAT;
var requestOptions = (_a = {
method: 'GET'
},
_a[AutoCollectHttpDependencies.disableCollectionRequestOption] = true,
_a.headers = {
"Metadata": "True",
},
_a);
var req = Util.makeRequest(config, metadataRequestUrl, requestOptions, function (res) {
if (res.statusCode === 200) {
// Success; VM
_this._isVM = true;
var virtualMachineData_1 = "";
res.on('data', function (data) {
virtualMachineData_1 += data;
});
res.on('end', function () {
_this._vmData = _this._isJSON(virtualMachineData_1) ? JSON.parse(virtualMachineData_1) : {};
callback();
});
}
else {
// else Retry on next heartbeat metrics call
callback();
}
});
if (req) {
req.on('error', function (error) {
// Unable to contact endpoint.
// Do nothing for now.
if (error && error.message && error.message.indexOf(ConnectionErrorMessage) > -1) {
_this._isVM = false; // confirm it's not in VM
}
// errors other than connect ENETUNREACH - retry
callback();
});
req.end();
}
var _a;
};
HeartBeat.prototype._isJSON = function (str) {
try {
return (JSON.parse(str) && !!str);
}
catch (e) {
return false;
}
};
return HeartBeat;
}());
module.exports = HeartBeat;
//# sourceMappingURL=HeartBeat.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,22 @@
import Contracts = require("../Declarations/Contracts");
import TelemetryClient = require("../Library/TelemetryClient");
declare class AutoCollectHttpDependencies {
static disableCollectionRequestOption: string;
static INSTANCE: AutoCollectHttpDependencies;
private static requestNumber;
private static alreadyAutoCollectedFlag;
private _client;
private _isEnabled;
private _isInitialized;
constructor(client: TelemetryClient);
enable(isEnabled: boolean): void;
isInitialized(): boolean;
private _initialize();
/**
* Tracks an outgoing request. Because it may set headers this method must be called before
* writing content to or ending the request.
*/
static trackRequest(client: TelemetryClient, telemetry: Contracts.NodeHttpDependencyTelemetry): void;
dispose(): void;
}
export = AutoCollectHttpDependencies;
+209
View File
@@ -0,0 +1,209 @@
"use strict";
var http = require("http");
var https = require("https");
var Logging = require("../Library/Logging");
var Util = require("../Library/Util");
var RequestResponseHeaders = require("../Library/RequestResponseHeaders");
var HttpDependencyParser = require("./HttpDependencyParser");
var CorrelationContextManager_1 = require("./CorrelationContextManager");
var CorrelationIdManager = require("../Library/CorrelationIdManager");
var Traceparent = require("../Library/Traceparent");
var DiagChannel = require("./diagnostic-channel/initialization");
var AutoCollectHttpDependencies = (function () {
function AutoCollectHttpDependencies(client) {
if (!!AutoCollectHttpDependencies.INSTANCE) {
throw new Error("Client request tracking should be configured from the applicationInsights object");
}
AutoCollectHttpDependencies.INSTANCE = this;
this._client = client;
}
AutoCollectHttpDependencies.prototype.enable = function (isEnabled) {
this._isEnabled = isEnabled;
if (this._isEnabled && !this._isInitialized) {
this._initialize();
}
if (DiagChannel.IsInitialized) {
require("./diagnostic-channel/azure-coretracing.sub").enable(true, this._client);
require("./diagnostic-channel/mongodb.sub").enable(isEnabled, this._client);
require("./diagnostic-channel/mysql.sub").enable(isEnabled, this._client);
require("./diagnostic-channel/redis.sub").enable(isEnabled, this._client);
require("./diagnostic-channel/postgres.sub").enable(isEnabled, this._client);
}
};
AutoCollectHttpDependencies.prototype.isInitialized = function () {
return this._isInitialized;
};
AutoCollectHttpDependencies.prototype._initialize = function () {
var _this = this;
this._isInitialized = true;
var originalGet = http.get;
var originalRequest = http.request;
var originalHttpsRequest = https.request;
var clientRequestPatch = function (request, options) {
var shouldCollect = !options[AutoCollectHttpDependencies.disableCollectionRequestOption] &&
!request[AutoCollectHttpDependencies.alreadyAutoCollectedFlag];
// If someone else patched traceparent headers onto this request
if (options.headers && options.headers['user-agent'] && options.headers['user-agent'].toString().indexOf('azsdk-js') !== -1) {
shouldCollect = false;
}
request[AutoCollectHttpDependencies.alreadyAutoCollectedFlag] = true;
if (request && options && shouldCollect) {
CorrelationContextManager_1.CorrelationContextManager.wrapEmitter(request);
AutoCollectHttpDependencies.trackRequest(_this._client, { options: options, request: request });
}
};
// On node >= v0.11.12 and < 9.0 (excluding 8.9.0) https.request just calls http.request (with additional options).
// On node < 0.11.12, 8.9.0, and 9.0 > https.request is handled separately
// Patch both and leave a flag to not double-count on versions that just call through
// We add the flag to both http and https to protect against strange double collection in other scenarios
http.request = function (options) {
var requestArgs = [];
for (var _i = 1; _i < arguments.length; _i++) {
requestArgs[_i - 1] = arguments[_i];
}
var request = originalRequest.call.apply(originalRequest, [http, options].concat(requestArgs));
clientRequestPatch(request, options);
return request;
};
https.request = function (options) {
var requestArgs = [];
for (var _i = 1; _i < arguments.length; _i++) {
requestArgs[_i - 1] = arguments[_i];
}
var request = originalHttpsRequest.call.apply(originalHttpsRequest, [https, options].concat(requestArgs));
clientRequestPatch(request, options);
return request;
};
// Node 8 calls http.request from http.get using a local reference!
// We have to patch .get manually in this case and can't just assume request is enough
// We have to replace the entire method in this case. We can't call the original.
// This is because calling the original will give us no chance to set headers as it internally does .end().
http.get = function (options) {
var requestArgs = [];
for (var _i = 1; _i < arguments.length; _i++) {
requestArgs[_i - 1] = arguments[_i];
}
var request = (_a = http.request).call.apply(_a, [http, options].concat(requestArgs));
request.end();
return request;
var _a;
};
https.get = function (options) {
var requestArgs = [];
for (var _i = 1; _i < arguments.length; _i++) {
requestArgs[_i - 1] = arguments[_i];
}
var request = (_a = https.request).call.apply(_a, [https, options].concat(requestArgs));
request.end();
return request;
var _a;
};
};
/**
* Tracks an outgoing request. Because it may set headers this method must be called before
* writing content to or ending the request.
*/
AutoCollectHttpDependencies.trackRequest = function (client, telemetry) {
if (!telemetry.options || !telemetry.request || !client) {
Logging.info("AutoCollectHttpDependencies.trackRequest was called with invalid parameters: ", !telemetry.options, !telemetry.request, !client);
return;
}
var requestParser = new HttpDependencyParser(telemetry.options, telemetry.request);
var currentContext = CorrelationContextManager_1.CorrelationContextManager.getCurrentContext();
var uniqueRequestId;
var uniqueTraceparent;
if (currentContext && currentContext.operation && currentContext.operation.traceparent && Traceparent.isValidTraceId(currentContext.operation.traceparent.traceId)) {
currentContext.operation.traceparent.updateSpanId();
uniqueRequestId = currentContext.operation.traceparent.getBackCompatRequestId();
}
else if (CorrelationIdManager.w3cEnabled) {
// Start an operation now so that we can include the w3c headers in the outgoing request
var traceparent = new Traceparent();
uniqueTraceparent = traceparent.toString();
uniqueRequestId = traceparent.getBackCompatRequestId();
}
else {
uniqueRequestId = currentContext && currentContext.operation && (currentContext.operation.parentId + AutoCollectHttpDependencies.requestNumber++ + '.');
}
// Add the source correlationId to the request headers, if a value was not already provided.
// The getHeader/setHeader methods aren't available on very old Node versions, and
// are not included in the v0.10 type declarations currently used. So check if the
// methods exist before invoking them.
if (Util.canIncludeCorrelationHeader(client, requestParser.getUrl()) && telemetry.request.getHeader && telemetry.request.setHeader) {
if (client.config && client.config.correlationId) {
// getHeader returns "any" type in newer versions of node. In basic scenarios, this will be <string | string[] | number>, but could be modified to anything else via middleware
var correlationHeader = telemetry.request.getHeader(RequestResponseHeaders.requestContextHeader);
try {
Util.safeIncludeCorrelationHeader(client, telemetry.request, correlationHeader);
}
catch (err) {
Logging.warn("Request-Context header could not be set. Correlation of requests may be lost", err);
}
if (currentContext && currentContext.operation) {
try {
telemetry.request.setHeader(RequestResponseHeaders.requestIdHeader, uniqueRequestId);
// Also set legacy headers
if (!client.config.ignoreLegacyHeaders) {
telemetry.request.setHeader(RequestResponseHeaders.parentIdHeader, currentContext.operation.id);
telemetry.request.setHeader(RequestResponseHeaders.rootIdHeader, uniqueRequestId);
}
// Set W3C headers, if available
if (uniqueTraceparent || currentContext.operation.traceparent) {
telemetry.request.setHeader(RequestResponseHeaders.traceparentHeader, uniqueTraceparent || currentContext.operation.traceparent.toString());
}
else if (CorrelationIdManager.w3cEnabled) {
// should never get here since we set uniqueTraceparent above for the w3cEnabled scenario
var traceparent = new Traceparent().toString();
telemetry.request.setHeader(RequestResponseHeaders.traceparentHeader, traceparent);
}
if (currentContext.operation.tracestate) {
var tracestate = currentContext.operation.tracestate.toString();
if (tracestate) {
telemetry.request.setHeader(RequestResponseHeaders.traceStateHeader, tracestate);
}
}
var correlationContextHeader = currentContext.customProperties.serializeToHeader();
if (correlationContextHeader) {
telemetry.request.setHeader(RequestResponseHeaders.correlationContextHeader, correlationContextHeader);
}
}
catch (err) {
Logging.warn("Correlation headers could not be set. Correlation of requests may be lost.", err);
}
}
}
}
// Collect dependency telemetry about the request when it finishes.
if (telemetry.request.on) {
telemetry.request.on('response', function (response) {
requestParser.onResponse(response);
var dependencyTelemetry = requestParser.getDependencyTelemetry(telemetry, uniqueRequestId);
dependencyTelemetry.contextObjects = dependencyTelemetry.contextObjects || {};
dependencyTelemetry.contextObjects["http.RequestOptions"] = telemetry.options;
dependencyTelemetry.contextObjects["http.ClientRequest"] = telemetry.request;
dependencyTelemetry.contextObjects["http.ClientResponse"] = response;
client.trackDependency(dependencyTelemetry);
});
telemetry.request.on('error', function (e) {
requestParser.onError(e);
var dependencyTelemetry = requestParser.getDependencyTelemetry(telemetry, uniqueRequestId);
dependencyTelemetry.contextObjects = dependencyTelemetry.contextObjects || {};
dependencyTelemetry.contextObjects["http.RequestOptions"] = telemetry.options;
dependencyTelemetry.contextObjects["http.ClientRequest"] = telemetry.request;
dependencyTelemetry.contextObjects["Error"] = e;
client.trackDependency(dependencyTelemetry);
});
}
};
AutoCollectHttpDependencies.prototype.dispose = function () {
AutoCollectHttpDependencies.INSTANCE = null;
this.enable(false);
this._isInitialized = false;
};
AutoCollectHttpDependencies.disableCollectionRequestOption = 'disableAppInsightsAutoCollection';
AutoCollectHttpDependencies.requestNumber = 1;
AutoCollectHttpDependencies.alreadyAutoCollectedFlag = '_appInsightsAutoCollected';
return AutoCollectHttpDependencies;
}());
module.exports = AutoCollectHttpDependencies;
//# sourceMappingURL=HttpDependencies.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,30 @@
/// <reference types="node" />
import http = require("http");
import https = require("https");
import Contracts = require("../Declarations/Contracts");
import RequestParser = require("./RequestParser");
/**
* Helper class to read data from the request/response objects and convert them into the telemetry contract
*/
declare class HttpDependencyParser extends RequestParser {
private correlationId;
constructor(requestOptions: object | string | http.RequestOptions | https.RequestOptions, request: http.ClientRequest);
/**
* Called when the ClientRequest emits an error event.
*/
onError(error: Error): void;
/**
* Called when the ClientRequest emits a response event.
*/
onResponse(response: http.ClientResponse): void;
/**
* Gets a dependency data contract object for a completed ClientRequest.
*/
getDependencyTelemetry(baseTelemetry?: Contracts.Telemetry, dependencyId?: string): Contracts.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.
*/
private static _getUrlFromRequestOptions(options, request);
}
export = HttpDependencyParser;
@@ -0,0 +1,167 @@
"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
File diff suppressed because one or more lines are too long
@@ -0,0 +1,59 @@
/// <reference types="node" />
import http = require("http");
import Contracts = require("../Declarations/Contracts");
import RequestParser = require("./RequestParser");
import Tracestate = require("../Library/Tracestate");
import Traceparent = require("../Library/Traceparent");
import { HttpRequest } from "../Library/Functions";
/**
* Helper class to read data from the request/response objects and convert them into the telemetry contract
*/
declare class HttpRequestParser extends RequestParser {
private static keys;
private rawHeaders;
private socketRemoteAddress;
private connectionRemoteAddress;
private legacySocketRemoteAddress;
private userAgent;
private sourceCorrelationId;
private parentId;
private operationId;
private requestId;
private traceparent;
private tracestate;
private legacyRootId;
private correlationContextHeader;
constructor(request: http.IncomingMessage | HttpRequest, requestId?: string);
onError(error: Error | string, ellapsedMilliseconds?: number): void;
onResponse(response: http.ServerResponse, ellapsedMilliseconds?: number): void;
getRequestTelemetry(baseTelemetry?: Contracts.Telemetry): Contracts.RequestTelemetry;
getRequestTags(tags: {
[key: string]: string;
}): {
[key: string]: string;
};
getOperationId(tags: {
[key: string]: string;
}): string;
getOperationParentId(tags: {
[key: string]: string;
}): string;
getOperationName(tags: {
[key: string]: string;
}): string;
getRequestId(): string;
getCorrelationContextHeader(): string;
getTraceparent(): Traceparent;
getTracestate(): Tracestate;
getLegacyRootId(): string;
private _getAbsoluteUrl(request);
private _getIp();
private _getId(name);
/**
* Sets this operation's operationId, parentId, requestId (and legacyRootId, if necessary) based on this operation's traceparent
*/
private setBackCompatFromThisTraceContext();
private parseHeaders(request, requestId?);
static parseId(cookieValue: string): string;
}
export = HttpRequestParser;
@@ -0,0 +1,259 @@
"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");
var Tracestate = require("../Library/Tracestate");
var Traceparent = require("../Library/Traceparent");
/**
* Helper class to read data from the request/response objects and convert them into the telemetry contract
*/
var HttpRequestParser = (function (_super) {
__extends(HttpRequestParser, _super);
function HttpRequestParser(request, requestId) {
var _this = _super.call(this) || this;
if (request) {
_this.method = request.method;
_this.url = _this._getAbsoluteUrl(request);
_this.startTime = +new Date();
_this.socketRemoteAddress = request.socket && request.socket.remoteAddress;
_this.parseHeaders(request, requestId);
if (request.connection) {
_this.connectionRemoteAddress = request.connection.remoteAddress;
_this.legacySocketRemoteAddress = request.connection["socket"] && request.connection["socket"].remoteAddress;
}
}
return _this;
}
HttpRequestParser.prototype.onError = function (error, ellapsedMilliseconds) {
this._setStatus(undefined, error);
// This parameter is only for overrides. setStatus handles this internally for the autocollected case
if (ellapsedMilliseconds) {
this.duration = ellapsedMilliseconds;
}
};
HttpRequestParser.prototype.onResponse = function (response, ellapsedMilliseconds) {
this._setStatus(response.statusCode, undefined);
// This parameter is only for overrides. setStatus handles this internally for the autocollected case
if (ellapsedMilliseconds) {
this.duration = ellapsedMilliseconds;
}
};
HttpRequestParser.prototype.getRequestTelemetry = function (baseTelemetry) {
var requestTelemetry = {
id: this.requestId,
name: this.method + " " + url.parse(this.url).pathname,
url: this.url,
/*
See https://github.com/microsoft/ApplicationInsights-dotnet-server/blob/25d695e6a906fbe977f67be3966d25dbf1c50a79/Src/Web/Web.Shared.Net/RequestTrackingTelemetryModule.cs#L250
for reference
*/
source: this.sourceCorrelationId,
duration: this.duration,
resultCode: this.statusCode ? this.statusCode.toString() : null,
success: this._isSuccess(),
properties: this.properties
};
if (baseTelemetry && baseTelemetry.time) {
requestTelemetry.time = baseTelemetry.time;
}
else if (this.startTime) {
requestTelemetry.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 (!requestTelemetry[key]) {
requestTelemetry[key] = baseTelemetry[key];
}
}
// Merge properties
if (baseTelemetry.properties) {
for (var key in baseTelemetry.properties) {
requestTelemetry.properties[key] = baseTelemetry.properties[key];
}
}
}
return requestTelemetry;
};
HttpRequestParser.prototype.getRequestTags = function (tags) {
// create a copy of the context for requests since client info will be used here
var newTags = {};
for (var key in tags) {
newTags[key] = tags[key];
}
// don't override tags if they are already set
newTags[HttpRequestParser.keys.locationIp] = tags[HttpRequestParser.keys.locationIp] || this._getIp();
newTags[HttpRequestParser.keys.sessionId] = tags[HttpRequestParser.keys.sessionId] || this._getId("ai_session");
newTags[HttpRequestParser.keys.userId] = tags[HttpRequestParser.keys.userId] || this._getId("ai_user");
newTags[HttpRequestParser.keys.userAuthUserId] = tags[HttpRequestParser.keys.userAuthUserId] || this._getId("ai_authUser");
newTags[HttpRequestParser.keys.operationName] = this.getOperationName(tags);
newTags[HttpRequestParser.keys.operationParentId] = this.getOperationParentId(tags);
newTags[HttpRequestParser.keys.operationId] = this.getOperationId(tags);
return newTags;
};
HttpRequestParser.prototype.getOperationId = function (tags) {
return tags[HttpRequestParser.keys.operationId] || this.operationId;
};
HttpRequestParser.prototype.getOperationParentId = function (tags) {
return tags[HttpRequestParser.keys.operationParentId] || this.parentId || this.getOperationId(tags);
};
HttpRequestParser.prototype.getOperationName = function (tags) {
return tags[HttpRequestParser.keys.operationName] || this.method + " " + url.parse(this.url).pathname;
};
HttpRequestParser.prototype.getRequestId = function () {
return this.requestId;
};
HttpRequestParser.prototype.getCorrelationContextHeader = function () {
return this.correlationContextHeader;
};
HttpRequestParser.prototype.getTraceparent = function () {
return this.traceparent;
};
HttpRequestParser.prototype.getTracestate = function () {
return this.tracestate;
};
HttpRequestParser.prototype.getLegacyRootId = function () {
return this.legacyRootId;
};
HttpRequestParser.prototype._getAbsoluteUrl = function (request) {
if (!request.headers) {
return request.url;
}
var encrypted = request.connection ? request.connection.encrypted : null;
var requestUrl = url.parse(request.url);
var pathName = requestUrl.pathname;
var search = requestUrl.search;
var absoluteUrl = url.format({
protocol: encrypted ? "https" : "http",
host: request.headers.host,
pathname: pathName,
search: search
});
return absoluteUrl;
};
HttpRequestParser.prototype._getIp = function () {
// regex to match ipv4 without port
// Note: including the port would cause the payload to be rejected by the data collector
var ipMatch = /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/;
var check = function (str) {
var results = ipMatch.exec(str);
if (results) {
return results[0];
}
};
var ip = check(this.rawHeaders["x-forwarded-for"])
|| check(this.rawHeaders["x-client-ip"])
|| check(this.rawHeaders["x-real-ip"])
|| check(this.connectionRemoteAddress)
|| check(this.socketRemoteAddress)
|| check(this.legacySocketRemoteAddress);
// node v12 returns this if the address is "localhost"
if (!ip
&& this.connectionRemoteAddress
&& this.connectionRemoteAddress.substr
&& this.connectionRemoteAddress.substr(0, 2) === "::") {
ip = "127.0.0.1";
}
return ip;
};
HttpRequestParser.prototype._getId = function (name) {
var cookie = (this.rawHeaders && this.rawHeaders["cookie"] &&
typeof this.rawHeaders["cookie"] === 'string' && this.rawHeaders["cookie"]) || "";
var value = HttpRequestParser.parseId(Util.getCookie(name, cookie));
return value;
};
/**
* Sets this operation's operationId, parentId, requestId (and legacyRootId, if necessary) based on this operation's traceparent
*/
HttpRequestParser.prototype.setBackCompatFromThisTraceContext = function () {
// Set operationId
this.operationId = this.traceparent.traceId;
if (this.traceparent.legacyRootId) {
this.legacyRootId = this.traceparent.legacyRootId;
}
// Set parentId with existing spanId
this.parentId = this.traceparent.parentId;
// Update the spanId and set the current requestId
this.traceparent.updateSpanId();
this.requestId = this.traceparent.getBackCompatRequestId();
};
HttpRequestParser.prototype.parseHeaders = function (request, requestId) {
this.rawHeaders = request.headers || request.rawHeaders;
this.userAgent = request.headers && request.headers["user-agent"];
this.sourceCorrelationId = Util.getCorrelationContextTarget(request, RequestResponseHeaders.requestContextSourceKey);
if (request.headers) {
var tracestateHeader = request.headers[RequestResponseHeaders.traceStateHeader]; // w3c header
var traceparentHeader = request.headers[RequestResponseHeaders.traceparentHeader]; // w3c header
var requestIdHeader = request.headers[RequestResponseHeaders.requestIdHeader]; // default AI header
var legacy_parentId = request.headers[RequestResponseHeaders.parentIdHeader]; // legacy AI header
var legacy_rootId = request.headers[RequestResponseHeaders.rootIdHeader]; // legacy AI header
this.correlationContextHeader = request.headers[RequestResponseHeaders.correlationContextHeader];
if (CorrelationIdManager.w3cEnabled && (traceparentHeader || tracestateHeader)) {
// Parse W3C Trace Context headers
this.traceparent = new Traceparent(traceparentHeader); // new traceparent is always created from this
this.tracestate = traceparentHeader && tracestateHeader && new Tracestate(tracestateHeader); // discard tracestate if no traceparent is present
this.setBackCompatFromThisTraceContext();
}
else if (requestIdHeader) {
// Parse AI headers
if (CorrelationIdManager.w3cEnabled) {
this.traceparent = new Traceparent(null, requestIdHeader);
this.setBackCompatFromThisTraceContext();
}
else {
this.parentId = requestIdHeader;
this.requestId = CorrelationIdManager.generateRequestId(this.parentId);
this.operationId = CorrelationIdManager.getRootId(this.requestId);
}
}
else {
// Legacy fallback
if (CorrelationIdManager.w3cEnabled) {
this.traceparent = new Traceparent();
this.traceparent.parentId = legacy_parentId;
this.traceparent.legacyRootId = legacy_rootId || legacy_parentId;
this.setBackCompatFromThisTraceContext();
}
else {
this.parentId = legacy_parentId;
this.requestId = CorrelationIdManager.generateRequestId(legacy_rootId || this.parentId);
this.correlationContextHeader = null;
this.operationId = CorrelationIdManager.getRootId(this.requestId);
}
}
if (requestId) {
// For the scenarios that don't guarantee an AI-created context,
// override the requestId with the provided one.
this.requestId = requestId;
this.operationId = CorrelationIdManager.getRootId(this.requestId);
}
}
};
HttpRequestParser.parseId = function (cookieValue) {
var cookieParts = cookieValue.split("|");
if (cookieParts.length > 0) {
return cookieParts[0];
}
return ""; // old behavior was to return "" for incorrect parsing
};
HttpRequestParser.keys = new Contracts.ContextTagKeys();
return HttpRequestParser;
}(RequestParser));
module.exports = HttpRequestParser;
//# sourceMappingURL=HttpRequestParser.js.map
File diff suppressed because one or more lines are too long
+33
View File
@@ -0,0 +1,33 @@
import Contracts = require("../Declarations/Contracts");
import TelemetryClient = require("../Library/TelemetryClient");
import HttpRequestParser = require("./HttpRequestParser");
declare class AutoCollectHttpRequests {
static INSTANCE: AutoCollectHttpRequests;
private static alreadyAutoCollectedFlag;
private _client;
private _isEnabled;
private _isInitialized;
private _isAutoCorrelating;
constructor(client: TelemetryClient);
enable(isEnabled: boolean): void;
useAutoCorrelation(isEnabled: boolean, forceClsHooked?: boolean): void;
isInitialized(): boolean;
isAutoCorrelating(): boolean;
private _generateCorrelationContext(requestParser);
private _initialize();
/**
* Tracks a request synchronously (doesn't wait for response 'finish' event)
*/
static trackRequestSync(client: TelemetryClient, telemetry: Contracts.NodeHttpRequestTelemetry): void;
/**
* Tracks a request by listening to the response 'finish' event
*/
static trackRequest(client: TelemetryClient, telemetry: Contracts.NodeHttpRequestTelemetry, _requestParser?: HttpRequestParser): void;
/**
* Add the target correlationId to the response headers, if not already provided.
*/
private static addResponseCorrelationIdHeader(client, response);
private static endRequest(client, requestParser, telemetry, ellapsedMilliseconds?, error?);
dispose(): void;
}
export = AutoCollectHttpRequests;
+238
View File
@@ -0,0 +1,238 @@
"use strict";
var http = require("http");
var https = require("https");
var Logging = require("../Library/Logging");
var Util = require("../Library/Util");
var RequestResponseHeaders = require("../Library/RequestResponseHeaders");
var HttpRequestParser = require("./HttpRequestParser");
var CorrelationContextManager_1 = require("./CorrelationContextManager");
var AutoCollectPerformance = require("./Performance");
var AutoCollectHttpRequests = (function () {
function AutoCollectHttpRequests(client) {
if (!!AutoCollectHttpRequests.INSTANCE) {
throw new Error("Server request tracking should be configured from the applicationInsights object");
}
AutoCollectHttpRequests.INSTANCE = this;
this._client = client;
}
AutoCollectHttpRequests.prototype.enable = function (isEnabled) {
this._isEnabled = isEnabled;
// Autocorrelation requires automatic monitoring of incoming server requests
// Disabling autocollection but enabling autocorrelation will still enable
// request monitoring but will not produce request events
if ((this._isAutoCorrelating || this._isEnabled || AutoCollectPerformance.isEnabled()) && !this._isInitialized) {
this.useAutoCorrelation(this._isAutoCorrelating);
this._initialize();
}
};
AutoCollectHttpRequests.prototype.useAutoCorrelation = function (isEnabled, forceClsHooked) {
if (isEnabled && !this._isAutoCorrelating) {
CorrelationContextManager_1.CorrelationContextManager.enable(forceClsHooked);
}
else if (!isEnabled && this._isAutoCorrelating) {
CorrelationContextManager_1.CorrelationContextManager.disable();
}
this._isAutoCorrelating = isEnabled;
};
AutoCollectHttpRequests.prototype.isInitialized = function () {
return this._isInitialized;
};
AutoCollectHttpRequests.prototype.isAutoCorrelating = function () {
return this._isAutoCorrelating;
};
AutoCollectHttpRequests.prototype._generateCorrelationContext = function (requestParser) {
if (!this._isAutoCorrelating) {
return;
}
return CorrelationContextManager_1.CorrelationContextManager.generateContextObject(requestParser.getOperationId(this._client.context.tags), requestParser.getRequestId(), requestParser.getOperationName(this._client.context.tags), requestParser.getCorrelationContextHeader(), requestParser.getTraceparent(), requestParser.getTracestate());
};
AutoCollectHttpRequests.prototype._initialize = function () {
var _this = this;
this._isInitialized = true;
var wrapOnRequestHandler = function (onRequest) {
if (!onRequest) {
return undefined;
}
if (typeof onRequest !== 'function') {
throw new Error('onRequest handler must be a function');
}
return function (request, response) {
CorrelationContextManager_1.CorrelationContextManager.wrapEmitter(request);
CorrelationContextManager_1.CorrelationContextManager.wrapEmitter(response);
var shouldCollect = request && !request[AutoCollectHttpRequests.alreadyAutoCollectedFlag];
if (request && shouldCollect) {
// Set up correlation context
var requestParser_1 = new HttpRequestParser(request);
var correlationContext = _this._generateCorrelationContext(requestParser_1);
// Note: Check for if correlation is enabled happens within this method.
// If not enabled, function will directly call the callback.
CorrelationContextManager_1.CorrelationContextManager.runWithContext(correlationContext, function () {
if (_this._isEnabled) {
// Mark as auto collected
request[AutoCollectHttpRequests.alreadyAutoCollectedFlag] = true;
// Auto collect request
AutoCollectHttpRequests.trackRequest(_this._client, { request: request, response: response }, requestParser_1);
}
if (typeof onRequest === "function") {
onRequest(request, response);
}
});
}
else {
if (typeof onRequest === "function") {
onRequest(request, response);
}
}
};
};
// The `http.createServer` function will instantiate a new http.Server object.
// Inside the Server's constructor, it is using addListener to register the
// onRequest handler. So there are two ways to inject the wrapped onRequest handler:
// 1) Overwrite Server.prototype.addListener (and .on()) globally and not patching
// the http.createServer call. Or
// 2) Overwrite the http.createServer method and add a patched addListener to the
// fresh server instance. This seems more stable for possible future changes as
// it also covers the case where the Server might not use addListener to manage
// the callback internally.
// And also as long as the constructor uses addListener to add the handle, it is
// ok to patch the addListener after construction only. Because if we would patch
// the prototype one and the createServer method, we would wrap the handler twice
// in case of the constructor call.
var wrapServerEventHandler = function (server) {
var originalAddListener = server.addListener.bind(server);
server.addListener = function (eventType, eventHandler) {
switch (eventType) {
case 'request':
case 'checkContinue':
return originalAddListener(eventType, wrapOnRequestHandler(eventHandler));
default:
return originalAddListener(eventType, eventHandler);
}
};
// on is an alias to addListener only
server.on = server.addListener;
};
var originalHttpServer = http.createServer;
// options parameter was added in Node.js v9.6.0, v8.12.0
// function createServer(requestListener?: RequestListener): Server;
// function createServer(options: ServerOptions, requestListener?: RequestListener): Server;
http.createServer = function (param1, param2) {
// todo: get a pointer to the server so the IP address can be read from server.address
if (param2 && typeof param2 === 'function') {
var server = originalHttpServer(param1, wrapOnRequestHandler(param2));
wrapServerEventHandler(server);
return server;
}
else {
var server = originalHttpServer(wrapOnRequestHandler(param1));
wrapServerEventHandler(server);
return server;
}
};
var originalHttpsServer = https.createServer;
https.createServer = function (options, onRequest) {
var server = originalHttpsServer(options, wrapOnRequestHandler(onRequest));
wrapServerEventHandler(server);
return server;
};
};
/**
* Tracks a request synchronously (doesn't wait for response 'finish' event)
*/
AutoCollectHttpRequests.trackRequestSync = function (client, telemetry) {
if (!telemetry.request || !telemetry.response || !client) {
Logging.info("AutoCollectHttpRequests.trackRequestSync was called with invalid parameters: ", !telemetry.request, !telemetry.response, !client);
return;
}
AutoCollectHttpRequests.addResponseCorrelationIdHeader(client, telemetry.response);
// store data about the request
var correlationContext = CorrelationContextManager_1.CorrelationContextManager.getCurrentContext();
var requestParser = new HttpRequestParser(telemetry.request, (correlationContext && correlationContext.operation.parentId));
// Overwrite correlation context with request parser results
if (correlationContext) {
correlationContext.operation.id = requestParser.getOperationId(client.context.tags) || correlationContext.operation.id;
correlationContext.operation.name = requestParser.getOperationName(client.context.tags) || correlationContext.operation.name;
correlationContext.operation.parentId = requestParser.getRequestId() || correlationContext.operation.parentId;
correlationContext.customProperties.addHeaderData(requestParser.getCorrelationContextHeader());
}
AutoCollectHttpRequests.endRequest(client, requestParser, telemetry, telemetry.duration, telemetry.error);
};
/**
* Tracks a request by listening to the response 'finish' event
*/
AutoCollectHttpRequests.trackRequest = function (client, telemetry, _requestParser) {
if (!telemetry.request || !telemetry.response || !client) {
Logging.info("AutoCollectHttpRequests.trackRequest was called with invalid parameters: ", !telemetry.request, !telemetry.response, !client);
return;
}
// store data about the request
var correlationContext = CorrelationContextManager_1.CorrelationContextManager.getCurrentContext();
var requestParser = _requestParser || new HttpRequestParser(telemetry.request, correlationContext && correlationContext.operation.parentId);
if (Util.canIncludeCorrelationHeader(client, requestParser.getUrl())) {
AutoCollectHttpRequests.addResponseCorrelationIdHeader(client, telemetry.response);
}
// Overwrite correlation context with request parser results (if not an automatic track. we've already precalculated the correlation context in that case)
if (correlationContext && !_requestParser) {
correlationContext.operation.id = requestParser.getOperationId(client.context.tags) || correlationContext.operation.id;
correlationContext.operation.name = requestParser.getOperationName(client.context.tags) || correlationContext.operation.name;
correlationContext.operation.parentId = requestParser.getOperationParentId(client.context.tags) || correlationContext.operation.parentId;
correlationContext.customProperties.addHeaderData(requestParser.getCorrelationContextHeader());
}
// response listeners
if (telemetry.response.once) {
telemetry.response.once("finish", function () {
AutoCollectHttpRequests.endRequest(client, requestParser, telemetry, null, null);
});
}
// track a failed request if an error is emitted
if (telemetry.request.on) {
telemetry.request.on("error", function (error) {
AutoCollectHttpRequests.endRequest(client, requestParser, telemetry, null, error);
});
}
};
/**
* Add the target correlationId to the response headers, if not already provided.
*/
AutoCollectHttpRequests.addResponseCorrelationIdHeader = function (client, response) {
if (client.config && client.config.correlationId &&
response.getHeader && response.setHeader && !response.headersSent) {
var correlationHeader = response.getHeader(RequestResponseHeaders.requestContextHeader);
Util.safeIncludeCorrelationHeader(client, response, correlationHeader);
}
};
AutoCollectHttpRequests.endRequest = function (client, requestParser, telemetry, ellapsedMilliseconds, error) {
if (error) {
requestParser.onError(error, ellapsedMilliseconds);
}
else {
requestParser.onResponse(telemetry.response, ellapsedMilliseconds);
}
var requestTelemetry = requestParser.getRequestTelemetry(telemetry);
requestTelemetry.tagOverrides = requestParser.getRequestTags(client.context.tags);
if (telemetry.tagOverrides) {
for (var key in telemetry.tagOverrides) {
requestTelemetry.tagOverrides[key] = telemetry.tagOverrides[key];
}
}
var legacyRootId = requestParser.getLegacyRootId();
if (legacyRootId) {
requestTelemetry.properties["ai_legacyRootId"] = legacyRootId;
}
requestTelemetry.contextObjects = requestTelemetry.contextObjects || {};
requestTelemetry.contextObjects["http.ServerRequest"] = telemetry.request;
requestTelemetry.contextObjects["http.ServerResponse"] = telemetry.response;
client.trackRequest(requestTelemetry);
};
AutoCollectHttpRequests.prototype.dispose = function () {
AutoCollectHttpRequests.INSTANCE = null;
this.enable(false);
this._isInitialized = false;
CorrelationContextManager_1.CorrelationContextManager.disable();
this._isAutoCorrelating = false;
};
AutoCollectHttpRequests.alreadyAutoCollectedFlag = '_appInsightsAutoCollected';
return AutoCollectHttpRequests;
}());
module.exports = AutoCollectHttpRequests;
//# sourceMappingURL=HttpRequests.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,85 @@
import TelemetryClient = require("../Library/TelemetryClient");
/**
* Interface which defines which specific extended metrics should be disabled
*
* @export
* @interface IDisabledExtendedMetrics
*/
export interface IDisabledExtendedMetrics {
gc?: boolean;
heap?: boolean;
loop?: boolean;
}
export declare class AutoCollectNativePerformance {
static INSTANCE: AutoCollectNativePerformance;
private static _emitter;
private static _metricsAvailable;
private _isEnabled;
private _isInitialized;
private _handle;
private _client;
private _disabledMetrics;
constructor(client: TelemetryClient);
/**
* Reports if NativePerformance is able to run in this environment
*/
static isNodeVersionCompatible(): boolean;
/**
* Start instance of native metrics agent.
*
* @param {boolean} isEnabled
* @param {number} [collectionInterval=60000]
* @memberof AutoCollectNativePerformance
*/
enable(isEnabled: boolean, disabledMetrics?: IDisabledExtendedMetrics, collectionInterval?: number): void;
/**
* Cleanup this instance of AutoCollectNativePerformance
*
* @memberof AutoCollectNativePerformance
*/
dispose(): void;
/**
* Parse environment variable and overwrite isEnabled based on respective fields being set
*
* @private
* @static
* @param {(boolean | IDisabledExtendedMetrics)} collectExtendedMetrics
* @returns {(boolean | IDisabledExtendedMetrics)}
* @memberof AutoCollectNativePerformance
*/
static parseEnabled(collectExtendedMetrics: boolean | IDisabledExtendedMetrics): {
isEnabled: boolean;
disabledMetrics: IDisabledExtendedMetrics;
};
/**
* Trigger an iteration of native metrics collection
*
* @private
* @memberof AutoCollectNativePerformance
*/
private _trackNativeMetrics();
/**
* Tracks garbage collection stats for this interval. One custom metric is sent per type of garbage
* collection that occurred during this collection interval.
*
* @private
* @memberof AutoCollectNativePerformance
*/
private _trackGarbageCollection();
/**
* Tracks event loop ticks per interval as a custom metric. Also included in the metric is min/max/avg
* time spent in event loop for this interval.
*
* @private
* @returns {void}
* @memberof AutoCollectNativePerformance
*/
private _trackEventLoop();
/**
* Track heap memory usage metrics as a custom metric.
*
* @private
* @memberof AutoCollectNativePerformance
*/
private _trackHeapUsage();
}
@@ -0,0 +1,251 @@
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var Config = require("../Library/Config");
var Context = require("../Library/Context");
var Logging = require("../Library/Logging");
var AutoCollectNativePerformance = (function () {
function AutoCollectNativePerformance(client) {
this._disabledMetrics = {};
// Note: Only 1 instance of this can exist. So when we reconstruct this object,
// just disable old native instance and reset JS member variables
if (AutoCollectNativePerformance.INSTANCE) {
AutoCollectNativePerformance.INSTANCE.dispose();
}
AutoCollectNativePerformance.INSTANCE = this;
this._client = client;
}
/**
* Reports if NativePerformance is able to run in this environment
*/
AutoCollectNativePerformance.isNodeVersionCompatible = function () {
var nodeVer = process.versions.node.split(".");
return parseInt(nodeVer[0]) >= 6;
};
/**
* Start instance of native metrics agent.
*
* @param {boolean} isEnabled
* @param {number} [collectionInterval=60000]
* @memberof AutoCollectNativePerformance
*/
AutoCollectNativePerformance.prototype.enable = function (isEnabled, disabledMetrics, collectionInterval) {
var _this = this;
if (disabledMetrics === void 0) { disabledMetrics = {}; }
if (collectionInterval === void 0) { collectionInterval = 60000; }
if (!AutoCollectNativePerformance.isNodeVersionCompatible()) {
return;
}
if (AutoCollectNativePerformance._metricsAvailable == undefined && isEnabled && !this._isInitialized) {
// Try to require in the native-metrics library. If it's found initialize it, else do nothing and never try again.
try {
var NativeMetricsEmitters = require("applicationinsights-native-metrics");
AutoCollectNativePerformance._emitter = new NativeMetricsEmitters();
AutoCollectNativePerformance._metricsAvailable = true;
Logging.info("Native metrics module successfully loaded!");
}
catch (err) {
// Package not available. Never try again
AutoCollectNativePerformance._metricsAvailable = false;
return;
}
}
this._isEnabled = isEnabled;
this._disabledMetrics = disabledMetrics;
if (this._isEnabled && !this._isInitialized) {
this._isInitialized = true;
}
// Enable the emitter if we were able to construct one
if (this._isEnabled && AutoCollectNativePerformance._emitter) {
// enable self
AutoCollectNativePerformance._emitter.enable(true, collectionInterval);
this._handle = setInterval(function () { return _this._trackNativeMetrics(); }, collectionInterval);
this._handle.unref();
}
else if (AutoCollectNativePerformance._emitter) {
// disable self
AutoCollectNativePerformance._emitter.enable(false);
if (this._handle) {
clearInterval(this._handle);
this._handle = undefined;
}
}
};
/**
* Cleanup this instance of AutoCollectNativePerformance
*
* @memberof AutoCollectNativePerformance
*/
AutoCollectNativePerformance.prototype.dispose = function () {
this.enable(false);
};
/**
* Parse environment variable and overwrite isEnabled based on respective fields being set
*
* @private
* @static
* @param {(boolean | IDisabledExtendedMetrics)} collectExtendedMetrics
* @returns {(boolean | IDisabledExtendedMetrics)}
* @memberof AutoCollectNativePerformance
*/
AutoCollectNativePerformance.parseEnabled = function (collectExtendedMetrics) {
var disableAll = process.env[Config.ENV_nativeMetricsDisableAll];
var individualOptOuts = process.env[Config.ENV_nativeMetricsDisablers];
// case 1: disable all env var set, RETURN with isEnabled=false
if (disableAll) {
return { isEnabled: false, disabledMetrics: {} };
}
// case 2: individual env vars set, RETURN with isEnabled=true, disabledMetrics={...}
if (individualOptOuts) {
var optOutsArr = individualOptOuts.split(",");
var disabledMetrics = {};
if (optOutsArr.length > 0) {
for (var _i = 0, optOutsArr_1 = optOutsArr; _i < optOutsArr_1.length; _i++) {
var opt = optOutsArr_1[_i];
disabledMetrics[opt] = true;
}
}
// case 2a: collectExtendedMetrics is an object, overwrite existing ones if they exist
if (typeof collectExtendedMetrics === "object") {
return { isEnabled: true, disabledMetrics: __assign({}, collectExtendedMetrics, disabledMetrics) };
}
// case 2b: collectExtendedMetrics is a boolean, set disabledMetrics as is
return { isEnabled: collectExtendedMetrics, disabledMetrics: disabledMetrics };
}
// case 4: no env vars set, input arg is a boolean, RETURN with isEnabled=collectExtendedMetrics, disabledMetrics={}
if (typeof collectExtendedMetrics === "boolean") {
return { isEnabled: collectExtendedMetrics, disabledMetrics: {} };
}
else {
// case 5: no env vars set, input arg is object, RETURN with isEnabled=true, disabledMetrics=collectExtendedMetrics
return { isEnabled: true, disabledMetrics: collectExtendedMetrics };
}
};
/**
* Trigger an iteration of native metrics collection
*
* @private
* @memberof AutoCollectNativePerformance
*/
AutoCollectNativePerformance.prototype._trackNativeMetrics = function () {
var shouldSendAll = true;
if (typeof this._isEnabled !== "object") {
shouldSendAll = this._isEnabled;
}
if (shouldSendAll) {
this._trackGarbageCollection();
this._trackEventLoop();
this._trackHeapUsage();
}
};
/**
* Tracks garbage collection stats for this interval. One custom metric is sent per type of garbage
* collection that occurred during this collection interval.
*
* @private
* @memberof AutoCollectNativePerformance
*/
AutoCollectNativePerformance.prototype._trackGarbageCollection = function () {
if (this._disabledMetrics.gc) {
return;
}
var gcData = AutoCollectNativePerformance._emitter.getGCData();
for (var gc in gcData) {
var metrics = gcData[gc].metrics;
var name_1 = gc + " Garbage Collection Duration";
var stdDev = Math.sqrt(metrics.sumSquares / metrics.count - Math.pow(metrics.total / metrics.count, 2)) || 0;
this._client.trackMetric({
name: name_1,
value: metrics.total,
count: metrics.count,
max: metrics.max,
min: metrics.min,
stdDev: stdDev,
tagOverrides: (_a = {},
_a[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion,
_a)
});
}
var _a;
};
/**
* Tracks event loop ticks per interval as a custom metric. Also included in the metric is min/max/avg
* time spent in event loop for this interval.
*
* @private
* @returns {void}
* @memberof AutoCollectNativePerformance
*/
AutoCollectNativePerformance.prototype._trackEventLoop = function () {
if (this._disabledMetrics.loop) {
return;
}
var loopData = AutoCollectNativePerformance._emitter.getLoopData();
var metrics = loopData.loopUsage;
if (metrics.count == 0) {
return;
}
var name = "Event Loop CPU Time";
var stdDev = Math.sqrt(metrics.sumSquares / metrics.count - Math.pow(metrics.total / metrics.count, 2)) || 0;
this._client.trackMetric({
name: name,
value: metrics.total,
count: metrics.count,
min: metrics.min,
max: metrics.max,
stdDev: stdDev,
tagOverrides: (_a = {},
_a[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion,
_a)
});
var _a;
};
/**
* Track heap memory usage metrics as a custom metric.
*
* @private
* @memberof AutoCollectNativePerformance
*/
AutoCollectNativePerformance.prototype._trackHeapUsage = function () {
if (this._disabledMetrics.heap) {
return;
}
var memoryUsage = process.memoryUsage();
var heapUsed = memoryUsage.heapUsed, heapTotal = memoryUsage.heapTotal, rss = memoryUsage.rss;
this._client.trackMetric({
name: "Memory Usage (Heap)",
value: heapUsed,
count: 1,
tagOverrides: (_a = {},
_a[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion,
_a)
});
this._client.trackMetric({
name: "Memory Total (Heap)",
value: heapTotal,
count: 1,
tagOverrides: (_b = {},
_b[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion,
_b)
});
this._client.trackMetric({
name: "Memory Usage (Non-Heap)",
value: rss - heapTotal,
count: 1,
tagOverrides: (_c = {},
_c[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion,
_c)
});
var _a, _b, _c;
};
return AutoCollectNativePerformance;
}());
exports.AutoCollectNativePerformance = AutoCollectNativePerformance;
//# sourceMappingURL=NativePerformance.js.map
File diff suppressed because one or more lines are too long
+45
View File
@@ -0,0 +1,45 @@
import TelemetryClient = require("../Library/TelemetryClient");
declare class AutoCollectPerformance {
static INSTANCE: AutoCollectPerformance;
private static _totalRequestCount;
private static _totalFailedRequestCount;
private static _lastRequestExecutionTime;
private static _totalDependencyCount;
private static _totalFailedDependencyCount;
private static _lastDependencyExecutionTime;
private static _totalExceptionCount;
private static _intervalDependencyExecutionTime;
private static _intervalRequestExecutionTime;
private _lastIntervalRequestExecutionTime;
private _lastIntervalDependencyExecutionTime;
private _enableLiveMetricsCounters;
private _collectionInterval;
private _client;
private _handle;
private _isEnabled;
private _isInitialized;
private _lastAppCpuUsage;
private _lastHrtime;
private _lastCpus;
private _lastDependencies;
private _lastRequests;
private _lastExceptions;
/**
* @param enableLiveMetricsCounters - enable sending additional live metrics information (dependency metrics, exception metrics, committed memory)
*/
constructor(client: TelemetryClient, collectionInterval?: number, enableLiveMetricsCounters?: boolean);
enable(isEnabled: boolean, collectionInterval?: number): void;
static countRequest(duration: number | string, success: boolean): void;
static countException(): void;
static countDependency(duration: number | string, success: boolean): void;
isInitialized(): boolean;
static isEnabled(): boolean;
trackPerformance(): void;
private _trackCpu();
private _trackMemory();
private _trackNetwork();
private _trackDependencyRate();
private _trackExceptionRate();
dispose(): void;
}
export = AutoCollectPerformance;
+278
View File
@@ -0,0 +1,278 @@
"use strict";
var os = require("os");
var Constants = require("../Declarations/Constants");
var AutoCollectPerformance = (function () {
/**
* @param enableLiveMetricsCounters - enable sending additional live metrics information (dependency metrics, exception metrics, committed memory)
*/
function AutoCollectPerformance(client, collectionInterval, enableLiveMetricsCounters) {
if (collectionInterval === void 0) { collectionInterval = 60000; }
if (enableLiveMetricsCounters === void 0) { enableLiveMetricsCounters = false; }
this._lastIntervalRequestExecutionTime = 0; // the sum of durations which took place during from app start until last interval
this._lastIntervalDependencyExecutionTime = 0;
if (!AutoCollectPerformance.INSTANCE) {
AutoCollectPerformance.INSTANCE = this;
}
this._isInitialized = false;
this._client = client;
this._collectionInterval = collectionInterval;
this._enableLiveMetricsCounters = enableLiveMetricsCounters;
}
AutoCollectPerformance.prototype.enable = function (isEnabled, collectionInterval) {
var _this = this;
this._isEnabled = isEnabled;
if (this._isEnabled && !this._isInitialized) {
this._isInitialized = true;
}
if (isEnabled) {
if (!this._handle) {
this._lastCpus = os.cpus();
this._lastRequests = {
totalRequestCount: AutoCollectPerformance._totalRequestCount,
totalFailedRequestCount: AutoCollectPerformance._totalFailedRequestCount,
time: +new Date
};
this._lastDependencies = {
totalDependencyCount: AutoCollectPerformance._totalDependencyCount,
totalFailedDependencyCount: AutoCollectPerformance._totalFailedDependencyCount,
time: +new Date
};
this._lastExceptions = {
totalExceptionCount: AutoCollectPerformance._totalExceptionCount,
time: +new Date
};
if (typeof process.cpuUsage === 'function') {
this._lastAppCpuUsage = process.cpuUsage();
}
this._lastHrtime = process.hrtime();
this._collectionInterval = collectionInterval || this._collectionInterval;
this._handle = setInterval(function () { return _this.trackPerformance(); }, this._collectionInterval);
this._handle.unref(); // Allow the app to terminate even while this loop is going on
}
}
else {
if (this._handle) {
clearInterval(this._handle);
this._handle = undefined;
}
}
};
AutoCollectPerformance.countRequest = function (duration, success) {
var durationMs;
if (!AutoCollectPerformance.isEnabled()) {
return;
}
if (typeof duration === 'string') {
// dependency duration is passed in as "00:00:00.123" by autocollectors
durationMs = +new Date('1970-01-01T' + duration + 'Z'); // convert to num ms, returns NaN if wrong
}
else if (typeof duration === 'number') {
durationMs = duration;
}
else {
return;
}
AutoCollectPerformance._intervalRequestExecutionTime += durationMs;
if (success === false) {
AutoCollectPerformance._totalFailedRequestCount++;
}
AutoCollectPerformance._totalRequestCount++;
};
AutoCollectPerformance.countException = function () {
AutoCollectPerformance._totalExceptionCount++;
};
AutoCollectPerformance.countDependency = function (duration, success) {
var durationMs;
if (!AutoCollectPerformance.isEnabled()) {
return;
}
if (typeof duration === 'string') {
// dependency duration is passed in as "00:00:00.123" by autocollectors
durationMs = +new Date('1970-01-01T' + duration + 'Z'); // convert to num ms, returns NaN if wrong
}
else if (typeof duration === 'number') {
durationMs = duration;
}
else {
return;
}
AutoCollectPerformance._intervalDependencyExecutionTime += durationMs;
if (success === false) {
AutoCollectPerformance._totalFailedDependencyCount++;
}
AutoCollectPerformance._totalDependencyCount++;
};
AutoCollectPerformance.prototype.isInitialized = function () {
return this._isInitialized;
};
AutoCollectPerformance.isEnabled = function () {
return AutoCollectPerformance.INSTANCE && AutoCollectPerformance.INSTANCE._isEnabled;
};
AutoCollectPerformance.prototype.trackPerformance = function () {
this._trackCpu();
this._trackMemory();
this._trackNetwork();
this._trackDependencyRate();
this._trackExceptionRate();
};
AutoCollectPerformance.prototype._trackCpu = function () {
// this reports total ms spent in each category since the OS was booted, to calculate percent it is necessary
// to find the delta since the last measurement
var cpus = os.cpus();
if (cpus && cpus.length && this._lastCpus && cpus.length === this._lastCpus.length) {
var totalUser = 0;
var totalSys = 0;
var totalNice = 0;
var totalIdle = 0;
var totalIrq = 0;
for (var i = 0; !!cpus && i < cpus.length; i++) {
var cpu = cpus[i];
var lastCpu = this._lastCpus[i];
var name = "% cpu(" + i + ") ";
var model = cpu.model;
var speed = cpu.speed;
var times = cpu.times;
var lastTimes = lastCpu.times;
// user cpu time (or) % CPU time spent in user space
var user = (times.user - lastTimes.user) || 0;
totalUser += user;
// system cpu time (or) % CPU time spent in kernel space
var sys = (times.sys - lastTimes.sys) || 0;
totalSys += sys;
// user nice cpu time (or) % CPU time spent on low priority processes
var nice = (times.nice - lastTimes.nice) || 0;
totalNice += nice;
// idle cpu time (or) % CPU time spent idle
var idle = (times.idle - lastTimes.idle) || 0;
totalIdle += idle;
// irq (or) % CPU time spent servicing/handling hardware interrupts
var irq = (times.irq - lastTimes.irq) || 0;
totalIrq += irq;
}
// Calculate % of total cpu time (user + system) this App Process used (Only supported by node v6.1.0+)
var appCpuPercent = undefined;
if (typeof process.cpuUsage === 'function') {
var appCpuUsage = process.cpuUsage();
var hrtime = process.hrtime();
var totalApp = ((appCpuUsage.user - this._lastAppCpuUsage.user) + (appCpuUsage.system - this._lastAppCpuUsage.system)) || 0;
if (typeof this._lastHrtime !== 'undefined' && this._lastHrtime.length === 2) {
var elapsedTime = ((hrtime[0] - this._lastHrtime[0]) * 1e6 + (hrtime[1] - this._lastHrtime[1]) / 1e3) || 0; // convert to microseconds
appCpuPercent = 100 * totalApp / (elapsedTime * cpus.length);
}
// Set previous
this._lastAppCpuUsage = appCpuUsage;
this._lastHrtime = hrtime;
}
var combinedTotal = (totalUser + totalSys + totalNice + totalIdle + totalIrq) || 1;
this._client.trackMetric({ name: Constants.PerformanceCounter.PROCESSOR_TIME, value: ((combinedTotal - totalIdle) / combinedTotal) * 100 });
this._client.trackMetric({ name: Constants.PerformanceCounter.PROCESS_TIME, value: appCpuPercent || ((totalUser / combinedTotal) * 100) });
}
this._lastCpus = cpus;
};
AutoCollectPerformance.prototype._trackMemory = function () {
var freeMem = os.freemem();
var usedMem = process.memoryUsage().rss;
var committedMemory = os.totalmem() - freeMem;
this._client.trackMetric({ name: Constants.PerformanceCounter.PRIVATE_BYTES, value: usedMem });
this._client.trackMetric({ name: Constants.PerformanceCounter.AVAILABLE_BYTES, value: freeMem });
// Only supported by quickpulse service
if (this._enableLiveMetricsCounters) {
this._client.trackMetric({ name: Constants.QuickPulseCounter.COMMITTED_BYTES, value: committedMemory });
}
};
AutoCollectPerformance.prototype._trackNetwork = function () {
// track total request counters
var lastRequests = this._lastRequests;
var requests = {
totalRequestCount: AutoCollectPerformance._totalRequestCount,
totalFailedRequestCount: AutoCollectPerformance._totalFailedRequestCount,
time: +new Date
};
var intervalRequests = (requests.totalRequestCount - lastRequests.totalRequestCount) || 0;
var intervalFailedRequests = (requests.totalFailedRequestCount - lastRequests.totalFailedRequestCount) || 0;
var elapsedMs = requests.time - lastRequests.time;
var elapsedSeconds = elapsedMs / 1000;
var averageRequestExecutionTime = ((AutoCollectPerformance._intervalRequestExecutionTime - this._lastIntervalRequestExecutionTime) / intervalRequests) || 0; // default to 0 in case no requests in this interval
this._lastIntervalRequestExecutionTime = AutoCollectPerformance._intervalRequestExecutionTime; // reset
if (elapsedMs > 0) {
var requestsPerSec = intervalRequests / elapsedSeconds;
var failedRequestsPerSec = intervalFailedRequests / elapsedSeconds;
this._client.trackMetric({ name: Constants.PerformanceCounter.REQUEST_RATE, value: requestsPerSec });
// Only send duration to live metrics if it has been updated!
if (!this._enableLiveMetricsCounters || intervalRequests > 0) {
this._client.trackMetric({ name: Constants.PerformanceCounter.REQUEST_DURATION, value: averageRequestExecutionTime });
}
// Only supported by quickpulse service
if (this._enableLiveMetricsCounters) {
this._client.trackMetric({ name: Constants.QuickPulseCounter.REQUEST_FAILURE_RATE, value: failedRequestsPerSec });
}
}
this._lastRequests = requests;
};
// Static counter is accumulated externally. Report the rate to client here
// Note: This is currently only used with QuickPulse client
AutoCollectPerformance.prototype._trackDependencyRate = function () {
if (this._enableLiveMetricsCounters) {
var lastDependencies = this._lastDependencies;
var dependencies = {
totalDependencyCount: AutoCollectPerformance._totalDependencyCount,
totalFailedDependencyCount: AutoCollectPerformance._totalFailedDependencyCount,
time: +new Date
};
var intervalDependencies = (dependencies.totalDependencyCount - lastDependencies.totalDependencyCount) || 0;
var intervalFailedDependencies = (dependencies.totalFailedDependencyCount - lastDependencies.totalFailedDependencyCount) || 0;
var elapsedMs = dependencies.time - lastDependencies.time;
var elapsedSeconds = elapsedMs / 1000;
var averageDependencyExecutionTime = ((AutoCollectPerformance._intervalDependencyExecutionTime - this._lastIntervalDependencyExecutionTime) / intervalDependencies) || 0;
this._lastIntervalDependencyExecutionTime = AutoCollectPerformance._intervalDependencyExecutionTime; // reset
if (elapsedMs > 0) {
var dependenciesPerSec = intervalDependencies / elapsedSeconds;
var failedDependenciesPerSec = intervalFailedDependencies / elapsedSeconds;
this._client.trackMetric({ name: Constants.QuickPulseCounter.DEPENDENCY_RATE, value: dependenciesPerSec });
this._client.trackMetric({ name: Constants.QuickPulseCounter.DEPENDENCY_FAILURE_RATE, value: failedDependenciesPerSec });
// redundant check for livemetrics, but kept for consistency w/ requests
// Only send duration to live metrics if it has been updated!
if (!this._enableLiveMetricsCounters || intervalDependencies > 0) {
this._client.trackMetric({ name: Constants.QuickPulseCounter.DEPENDENCY_DURATION, value: averageDependencyExecutionTime });
}
}
this._lastDependencies = dependencies;
}
};
// Static counter is accumulated externally. Report the rate to client here
// Note: This is currently only used with QuickPulse client
AutoCollectPerformance.prototype._trackExceptionRate = function () {
if (this._enableLiveMetricsCounters) {
var lastExceptions = this._lastExceptions;
var exceptions = {
totalExceptionCount: AutoCollectPerformance._totalExceptionCount,
time: +new Date
};
var intervalExceptions = (exceptions.totalExceptionCount - lastExceptions.totalExceptionCount) || 0;
var elapsedMs = exceptions.time - lastExceptions.time;
var elapsedSeconds = elapsedMs / 1000;
if (elapsedMs > 0) {
var exceptionsPerSec = intervalExceptions / elapsedSeconds;
this._client.trackMetric({ name: Constants.QuickPulseCounter.EXCEPTION_RATE, value: exceptionsPerSec });
}
this._lastExceptions = exceptions;
}
};
AutoCollectPerformance.prototype.dispose = function () {
AutoCollectPerformance.INSTANCE = null;
this.enable(false);
this._isInitialized = false;
};
AutoCollectPerformance._totalRequestCount = 0;
AutoCollectPerformance._totalFailedRequestCount = 0;
AutoCollectPerformance._lastRequestExecutionTime = 0;
AutoCollectPerformance._totalDependencyCount = 0;
AutoCollectPerformance._totalFailedDependencyCount = 0;
AutoCollectPerformance._lastDependencyExecutionTime = 0;
AutoCollectPerformance._totalExceptionCount = 0;
AutoCollectPerformance._intervalDependencyExecutionTime = 0;
AutoCollectPerformance._intervalRequestExecutionTime = 0;
return AutoCollectPerformance;
}());
module.exports = AutoCollectPerformance;
//# sourceMappingURL=Performance.js.map
File diff suppressed because one or more lines are too long
+22
View File
@@ -0,0 +1,22 @@
/**
* Base class for helpers that read data from HTTP request/response objects and convert them
* into the telemetry contract objects.
*/
declare abstract class RequestParser {
protected method: string;
protected url: string;
protected startTime: number;
protected duration: number;
protected statusCode: number;
protected properties: {
[key: string]: string;
};
/**
* Gets a url parsed out from request options
*/
getUrl(): string;
protected RequestParser(): void;
protected _setStatus(status: number, error: Error | string): void;
protected _isSuccess(): boolean;
}
export = RequestParser;
+44
View File
@@ -0,0 +1,44 @@
"use strict";
/**
* Base class for helpers that read data from HTTP request/response objects and convert them
* into the telemetry contract objects.
*/
var RequestParser = (function () {
function RequestParser() {
}
/**
* Gets a url parsed out from request options
*/
RequestParser.prototype.getUrl = function () {
return this.url;
};
RequestParser.prototype.RequestParser = function () {
this.startTime = +new Date();
};
RequestParser.prototype._setStatus = function (status, error) {
var endTime = +new Date();
this.duration = endTime - this.startTime;
this.statusCode = status;
var properties = this.properties || {};
if (error) {
if (typeof error === "string") {
properties["error"] = error;
}
else if (error instanceof Error) {
properties["error"] = error.message;
}
else if (typeof error === "object") {
for (var key in error) {
properties[key] = error[key] && error[key].toString && error[key].toString();
}
}
}
this.properties = properties;
};
RequestParser.prototype._isSuccess = function () {
return (0 < this.statusCode) && (this.statusCode < 400);
};
return RequestParser;
}());
module.exports = RequestParser;
//# sourceMappingURL=RequestParser.js.map
@@ -0,0 +1 @@
{"version":3,"file":"RequestParser.js","sourceRoot":"","sources":["../../AutoCollection/RequestParser.ts"],"names":[],"mappings":";AAAA;;;GAGG;AACH;IAAA;IA2CA,CAAC;IAnCG;;OAEG;IACI,8BAAM,GAAb;QACI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;IACpB,CAAC;IAES,qCAAa,GAAvB;QACI,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACjC,CAAC;IAES,kCAAU,GAApB,UAAqB,MAAc,EAAE,KAAqB;QACtD,IAAI,OAAO,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;QACzC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QAEzB,IAAI,UAAU,GAA4B,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;QAChE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACR,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;gBAC5B,UAAU,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;YAChC,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC;gBAChC,UAAU,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;YACxC,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACnC,GAAG,CAAC,CAAC,IAAI,GAAG,IAAS,KAAK,CAAC,CAAC,CAAC;oBACzB,UAAU,CAAC,GAAG,CAAC,GAAS,KAAM,CAAC,GAAG,CAAC,IAAU,KAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAU,KAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACtG,CAAC;YACL,CAAC;QACL,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,CAAC;IAES,kCAAU,GAApB;QACI,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;IAC5D,CAAC;IACL,oBAAC;AAAD,CAAC,AA3CD,IA2CC;AAED,iBAAS,aAAa,CAAC","sourcesContent":["/**\r\n * Base class for helpers that read data from HTTP request/response objects and convert them\r\n * into the telemetry contract objects.\r\n */\r\nabstract class RequestParser {\r\n protected method: string;\r\n protected url: string;\r\n protected startTime: number;\r\n protected duration: number;\r\n protected statusCode: number;\r\n protected properties: { [key: string]: string };\r\n\r\n /**\r\n * Gets a url parsed out from request options\r\n */\r\n public getUrl(): string {\r\n return this.url;\r\n }\r\n\r\n protected RequestParser() {\r\n this.startTime = +new Date();\r\n }\r\n\r\n protected _setStatus(status: number, error: Error | string) {\r\n let endTime = +new Date();\r\n this.duration = endTime - this.startTime;\r\n this.statusCode = status;\r\n\r\n let properties: {[key: string]: string} = this.properties || {};\r\n if (error) {\r\n if (typeof error === \"string\") {\r\n properties[\"error\"] = error;\r\n } else if (error instanceof Error) {\r\n properties[\"error\"] = error.message;\r\n } else if (typeof error === \"object\") {\r\n for (var key in <any>error) {\r\n properties[key] = (<any>error)[key] && (<any>error)[key].toString && (<any>error)[key].toString();\r\n }\r\n }\r\n }\r\n\r\n this.properties = properties;\r\n }\r\n\r\n protected _isSuccess() {\r\n return (0 < this.statusCode) && (this.statusCode < 400);\r\n }\r\n}\r\n\r\nexport = RequestParser;\r\n"]}
@@ -0,0 +1,3 @@
import { Span } from "../AsyncHooksScopeManager";
import * as Contracts from "../../Declarations/Contracts";
export declare function spanToTelemetryContract(span: Span): (Contracts.DependencyTelemetry & Contracts.RequestTelemetry) & Contracts.Identified;
@@ -0,0 +1,88 @@
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
var AsyncHooksScopeManager_1 = require("../AsyncHooksScopeManager");
var Constants = require("../../Declarations/Constants");
function filterSpanAttributes(attributes) {
var newAttributes = __assign({}, attributes);
Object.keys(Constants.SpanAttribute).forEach(function (key) {
delete newAttributes[key];
});
return newAttributes;
}
function spanToTelemetryContract(span) {
var id = "|" + span.context().traceId + "." + span.context().spanId + ".";
var duration = Math.round(span._duration[0] * 1e3 + span._duration[1] / 1e6);
var peerAddress = span.attributes["peer.address"] ? span.attributes["peer.address"].toString() : "";
var component = span.attributes["component"] ? span.attributes["component"].toString() : "";
var isHttp = ((component).toUpperCase() === Constants.DependencyTypeName.Http) || (!!span.attributes[Constants.SpanAttribute.HttpUrl]);
var isGrpc = (component).toLowerCase() === Constants.DependencyTypeName.Grpc;
if (isHttp) {
// Read http span attributes
var method = span.attributes[Constants.SpanAttribute.HttpMethod] || "GET";
var url = new URL(span.attributes[Constants.SpanAttribute.HttpUrl].toString());
var host = span.attributes[Constants.SpanAttribute.HttpHost] || url.host;
var port = span.attributes[Constants.SpanAttribute.HttpPort] || url.port || null;
var pathname = url.pathname || "/";
// Translate to AI Dependency format
var name_1 = method + " " + pathname;
var dependencyTypeName = Constants.DependencyTypeName.Http;
var target = port ? (host + ":" + port).toString() : host.toString();
var data = url.toString();
var resultCode = span.attributes[Constants.SpanAttribute.HttpStatusCode] || span.status.code || 0;
var success = resultCode < 400; // Status.OK
return {
id: id, name: name_1, dependencyTypeName: dependencyTypeName,
target: target, data: data,
success: success, duration: duration,
url: data,
resultCode: String(resultCode),
properties: filterSpanAttributes(span.attributes)
};
}
else if (isGrpc) {
var method = span.attributes[Constants.SpanAttribute.GrpcMethod] || "rpc";
var service = span.attributes[Constants.SpanAttribute.GrpcService];
var name_2 = service ? method + " " + service : span.name;
return {
id: id, duration: duration, name: name_2,
target: service.toString(),
data: service.toString() || name_2,
url: service.toString() || name_2,
dependencyTypeName: Constants.DependencyTypeName.Grpc,
resultCode: String(span.status.code || 0),
success: span.status.code === 0,
properties: filterSpanAttributes(span.attributes),
};
}
else {
var name_3 = span.name;
var links = span.links && span.links.map(function (link) {
return {
operation_Id: link.context.traceId,
id: link.context.spanId
};
});
return {
id: id, duration: duration, name: name_3,
target: peerAddress,
data: peerAddress || name_3,
url: peerAddress || name_3,
dependencyTypeName: span.kind === AsyncHooksScopeManager_1.SpanKind.INTERNAL ? Constants.DependencyTypeName.InProc : (component || span.name),
resultCode: String(span.status.code || 0),
success: span.status.code === 0,
properties: __assign({}, filterSpanAttributes(span.attributes), { "_MS.links": links || undefined }),
};
}
}
exports.spanToTelemetryContract = spanToTelemetryContract;
//# sourceMappingURL=SpanParser.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
import TelemetryClient = require("../../Library/TelemetryClient");
import { IStandardEvent } from "diagnostic-channel";
import { Span } from "../AsyncHooksScopeManager";
export declare const subscriber: (event: IStandardEvent<Span>) => void;
export declare function enable(enabled: boolean, client: TelemetryClient): void;
@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var diagnostic_channel_1 = require("diagnostic-channel");
var Traceparent = require("../../Library/Traceparent");
var SpanParser = require("./SpanParser");
var AsyncHooksScopeManager_1 = require("../AsyncHooksScopeManager");
var clients = [];
exports.subscriber = function (event) {
var span = event.data;
var telemetry = SpanParser.spanToTelemetryContract(span);
var spanContext = span.context();
var traceparent = new Traceparent();
traceparent.traceId = spanContext.traceId;
traceparent.spanId = spanContext.spanId;
traceparent.traceFlag = spanContext.traceFlags.toString();
traceparent.parentId = span.parentSpanId ? "|" + spanContext.traceId + "." + span.parentSpanId + "." : null;
AsyncHooksScopeManager_1.AsyncScopeManager.with(span, function () {
clients.forEach(function (client) {
if (span.kind === AsyncHooksScopeManager_1.SpanKind.SERVER) {
// Server or Consumer
client.trackRequest(telemetry);
}
else if (span.kind === AsyncHooksScopeManager_1.SpanKind.CLIENT || span.kind === AsyncHooksScopeManager_1.SpanKind.INTERNAL) {
// Client or Producer or Internal
client.trackDependency(telemetry);
}
// else - ignore producer/consumer spans for now until it is clear how this sdk should interpret them
});
});
};
function enable(enabled, client) {
if (enabled) {
if (clients.length === 0) {
diagnostic_channel_1.channel.subscribe("azure-coretracing", exports.subscriber);
}
;
clients.push(client);
}
else {
clients = clients.filter(function (c) { return c != client; });
if (clients.length === 0) {
diagnostic_channel_1.channel.unsubscribe("azure-coretracing", exports.subscriber);
}
}
}
exports.enable = enable;
//# sourceMappingURL=azure-coretracing.sub.js.map
@@ -0,0 +1 @@
{"version":3,"file":"azure-coretracing.sub.js","sourceRoot":"","sources":["../../../AutoCollection/diagnostic-channel/azure-coretracing.sub.ts"],"names":[],"mappings":";;AAGA,yDAA6D;AAE7D,uDAA0D;AAC1D,yCAA2C;AAC3C,oEAA8E;AAE9E,IAAI,OAAO,GAAsB,EAAE,CAAC;AAEvB,QAAA,UAAU,GAAG,UAAC,KAA2B;IAClD,IAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAM,SAAS,GAAG,UAAU,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAC3D,IAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IACnC,IAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;IACtC,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;IAC1C,WAAW,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;IACxC,WAAW,CAAC,SAAS,GAAG,WAAW,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IAC1D,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC,YAAY,GAAG,MAAI,WAAW,CAAC,OAAO,SAAI,IAAI,CAAC,YAAY,MAAG,GAAG,IAAI,CAAC;IAElG,0CAAiB,CAAC,IAAI,CAAC,IAAI,EAAE;QACzB,OAAO,CAAC,OAAO,CAAC,UAAC,MAAM;YACnB,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,iCAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;gBAChC,qBAAqB;gBACrB,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YACnC,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,iCAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,iCAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC1E,iCAAiC;gBACjC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;YACtC,CAAC;YACD,qGAAqG;QACzG,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,gBAAuB,OAAgB,EAAE,MAAuB;IAC5D,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACV,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,SAAS,CAAM,mBAAmB,EAAE,kBAAU,CAAC,CAAC;QAC5D,CAAC;QAAA,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,IAAI,CAAC,CAAC;QACJ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,IAAI,MAAM,EAAX,CAAW,CAAC,CAAC;QAC7C,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,WAAW,CAAC,mBAAmB,EAAE,kBAAU,CAAC,CAAC;QACzD,CAAC;IACL,CAAC;AACL,CAAC;AAZD,wBAYC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license. See LICENSE file in the project root for details.\r\nimport TelemetryClient = require(\"../../Library/TelemetryClient\");\r\nimport { channel, IStandardEvent } from \"diagnostic-channel\";\r\n\r\nimport Traceparent = require(\"../../Library/Traceparent\");\r\nimport * as SpanParser from \"./SpanParser\";\r\nimport { Span, AsyncScopeManager, SpanKind } from \"../AsyncHooksScopeManager\";\r\n\r\nlet clients: TelemetryClient[] = [];\r\n\r\nexport const subscriber = (event: IStandardEvent<Span>) => {\r\n const span = event.data;\r\n const telemetry = SpanParser.spanToTelemetryContract(span);\r\n const spanContext = span.context();\r\n const traceparent = new Traceparent();\r\n traceparent.traceId = spanContext.traceId;\r\n traceparent.spanId = spanContext.spanId;\r\n traceparent.traceFlag = spanContext.traceFlags.toString();\r\n traceparent.parentId = span.parentSpanId ? `|${spanContext.traceId}.${span.parentSpanId}.` : null;\r\n\r\n AsyncScopeManager.with(span, () => {\r\n clients.forEach((client) => {\r\n if (span.kind === SpanKind.SERVER) {\r\n // Server or Consumer\r\n client.trackRequest(telemetry);\r\n } else if (span.kind === SpanKind.CLIENT || span.kind === SpanKind.INTERNAL) {\r\n // Client or Producer or Internal\r\n client.trackDependency(telemetry);\r\n }\r\n // else - ignore producer/consumer spans for now until it is clear how this sdk should interpret them\r\n });\r\n });\r\n};\r\n\r\nexport function enable(enabled: boolean, client: TelemetryClient) {\r\n if (enabled) {\r\n if (clients.length === 0) {\r\n channel.subscribe<any>(\"azure-coretracing\", subscriber);\r\n };\r\n clients.push(client);\r\n } else {\r\n clients = clients.filter((c) => c != client);\r\n if (clients.length === 0) {\r\n channel.unsubscribe(\"azure-coretracing\", subscriber);\r\n }\r\n }\r\n}\r\n"]}
@@ -0,0 +1,3 @@
import TelemetryClient = require("../../Library/TelemetryClient");
export declare function enable(enabled: boolean, client: TelemetryClient): void;
export declare function dispose(): void;
@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Contracts_1 = require("../../Declarations/Contracts");
var diagnostic_channel_1 = require("diagnostic-channel");
var clients = [];
// Mapping from bunyan levels defined at https://github.com/trentm/node-bunyan/blob/master/lib/bunyan.js#L256
var bunyanToAILevelMap = {
10: Contracts_1.SeverityLevel.Verbose,
20: Contracts_1.SeverityLevel.Verbose,
30: Contracts_1.SeverityLevel.Information,
40: Contracts_1.SeverityLevel.Warning,
50: Contracts_1.SeverityLevel.Error,
60: Contracts_1.SeverityLevel.Critical,
};
var subscriber = function (event) {
var message = event.data.result;
clients.forEach(function (client) {
var AIlevel = bunyanToAILevelMap[event.data.level];
if (message instanceof Error) {
client.trackException({ exception: (message) });
}
else {
client.trackTrace({ message: message, severity: AIlevel });
}
});
};
function enable(enabled, client) {
if (enabled) {
if (clients.length === 0) {
diagnostic_channel_1.channel.subscribe("bunyan", subscriber);
}
;
clients.push(client);
}
else {
clients = clients.filter(function (c) { return c != client; });
if (clients.length === 0) {
diagnostic_channel_1.channel.unsubscribe("bunyan", subscriber);
}
}
}
exports.enable = enable;
function dispose() {
diagnostic_channel_1.channel.unsubscribe("bunyan", subscriber);
clients = [];
}
exports.dispose = dispose;
//# sourceMappingURL=bunyan.sub.js.map
@@ -0,0 +1 @@
{"version":3,"file":"bunyan.sub.js","sourceRoot":"","sources":["../../../AutoCollection/diagnostic-channel/bunyan.sub.ts"],"names":[],"mappings":";;AAGA,0DAA2D;AAE3D,yDAA2D;AAI3D,IAAI,OAAO,GAAsB,EAAE,CAAC;AAEpC,6GAA6G;AAC7G,IAAM,kBAAkB,GAA6B;IACjD,EAAE,EAAE,yBAAa,CAAC,OAAO;IACzB,EAAE,EAAE,yBAAa,CAAC,OAAO;IACzB,EAAE,EAAE,yBAAa,CAAC,WAAW;IAC7B,EAAE,EAAE,yBAAa,CAAC,OAAO;IACzB,EAAE,EAAE,yBAAa,CAAC,KAAK;IACvB,EAAE,EAAE,yBAAa,CAAC,QAAQ;CAC7B,CAAC;AAEF,IAAM,UAAU,GAAG,UAAC,KAAyC;IACzD,IAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAwB,CAAC;IACpD,OAAO,CAAC,OAAO,CAAC,UAAC,MAAM;QACnB,IAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,EAAE,CAAC,CAAC,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC;YAC3B,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACpD,CAAC;QAAC,IAAI,CAAC,CAAC;YACJ,MAAM,CAAC,UAAU,CAAC,EAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAC,CAAC,CAAC;QAC7D,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,gBAAuB,OAAgB,EAAE,MAAuB;IAC5D,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACV,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,SAAS,CAAqB,QAAQ,EAAE,UAAU,CAAC,CAAC;QAChE,CAAC;QAAA,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,IAAI,CAAC,CAAC;QACJ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,IAAI,MAAM,EAAX,CAAW,CAAC,CAAC;QAC7C,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC9C,CAAC;IACL,CAAC;AACL,CAAC;AAZD,wBAYC;AAED;IACI,4BAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC1C,OAAO,GAAG,EAAE,CAAC;AACjB,CAAC;AAHD,0BAGC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license. See LICENSE file in the project root for details.\r\nimport TelemetryClient = require(\"../../Library/TelemetryClient\");\r\nimport {SeverityLevel} from \"../../Declarations/Contracts\";\r\n\r\nimport {channel, IStandardEvent} from \"diagnostic-channel\";\r\n\r\nimport {bunyan} from \"diagnostic-channel-publishers\";\r\n\r\nlet clients: TelemetryClient[] = [];\r\n\r\n// Mapping from bunyan levels defined at https://github.com/trentm/node-bunyan/blob/master/lib/bunyan.js#L256\r\nconst bunyanToAILevelMap: {[key: number] : number} = {\r\n 10: SeverityLevel.Verbose,\r\n 20: SeverityLevel.Verbose,\r\n 30: SeverityLevel.Information,\r\n 40: SeverityLevel.Warning,\r\n 50: SeverityLevel.Error,\r\n 60: SeverityLevel.Critical,\r\n};\r\n\r\nconst subscriber = (event: IStandardEvent<bunyan.IBunyanData>) => {\r\n const message = event.data.result as Error | string;\r\n clients.forEach((client) => {\r\n const AIlevel = bunyanToAILevelMap[event.data.level];\r\n if (message instanceof Error) {\r\n client.trackException({ exception: (message) });\r\n } else {\r\n client.trackTrace({message: message, severity: AIlevel});\r\n }\r\n });\r\n};\r\n\r\nexport function enable(enabled: boolean, client: TelemetryClient) {\r\n if (enabled) {\r\n if (clients.length === 0) {\r\n channel.subscribe<bunyan.IBunyanData>(\"bunyan\", subscriber);\r\n };\r\n clients.push(client);\r\n } else {\r\n clients = clients.filter((c) => c != client);\r\n if (clients.length === 0) {\r\n channel.unsubscribe(\"bunyan\", subscriber);\r\n }\r\n }\r\n}\r\n\r\nexport function dispose() {\r\n channel.unsubscribe(\"bunyan\", subscriber);\r\n clients = [];\r\n}\r\n"]}
@@ -0,0 +1,3 @@
import TelemetryClient = require("../../Library/TelemetryClient");
export declare function enable(enabled: boolean, client: TelemetryClient): void;
export declare function dispose(): void;
@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Contracts_1 = require("../../Declarations/Contracts");
var diagnostic_channel_1 = require("diagnostic-channel");
var clients = [];
var subscriber = function (event) {
var message = event.data.message;
clients.forEach(function (client) {
if (message instanceof Error) {
client.trackException({ exception: message });
}
else {
// Message can have a trailing newline
if (message.lastIndexOf("\n") == message.length - 1) {
message = message.substring(0, message.length - 1);
}
client.trackTrace({ message: message, severity: (event.data.stderr ? Contracts_1.SeverityLevel.Warning : Contracts_1.SeverityLevel.Information) });
}
});
};
function enable(enabled, client) {
if (enabled) {
if (clients.length === 0) {
diagnostic_channel_1.channel.subscribe("console", subscriber);
}
;
clients.push(client);
}
else {
clients = clients.filter(function (c) { return c != client; });
if (clients.length === 0) {
diagnostic_channel_1.channel.unsubscribe("console", subscriber);
}
}
}
exports.enable = enable;
function dispose() {
diagnostic_channel_1.channel.unsubscribe("console", subscriber);
clients = [];
}
exports.dispose = dispose;
//# sourceMappingURL=console.sub.js.map
@@ -0,0 +1 @@
{"version":3,"file":"console.sub.js","sourceRoot":"","sources":["../../../AutoCollection/diagnostic-channel/console.sub.ts"],"names":[],"mappings":";;AAGA,0DAA2D;AAE3D,yDAA2D;AAI3D,IAAI,OAAO,GAAsB,EAAE,CAAC;AAEpC,IAAM,UAAU,GAAG,UAAC,KAA8C;IAC9D,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAyB,CAAC;IACnD,OAAO,CAAC,OAAO,CAAC,UAAC,MAAM;QACnB,EAAE,CAAC,CAAC,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC;YAC3B,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,OAAO,EAAC,CAAC,CAAC;QACjD,CAAC;QAAC,IAAI,CAAC,CAAC;YACJ,sCAAsC;YACtC,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBAClD,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,CAAC,UAAU,CAAC,EAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,yBAAa,CAAC,OAAO,GAAG,yBAAa,CAAC,WAAW,CAAC,EAAC,CAAC,CAAC;QAC7H,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,gBAAuB,OAAgB,EAAE,MAAuB;IAC5D,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACV,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,SAAS,CAA0B,SAAS,EAAE,UAAU,CAAC,CAAC;QACtE,CAAC;QAAA,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,IAAI,CAAC,CAAC;QACJ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,IAAI,MAAM,EAAX,CAAW,CAAC,CAAC;QAC7C,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;AACL,CAAC;AAZD,wBAYC;AAED;IACI,4BAAO,CAAC,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC3C,OAAO,GAAG,EAAE,CAAC;AACjB,CAAC;AAHD,0BAGC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license. See LICENSE file in the project root for details.\r\nimport TelemetryClient = require(\"../../Library/TelemetryClient\");\r\nimport {SeverityLevel} from \"../../Declarations/Contracts\";\r\n\r\nimport {channel, IStandardEvent} from \"diagnostic-channel\";\r\n\r\nimport {console as consolePub} from \"diagnostic-channel-publishers\";\r\n\r\nlet clients: TelemetryClient[] = [];\r\n\r\nconst subscriber = (event: IStandardEvent<consolePub.IConsoleData>) => {\r\n let message = event.data.message as Error | string;\r\n clients.forEach((client) => {\r\n if (message instanceof Error) {\r\n client.trackException({ exception: message});\r\n } else {\r\n // Message can have a trailing newline\r\n if (message.lastIndexOf(\"\\n\") == message.length - 1) {\r\n message = message.substring(0, message.length - 1);\r\n }\r\n client.trackTrace({message: message, severity: (event.data.stderr ? SeverityLevel.Warning : SeverityLevel.Information)});\r\n }\r\n });\r\n};\r\n\r\nexport function enable(enabled: boolean, client: TelemetryClient) {\r\n if (enabled) {\r\n if (clients.length === 0) {\r\n channel.subscribe<consolePub.IConsoleData>(\"console\", subscriber);\r\n };\r\n clients.push(client);\r\n } else {\r\n clients = clients.filter((c) => c != client);\r\n if (clients.length === 0) {\r\n channel.unsubscribe(\"console\", subscriber);\r\n }\r\n }\r\n}\r\n\r\nexport function dispose() {\r\n channel.unsubscribe(\"console\", subscriber);\r\n clients = [];\r\n}\r\n"]}
@@ -0,0 +1,2 @@
export declare const IsInitialized: boolean;
export declare function registerContextPreservation(cb: (cb: Function) => Function): void;
@@ -0,0 +1,47 @@
"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
Object.defineProperty(exports, "__esModule", { value: true });
var AsyncHooksScopeManager_1 = require("../AsyncHooksScopeManager");
var Logging = require("../../Library/Logging");
exports.IsInitialized = !process.env["APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL"];
var TAG = "DiagnosticChannel";
if (exports.IsInitialized) {
var publishers = require("diagnostic-channel-publishers");
var individualOptOuts = process.env["APPLICATION_INSIGHTS_NO_PATCH_MODULES"] || "";
var unpatchedModules = individualOptOuts.split(",");
var modules = {
bunyan: publishers.bunyan,
console: publishers.console,
mongodb: publishers.mongodb,
mongodbCore: publishers.mongodbCore,
mysql: publishers.mysql,
redis: publishers.redis,
pg: publishers.pg,
pgPool: publishers.pgPool,
winston: publishers.winston,
azuresdk: publishers.azuresdk
};
for (var mod in modules) {
if (unpatchedModules.indexOf(mod) === -1) {
modules[mod].enable();
Logging.info(TAG, "Subscribed to " + mod + " events");
}
}
if (unpatchedModules.length > 0) {
Logging.info(TAG, "Some modules will not be patched", unpatchedModules);
}
}
else {
Logging.info(TAG, "Not subscribing to dependency autocollection because APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL was set");
}
function registerContextPreservation(cb) {
if (!exports.IsInitialized) {
return;
}
var diagChannel = require("diagnostic-channel");
diagChannel.channel.addContextPreservation(cb);
diagChannel.channel.spanContextPropagator = AsyncHooksScopeManager_1.AsyncScopeManager;
}
exports.registerContextPreservation = registerContextPreservation;
//# sourceMappingURL=initialization.js.map
@@ -0,0 +1 @@
{"version":3,"file":"initialization.js","sourceRoot":"","sources":["../../../AutoCollection/diagnostic-channel/initialization.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,oFAAoF;;AAMpF,oEAA8D;AAC9D,+CAAkD;AAErC,QAAA,aAAa,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;AACxF,IAAM,GAAG,GAAG,mBAAmB,CAAC;AAEhC,EAAE,CAAC,CAAC,qBAAa,CAAC,CAAC,CAAC;IAChB,IAAM,UAAU,GAAiC,OAAO,CAAC,+BAA+B,CAAC,CAAC;IAC1F,IAAM,iBAAiB,GAAW,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,IAAI,EAAE,CAAC;IAC7F,IAAM,gBAAgB,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtD,IAAM,OAAO,GAA0B;QACnC,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,EAAE,EAAE,UAAU,CAAC,EAAE;QACjB,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,QAAQ,EAAE,UAAU,CAAC,QAAQ;KAChC,CAAC;IACF,GAAG,CAAC,CAAC,IAAM,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC;QACxB,EAAE,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,mBAAiB,GAAG,YAAS,CAAC,CAAC;QACrD,CAAC;IACL,CAAC;IACD,EAAE,CAAC,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,kCAAkC,EAAE,gBAAgB,CAAC,CAAC;IAC5E,CAAC;AACL,CAAC;AAAC,IAAI,CAAC,CAAC;IACJ,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,yGAAyG,CAAC,CAAC;AACjI,CAAC;AAED,qCAA4C,EAA8B;IACtE,EAAE,CAAC,CAAC,CAAC,qBAAa,CAAC,CAAC,CAAC;QACjB,MAAM,CAAC;IACX,CAAC;IACD,IAAM,WAAW,GAAI,OAAO,CAAC,oBAAoB,CAAwB,CAAC;IAC1E,WAAW,CAAC,OAAO,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;IAC/C,WAAW,CAAC,OAAO,CAAC,qBAAqB,GAAG,0CAAiB,CAAC;AAClE,CAAC;AAPD,kEAOC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license. See LICENSE file in the project root for details.\r\n\r\n// Don't reference modules from these directly. Use only for types.\r\n// This is to avoid requiring the actual module if the NO_DIAGNOSTIC_CHANNEL env is present\r\nimport * as DiagChannelPublishers from \"diagnostic-channel-publishers\";\r\nimport * as DiagChannel from \"diagnostic-channel\";\r\nimport { AsyncScopeManager } from \"../AsyncHooksScopeManager\";\r\nimport Logging = require(\"../../Library/Logging\");\r\n\r\nexport const IsInitialized = !process.env[\"APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL\"];\r\nconst TAG = \"DiagnosticChannel\";\r\n\r\nif (IsInitialized) {\r\n const publishers: typeof DiagChannelPublishers = require(\"diagnostic-channel-publishers\");\r\n const individualOptOuts: string = process.env[\"APPLICATION_INSIGHTS_NO_PATCH_MODULES\"] || \"\";\r\n const unpatchedModules = individualOptOuts.split(\",\");\r\n const modules: {[key: string] : any} = {\r\n bunyan: publishers.bunyan,\r\n console: publishers.console,\r\n mongodb: publishers.mongodb,\r\n mongodbCore: publishers.mongodbCore,\r\n mysql: publishers.mysql,\r\n redis: publishers.redis,\r\n pg: publishers.pg,\r\n pgPool: publishers.pgPool,\r\n winston: publishers.winston,\r\n azuresdk: publishers.azuresdk\r\n };\r\n for (const mod in modules) {\r\n if (unpatchedModules.indexOf(mod) === -1) {\r\n modules[mod].enable();\r\n Logging.info(TAG, `Subscribed to ${mod} events`);\r\n }\r\n }\r\n if (unpatchedModules.length > 0) {\r\n Logging.info(TAG, \"Some modules will not be patched\", unpatchedModules);\r\n }\r\n} else {\r\n Logging.info(TAG, \"Not subscribing to dependency autocollection because APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL was set\");\r\n}\r\n\r\nexport function registerContextPreservation(cb: (cb: Function) => Function) {\r\n if (!IsInitialized) {\r\n return;\r\n }\r\n const diagChannel = (require(\"diagnostic-channel\") as typeof DiagChannel);\r\n diagChannel.channel.addContextPreservation(cb);\r\n diagChannel.channel.spanContextPropagator = AsyncScopeManager;\r\n}\r\n"]}
@@ -0,0 +1,5 @@
import TelemetryClient = require("../../Library/TelemetryClient");
import { IStandardEvent } from "diagnostic-channel";
import { mongodb } from "diagnostic-channel-publishers";
export declare const subscriber: (event: IStandardEvent<mongodb.IMongoData>) => void;
export declare function enable(enabled: boolean, client: TelemetryClient): void;
@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var diagnostic_channel_1 = require("diagnostic-channel");
var clients = [];
exports.subscriber = function (event) {
if (event.data.event.commandName === "ismaster") {
// suppress noisy ismaster commands
return;
}
clients.forEach(function (client) {
var dbName = (event.data.startedData && event.data.startedData.databaseName) || "Unknown database";
client.trackDependency({
target: dbName,
data: event.data.event.commandName,
name: event.data.event.commandName,
duration: event.data.event.duration,
success: event.data.succeeded,
/* TODO: transmit result code from mongo */
resultCode: event.data.succeeded ? "0" : "1",
time: event.data.startedData.time,
dependencyTypeName: 'mongodb'
});
});
};
function enable(enabled, client) {
if (enabled) {
if (clients.length === 0) {
diagnostic_channel_1.channel.subscribe("mongodb", exports.subscriber);
}
;
clients.push(client);
}
else {
clients = clients.filter(function (c) { return c != client; });
if (clients.length === 0) {
diagnostic_channel_1.channel.unsubscribe("mongodb", exports.subscriber);
}
}
}
exports.enable = enable;
//# sourceMappingURL=mongodb.sub.js.map
@@ -0,0 +1 @@
{"version":3,"file":"mongodb.sub.js","sourceRoot":"","sources":["../../../AutoCollection/diagnostic-channel/mongodb.sub.ts"],"names":[],"mappings":";;AAGA,yDAA6D;AAI7D,IAAI,OAAO,GAAsB,EAAE,CAAC;AAEvB,QAAA,UAAU,GAAG,UAAC,KAAyC;IAChE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC;QAC9C,mCAAmC;QACnC,MAAM,CAAC;IACX,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,UAAC,MAAM;QACnB,IAAM,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,kBAAkB,CAAC;QACrG,MAAM,CAAC,eAAe,CAClB;YACI,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW;YAClC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW;YAClC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;YACnC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS;YAC7B,2CAA2C;YAC3C,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,GAAG,GAAG,GAAG;YAC5C,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI;YACjC,kBAAkB,EAAE,SAAS;SAChC,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,gBAAuB,OAAgB,EAAE,MAAuB;IAC5D,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACV,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,SAAS,CAAqB,SAAS,EAAE,kBAAU,CAAC,CAAC;QACjE,CAAC;QAAA,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,IAAI,CAAC,CAAC;QACJ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,IAAI,MAAM,EAAX,CAAW,CAAC,CAAC;QAC7C,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,WAAW,CAAC,SAAS,EAAE,kBAAU,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;AACL,CAAC;AAZD,wBAYC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license. See LICENSE file in the project root for details.\r\nimport TelemetryClient = require(\"../../Library/TelemetryClient\");\r\nimport { channel, IStandardEvent } from \"diagnostic-channel\";\r\n\r\nimport { mongodb } from \"diagnostic-channel-publishers\";\r\n\r\nlet clients: TelemetryClient[] = [];\r\n\r\nexport const subscriber = (event: IStandardEvent<mongodb.IMongoData>) => {\r\n if (event.data.event.commandName === \"ismaster\") {\r\n // suppress noisy ismaster commands\r\n return;\r\n }\r\n clients.forEach((client) => {\r\n const dbName = (event.data.startedData && event.data.startedData.databaseName) || \"Unknown database\";\r\n client.trackDependency(\r\n {\r\n target: dbName,\r\n data: event.data.event.commandName,\r\n name: event.data.event.commandName,\r\n duration: event.data.event.duration,\r\n success: event.data.succeeded,\r\n /* TODO: transmit result code from mongo */\r\n resultCode: event.data.succeeded ? \"0\" : \"1\",\r\n time: event.data.startedData.time,\r\n dependencyTypeName: 'mongodb'\r\n });\r\n });\r\n};\r\n\r\nexport function enable(enabled: boolean, client: TelemetryClient) {\r\n if (enabled) {\r\n if (clients.length === 0) {\r\n channel.subscribe<mongodb.IMongoData>(\"mongodb\", subscriber);\r\n };\r\n clients.push(client);\r\n } else {\r\n clients = clients.filter((c) => c != client);\r\n if (clients.length === 0) {\r\n channel.unsubscribe(\"mongodb\", subscriber);\r\n }\r\n }\r\n}\r\n"]}
@@ -0,0 +1,5 @@
import TelemetryClient = require("../../Library/TelemetryClient");
import { IStandardEvent } from "diagnostic-channel";
import { mysql } from "diagnostic-channel-publishers";
export declare const subscriber: (event: IStandardEvent<mysql.IMysqlData>) => void;
export declare function enable(enabled: boolean, client: TelemetryClient): void;
@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var diagnostic_channel_1 = require("diagnostic-channel");
var clients = [];
exports.subscriber = function (event) {
clients.forEach(function (client) {
var queryObj = event.data.query || {};
var sqlString = queryObj.sql || "Unknown query";
var success = !event.data.err;
var connection = queryObj._connection || {};
var connectionConfig = connection.config || {};
var dbName = connectionConfig.socketPath ? connectionConfig.socketPath : (connectionConfig.host || "localhost") + ":" + connectionConfig.port;
client.trackDependency({
target: dbName,
data: sqlString,
name: sqlString,
duration: event.data.duration,
success: success,
/* TODO: transmit result code from mysql */
resultCode: success ? "0" : "1",
time: event.data.time,
dependencyTypeName: "mysql"
});
});
};
function enable(enabled, client) {
if (enabled) {
if (clients.length === 0) {
diagnostic_channel_1.channel.subscribe("mysql", exports.subscriber);
}
;
clients.push(client);
}
else {
clients = clients.filter(function (c) { return c != client; });
if (clients.length === 0) {
diagnostic_channel_1.channel.unsubscribe("mysql", exports.subscriber);
}
}
}
exports.enable = enable;
//# sourceMappingURL=mysql.sub.js.map
@@ -0,0 +1 @@
{"version":3,"file":"mysql.sub.js","sourceRoot":"","sources":["../../../AutoCollection/diagnostic-channel/mysql.sub.ts"],"names":[],"mappings":";;AAGA,yDAA2D;AAI3D,IAAI,OAAO,GAAsB,EAAE,CAAC;AAEvB,QAAA,UAAU,GAAG,UAAC,KAAuC;IAC9D,OAAO,CAAC,OAAO,CAAC,UAAC,MAAM;QACnB,IAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACxC,IAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,IAAI,eAAe,CAAC;QAClD,IAAM,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;QAEhC,IAAM,UAAU,GAAG,QAAQ,CAAC,WAAW,IAAI,EAAE,CAAC;QAC9C,IAAM,gBAAgB,GAAG,UAAU,CAAC,MAAM,IAAI,EAAE,CAAC;QACjD,IAAM,MAAM,GAAG,gBAAgB,CAAC,UAAU,GAAG,gBAAgB,CAAC,UAAU,GAAG,CAAG,gBAAgB,CAAC,IAAI,IAAI,WAAW,UAAI,gBAAgB,CAAC,IAAM,CAAC;QAC9I,MAAM,CAAC,eAAe,CAClB;YACI,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;YAC7B,OAAO,EAAE,OAAO;YAChB,2CAA2C;YAC3C,UAAU,EAAE,OAAO,GAAE,GAAG,GAAE,GAAG;YAC7B,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;YACrB,kBAAkB,EAAE,OAAO;SAC9B,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,gBAAuB,OAAgB,EAAE,MAAuB;IAC5D,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACV,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,SAAS,CAAmB,OAAO,EAAE,kBAAU,CAAC,CAAC;QAC7D,CAAC;QAAA,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,IAAI,CAAC,CAAC;QACJ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,IAAI,MAAM,EAAX,CAAW,CAAC,CAAC;QAC7C,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,WAAW,CAAC,OAAO,EAAE,kBAAU,CAAC,CAAC;QAC7C,CAAC;IACL,CAAC;AACL,CAAC;AAZD,wBAYC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license. See LICENSE file in the project root for details.\r\nimport TelemetryClient = require(\"../../Library/TelemetryClient\");\r\nimport {channel, IStandardEvent} from \"diagnostic-channel\";\r\n\r\nimport {mysql} from \"diagnostic-channel-publishers\";\r\n\r\nlet clients: TelemetryClient[] = [];\r\n\r\nexport const subscriber = (event: IStandardEvent<mysql.IMysqlData>) => {\r\n clients.forEach((client) => {\r\n const queryObj = event.data.query || {};\r\n const sqlString = queryObj.sql || \"Unknown query\";\r\n const success = !event.data.err;\r\n\r\n const connection = queryObj._connection || {};\r\n const connectionConfig = connection.config || {};\r\n const dbName = connectionConfig.socketPath ? connectionConfig.socketPath : `${connectionConfig.host || \"localhost\"}:${connectionConfig.port}`;\r\n client.trackDependency(\r\n {\r\n target: dbName,\r\n data: sqlString,\r\n name: sqlString,\r\n duration: event.data.duration,\r\n success: success,\r\n /* TODO: transmit result code from mysql */\r\n resultCode: success? \"0\": \"1\",\r\n time: event.data.time,\r\n dependencyTypeName: \"mysql\"\r\n });\r\n });\r\n};\r\n\r\nexport function enable(enabled: boolean, client: TelemetryClient) {\r\n if (enabled) {\r\n if (clients.length === 0) {\r\n channel.subscribe<mysql.IMysqlData>(\"mysql\", subscriber);\r\n };\r\n clients.push(client);\r\n } else {\r\n clients = clients.filter((c) => c != client);\r\n if (clients.length === 0) {\r\n channel.unsubscribe(\"mysql\", subscriber);\r\n }\r\n }\r\n}\r\n"]}
@@ -0,0 +1,5 @@
import TelemetryClient = require("../../Library/TelemetryClient");
import { IStandardEvent } from "diagnostic-channel";
import { pg } from "diagnostic-channel-publishers";
export declare const subscriber: (event: IStandardEvent<pg.IPostgresData>) => void;
export declare function enable(enabled: boolean, client: TelemetryClient): void;
@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var diagnostic_channel_1 = require("diagnostic-channel");
var clients = [];
exports.subscriber = function (event) {
clients.forEach(function (client) {
var q = event.data.query;
var sql = (q.preparable && q.preparable.text) || q.plan || q.text || "unknown query";
var success = !event.data.error;
var conn = event.data.database.host + ":" + event.data.database.port;
client.trackDependency({
target: conn,
data: sql,
name: sql,
duration: event.data.duration,
success: success,
resultCode: success ? "0" : "1",
time: event.data.time,
dependencyTypeName: "postgres"
});
});
};
function enable(enabled, client) {
if (enabled) {
if (clients.length === 0) {
diagnostic_channel_1.channel.subscribe("postgres", exports.subscriber);
}
;
clients.push(client);
}
else {
clients = clients.filter(function (c) { return c != client; });
if (clients.length === 0) {
diagnostic_channel_1.channel.unsubscribe("postgres", exports.subscriber);
}
}
}
exports.enable = enable;
//# sourceMappingURL=postgres.sub.js.map
@@ -0,0 +1 @@
{"version":3,"file":"postgres.sub.js","sourceRoot":"","sources":["../../../AutoCollection/diagnostic-channel/postgres.sub.ts"],"names":[],"mappings":";;AAGA,yDAA6D;AAI7D,IAAI,OAAO,GAAsB,EAAE,CAAC;AAEvB,QAAA,UAAU,GAAG,UAAC,KAAuC;IAC9D,OAAO,CAAC,OAAO,CAAC,UAAC,MAAM;QACnB,IAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAC3B,IAAM,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC;QACvF,IAAM,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAClC,IAAM,IAAI,GAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,SAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAM,CAAC;QACvE,MAAM,CAAC,eAAe,CAAC;YACnB,MAAM,EAAE,IAAI;YACZ,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;YAC7B,OAAO,EAAE,OAAO;YAChB,UAAU,EAAE,OAAO,GAAG,GAAG,GAAG,GAAG;YAC/B,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;YACrB,kBAAkB,EAAE,UAAU;SAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,gBAAuB,OAAgB,EAAE,MAAuB;IAC5D,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACV,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,SAAS,CAAmB,UAAU,EAAE,kBAAU,CAAC,CAAC;QAChE,CAAC;QAAA,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,IAAI,CAAC,CAAC;QACJ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,IAAI,MAAM,EAAX,CAAW,CAAC,CAAC;QAC7C,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,WAAW,CAAC,UAAU,EAAE,kBAAU,CAAC,CAAC;QAChD,CAAC;IACL,CAAC;AACL,CAAC;AAZD,wBAYC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license. See LICENSE file in the project root for details.\r\nimport TelemetryClient = require(\"../../Library/TelemetryClient\");\r\nimport { channel, IStandardEvent } from \"diagnostic-channel\";\r\n\r\nimport { pg } from \"diagnostic-channel-publishers\";\r\n\r\nlet clients: TelemetryClient[] = [];\r\n\r\nexport const subscriber = (event: IStandardEvent<pg.IPostgresData>) => {\r\n clients.forEach((client) => {\r\n const q = event.data.query;\r\n const sql = (q.preparable && q.preparable.text) || q.plan || q.text || \"unknown query\";\r\n const success = !event.data.error;\r\n const conn = `${event.data.database.host}:${event.data.database.port}`;\r\n client.trackDependency({\r\n target: conn,\r\n data: sql,\r\n name: sql,\r\n duration: event.data.duration,\r\n success: success,\r\n resultCode: success ? \"0\" : \"1\",\r\n time: event.data.time,\r\n dependencyTypeName: \"postgres\"});\r\n });\r\n};\r\n\r\nexport function enable(enabled: boolean, client: TelemetryClient) {\r\n if (enabled) {\r\n if (clients.length === 0) {\r\n channel.subscribe<pg.IPostgresData>(\"postgres\", subscriber);\r\n };\r\n clients.push(client);\r\n } else {\r\n clients = clients.filter((c) => c != client);\r\n if (clients.length === 0) {\r\n channel.unsubscribe(\"postgres\", subscriber);\r\n }\r\n }\r\n}\r\n"]}
@@ -0,0 +1,5 @@
import TelemetryClient = require("../../Library/TelemetryClient");
import { IStandardEvent } from "diagnostic-channel";
import { redis } from "diagnostic-channel-publishers";
export declare const subscriber: (event: IStandardEvent<redis.IRedisData>) => void;
export declare function enable(enabled: boolean, client: TelemetryClient): void;
@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var diagnostic_channel_1 = require("diagnostic-channel");
var clients = [];
exports.subscriber = function (event) {
clients.forEach(function (client) {
if (event.data.commandObj.command === "info") {
// We don't want to report 'info', it's irrelevant
return;
}
client.trackDependency({
target: event.data.address,
name: event.data.commandObj.command,
data: event.data.commandObj.command,
duration: event.data.duration,
success: !event.data.err,
/* TODO: transmit result code from redis */
resultCode: event.data.err ? "1" : "0",
time: event.data.time,
dependencyTypeName: "redis"
});
});
};
function enable(enabled, client) {
if (enabled) {
if (clients.length === 0) {
diagnostic_channel_1.channel.subscribe("redis", exports.subscriber);
}
;
clients.push(client);
}
else {
clients = clients.filter(function (c) { return c != client; });
if (clients.length === 0) {
diagnostic_channel_1.channel.unsubscribe("redis", exports.subscriber);
}
}
}
exports.enable = enable;
//# sourceMappingURL=redis.sub.js.map
@@ -0,0 +1 @@
{"version":3,"file":"redis.sub.js","sourceRoot":"","sources":["../../../AutoCollection/diagnostic-channel/redis.sub.ts"],"names":[],"mappings":";;AAGA,yDAA6D;AAI7D,IAAI,OAAO,GAAsB,EAAE,CAAC;AAEvB,QAAA,UAAU,GAAG,UAAC,KAAuC;IAC9D,OAAO,CAAC,OAAO,CAAC,UAAC,MAAM;QACnB,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC;YAC3C,kDAAkD;YAClD,MAAM,CAAC;QACX,CAAC;QACD,MAAM,CAAC,eAAe,CAClB;YACI,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO;YAC1B,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO;YACnC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO;YACnC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;YAC7B,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG;YACxB,2CAA2C;YAC3C,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG;YACtC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;YACrB,kBAAkB,EAAE,OAAO;SAC9B,CAAC,CAAC;IAEX,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,gBAAuB,OAAgB,EAAE,MAAuB;IAC5D,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACV,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,SAAS,CAAmB,OAAO,EAAE,kBAAU,CAAC,CAAC;QAC7D,CAAC;QAAA,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,IAAI,CAAC,CAAC;QACJ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,IAAI,MAAM,EAAX,CAAW,CAAC,CAAC;QAC7C,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,4BAAO,CAAC,WAAW,CAAC,OAAO,EAAE,kBAAU,CAAC,CAAC;QAC7C,CAAC;IACL,CAAC;AACL,CAAC;AAZD,wBAYC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license. See LICENSE file in the project root for details.\r\nimport TelemetryClient = require(\"../../Library/TelemetryClient\");\r\nimport { channel, IStandardEvent } from \"diagnostic-channel\";\r\n\r\nimport { redis } from \"diagnostic-channel-publishers\";\r\n\r\nlet clients: TelemetryClient[] = [];\r\n\r\nexport const subscriber = (event: IStandardEvent<redis.IRedisData>) => {\r\n clients.forEach((client) => {\r\n if (event.data.commandObj.command === \"info\") {\r\n // We don't want to report 'info', it's irrelevant\r\n return;\r\n }\r\n client.trackDependency(\r\n {\r\n target: event.data.address,\r\n name: event.data.commandObj.command,\r\n data: event.data.commandObj.command,\r\n duration: event.data.duration,\r\n success: !event.data.err,\r\n /* TODO: transmit result code from redis */\r\n resultCode: event.data.err ? \"1\" : \"0\",\r\n time: event.data.time,\r\n dependencyTypeName: \"redis\"\r\n });\r\n\r\n });\r\n};\r\n\r\nexport function enable(enabled: boolean, client: TelemetryClient) {\r\n if (enabled) {\r\n if (clients.length === 0) {\r\n channel.subscribe<redis.IRedisData>(\"redis\", subscriber);\r\n };\r\n clients.push(client);\r\n } else {\r\n clients = clients.filter((c) => c != client);\r\n if (clients.length === 0) {\r\n channel.unsubscribe(\"redis\", subscriber);\r\n }\r\n }\r\n}\r\n"]}
@@ -0,0 +1,3 @@
import TelemetryClient = require("../../Library/TelemetryClient");
export declare function enable(enabled: boolean, client: TelemetryClient): void;
export declare function dispose(): void;
@@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Contracts_1 = require("../../Declarations/Contracts");
var diagnostic_channel_1 = require("diagnostic-channel");
var clients = [];
var winstonToAILevelMap = {
syslog: function (og) {
var map = {
emerg: Contracts_1.SeverityLevel.Critical,
alert: Contracts_1.SeverityLevel.Critical,
crit: Contracts_1.SeverityLevel.Critical,
error: Contracts_1.SeverityLevel.Error,
warning: Contracts_1.SeverityLevel.Warning,
notice: Contracts_1.SeverityLevel.Information,
info: Contracts_1.SeverityLevel.Information,
debug: Contracts_1.SeverityLevel.Verbose
};
return map[og] === undefined ? Contracts_1.SeverityLevel.Information : map[og];
},
npm: function (og) {
var map = {
error: Contracts_1.SeverityLevel.Error,
warn: Contracts_1.SeverityLevel.Warning,
info: Contracts_1.SeverityLevel.Information,
verbose: Contracts_1.SeverityLevel.Verbose,
debug: Contracts_1.SeverityLevel.Verbose,
silly: Contracts_1.SeverityLevel.Verbose
};
return map[og] === undefined ? Contracts_1.SeverityLevel.Information : map[og];
},
unknown: function (og) {
return Contracts_1.SeverityLevel.Information;
}
};
var subscriber = function (event) {
var message = event.data.message;
clients.forEach(function (client) {
if (message instanceof Error) {
client.trackException({
exception: message,
properties: event.data.meta
});
}
else {
var AIlevel = winstonToAILevelMap[event.data.levelKind](event.data.level);
client.trackTrace({
message: message,
severity: AIlevel,
properties: event.data.meta
});
}
});
};
function enable(enabled, client) {
if (enabled) {
if (clients.length === 0) {
diagnostic_channel_1.channel.subscribe("winston", subscriber);
}
;
clients.push(client);
}
else {
clients = clients.filter(function (c) { return c != client; });
if (clients.length === 0) {
diagnostic_channel_1.channel.unsubscribe("winston", subscriber);
}
}
}
exports.enable = enable;
function dispose() {
diagnostic_channel_1.channel.unsubscribe("winston", subscriber);
clients = [];
}
exports.dispose = dispose;
//# sourceMappingURL=winston.sub.js.map
File diff suppressed because one or more lines are too long