APM tips blog

Blog about application monitoring.

Telemetry Initializers

| Comments

Application Insights .NET SDK has number of extensibility points. One of them is called telemetry initializer. Telemetry initializer is a class implementing ITelemetryInitializer interface. The only method of this interface “Initialize” is called whenever a TraceFoo method is called for one of telemetry data items (Event, Metric, Request, Exception, etc.).

The Application Insights web SDK comes with two default telemetry initializers - web operation name and Id initializers:

1
2
3
4
<TelemetryInitializers>
  <Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebOperationNameTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
  <Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebOperationIdTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
</TelemetryInitializers>

These initializers are used to mark every collected telemetry item with the current web request identity so that traces and exception can be correlated to corresponding requests:

The trace telemetry in this example, has the following context populated by telemetry initializers mentioned above:

1
"operation":{"id":"1940098063557174680","name":"GET Home/Index"}

It is easy to implement your own telemetry initializer. Say, you want to mark every telemetry data item with ETW ActivityID and System.Diagnostics ActivityID. To do this, first, you create a class that implements the ITelemetryInitializer interface. In the interface’s Initialize method you can fill out telemetry data item properties:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace ApmTips.Tools
{
    using Microsoft.ApplicationInsights.Extensibility;
    using Microsoft.Diagnostics.Tracing;
    using System.Diagnostics;

    public class ExtendedIDTelemetryInitializer : ITelemetryInitializer
    {
        public void Initialize(Microsoft.ApplicationInsights.Channel.ITelemetry telemetry)
        {
            telemetry.Context.Properties["ETW.ActivityID"] = EventSource.CurrentThreadActivityId.ToString();
            telemetry.Context.Properties["E2ETrace.ActivityID"] = Trace.CorrelationManager.ActivityId.ToString();
        }
    }
}

You then need to register your telemetry initializer using one of the following two options: Adding it to ApplicationInsights.config file:

1
2
3
<TelemetryInitializers>
  <Add Type="ApmTips.Tools.ExtendedIDTelemetryInitializer, ApmTips.Tools" />
</TelemetryInitializers>

or programmatically:

1
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.TelemetryInitializers.Add(new ExtendedIDTelemetryInitializer());

This is what every data item will be marked with after you start your application with the new telemetry initializer configured:

1
"properties":{"ETW.ActivityID":"00000000-0000-0000-0000-000000000000","E2ETrace.ActivityID":"00000000-0000-0000-0700-0080000000f9"}

And here is how it looks like in UI:

Telemetry initializers are a powerful, but dangerous tool. They are called synchronously and block program execution flow; if written poorly they can harm application performance.

The following example demonstrates synchronous execution of telemetry initializers. It traces every telemetry initializer into the file with the stack trace where telemetry data item was created from:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace ApmTips.Tools
{
    using Microsoft.ApplicationInsights.Extensibility;
    using System;
    using System.Diagnostics;
    using System.IO;

    public class DiagnosticsTraceTelemetryInitializer : ITelemetryInitializer
    {
        public void Initialize(Microsoft.ApplicationInsights.Channel.ITelemetry telemetry)
        {
            var stack = new StackTrace();

            using (StreamWriter sw = new StreamWriter(Environment.ExpandEnvironmentVariables("%tmp%\\ai-log.txt"), true))
            {
                sw.WriteLine(telemetry.GetType().Name + " was traced");
                sw.WriteLine(" from " + stack.ToString());
            }
        }
    }
}

