UNPKG

botbuilder-applicationinsights

Version:

Application Insights extensions for Microsoft BotBuilder.

190 lines 8.01 kB
"use strict"; 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