{"id":11641,"date":"2016-02-11T14:59:47","date_gmt":"2016-02-11T14:59:47","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudioalm\/?p=11641"},"modified":"2019-02-14T17:36:21","modified_gmt":"2019-02-15T01:36:21","slug":"monitor-team-services-web-extensions-with-visual-studio-application-insights","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/monitor-team-services-web-extensions-with-visual-studio-application-insights\/","title":{"rendered":"Monitor Team Services web extensions with Visual Studio Application Insights"},"content":{"rendered":"<p>One\u00a0of the top questions we get\u00a0from developers\u00a0building extensions for Visual Studio Team Services is &#8220;<strong>Are people using my extension<\/strong>&#8220;? The <a href=\"http:\/\/marketplace.visualstudio.com\">Visual Studio Marketplace<\/a> (launched in November and currently in preview) shows\u00a0the number of Team Services accounts an extension is installed to, but not the number of people actually using it or how these people are using it.\u00a0Enter Visual Studio Application Insights.<\/p>\n<blockquote>\n<p style=\"font-size: 1.2em\">Get an overview of <a href=\"https:\/\/www.visualstudio.com\/integrate\/extensions\/overview\">extensions for Team Services<\/a>. Extensions are also available on-premises with Team Foundation Server 2015 Update 2 RC1 (see the <a href=\"https:\/\/www.visualstudio.com\/news\/tfs2015-update2-vs\">release notes<\/a>).<\/p>\n<\/blockquote>\n<p>Application Insights, or AI, is a Microsoft Azure-hosted service that provides real-time monitoring of Java, .NET, JavaScript (and more) applications.\u00a0Application Insights\u00a0can alert you to problems in your extension, and almost as importantly, it\u00a0can help\u00a0you understand usage of your extension, and help answer questions like:<\/p>\n<ol>\n<li>How many people are using my extension?<\/li>\n<li>Which features\u00a0of my extension are most\/least used?<\/li>\n<li>What geography are users accessing my extensions from?<\/li>\n<li>Did I just break all of my users with my update at 3 AM today?<\/li>\n<\/ol>\n<p>The answers AI provides are <strong>not just\u00a0<\/strong><b>fun facts<\/b>. AI can help guide your decision-making process (should you stop investing in a particular feature or should you double down?). AI can alert you to\u00a0problems in your extension (before there is a\u00a0mass exodus by your users). AI can also help you optimize your extension based on where users are accessing it from and what browsers they are using.<\/p>\n<p>This post will guide you through the simple steps of adding tracking to a web-based Team Services extension.<\/p>\n<blockquote>\n<p style=\"font-size: 1.2em\">See real code in action: check out the\u00a0<a href=\"https:\/\/github.com\/Microsoft\/vsts-branch-delete\">Branch Delete<\/a> extension code on GitHub.<\/p>\n<\/blockquote>\n<h2>Create an\u00a0Application Insights resource<\/h2>\n<p>First step, is to sign-up for an Azure subscription. To get started, visit the <a href=\"https:\/\/azure.microsoft.com\/en-us\/services\/application-insights\/\">Application Insights<\/a> overview page.<\/p>\n<ol>\n<li>In the Azure Portal, click the New button, and search for<strong> Application Insights<\/strong>.<\/li>\n<li>Click Create, enter a name for your AI resource, pick an\u00a0application type, and click <strong>Create<\/strong>.<\/li>\n<\/ol>\n<p>For the name, I chose a name that equates to my Team Services publisher name so that I can monitor usage for multiple extensions in one AI instance. You might just chose to create one AI instance per extension.\u00a0I chose ASP.NET as the application type even though my extension is fully-hosted by Team Services.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/CreateAppInsights.png\"><img decoding=\"async\" class=\"alignnone wp-image-11651 \" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/02\/CreateAppInsights.png\" alt=\"CreateAppInsights\" width=\"812\" height=\"632\" \/><\/a><\/p>\n<h2>Tracking activity in your extension<\/h2>\n<p>Now the fun part. Start by grabbing the provided bootstrapping snippet. You will embed this code in your web extension&#8217;s main HTML page.<\/p>\n<h3>Add the AI JavaScript SDK<\/h3>\n<p>AI provides you a customized JavaScript snippet that you can embed in your extension&#8217;s main page.<\/p>\n<ol>\n<li>Click the get started icon in the main blade and then click the <b>Get code to monitor my web pages<\/b> link:\n<a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/CodeJsCode1.png\"><img decoding=\"async\" class=\"alignnone size-large wp-image-11671\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/02\/CodeJsCode1-1024x534.png\" alt=\"CodeJsCode\" width=\"879\" height=\"458\" \/><\/a><\/li>\n<li>Copy the JavaScript code snippet.\n<ul>\n<li>The snippet is customized. It\u00a0includes an instrumentation key\u00a0that\u00a0connects the telemetry data coming from your extension to this AI instance.<\/li>\n<\/ul>\n<\/li>\n<li>In your extension&#8217;s HTML page, paste the snippet just before the ending &lt;\/head&gt; tag.<\/li>\n<\/ol>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/TrackPageCodeHead.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-11701\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/02\/TrackPageCodeHead.png\" alt=\"TrackPageCodeHead\" width=\"997\" height=\"339\" \/><\/a><\/p>\n<blockquote>\n<p style=\"font-size: 1.2em\">Read an <a href=\"http:\/\/apmtips.com\/blog\/2015\/03\/18\/javascript-snippet-explained\/\">in-depth explanation<\/a> of how this script works.<\/p>\n<\/blockquote>\n<h4>Track page views<\/h4>\n<p>Let&#8217;s track when our extension is loaded into the browser. This may be when a page is shown to the user in for example, a hub or work item form extension. This may also be when Team Services loads a page that is supporting a menu or toolbar contribution.<\/p>\n<p>Every extension is accessed by an authenticated Team Services user under the context of a Team Services account. We want to include this data with the telemetry data that is sent to AI from our extension. Note: you should never send personally identifiable information, or PII. Send only the data you need to understand usage patterns, not data (name, email address, etc) that can identify a person.<\/p>\n<ol>\n<li>From the code you pasted into the &lt;head&gt; section, remove the line that calls the <strong>trackPageView<\/strong> (we will call this later in our page).<\/li>\n<li>Define an anonymous function that will be called when the VSS (Visual Studio Services) web extension SDK is ready. This will ensure your extension page has been loaded and has access to context information.<\/li>\n<li>Add a call to the <b>setAuthenticatedUserContext<\/b> function on the window.appInsights object, passing the current user&#8217;s ID as well as the team project collection ID.<\/li>\n<li>Add a call to the <b>trackPageView<\/b> function, passing a name for your page. This is optional, but will make it easier to search later.<\/li>\n<\/ol>\n<p>For convenience, here is the code:<\/p>\n<pre>&lt;script&gt;\n VSS.init({ usePlatformScripts: true }); \n\n VSS.ready(function() {\n    window.appInsights.setAuthenticatedUserContext(\n        VSS.getWebContext().user.id, \n        VSS.getWebContext().collection.id);\n    window.appInsights.trackPageView(\"BranchDelete\"); \n });\n&lt;\/script&gt; \n<\/pre>\n<p>You can also call <code>trackPageView<\/code> in your extension as users navigate within it. For example, if you have a hub with multiple pivots, you can call this function when a user transitions from one pivot to another.<\/p>\n<h3>Track custom events<\/h3>\n<p>Let&#8217;s now add tracking for a custom event. This will allow us to know how (and if) a particular feature of our extension is being used.<\/p>\n<ol>\n<li>In your JavaScript code where an action is being performed by a user (or whenever you want to track something), add a call to the <b>trackEvent<\/b> function on the appInsights object.<\/li>\n<li>The first parameter is the name of the event. Give it a descriptive name so you can find it later.<\/li>\n<li>The second parameter is an optional object that can contain one or more additional properties that you might want to search\/query on later.<\/li>\n<\/ol>\n<p><img decoding=\"async\" class=\"alignnone size-mediumlarge wp-image-11691\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/02\/TrackEventCode-500x201.png\" alt=\"TrackEventCode\" width=\"500\" height=\"201\" \/><\/p>\n<pre>   \/\/ Publish event to Application Insights\n   if (window.appInsights) {\n      window.appInsights.trackEvent(\"BranchDeleted\", { \"customProperty\": \"xyz\" } );\n   }\n<\/pre>\n<p>Package and publish your updated extension via the Visual Studio Marketplace.<\/p>\n<h2>View and search the data<\/h2>\n<p>Now give your extension a try, making sure to hit all the places where you added page or event tracking code.<\/p>\n<ol>\n<li>Open the Azure Portal and navigate to your Application Insights resource<\/li>\n<li>Click <strong>Search<\/strong> at the top of the main blade.<\/li>\n<li>You should also see data appearing. For example, our sample extension is showing data about when it was opened and events that have already been triggered\n<a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/SearchData.png\"><img decoding=\"async\" class=\"alignnone size-large wp-image-11702\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/02\/SearchData-1024x682.png\" alt=\"SearchData\" width=\"879\" height=\"585\" \/><\/a><\/li>\n<\/ol>\n<h3>Other useful features<\/h3>\n<p>Application Insights has many other features that Team Services extension developers will find useful, including:<\/p>\n<ul>\n<li><strong>Usage<\/strong>: users, sessions, and page views\n<img decoding=\"async\" src=\"\" alt=\"\" \/><\/li>\n<li><strong>Alerts<\/strong>: get notified about potential back-end service problems\n<img decoding=\"async\" src=\"\" alt=\"\" \/><\/li>\n<li><strong>Problem diagnostics and metrics<\/strong>: Understand where problems are happening\n<img decoding=\"async\" src=\"\" alt=\"\" \/><\/li>\n<\/ul>\n<p>Start exploring all of the features today: <a href=\"https:\/\/azure.microsoft.com\/en-us\/documentation\/articles\/app-insights-overview\/\"><strong>Get started with Application Insights<\/strong><\/a><\/p>\n<p>Will Smythe,\u00a0<span style=\"line-height: 1.5\">Program Manager on Visual Studio Team Services<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One\u00a0of the top questions we get\u00a0from developers\u00a0building extensions for Visual Studio Team Services is &#8220;Are people using my extension&#8220;? The Visual Studio Marketplace (launched in November and currently in preview) shows\u00a0the number of Team Services accounts an extension is installed to, but not the number of people actually using it or how these people are [&hellip;]<\/p>\n","protected":false},"author":144,"featured_media":45953,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[224,1],"tags":[],"class_list":["post-11641","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-devops"],"acf":[],"blog_post_summary":"<p>One\u00a0of the top questions we get\u00a0from developers\u00a0building extensions for Visual Studio Team Services is &#8220;Are people using my extension&#8220;? The Visual Studio Marketplace (launched in November and currently in preview) shows\u00a0the number of Team Services accounts an extension is installed to, but not the number of people actually using it or how these people are [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/11641","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/users\/144"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=11641"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/11641\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/45953"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=11641"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=11641"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=11641"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}