Here is the output this telemetry initializer generates for a single request with Trace statement in controller. You can see that the Trace.Write method was called from the home controller (WebApplication3.Controllers.HomeController.Index). This in turn called the Application Insights trace listener which finally called Track method and our telemetry initializer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
TraceTelemetry was traced from
   at ApmTips.Tools.DiagnosticsTraceTelemetryInitializer.Initialize(ITelemetry telemetry)
   at Microsoft.ApplicationInsights.TelemetryClient.Track(ITelemetry telemetry)
   at Microsoft.ApplicationInsights.TraceListener.ApplicationInsightsTraceListener.Write(String message)
   at System.Diagnostics.TraceInternal.Write(String message)
   at System.Diagnostics.Trace.Write(String message)
   at WebApplication3.Controllers.HomeController.Index()
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.ActionInvocation.InvokeSynchronousActionMethod()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
   at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
   at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.<BeginInvokeAction>b__1c()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
   at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult)
   at System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
   at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
   at System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
   at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)
   at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult)
   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
   at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
   at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
   at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
   at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

RequestTelemetry was traced from
   at ApmTips.Tools.DiagnosticsTraceTelemetryInitializer.Initialize(ITelemetry telemetry)
   at Microsoft.ApplicationInsights.TelemetryClient.Track(ITelemetry telemetry)
   at Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.TelemetryModules.WebRequestTrackingTelemetryModule.OnEndRequest(RequestTelemetryContext state, HttpContext platformContext)
   at Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebPlatformModuleAdapter.ExecuteStepExceptionSafe[TX,TY](String stageName, Action`2 stage, TX state, TY platfromContext)
   at Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebPlatformModuleAdapter.OnEndRequest(HttpContext platformContext)
   at Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule.OnCallbackExceptionSafe(String callbackName, HttpContext platformContext, Action`1 action)
   at Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule.OnEndRequest(Object sender, EventArgs eventArgs)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
   at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
   at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
   at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

Use telemetry initializers wisely for properties that changes from one data item to another. There are other mechanisms to set global properties that will have the same value for all data items in the process.

JavaScript Snippet and Instrumentation Key

| Comments

When you create a new web application in Visual Studio 2013 you can chose to enable Application Insights for it. Once enabled - JavaScript snippet will be inserted into page template document \Views\Shared\\_Layout.cshtml:

This JavaScript snippet will collect end user behavior information in portal. You may notice that Instrumentation Key is set to constant in this snippet:

1
instrumentationKey:"dbdf606c-48ec-4beb-b82d-2a9e7a90e5a4"

Constant works fine unless you want to change the key before deploying to production. Here is how you can change default snippet in \Views\Shared\\_Layout.cshtml to use the same instrumentation key as server monitoring using:

1
instrumentationKey:"@Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey"

There are reasons not to use this by default. Performance is one of them. You may also want to separate end user behavior data from server-side telemetry. In any case keep in mind - by default there are two places where you need to change your instrumentation key when you deploying your application to production.

Programmatically Set Instrumentation Key

| Comments

As telemetry became a part of engineering process I hear one question more and more often - how can I separate events reported during development from data collected from production deployment? How can I limit access to data and integrate telemetry into my continues integration infrastructure? How can I separate events from staging and production, from different versions of application, from different components inside the application?

Well, nobody knows the answer better then you. Application Telemetry SDK is flexible and gives you full controls over data and configure data collection the way you need it. There are couple ways to slice your data. In this article I’ll explain how to separate telemetry data by sending it to different components.

Every component in Application Insights is represented by a single Instrumentation Key. You can get it in “properties” section of your component:

Easiest way to configure instrumentation key is to set it in ApplicationInsights.config. Whenever Application Insights will need to send data for the first time it will attempt to read instrumentation key from this config file. You can use TransformXml msbuild task to automate the release pipeline. Here is config snippet you need to modify:

1
<InstrumentationKey>ec126cb1-9adc-4681-9cd4-0fcad33511c9</InstrumentationKey>

However this approach is not working well with some deployments. You may already have distributed configuration management system in place. One example may be Azure Cloud Services where you may prefer to store instrumentation key in cscfg file. In this case you can leave InstrumentationKey section of ApplicationInsights.config file blank and set it programmatically:

