diff --git a/Node/core-AppInsights/README.md b/Node/core-AppInsights/README.md index 7f62d53128..61a701509e 100644 --- a/Node/core-AppInsights/README.md +++ b/Node/core-AppInsights/README.md @@ -9,7 +9,7 @@ A sample bot which logs telemetry to an Application Insights instance. The minimum prerequisites to run this sample are: * Latest Node.js with NPM. Download it from [here](https://nodejs.org/en/download/). -* The Bot Framework Emulator. To install the Bot Framework Emulator, download it from [here](https://aka.ms/bf-bc-emulator). Please refer to [this documentation article](https://docs.botframework.com/en-us/csharp/builder/sdkreference/gettingstarted.html#emulator) to know more about the Bot Framework Emulator. +* The Bot Framework Emulator. To install the Bot Framework Emulator, download it from [here](https://emulator.botframework.com/). Please refer to [this documentation article](https://github.com/microsoft/botframework-emulator/wiki/Getting-Started) to know more about the Bot Framework Emulator. * **[Recommended]** Visual Studio Code for IntelliSense and debugging, download it from [here](https://code.visualstudio.com/) for free. * An Application Insights instance in Azure. The Instrumentation Key for which must be put in the `APPINSIGHTS_INSTRUMENTATIONKEY` key in [.env](.env) file to try it out further. @@ -19,12 +19,14 @@ This bot is based off the State API bot, but adds in the ability to log custom t The notable changes to the State API bot which enable telemetry logging are threefold: 1. Addition of Application Insights SDK and `appInsightsClient` -````javascript -var appInsights = require("applicationinsights"); -appInsights.setup(process.env.APPINSIGHTS_INSTRUMENTATIONKEY).start(); -var appInsightsClient = appInsights.getClient(); -... -```` + + ````javascript + var appInsights = require('applicationinsights'); + appInsights.setup(process.env.APPINSIGHTS_INSTRUMENTATIONKEY).start(); + var appInsightsClient = appInsights.getClient(); + ... + ```` + 2. [Telemetry module](telemetry-module.js) to enable creation of Telemetry objects that will be pre-populated with conversation and user data to enable quick filter/pivoting in the Application Insights dashboard. 3. Usage of these methods throughout the bot's code (eg: here, here, and here) @@ -40,4 +42,11 @@ Clicking on any item in the table will open up another pane allowing you to view For more information logged directly from the Bot Connector, be sure to put your instrumentation key in to your bot's listing in the Bot Directory. -![Bot Directory Instrumentation Key field](images/botdirfield.png) \ No newline at end of file +![Bot Directory Instrumentation Key field](images/botdirfield.png) + +### More Information + +To get more information about how to get started in Bot Builder for Node and Attachments please review the following resources: +* [Bot Builder for Node.js Reference](https://docs.botframework.com/en-us/node/builder/overview/#navtitle) +* [AppInsights Overview](https://docs.microsoft.com/en-us/azure/application-insights/app-insights-overview) +* [AppInsights for Custom Events and Metrics](https://docs.microsoft.com/en-us/azure/application-insights/app-insights-api-custom-events-metrics) \ No newline at end of file diff --git a/Node/core-AppInsights/app.js b/Node/core-AppInsights/app.js index 75757e0580..f192fabc1b 100644 --- a/Node/core-AppInsights/app.js +++ b/Node/core-AppInsights/app.js @@ -3,7 +3,7 @@ var restify = require('restify'); require('dotenv-extended').load(); var telemetryModule = require('./telemetry-module.js'); -var appInsights = require("applicationinsights"); +var appInsights = require('applicationinsights'); appInsights.setup(process.env.APPINSIGHTS_INSTRUMENTATIONKEY).start(); var appInsightsClient = appInsights.getClient(); @@ -18,10 +18,7 @@ var connector = new builder.ChatConnector({ appPassword: process.env.MICROSOFT_APP_PASSWORD }); -// Create Bot with `persistConversationData` flag -var bot = new builder.UniversalBot(connector, { - persistConversationData: true -}); +// Listen for messages server.post('/api/messages', connector.listen()); var HelpMessage = '\n * If you want to know which city I\'m using for my searches type \'current city\'. \n * Want to change the current city? Type \'change city to cityName\'. \n * Want to change it just for your searches? Type \'change my city to cityName\''; @@ -29,32 +26,36 @@ var UserNameKey = 'UserName'; var UserWelcomedKey = 'UserWelcomed'; var CityKey = 'City'; -// Bot dialogs -bot.dialog('/', function (session) { +// Setup bot with default dialog +var bot = new builder.UniversalBot(connector, function (session) { var telemetry = telemetryModule.createTelemetry(session, { setDefault: false }); - // initialize default city + // initialize with default city if (!session.conversationData[CityKey]) { session.conversationData[CityKey] = 'Seattle'; - + telemetry.setDefault = true; - } + } var defaultCity = session.conversationData[CityKey]; session.send('Welcome to the Search City bot. I\'m currently configured to search for things in %s', defaultCity); - appInsightsClient.trackTrace("start", telemetry); + appInsightsClient.trackTrace('start', telemetry); - session.beginDialog('/search'); + session.beginDialog('search'); }); -bot.dialog('/search', new builder.IntentDialog() +// Enable Conversation Data persistence +bot.set('persistConversationData', true); + +// Main dialog +bot.dialog('search', new builder.IntentDialog() .onBegin(function (session, args, next) { // is user's name set? var userName = session.userData[UserNameKey]; if (!userName) { - session.beginDialog('/askUserName'); + session.beginDialog('greet'); return; } @@ -71,17 +72,17 @@ bot.dialog('/search', new builder.IntentDialog() } finally { var resumeAfterPromptTelemetry = telemetryModule.createTelemetry(session); - appInsightsClient.trackTrace("resumeAfterPrompt", resumeAfterPromptTelemetry); + appInsightsClient.trackTrace('resumeAfterPrompt', resumeAfterPromptTelemetry); } next(); - + }).matches(/^current city/i, function (session) { // print city settings var userName = session.userData[UserNameKey]; var defaultCity = session.conversationData[CityKey]; - var userCity = session.privateConversationData[CityKey] - if (!!userCity) { + var userCity = session.privateConversationData[CityKey]; + if (userCity) { session.send( '%s, you have overridden the city. Your searches are for things in %s. The default conversation city is %s.', userName, userCity, defaultCity); @@ -91,7 +92,7 @@ bot.dialog('/search', new builder.IntentDialog() } var telemetry = telemetryModule.createTelemetry(session); - appInsightsClient.trackEvent("current city", telemetry); + appInsightsClient.trackEvent('current city', telemetry); }).matches(/^change city to (.*)/i, function (session, args) { // change default city @@ -101,7 +102,7 @@ bot.dialog('/search', new builder.IntentDialog() session.send('All set %s. From now on, all my searches will be for things in %s.', userName, newCity); var telemetry = telemetryModule.createTelemetry(session); - appInsightsClient.trackEvent("change city to", telemetry); + appInsightsClient.trackEvent('change city to', telemetry); }).matches(/^change my city to (.*)/i, function (session, args) { // change user's city @@ -110,7 +111,7 @@ bot.dialog('/search', new builder.IntentDialog() var userName = session.userData[UserNameKey]; session.send('All set %s. I have overridden the city to %s just for you', userName, newCity); var telemetry = telemetryModule.createTelemetry(session); - appInsightsClient.trackEvent("change my city to", telemetry); + appInsightsClient.trackEvent('change my city to', telemetry); }).matches(/^reset/i, function (session, args) { // reset data @@ -130,32 +131,33 @@ bot.dialog('/search', new builder.IntentDialog() var userName = session.userData[UserNameKey]; var messageText = session.message.text.trim(); session.send('%s, wait a few seconds. Searching for \'%s\' in \'%s\'...', userName, messageText, city); - session.send('https://www.bing.com/search?q=%s', encodeURIComponent(messageText + ' in ' + city)); + session.send('https://www.bing.comsearch?q=%s', encodeURIComponent(messageText + ' in ' + city)); } catch (error) { measuredEventTelemetry.exception = error.toString(); - appInsightsClient.trackException("search", t) + appInsightsClient.trackException('search', t); } finally { var timerEnd = process.hrtime(timerStart); - measuredEventTelemetry.metrics = (timerEnd[0], timerEnd[1]/1000000); - appInsightsClient.trackEvent("timeTaken", measuredEventTelemetry); + measuredEventTelemetry.metrics = (timerEnd[0], timerEnd[1] / 1000000); + appInsightsClient.trackEvent('timeTaken', measuredEventTelemetry); - } + } })); -bot.dialog('/askUserName', new builder.SimpleDialog(function (session, results) { +// Greet dialog +bot.dialog('greet', new builder.SimpleDialog(function (session, results) { if (results && results.response) { session.userData[UserNameKey] = results.response; session.privateConversationData[UserWelcomedKey] = true; - session.send('Welcome %s! %s', results.response, HelpMessage) + session.send('Welcome %s! %s', results.response, HelpMessage); var telemetry = telemetryModule.createTelemetry(session); telemetry.userName = results.response; // You can add properties after-the-fact as well - appInsightsClient.trackEvent("new user", telemetry); + appInsightsClient.trackEvent('new user', telemetry); - // end the current dialog and replace it with '/search' dialog - session.replaceDialog('/search'); + // end the current dialog and replace it with 'search' dialog + session.replaceDialog('search'); return; } diff --git a/Node/core-AppInsights/package.json b/Node/core-AppInsights/package.json index a7003d2557..5b4057e2a6 100644 --- a/Node/core-AppInsights/package.json +++ b/Node/core-AppInsights/package.json @@ -9,9 +9,9 @@ "author": "", "license": "MIT", "dependencies": { - "applicationinsights": "^0.16.0", - "botbuilder": "^3.2.3", + "applicationinsights": "^0.17.1", + "botbuilder": "^3.5.1", "dotenv-extended": "^1.0.4", - "restify": "^4.1.1" + "restify": "^4.3.0" } } diff --git a/Node/core-AppInsights/telemetry-module.js b/Node/core-AppInsights/telemetry-module.js index e14ddc091d..e0a5376490 100644 --- a/Node/core-AppInsights/telemetry-module.js +++ b/Node/core-AppInsights/telemetry-module.js @@ -1,17 +1,17 @@ -exports.createTelemetry = (session, properties = null) => { +exports.createTelemetry = (session, properties) => { var data = { conversationData: JSON.stringify(session.conversationData), privateConversationData: JSON.stringify(session.privateConversationData), userData: JSON.stringify(session.userData), conversationId: session.message.address.conversation.id, userId: session.message.address.user.id - } + }; - if(properties) { - for(property in properties) { + if (properties) { + for (property in properties) { data[property] = properties[property]; } } - + return data; -} +}; \ No newline at end of file