botbuilder-applicationinsights
Version:
Application Insights extensions for Microsoft BotBuilder.
190 lines • 8.01 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationInsightsTelemetryClient = exports.ApplicationInsightsWebserverMiddleware = void 0;
/**
* @module botbuilder-applicationinsights
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const appInsights = __importStar(require("applicationinsights"));
const cls = __importStar(require("cls-hooked"));
const crypto = __importStar(require("crypto"));
// This is the currently recommended work-around for using Application Insights with async/await
// https://github.com/Microsoft/ApplicationInsights-node.js/issues/296
// This allows AppInsights to automatically apply the appropriate context objects deep inside the async/await chain.
const CorrelationContextManager_1 = require("applicationinsights/out/AutoCollection/CorrelationContextManager");
const origGetCurrentContext = CorrelationContextManager_1.CorrelationContextManager.getCurrentContext;
const ns = cls.createNamespace('my.request');
function getCurrentContext() {
return ns.get('ctx') || origGetCurrentContext();
}
// Overwrite the built-in getCurrentContext() method with a new one.
CorrelationContextManager_1.CorrelationContextManager.getCurrentContext = getCurrentContext;
const ApplicationInsightsWebserverMiddleware = (req, res, next) => {
// Check to see if the request contains an incoming request.
// If so, set it into the Application Insights context.
const activity = req.body;
if (activity && activity.id) {
const context = appInsights.getCorrelationContext();
context['activity'] = req.body;
}
ns.bindEmitter(req);
ns.bindEmitter(res);
ns.run(() => {
ns.set('ctx', origGetCurrentContext());
next();
});
};
exports.ApplicationInsightsWebserverMiddleware = ApplicationInsightsWebserverMiddleware;
/**
* This is a wrapper class around the Application Insights node client.
* This is primarily designed to be used alongside the WaterfallDialog telemetry collection.
* It provides a pre-configured App Insights client, and wrappers around
* the major tracking functions, allowing it to conform to Botbuilder's generic BotTelemetryClient interface.
* To use it, create pass in an instrumentation key:
*
* ```
* const myDialog = new WaterfallDialog('my_dialog', steps);
* const appInsightsClient = new ApplicationInsightsTelemetryClient(my_instrumentation_key);
* myDialog.telemetryClient = appInsightsClient;
* ```
*/
class ApplicationInsightsTelemetryClient {
/**
* @internal
*/
constructor(setupString) {
this.config = appInsights
.setup(setupString)
.setAutoDependencyCorrelation(true)
.setAutoCollectRequests(true)
.setAutoCollectPerformance(true)
.setAutoCollectExceptions(true)
.setAutoCollectDependencies(true)
.start();
this.client = appInsights.defaultClient;
this.client.addTelemetryProcessor(addBotIdentifiers);
}
// Protects against JSON.stringify cycles
toJSON() {
return { name: 'ApplicationInsightsTelemetryClient' };
}
/**
* Provides access to the Application Insights configuration that is running here.
* Allows developers to adjust the options, for example:
* `appInsightsClient.configuration.setAutoCollectDependencies(false)`
*
* @returns app insights configuration
*/
get configuration() {
return this.config;
}
/**
* Provides direct access to the telemetry client object, which might be necessary for some operations.
*
* @returns app insights telemetry client
*/
get defaultClient() {
return this.client;
}
/**
* Sends information about an external dependency (outgoing call) in the application.
*
* @param telemetry The [TelemetryDependency](xref:botbuilder-core.TelemetryDependency) to track.
*/
trackDependency(telemetry) {
this.defaultClient.trackDependency(telemetry);
}
/**
* Logs custom events with extensible named fields.
*
* @param telemetry The [TelemetryEvent](xref:botbuilder-core.TelemetryEvent) to track.
*/
trackEvent(telemetry) {
const { name, properties, metrics: measurements } = telemetry;
this.defaultClient.trackEvent({ name, properties, measurements });
}
/**
* Logs a system exception.
*
* @param telemetry The [TelemetryException](xref:botbuilder-core.TelemetryException) to track.
*/
trackException(telemetry) {
this.defaultClient.trackException(telemetry);
}
/**
* Sends a trace message.
*
* @param telemetry The [TelemetryTrace](xref:botbuilder-core.TelemetryTrace) to track.
*/
trackTrace(telemetry) {
this.defaultClient.trackTrace(telemetry);
}
/**
* Logs a dialog entry as an Application Insights page view.
*
* @param telemetry The [TelemetryPageView](xref:botbuilder-core.TelemetryPageView) to track.
*/
trackPageView(telemetry) {
this.defaultClient.trackPageView(telemetry);
}
/**
* Flushes the in-memory buffer and any metrics being pre-aggregated.
*/
flush() {
this.defaultClient.flush();
}
}
exports.ApplicationInsightsTelemetryClient = ApplicationInsightsTelemetryClient;
/* Define the telemetry initializer function which is responsible for setting the userId. sessionId and some other values
* so that application insights can correlate related events.
*/
function addBotIdentifiers(envelope, context) {
if (context.correlationContext && context.correlationContext.activity) {
const activity = context.correlationContext.activity;
const telemetryItem = envelope.data['baseData']; // TODO: update when envelope ts definition includes baseData
const userId = activity.from ? activity.from.id : '';
const channelId = activity.channelId || '';
const conversationId = activity.conversation ? activity.conversation.id : '';
// Hashed ID is used due to max session ID length for App Insights session Id
const sessionId = conversationId
? crypto.createHash('sha256').update(conversationId).digest('base64')
: '';
// set user id and session id
envelope.tags[appInsights.defaultClient.context.keys.userId] = channelId + userId;
envelope.tags[appInsights.defaultClient.context.keys.sessionId] = sessionId;
// Add additional properties
telemetryItem.properties = telemetryItem.properties || {};
telemetryItem.properties.activityId = activity.id;
telemetryItem.properties.channelId = channelId;
telemetryItem.properties.activityType = activity.type;
telemetryItem.properties.conversationId = conversationId;
}
return true;
}
//# sourceMappingURL=applicationInsightsTelemetryClient.js.map
;