1
2
3
TelemetryConfiguration.Active.InstrumentationKey = "ec126cb1-9adc-4681-9cd4-0fcad33511c9";
TelemetryClient tc = new TelemetryClient();
tc.TrackTrace("This trace goes to the default source");

The best place to do it for web application is Global.asax before any telemetry data items were tracked. Note, that if you’ll attempt to send telemetry data item before instrumentation key was set TelemetryClient.Track[Foo] method will throw an exception.

In both cases - using config or setting key programmatically you’ll see data reported into the same component. This key will be used as default for all telemetry clients you’ll instantiate.

There are situations when one default key is not enough. Scenarios I can imagine are:

  • reporting data from payment processing library separately from other telemetry
  • split telemetry information by tenants of your application and grant them access to their data only
  • library developer wants to collect telemetry from his library, not send it to application that uses this library

For all this scenarios you’ll need to configure your own custom telemetry client and set it’s instrumentation key:

1
2
3
TelemetryClient tcCustom = new TelemetryClient();
tcCustom.Context.InstrumentationKey = "67989f95-d6a2-46a9-918b-028a6a2070c1";
tcCustom.TrackTrace("This trace goes to custom telemetry client");

Sometimes you might want even more fine grained control over data. You may want to decide where to send telemetry data item based on it’s properties. For instance, you can have a library that decides where to send telemetry item based on current thread identity. In this case you’ll create and populate telemetry item and then pass it to this library so it will set the correct Instrumentation Key on this item:

1
2
3
4
TelemetryClient tcDefault = new TelemetryClient();
TraceTelemetry trace = new TraceTelemetry("This trace goes to the custom source");
trace.Context.InstrumentationKey = "67989f95-d6a2-46a9-918b-028a6a2070c1";
tcDefault.TrackTrace(trace);

Both code examples will send trace message to your custom application even though configuration file defines another instrumentation key.

Summary

Application Insights SDK gives you a flexible way to configure data collection. You have full programmatic control over where data will be reported to and it is very easy to integrate Application Insights into any continues deployment process with the minimal coding.

Collect ASP.NET MVC Web API Traces With Application Insights

| Comments

Application Insights is designed to be a continuation of development expirience. As you use traces for development it is very easy to start collecting traces for your application in production. Today I’ll walk thru steps to enable traces collection using Application Insights.

I’m going to demo how to enable System.Diagnotsics traces. One may argue that those traces are not very efficient and will be absolutely correct. There are many tracing libraries that are faster and more powerful. However there are lots of libraries out wild which already instrumented with this tracing framework. One of example is Web API tracing library.

Traced from ASP.NET Web API

Let’s take a simple Web API application. I created one using File->New dialog in VS 2013. Following the steps in this article we will enable tracing by installing package

1
PM> Install-Package Microsoft.AspNet.WebApi.Tracing 

and then modifying WebApiConfig.cs by adding call to extension method defined in that nuget package:

1
config.EnableSystemDiagnosticsTracing();

You may already have Application Insights enabled for your application. If not just follow instructions. Now you are ready to enable traces collection from your application. Enabling tracing is very easy. Just install the nuget:

1
PM> Install-Package Microsoft.ApplicationInsights.TraceListener -Pre

Under the hood nuget will add reference to new assembly containing trace listener and add this trace listener into web.config:

1
2
3
4
5
6
7
<system.diagnostics>
<trace autoflush="true" indentsize="0">
  <listeners>
    <add name="myAppInsightsListener" type="Microsoft.ApplicationInsights.TraceListener.ApplicationInsightsTraceListener, Microsoft.ApplicationInsights.TraceListener" />
  </listeners>
</trace>
</system.diagnostics>

Now when you running Web API methods you will not only see those methods as requests, but also traces associated with these requests. On my machine I just run application under debugger and called this GET method “http://localhost:57444/api/values” from browser. Here are result I see in azure portal: You see step by step execution of Web API pipeline - in the portal traces are in reverse order:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Request, Method=GET, Url=http://localhost:57444/api/values, Message='http://localhost:57444/api/values'
Message='Values', Operation=DefaultHttpControllerSelector.SelectController
Message='WebApplication1.Controllers.ValuesController', Operation=DefaultHttpControllerActivator.Create
Message='WebApplication1.Controllers.ValuesController', Operation=HttpControllerDescriptor.CreateController
Message='Selected action 'Get()'', Operation=ApiControllerActionSelector.SelectAction
Message='The authentication filter did not encounter an error or set a principal.', Operation=HostAuthenticationFilter.AuthenticateAsync
Message='Will use same 'JsonMediaTypeFormatter' formatter', Operation=JsonMediaTypeFormatter.GetPerRequestFormatterInstance
Operation=HostAuthenticationFilter.ChallengeAsync
Message='Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate
Operation=AuthorizeAttribute.OnAuthorizationAsync, Status=401 (Unauthorized)
Operation=ValuesController.ExecuteAsync, Status=401 (Unauthorized)
Operation=PassiveAuthenticationMessageHandler.SendAsync, Status=401 (Unauthorized)
Response, Status=401 (Unauthorized), Method=GET, Url=http://localhost:57444/api/values, Message='Content-type='application/json; charset=utf-8', content-length=unknown'
Operation=JsonMediaTypeFormatter.WriteToStreamAsync
Operation=ValuesController.Dispose

This it pretty cool, all existing traces will be sent to Application insights, indexed and sliced by requests and sessions. For every request you will see all troubleshooting informaiton. No more remote desktop to production server to get traces from the local file!

Named trace providers

Once installed Application Insights listen for default trace source. However your trace source may be named. In this case you’ll need to adjust configuration. Here is how to enable Application Insights tracing to listen for System.Net trace source (and shoot yourself in the foot ;-)). I haven’t planned that shooting part of this example. Let me explain what I did.

First, I moved Application Insights trace listener to sharedListeners section and added System.Net trace source. Here is how web.config looks like after my change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<system.diagnostics>
<trace autoflush="true" indentsize="0">
  <listeners>
    <add name="myAppInsightsListener" />
  </listeners>
</trace>
<sources>
  <source name="System.Net" switchName="sourceSwitch" tracemode="includehex" maxdatasize="1024">
    <listeners>
      <add name="myAppInsightsListener" />
      <remove name="Default"/>
    </listeners>
  </source>
</sources>
<switches>
  <add name="sourceSwitch" value="Information"/>
</switches>
<sharedListeners>
  <add name="myAppInsightsListener" type="Microsoft.ApplicationInsights.TraceListener.ApplicationInsightsTraceListener, Microsoft.ApplicationInsights.TraceListener" />
</sharedListeners>
</system.diagnostics>

Then I modified my applciaiton to make a simple call to bing:

1
2
3
4
5
var request = (HttpWebRequest)WebRequest.Create(new Uri("http://bing.com"));
using (var stream = new StreamReader(request.GetResponse().GetResponseStream()))
{
    stream.ReadToEnd();
}

And finally I started my application and… wait for it… got throttled on Application Insights endpoint. You can see 5 requests and 1.2K traces:

I looked at couple traces and quickly realized that I fall into recursion. First request to application was collected and generated Application Insights data item. This data item was compressed and sent to Application Insights using http call. This http call produced tons of traces (System.Net is quite chatty trace source). Those traces in turn were grouped into bunch, compressed and… sent using http that produced more http traces. In fact I was throttled even before a call to bing.com was traced ;-). Here is a trace message that helped me figure this out:

1
[1520] HttpWebRequest#65064868 - Request: POST /v2/track HTTP/1.1

One of the reasons why it happened is that in Visual Studio Application Insights works in “developer mode” that ensure data items are sent to portal really quick so you can see your telemetry data almost instantaneously.

Summary

It is very easy to collect traces using Application Insights. However it is important to be cautious of tracing level you configured.