示例#1
0
        private static void InitializeTelemetry(DependencyTelemetry telemetry, Guid operationId, long timestamp)
        {
            telemetry.Start(timestamp);

            var activity = Activity.Current;

            if (activity != null)
            {
                telemetry.Context.Operation.Id       = activity.RootId;
                telemetry.Context.Operation.ParentId = activity.ParentId;

                foreach (var item in activity.Baggage)
                {
                    if (!telemetry.Context.Properties.ContainsKey(item.Key))
                    {
                        telemetry.Context.Properties[item.Key] = item.Value;
                    }
                }
            }
            else
            {
                telemetry.Context.Operation.Id = operationId.ToString("N");
            }
        }
示例#2
0
        public void ValidateBasicDependency(string assemblyName, string requestPath)
        {
            using (InProcessServer server = new InProcessServer(assemblyName))
            {
                DependencyTelemetry expected = new DependencyTelemetry();
                expected.Name       = server.BaseHost + requestPath;
                expected.ResultCode = "200";
                expected.Success    = true;

                DateTimeOffset testStart  = DateTimeOffset.Now;
                var            timer      = Stopwatch.StartNew();
                var            httpClient = new HttpClient();
                var            task       = httpClient.GetAsync(server.BaseHost + requestPath);
                task.Wait(TestTimeoutMs);
                var result = task.Result;

                var actual = server.BackChannel.Buffer.OfType <DependencyTelemetry>().Single();
                timer.Stop();

                Assert.Equal(expected.Name, actual.Name);
                Assert.Equal(expected.Success, actual.Success);
                Assert.Equal(expected.ResultCode, actual.ResultCode);
            }
        }
示例#3
0
        private static void ValidateTelemetryPacket(
            DependencyTelemetry remoteDependencyTelemetryActual,
            string expectedName,
            bool expectedSuccess,
            string expectedResultCode,
            double timeBetweenBeginEndInMs,
            bool async = false)
        {
            Assert.AreEqual(expectedName, remoteDependencyTelemetryActual.Name, true, "Resource name in the sent telemetry is wrong");
            Assert.AreEqual(ExpectedType, remoteDependencyTelemetryActual.Type, "DependencyKind in the sent telemetry is wrong");
            Assert.AreEqual(expectedSuccess, remoteDependencyTelemetryActual.Success, "Success in the sent telemetry is wrong");
            Assert.AreEqual(expectedResultCode, remoteDependencyTelemetryActual.ResultCode, "ResultCode in the sent telemetry is wrong");

            if (!async)
            {
                Assert.IsTrue(remoteDependencyTelemetryActual.Duration.TotalMilliseconds <= timeBetweenBeginEndInMs + 1, "Incorrect duration. Collected " + remoteDependencyTelemetryActual.Duration.TotalMilliseconds + " should be less than max " + timeBetweenBeginEndInMs);
            }

            Assert.IsTrue(remoteDependencyTelemetryActual.Duration.TotalMilliseconds >= 0);

            string expectedVersion = SdkVersionHelper.GetExpectedSdkVersion(typeof(DependencyTrackingTelemetryModule), prefix: "rddp:");

            Assert.AreEqual(expectedVersion, remoteDependencyTelemetryActual.Context.GetInternalContext().SdkVersion);
        }
        protected override async Task <HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

            try
            {
                if (request != null && response != null && (_telemetryClient?.IsEnabled() ?? false))
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        var telemetry = new DependencyTelemetry();
                        telemetry.Type = "Http";
                        telemetry.Data = await request.Content?.ReadAsStringAsync();

                        telemetry.Name       = $"{request.Method.Method} {request.RequestUri.AbsolutePath}";
                        telemetry.Target     = request.RequestUri?.ToString();
                        telemetry.ResultCode = response.StatusCode.ToString();
                        telemetry.Properties.Add("Telemetry Source", "HttpClientAppInsightsHandler");
                        telemetry.Properties.Add("Request Headers", request.Headers.ToString());
                        telemetry.Properties.Add("Request Content Headers", request.Content.Headers.ToString());
                        telemetry.Properties.Add("Response Headers", response.Headers.ToString());
                        telemetry.Properties.Add("Response Body", await response.Content?.ReadAsStringAsync());
                        telemetry.Success = false;
                        _telemetryClient.TrackDependency(telemetry);
                    }
                }
            }
            catch
            {
                // Swallow as we don't want this to break anything.
            }

            return(response);
        }
        /// <summary>
        /// Populates WebRequest using the user, session initialized in telemetry item.
        /// </summary>
        /// <param name="dependencyTelemetry">Dependency telemetry item.</param>
        /// <param name="webRequest">Http web request.</param>
        internal static void SetUserAndSessionContextForWebRequest(DependencyTelemetry dependencyTelemetry, WebRequest webRequest)
        {
            if (dependencyTelemetry == null)
            {
                throw new ArgumentNullException("dependencyTelemetry");
            }

            if (webRequest != null)
            {
                if (dependencyTelemetry.Context.User.Id != null)
                {
                    CreateAndAddCookie(webRequest, WebUserCookieName, dependencyTelemetry.Context.User.Id);
                }

                if (dependencyTelemetry.Context.Session.Id != null)
                {
                    CreateAndAddCookie(webRequest, WebSessionCookieName, dependencyTelemetry.Context.Session.Id);
                }
            }
            else
            {
                DependencyCollectorEventSource.Log.WebRequestIsNullWarning();
            }
        }
        /// <summary>
        /// Track a Cosmos dependency call in Azure Monitor Application Insights
        /// </summary>
        /// <typeparam name="T">The type parameter of the Cosmos Response<typeparamref name="T"/></typeparam>
        /// <param name="telemetry">An initialised TelemetryClient</param>
        /// <param name="response">The Cosmos Response returned</param>
        /// <param name="command">The command text to display in the dependency trace. NOTE: Do not include PII or Secrets</param>
        /// <param name="timestamp">The timestamp for this call. Usually the DateTimeOffset.UtcNow immediately before the dependency call was made.</param>
        /// <param name="duration">The measured duration of the dependency call as TimeSpan</param>
        public static void TrackCosmosDependency <T>(
            this TelemetryClient telemetry,
            Response <T> response,
            string command,
            DateTimeOffset timestamp,
            TimeSpan duration)
        {
            var diagnostics = Diagnostics(response);
            var statistics  = diagnostics.Context.FirstOrDefault(c => c.Id == "StoreResponseStatistics");

            var dependency = new DependencyTelemetry
            {
                Data       = command,
                Duration   = duration,
                Name       = Name(statistics),
                ResultCode = StatusCode(response),
                Timestamp  = timestamp,
                Success    = StatusCodeSuccess(response),
                Target     = statistics?.LocationEndpoint?.Host,
                Type       = "Azure DocumentDB" // This type name will display the Cosmos icon in the UI
            };

            telemetry.TrackDependency(dependency);
        }
示例#7
0
        public void Add(UniqueId messageId, DependencyTelemetry telemetry, TimeSpan timeout)
        {
            if (messageId == null)
            {
                throw new ArgumentNullException(nameof(messageId));
            }

            if (telemetry == null)
            {
                throw new ArgumentNullException(nameof(telemetry));
            }

            lock (this.lockObject)
            {
                if (this.disposed)
                {
                    throw new ObjectDisposedException(nameof(MessageCorrelator));
                }

                var pending = new PendingMessage(messageId, telemetry);
                this.pendingMessages[messageId.ToString()] = pending;
                pending.Start(timeout, this.OnTimeout);
            }
        }
示例#8
0
        private void ModifyDependencyItem(DependencyTelemetry dependencyTelemetryItem)
        {
            // Obfuscate the hashed email address from Gravatar URLs.
            if (!dependencyTelemetryItem.Type.Equals(HttpDependencyType, StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            if (!Uri.TryCreate(dependencyTelemetryItem.Data, UriKind.Absolute, out var uri))
            {
                return;
            }

            if (!uri.Host.EndsWith("gravatar.com") || !uri.AbsolutePath.StartsWith("/avatar/"))
            {
                return;
            }

            var builder = new UriBuilder(uri);

            builder.Path = "/avatar/Obfuscated";
            dependencyTelemetryItem.Name = "GET /avatar/Obfuscated";
            dependencyTelemetryItem.Data = builder.Uri.ToString();
        }
示例#9
0
        private void ValidateTelemetryForDiagnosticSource(
            DependencyTelemetry item,
            Uri url,
            WebRequest requestMsg,
            bool expectLegacyHeaders,
            bool expectW3CHeaders,
            bool expectRequestId)
        {
            var expectedMethod = requestMsg != null ? requestMsg.Method : "GET";

            Assert.AreEqual(expectedMethod + " " + url.AbsolutePath, item.Name);

            Assert.AreEqual(
                SdkVersionHelper.GetExpectedSdkVersion(typeof(DependencyTrackingTelemetryModule), "rdddsd:"),
                item.Context.GetInternalContext().SdkVersion);

            var requestId = item.Id;

            if (requestMsg != null)
            {
                if (expectW3CHeaders)
                {
                    var traceId             = item.Context.Operation.Id;
                    var spanId              = requestId.Substring(34, 16);
                    var expectedTraceparent = $"00-{traceId}-{spanId}-00";

                    Assert.AreEqual(expectedTraceparent, requestMsg.Headers[W3C.W3CConstants.TraceParentHeader]);
                    Assert.AreEqual(Activity.Current?.TraceStateString, requestMsg.Headers[W3C.W3CConstants.TraceStateHeader]);
                }
                else
                {
                    Assert.IsNull(requestMsg.Headers[W3C.W3CConstants.TraceParentHeader]);
                    Assert.IsNull(requestMsg.Headers[W3C.W3CConstants.TraceStateHeader]);
                }

                if (expectRequestId)
                {
                    Assert.AreEqual(requestId, requestMsg.Headers[RequestResponseHeaders.RequestIdHeader]);
                }
                else
                {
                    Assert.IsNull(requestMsg.Headers[RequestResponseHeaders.RequestIdHeader]);
                }

                if (expectLegacyHeaders)
                {
                    Assert.AreEqual(requestId, requestMsg.Headers[RequestResponseHeaders.StandardParentIdHeader]);
                    Assert.AreEqual(item.Context.Operation.Id, requestMsg.Headers[RequestResponseHeaders.StandardRootIdHeader]);
                }
                else
                {
                    Assert.IsNull(requestMsg.Headers[RequestResponseHeaders.StandardParentIdHeader]);
                    Assert.IsNull(requestMsg.Headers[RequestResponseHeaders.StandardRootIdHeader]);
                }

                if (Activity.Current != null)
                {
                    var correlationContextHeader = requestMsg.Headers[RequestResponseHeaders.CorrelationContextHeader]
                                                   .Split(',');

                    var baggage = Activity.Current.Baggage.Select(kvp => $"{kvp.Key}={kvp.Value}").ToArray();
                    Assert.AreEqual(baggage.Length, correlationContextHeader.Length);

                    foreach (var baggageItem in baggage)
                    {
                        Assert.IsTrue(correlationContextHeader.Contains(baggageItem));
                    }
                }
                else
                {
                    Assert.IsNull(requestMsg.Headers[RequestResponseHeaders.CorrelationContextHeader]);
                }
            }
        }
示例#10
0
        public void TestDependencyCollectionNoParentActivity()
        {
            ITelemetry sentTelemetry = null;

            var channel = new StubTelemetryChannel
            {
                OnSend = telemetry =>
                {
                    // The correlation id lookup service also makes http call, just make sure we skip that
                    DependencyTelemetry depTelemetry = telemetry as DependencyTelemetry;
                    if (depTelemetry != null &&
                        !depTelemetry.Data.StartsWith(FakeProfileApiEndpoint, StringComparison.OrdinalIgnoreCase))
                    {
                        Assert.IsNull(sentTelemetry);
                        sentTelemetry = telemetry;
                    }
                }
            };

            var config = new TelemetryConfiguration
            {
                InstrumentationKey = IKey,
                TelemetryChannel   = channel
            };

            config.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());

            using (var module = new DependencyTrackingTelemetryModule())
            {
                module.ProfileQueryEndpoint = FakeProfileApiEndpoint;
                module.Initialize(config);

                var            url     = new Uri("http://bing.com");
                HttpWebRequest request = WebRequest.CreateHttp(url);
                request.GetResponse();

                Assert.IsNotNull(sentTelemetry);
                var item = (DependencyTelemetry)sentTelemetry;
                Assert.AreEqual(url, item.Data);
                Assert.AreEqual(url.Host, item.Target);
                Assert.AreEqual("GET " + url.AbsolutePath, item.Name);
                Assert.IsTrue(item.Duration > TimeSpan.FromMilliseconds(0), "Duration has to be positive");
                Assert.AreEqual(RemoteDependencyConstants.HTTP, item.Type, "HttpAny has to be dependency kind as it includes http and azure calls");
                Assert.IsTrue(
                    DateTime.UtcNow.Subtract(item.Timestamp.UtcDateTime).TotalMilliseconds <
                    TimeSpan.FromMinutes(1).TotalMilliseconds,
                    "timestamp < now");
                Assert.IsTrue(
                    item.Timestamp.Subtract(DateTime.UtcNow).TotalMilliseconds >
                    -TimeSpan.FromMinutes(1).TotalMilliseconds,
                    "now - 1 min < timestamp");
                Assert.AreEqual("200", item.ResultCode);

                var requestId = item.Id;
                Assert.AreEqual(requestId, request.Headers["Request-Id"]);
                Assert.AreEqual(requestId, request.Headers["x-ms-request-id"]);
                Assert.IsTrue(requestId.StartsWith('|' + item.Context.Operation.Id + '.'));

                Assert.IsNull(request.Headers["Correlation-Context"]);
            }
        }
示例#11
0
 private void ValidateSentTelemetry(DependencyTelemetry telemetry)
 {
     Assert.AreEqual(telemetry.Timestamp, telemetry.Timestamp);
     Assert.IsTrue(telemetry.Duration.Milliseconds >= 0);
 }
示例#12
0
        public OpenAsyncResult(IChannel innerChannel, TimeSpan timeout, AsyncCallback onOpenDone, AsyncCallback callback, object state, DependencyTelemetry telemetry)
            : base(onOpenDone, callback, state, telemetry)
        {
            this.InnerChannel = innerChannel;

            var originalResult = innerChannel.BeginOpen(timeout, OnComplete, this);

            if (originalResult.CompletedSynchronously)
            {
                innerChannel.EndOpen(originalResult);
                this.CompleteSynchronously();
            }
        }
        public RequestAsyncResult(IRequestChannel innerChannel, Message message, TimeSpan timeout, AsyncCallback onRequestDone, AsyncCallback callback, object state, DependencyTelemetry telemetry)
            : base(onRequestDone, callback, state, telemetry)
        {
            this.InnerChannel = innerChannel;

            this.OriginalResult = innerChannel.BeginRequest(message, timeout, OnComplete, this);
            if (this.OriginalResult.CompletedSynchronously)
            {
                this.Reply = innerChannel.EndRequest(this.OriginalResult);
                this.CompleteSynchronously();
            }
        }
 private static void SetStatusCode(DependencyTelemetry telemetry, int statusCode)
 {
     telemetry.ResultCode = statusCode > 0 ? statusCode.ToString(CultureInfo.InvariantCulture) : string.Empty;
     telemetry.Success    = (statusCode > 0) && (statusCode < 400);
 }
示例#15
0
        private static void SerializeTelemetryItem(ITelemetry telemetryItem, JsonSerializationWriter jsonSerializationWriter)
        {
            jsonSerializationWriter.WriteStartObject();

            if (telemetryItem is EventTelemetry)
            {
                EventTelemetry eventTelemetry = telemetryItem as EventTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, eventTelemetry.Data.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, eventTelemetry.BaseType, EventTelemetry.TelemetryName);
            }
            else if (telemetryItem is ExceptionTelemetry)
            {
                ExceptionTelemetry exTelemetry = telemetryItem as ExceptionTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, exTelemetry.Data.Data.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, exTelemetry.BaseType, ExceptionTelemetry.TelemetryName);
            }
            else if (telemetryItem is MetricTelemetry)
            {
                MetricTelemetry mTelemetry = telemetryItem as MetricTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, mTelemetry.Data.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, mTelemetry.BaseType, MetricTelemetry.TelemetryName);
            }
            else if (telemetryItem is PageViewTelemetry)
            {
                PageViewTelemetry pvTelemetry = telemetryItem as PageViewTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, pvTelemetry.Data.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, pvTelemetry.BaseType, PageViewTelemetry.TelemetryName);
            }
            else if (telemetryItem is PageViewPerformanceTelemetry)
            {
                PageViewPerformanceTelemetry pvptelemetry = telemetryItem as PageViewPerformanceTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, pvptelemetry.Data.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, PageViewPerformanceTelemetry.BaseType, PageViewPerformanceTelemetry.TelemetryName);
            }
            else if (telemetryItem is DependencyTelemetry)
            {
                DependencyTelemetry depTelemetry = telemetryItem as DependencyTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, depTelemetry.InternalData.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, depTelemetry.BaseType, DependencyTelemetry.TelemetryName);
            }
            else if (telemetryItem is RequestTelemetry)
            {
                RequestTelemetry reqTelemetry = telemetryItem as RequestTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, reqTelemetry.Data.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, reqTelemetry.BaseType, RequestTelemetry.TelemetryName);
            }
#pragma warning disable 618
            else if (telemetryItem is PerformanceCounterTelemetry)
            {
                PerformanceCounterTelemetry pcTelemetry = telemetryItem as PerformanceCounterTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, pcTelemetry.Properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, pcTelemetry.Data.BaseType, MetricTelemetry.TelemetryName);
            }
            else if (telemetryItem is SessionStateTelemetry)
            {
                SessionStateTelemetry ssTelemetry = telemetryItem as SessionStateTelemetry;
                SerializeHelper(telemetryItem, jsonSerializationWriter, ssTelemetry.Data.BaseType, EventTelemetry.TelemetryName);
            }
#pragma warning restore 618
            else if (telemetryItem is TraceTelemetry)
            {
                TraceTelemetry traceTelemetry = telemetryItem as TraceTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, traceTelemetry.Data.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, traceTelemetry.BaseType, TraceTelemetry.TelemetryName);
            }
            else if (telemetryItem is AvailabilityTelemetry)
            {
                AvailabilityTelemetry availabilityTelemetry = telemetryItem as AvailabilityTelemetry;
                Utils.CopyDictionary(telemetryItem.Context.GlobalProperties, availabilityTelemetry.Data.properties);

                SerializeHelper(telemetryItem, jsonSerializationWriter, availabilityTelemetry.BaseType, AvailabilityTelemetry.TelemetryName);
            }
            else
            {
                string msg = string.Format(CultureInfo.InvariantCulture, "Unknown telemetry type: {0}", telemetryItem.GetType());
                CoreEventSource.Log.LogVerbose(msg);
            }

            jsonSerializationWriter.WriteEndObject();
        }
        public void QuickPulseTelemetryModuleSupportsMultipleTelemetryProcessorsForMultipleConfigurations()
        {
            if (QuickPulseTelemetryModuleTests.Ignored)
            {
                return;
            }

            // ARRANGE
            var pollingInterval           = TimeSpan.FromMilliseconds(1);
            var collectionInterval        = TimeSpan.FromMilliseconds(1);
            var timings                   = new QuickPulseTimings(pollingInterval, collectionInterval);
            var collectionTimeSlotManager = new QuickPulseCollectionTimeSlotManagerMock(timings);

            CollectionConfigurationError[] errors;
            var accumulatorManager =
                new QuickPulseDataAccumulatorManager(
                    new CollectionConfiguration(
                        new CollectionConfigurationInfo()
            {
                ETag = string.Empty, Metrics = new CalculatedMetricInfo[0]
            },
                        out errors,
                        new ClockMock()));
            var serviceClient = new QuickPulseServiceClientMock {
                ReturnValueFromPing = true, ReturnValueFromSubmitSample = true
            };
            var performanceCollector = new PerformanceCollectorMock();
            var topCpuCollector      = new QuickPulseTopCpuCollectorMock();

            var module = new QuickPulseTelemetryModule(
                collectionTimeSlotManager,
                accumulatorManager,
                serviceClient,
                performanceCollector,
                topCpuCollector,
                timings);

            const int TelemetryProcessorCount = 4;

            var ikey   = "some ikey";
            var config = new TelemetryConfiguration {
                InstrumentationKey = ikey
            };

            // spawn a bunch of configurations, each one having an individual instance of QuickPulseTelemetryProcessor
            var telemetryProcessors = new List <QuickPulseTelemetryProcessor>();

            for (int i = 0; i < TelemetryProcessorCount; i++)
            {
                var configuration = new TelemetryConfiguration();
                var builder       = configuration.TelemetryProcessorChainBuilder;
                builder = builder.Use(current => new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()));
                builder.Build();

                telemetryProcessors.Add(configuration.TelemetryProcessors.OfType <QuickPulseTelemetryProcessor>().Single());
            }

            // ACT
            foreach (var telemetryProcessor in telemetryProcessors)
            {
                module.RegisterTelemetryProcessor(telemetryProcessor);
            }

            module.Initialize(config);

            Thread.Sleep(TimeSpan.FromMilliseconds(100));

            // send data to each instance of QuickPulseTelemetryProcessor
            var request = new RequestTelemetry()
            {
                ResponseCode = "200", Success = true, Context = { InstrumentationKey = ikey }
            };

            telemetryProcessors[0].Process(request);

            request = new RequestTelemetry()
            {
                ResponseCode = "500", Success = false, Context = { InstrumentationKey = ikey }
            };
            telemetryProcessors[1].Process(request);

            var dependency = new DependencyTelemetry()
            {
                Success = true, Context = { InstrumentationKey = ikey }
            };

            telemetryProcessors[2].Process(dependency);

            dependency = new DependencyTelemetry()
            {
                Success = false, Context = { InstrumentationKey = ikey }
            };
            telemetryProcessors[3].Process(dependency);

            Thread.Sleep(TimeSpan.FromMilliseconds(100));

            // ASSERT
            // verify that every telemetry processor has contributed to the accumulator
            int samplesWithSomeRequests     = serviceClient.SnappedSamples.Count(s => s.AIRequestsPerSecond > 0);
            int samplesWithSomeDependencies = serviceClient.SnappedSamples.Count(s => s.AIDependencyCallsPerSecond > 0);

            Assert.AreEqual(TelemetryProcessorCount, QuickPulseTestHelper.GetTelemetryProcessors(module).Count);
            Assert.IsTrue(samplesWithSomeRequests > 0 && samplesWithSomeRequests <= 2);
            Assert.AreEqual(1, serviceClient.SnappedSamples.Count(s => s.AIRequestsFailedPerSecond > 0));
            Assert.IsTrue(samplesWithSomeDependencies > 0 && samplesWithSomeDependencies < 2);
            Assert.AreEqual(1, serviceClient.SnappedSamples.Count(s => s.AIDependencyCallsFailedPerSecond > 0));
        }
        public void HttpDependenciesParsingTelemetryInitializerConvertsBlobs()
        {
            HttpDependenciesParsingTelemetryInitializer initializer = new HttpDependenciesParsingTelemetryInitializer();
            var d = new DependencyTelemetry(RemoteDependencyConstants.HTTP, "tofinthyperion2dets001.blob.core.windows.net", "GET /observations-v01-1410//ecaf8435-5395-434f-b1e2-f06cd5703792/K0000000102-R1623814285-T3804215385-C3804215385/16/2100", "https://tofinthyperion2dets001.blob.core.windows.net/observations-v01-1410//ecaf8435-5395-434f-b1e2-f06cd5703792/K0000000102-R1623814285-T3804215385-C3804215385/16/2100?comp=page&timeout=3");
            initializer.Initialize(d);
            Assert.AreEqual(RemoteDependencyConstants.AzureBlob, d.Type);
            Assert.AreEqual("tofinthyperion2dets001.blob.core.windows.net", d.Target);
            Assert.AreEqual("GET tofinthyperion2dets001/observations-v01-1410", d.Name);

            var testCases = new List<string[]>()
            {
                ////
                //// copied from https://msdn.microsoft.com/en-us/library/azure/dd135733.aspx 9/29/2016
                ////

                new string[5] { "List Containers",                  "GET",      "https://myaccount.blob.core.windows.net/?comp=list",                                                           "myaccount", string.Empty },
                new string[5] { "Set Blob Service Properties",      "PUT",      "https://myaccount.blob.core.windows.net/?restype=service&comp=properties",                                     "myaccount", string.Empty },
                new string[5] { "Get Blob Service Properties",      "GET",      "https://myaccount.blob.core.windows.net/?restype=service&comp=properties",                                     "myaccount", string.Empty },
                new string[5] { "Preflight Blob Request",           "OPTIONS",  "http://myaccount.blob.core.windows.net/mycontainer/myblockblob",                                               "myaccount", "mycontainer" },
                new string[5] { "Get Blob Service Stats",           "GET",      "https://myaccount.blob.core.windows.net/?restype=service&comp=stats",                                          "myaccount", string.Empty },
                new string[5] { "Create Container",                 "PUT",      "https://myaccount.blob.core.windows.net/mycontainer?restype=container",                                        "myaccount", "mycontainer" },
                new string[5] { "Get Container Properties",         "GET",      "https://myaccount.blob.core.windows.net/mycontainer?restype=container",                                        "myaccount", "mycontainer" },
                new string[5] { "Get Container Properties",         "HEAD",     "https://myaccount.blob.core.windows.net/mycontainer?restype=container",                                        "myaccount", "mycontainer" },
                new string[5] { "Get Container Metadata",           "GET",      "https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=metadata",                          "myaccount", "mycontainer" },
                new string[5] { "Get Container Metadata",           "HEAD",     "https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=metadata",                          "myaccount", "mycontainer" },
                new string[5] { "Set Container Metadata",           "PUT",      "https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=metadata",                          "myaccount", "mycontainer" },
                new string[5] { "Get Container ACL",                "GET",      "https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=acl",                               "myaccount", "mycontainer" },
                new string[5] { "Get Container ACL",                "HEAD",     "https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=acl",                               "myaccount", "mycontainer" },
                new string[5] { "Set Container ACL",                "PUT",      "https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=acl",                               "myaccount", "mycontainer" },
                new string[5] { "Lease Container",                  "PUT",      "https://myaccount.blob.core.windows.net/mycontainer?comp=lease&restype=container",                             "myaccount", "mycontainer" },
                new string[5] { "Delete Container",                 "DELETE",   "https://myaccount.blob.core.windows.net/mycontainer?restype=container",                                        "myaccount", "mycontainer" },
                new string[5] { "List Blobs",                       "GET",      "https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=list",                              "myaccount", "mycontainer" },
                new string[5] { "Put Blob",                         "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob",                                                   "myaccount", "mycontainer" },
                new string[5] { "Get Blob",                         "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob",                                                   "myaccount", "mycontainer" },
                new string[5] { "Get Blob",                         "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?snapshot=DateTime",                                 "myaccount", "mycontainer" },
                new string[5] { "Get Blob Properties",              "HEAD",     "https://myaccount.blob.core.windows.net/mycontainer/myblob",                                                   "myaccount", "mycontainer" },
                new string[5] { "Get Blob Properties",              "HEAD",     "https://myaccount.blob.core.windows.net/mycontainer/myblob?snapshot=DateTime",                                 "myaccount", "mycontainer" },
                new string[5] { "Set Blob Properties",              "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=properties",                                   "myaccount", "mycontainer" },
                new string[5] { "Get Blob Metadata",                "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=metadata",                                     "myaccount", "mycontainer" },
                new string[5] { "Get Blob Metadata",                "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=metadata&snapshot=DateTime",                   "myaccount", "mycontainer" },
                new string[5] { "Get Blob Metadata",                "HEAD",     "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=metadata",                                     "myaccount", "mycontainer" },
                new string[5] { "Get Blob Metadata",                "HEAD",     "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=metadata&snapshot=DateTime",                   "myaccount", "mycontainer" },
                new string[5] { "Set Blob Metadata",                "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=metadata",                                     "myaccount", "mycontainer" },
                new string[5] { "Delete Blob",                      "DELETE",   "https://myaccount.blob.core.windows.net/mycontainer/myblob",                                                   "myaccount", "mycontainer" },
                new string[5] { "Delete Blob",                      "DELETE",   "https://myaccount.blob.core.windows.net/mycontainer/myblob?snapshot=DateTime",                                 "myaccount", "mycontainer" },
                new string[5] { "Lease Blob",                       "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=lease",                                        "myaccount", "mycontainer" },
                new string[5] { "Snapshot Blob",                    "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=snapshot",                                     "myaccount", "mycontainer" },
                new string[5] { "Copy Blob",                        "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob",                                                   "myaccount", "mycontainer" },
                new string[5] { "Abort Copy Blob",                  "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=copy&copyid=id",                               "myaccount", "mycontainer" },
                new string[5] { "Put Block",                        "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=block&blockid=id",                             "myaccount", "mycontainer" },
                new string[5] { "Put Block List",                   "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=blocklist",                                    "myaccount", "mycontainer" },
                new string[5] { "Get Block List",                   "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=blocklist",                                    "myaccount", "mycontainer" },
                new string[5] { "Get Block List",                   "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=blocklist&snapshot=DateTime",                  "myaccount", "mycontainer" },
                new string[5] { "Put Page",                         "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=page",                                         "myaccount", "mycontainer" },
                new string[5] { "Get Page Ranges",                  "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=pagelist",                                     "myaccount", "mycontainer" },
                new string[5] { "Get Page Ranges",                  "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=pagelist&snapshot=DateTime",                   "myaccount", "mycontainer" },
                new string[5] { "Get Page Ranges",                  "GET",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=pagelist&snapshot=DateTime&prevsnapshot=Date", "myaccount", "mycontainer" },
                new string[5] { "Append Block",                     "PUT",      "https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=appendblock",                                  "myaccount", "mycontainer" }
            };

            foreach (var testCase in testCases)
            {
                this.HttpDependenciesParsingTelemetryInitializerConvertsBlobs(testCase[0], testCase[1], testCase[2], testCase[3], testCase[4]);
            }
        }
 /// <summary>
 /// Implemented by the derived class for adding the tuple to its specific cache.
 /// </summary>
 /// <param name="webRequest">The request which acts the key.</param>
 /// <param name="telemetry">The dependency telemetry for the tuple.</param>
 /// <param name="isCustomCreated">Boolean value that tells if the current telemetry item is being added by the customer or not.</param>
 protected abstract void AddTupleForWebDependencies(WebRequest webRequest, DependencyTelemetry telemetry, bool isCustomCreated);
        private void HttpDependenciesParsingTelemetryInitializerConvertsServices(string verb, string url, string expectedType, string expectedName)
        {
            HttpDependenciesParsingTelemetryInitializer initializer = new HttpDependenciesParsingTelemetryInitializer();
            Uri parsedUrl = new Uri(url);

            // Parse with verb
            var d = new DependencyTelemetry(
                dependencyTypeName: RemoteDependencyConstants.HTTP,
                target: parsedUrl.Host,
                dependencyName: verb + " " + parsedUrl.AbsolutePath,
                data: parsedUrl.OriginalString);

            initializer.Initialize(d);

            Assert.AreEqual(expectedType, d.Type);
            Assert.AreEqual(parsedUrl.Host, d.Target);
            Assert.AreEqual(verb + " " + expectedName, d.Name);

            // Parse without verb
            d = new DependencyTelemetry(
                dependencyTypeName: RemoteDependencyConstants.HTTP,
                target: parsedUrl.Host,
                dependencyName: parsedUrl.AbsolutePath,
                data: parsedUrl.OriginalString);

            initializer.Initialize(d);

            Assert.AreEqual(expectedType, d.Type);
            Assert.AreEqual(parsedUrl.Host, d.Target);
            Assert.AreEqual(expectedName, d.Name);
        }
        /// <summary>
        /// Common helper for all Begin Callbacks.
        /// </summary>
        /// <param name="thisObj">This object.</param>
        /// <param name="injectCorrelationHeaders">Flag that enables Request-Id and Correlation-Context headers injection.
        /// Should be set to true only for profiler and old versions of DiagnosticSource Http hook events.</param>
        /// <returns>Null object as all context is maintained in this class via weak tables.</returns>
        internal object OnBegin(object thisObj, bool injectCorrelationHeaders = true)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return(null);
                }

                WebRequest webRequest = thisObj as WebRequest;
                if (webRequest == null)
                {
                    DependencyCollectorEventSource.Log.UnexpectedCallbackParameter("WebRequest");
                }

                var url = GetUrl(webRequest);
                if (url == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(thisObj.GetHashCode(), "OnBeginHttp",
                                                                           "resourceName is empty");
                    return(null);
                }

                string httpMethod   = webRequest.Method;
                string resourceName = url.AbsolutePath;

                if (!string.IsNullOrEmpty(httpMethod))
                {
                    resourceName = httpMethod + " " + resourceName;
                }

                DependencyCollectorEventSource.Log.BeginCallbackCalled(thisObj.GetHashCode(), resourceName);

                if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(url))
                {
                    // Not logging as we will be logging for all outbound AI calls
                    return(null);
                }

                if (webRequest.Headers[W3C.W3CConstants.TraceParentHeader] != null && Activity.DefaultIdFormat == ActivityIdFormat.W3C)
                {
                    DependencyCollectorEventSource.Log.HttpRequestAlreadyInstrumented();
                    return(null);
                }

                // If the object already exists, don't add again. This happens because either GetResponse or GetRequestStream could
                // be the starting point for the outbound call.
                DependencyTelemetry telemetry = null;
                var telemetryTuple            = this.GetTupleForWebDependencies(webRequest);
                if (telemetryTuple?.Item1 != null)
                {
                    DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                    return(null);
                }

                // Create and initialize a new telemetry object
                telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                this.AddTupleForWebDependencies(webRequest, telemetry, false);

                if (string.IsNullOrEmpty(telemetry.Context.InstrumentationKey))
                {
                    // Instrumentation key is probably empty, because the context has not yet had a chance to associate the requestTelemetry to the telemetry client yet.
                    // and get they instrumentation key from all possible sources in the process. Let's do that now.
                    this.telemetryClient.InitializeInstrumentationKey(telemetry);
                }

                telemetry.Name   = resourceName;
                telemetry.Target = DependencyTargetNameHelper.GetDependencyTargetName(url);
                telemetry.Type   = RemoteDependencyConstants.HTTP;
                telemetry.Data   = url.OriginalString;
                telemetry.SetOperationDetail(RemoteDependencyConstants.HttpRequestOperationDetailName, webRequest);

                Activity currentActivity = Activity.Current;
                // Add the source instrumentation key header if collection is enabled, the request host is not in the excluded list and the same header doesn't already exist
                if (this.setCorrelationHeaders && !this.correlationDomainExclusionList.Contains(url.Host))
                {
                    string applicationId = null;
                    try
                    {
                        if (!string.IsNullOrEmpty(telemetry.Context.InstrumentationKey) &&
                            webRequest.Headers.GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader,
                                                                       RequestResponseHeaders.RequestContextCorrelationSourceKey) == null &&
                            (this.configuration.ApplicationIdProvider?.TryGetApplicationId(
                                 telemetry.Context.InstrumentationKey, out applicationId) ?? false))
                        {
                            webRequest.Headers.SetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader,
                                                                       RequestResponseHeaders.RequestContextCorrelationSourceKey, applicationId);
                        }
                    }
                    catch (Exception ex)
                    {
                        AppMapCorrelationEventSource.Log.SetCrossComponentCorrelationHeaderFailed(
                            ex.ToInvariantString());
                    }

                    if (this.injectLegacyHeaders)
                    {
                        // Add the root ID
                        var rootId = telemetry.Context.Operation.Id;
                        if (!string.IsNullOrEmpty(rootId) &&
                            webRequest.Headers[RequestResponseHeaders.StandardRootIdHeader] == null)
                        {
                            webRequest.Headers.Add(RequestResponseHeaders.StandardRootIdHeader, rootId);
                        }

                        // Add the parent ID
                        var parentId = telemetry.Id;
                        if (!string.IsNullOrEmpty(parentId))
                        {
                            if (webRequest.Headers[RequestResponseHeaders.StandardParentIdHeader] == null)
                            {
                                webRequest.Headers.Add(RequestResponseHeaders.StandardParentIdHeader, parentId);
                            }
                        }
                    }

                    if (currentActivity != null)
                    {
                        // ApplicationInsights only needs to inject W3C, potentially Request-Id and Correlation-Context
                        // headers for profiler instrumentation.
                        // in case of Http Desktop DiagnosticSourceListener they are injected in
                        // DiagnosticSource (with the System.Net.Http.Desktop.HttpRequestOut.Start event)
                        if (injectCorrelationHeaders)
                        {
                            if (currentActivity.IdFormat == ActivityIdFormat.W3C)
                            {
                                if (webRequest.Headers[W3C.W3CConstants.TraceParentHeader] == null)
                                {
                                    webRequest.Headers.Add(W3C.W3CConstants.TraceParentHeader, currentActivity.Id);
                                }

                                if (webRequest.Headers[W3C.W3CConstants.TraceStateHeader] == null &&
                                    !string.IsNullOrEmpty(currentActivity.TraceStateString))
                                {
                                    webRequest.Headers.Add(W3C.W3CConstants.TraceStateHeader,
                                                           currentActivity.TraceStateString);
                                }
                            }
                            else
                            {
                                // Request-Id format
                                if (webRequest.Headers[RequestResponseHeaders.RequestIdHeader] == null)
                                {
                                    webRequest.Headers.Add(RequestResponseHeaders.RequestIdHeader, telemetry.Id);
                                }
                            }

                            InjectCorrelationContext(webRequest.Headers, currentActivity);
                        }
                    }
                }

                // Active bug in .NET Fx diagnostics hook: https://github.com/dotnet/corefx/pull/40777
                // Application Insights has to inject Request-Id to work it around
                if (currentActivity?.IdFormat == ActivityIdFormat.W3C)
                {
                    // if (this.injectRequestIdInW3CMode)
                    {
                        if (webRequest.Headers[RequestResponseHeaders.RequestIdHeader] == null)
                        {
                            webRequest.Headers.Add(RequestResponseHeaders.RequestIdHeader, string.Concat('|', telemetry.Context.Operation.Id, '.', telemetry.Id, '.'));
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(),
                                                                 "OnBeginHttp", exception);
            }
            finally
            {
                Activity current = Activity.Current;
                if (current?.OperationName == ClientServerDependencyTracker.DependencyActivityName)
                {
                    current.Stop();
                }
            }

            return(null);
        }
        public void HttpDependenciesParsingTelemetryInitializerConvertsBlobs(string operation, string verb, string url, string accountName, string container)
        {
            HttpDependenciesParsingTelemetryInitializer initializer = new HttpDependenciesParsingTelemetryInitializer();
            Uri parsedUrl = new Uri(url);

            // Parse with verb
            var d = new DependencyTelemetry(
                dependencyTypeName: RemoteDependencyConstants.HTTP,
                target: parsedUrl.Host,
                dependencyName: verb + " " + parsedUrl.AbsolutePath,
                data: parsedUrl.OriginalString);

            initializer.Initialize(d);

            Assert.AreEqual(RemoteDependencyConstants.AzureBlob, d.Type, operation);
            Assert.AreEqual(parsedUrl.Host, d.Target, operation);
            Assert.AreEqual(verb + " " + accountName + "/" + container, d.Name, operation);

            // Parse without verb
            d = new DependencyTelemetry(
                dependencyTypeName: RemoteDependencyConstants.HTTP,
                target: parsedUrl.Host,
                dependencyName: parsedUrl.AbsolutePath,
                data: parsedUrl.OriginalString);

            initializer.Initialize(d);

            Assert.AreEqual(RemoteDependencyConstants.AzureBlob, d.Type, operation);
            Assert.AreEqual(parsedUrl.Host, d.Target, operation);
            Assert.AreEqual(accountName + "/" + container, d.Name, operation);
        }
示例#22
0
        internal void OnCommandStarted(CommandStartedEvent evt)
        {
            Prune(DateTime.UtcNow);

            if (_settings.FilteredCommands.Contains(evt.CommandName))
            {
                return;
            }

            var target         = $"{FormatEndPoint(evt.ConnectionId.ServerId.EndPoint)} | {evt.DatabaseNamespace}";
            var dependencyName = $"{target} | {evt.CommandName}";

            var commandText = string.Empty;

            if (_settings.EnableMongoCommandTextInstrumentation)
            {
                // Command can't be null -- the CommandStartedEvent constructor throws to prevent this
                commandText = evt.Command.ToString();
            }

            var telemetry = new DependencyTelemetry()
            {
                Name    = dependencyName,
                Type    = "MongoDB",
                Target  = target,
                Data    = commandText,
                Success = true,
            };

            telemetry.GenerateOperationId();
            telemetry.Timestamp = DateTimeOffset.UtcNow;

            /*
             * copying implementation below from Microsoft's SqlClientDiagnosticSourceListener
             * https://github.com/microsoft/ApplicationInsights-dotnet/blob/5ac6bb98d04b7da6d151c0338efece4c124c750a/WEB/Src/DependencyCollector/DependencyCollector/Implementation/SqlClientDiagnostics/SqlClientDiagnosticSourceListener.cs#L347
             */

            var activity = Activity.Current;

            if (activity != null)
            {
                // for web applications the IdFormat is W3C so without the below check the parient ID is set incorrectly
                if (activity.IdFormat == ActivityIdFormat.W3C)
                {
                    var traceId = activity.TraceId.ToHexString();
                    telemetry.Context.Operation.Id       = traceId;
                    telemetry.Context.Operation.ParentId = activity.SpanId.ToHexString();
                }
                else
                {
                    telemetry.Context.Operation.Id       = activity.RootId;
                    telemetry.Context.Operation.ParentId = activity.Id;
                }

                foreach (var item in activity.Baggage)
                {
                    if (!telemetry.Properties.ContainsKey(item.Key))
                    {
                        telemetry.Properties[item.Key] = item.Value;
                    }
                }
            }
            else
            {
                telemetry.Context.Operation.Id = telemetry.Id;
            }

            var query = new CachedQuery {
                CachedAt = DateTime.UtcNow, Telemetry = telemetry
            };

            _queryCache.TryAdd(evt.RequestId, query);
        }
        /// <summary>
        /// Send information about external dependency call in the application.
        /// </summary>
        public void TrackDependency(DependencyTelemetry telemetry)
        {
            if (telemetry == null)
            {
                telemetry = new DependencyTelemetry();
            }

            this.Track(telemetry);
        }
        //// netcoreapp 2.0 event

        /// <summary>
        /// Handler for Activity stop event (response is received for the outgoing request).
        /// </summary>
        internal void OnActivityStop(HttpResponseMessage response, HttpRequestMessage request, TaskStatus requestTaskStatus)
        {
            // Even though we have the IsEnabled filter to reject ApplicationInsights URLs before any events are fired, if there
            // are multiple subscribers and one subscriber returns true to IsEnabled then all subscribers will receive the event.
            if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(request.RequestUri))
            {
                return;
            }

            Activity currentActivity = Activity.Current;

            if (currentActivity == null)
            {
                DependencyCollectorEventSource.Log.CurrentActivityIsNull(HttpOutStopEventName);
                return;
            }

            DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerStop(currentActivity.Id);

            Uri requestUri   = request.RequestUri;
            var resourceName = request.Method.Method + " " + requestUri.AbsolutePath;

            DependencyTelemetry telemetry = new DependencyTelemetry();

            // properly fill dependency telemetry operation context: OperationCorrelationTelemetryInitializer initializes child telemetry
            telemetry.Context.Operation.Id       = currentActivity.RootId;
            telemetry.Context.Operation.ParentId = currentActivity.ParentId;
            telemetry.Id = currentActivity.Id;
            foreach (var item in currentActivity.Baggage)
            {
                if (!telemetry.Context.Properties.ContainsKey(item.Key))
                {
                    telemetry.Context.Properties[item.Key] = item.Value;
                }
            }

            this.client.Initialize(telemetry);

            telemetry.Timestamp = currentActivity.StartTimeUtc;
            telemetry.Name      = resourceName;
            telemetry.Target    = requestUri.Host;
            telemetry.Type      = RemoteDependencyConstants.HTTP;
            telemetry.Data      = requestUri.OriginalString;
            telemetry.Duration  = currentActivity.Duration;
            if (response != null)
            {
                this.ParseResponse(response, telemetry);
            }
            else
            {
                Exception exception;
                if (this.pendingExceptions.TryRemove(currentActivity.Id, out exception))
                {
                    telemetry.Context.Properties[DependencyErrorPropertyKey] = exception.GetBaseException().Message;
                }

                telemetry.ResultCode = requestTaskStatus.ToString();
                telemetry.Success    = false;
            }

            this.client.Track(telemetry);
        }
        private static void SerializeDependencyTelemetry(DependencyTelemetry dependencyTelemetry, JsonWriter writer)
        {
            writer.WriteStartObject();

            dependencyTelemetry.WriteTelemetryName(writer, DependencyTelemetry.TelemetryName);
            dependencyTelemetry.WriteEnvelopeProperties(writer);
            writer.WritePropertyName("data");
            {
                writer.WriteStartObject();

                // TODO: DependencyTelemetry should write type as this.data.baseType once Common Schema 2.0 compliant.
                writer.WriteProperty("baseType", dependencyTelemetry.BaseType);
                writer.WritePropertyName("baseData");
                {
                    writer.WriteStartObject();

                    writer.WriteProperty("ver", dependencyTelemetry.Data.ver);
                    writer.WriteProperty("name", dependencyTelemetry.Data.name);

                    writer.WriteProperty("commandName", dependencyTelemetry.Data.commandName);
                    writer.WriteProperty("kind", (int)dependencyTelemetry.Data.kind);
                    writer.WriteProperty("value", dependencyTelemetry.Data.value);

                    writer.WriteProperty("dependencyKind", (int)dependencyTelemetry.Data.dependencyKind);
                    writer.WriteProperty("success", dependencyTelemetry.Data.success);
                    writer.WriteProperty("async", dependencyTelemetry.Data.async);
                    writer.WriteProperty("dependencySource", (int)dependencyTelemetry.Data.dependencySource);
                    writer.WriteProperty("dependencyTypeName", dependencyTelemetry.Data.dependencyTypeName);

                    writer.WriteProperty("properties", dependencyTelemetry.Data.properties);
                    writer.WriteEndObject();
                }

                writer.WriteEndObject();
            }

            writer.WriteEndObject();
        }
示例#26
0
        /// <summary>
        /// Extracts appropriate data points for auto-collected, pre-aggregated metrics from a single <c>DependencyTelemetry</c> item.
        /// </summary>
        /// <param name="fromItem">The telemetry item from which to extract the metric data points.</param>
        /// <param name="isItemProcessed">Whether of not the specified item was processed (aka not ignored) by this extractor.</param>
        public void ExtractMetrics(ITelemetry fromItem, out bool isItemProcessed)
        {
            //// If this item is not a DependencyTelemetry, we will not process it:
            DependencyTelemetry dependencyCall = fromItem as DependencyTelemetry;

            if (dependencyCall == null)
            {
                isItemProcessed = false;
                return;
            }

            Metric dependencyCallMetric = this.dependencyCallDurationMetric;

            //// If there is no Metric, then this extractor has not been properly initialized yet:
            if (dependencyCallMetric == null)
            {
                //// This should be caught and properly logged by the base class:
                throw new InvalidOperationException(Invariant($"Cannot execute {nameof(this.ExtractMetrics)}.")
                                                    + Invariant($" There is no {nameof(this.dependencyCallDurationMetric)}.")
                                                    + Invariant($" Either this metrics extractor has not been initialized, or it has been disposed."));
            }

            //// Get dependency call success status:
            bool   dependencyFailed        = (dependencyCall.Success != null) && (dependencyCall.Success == false);
            string dependnecySuccessString = dependencyFailed ? Boolean.FalseString : Boolean.TrueString;

            //// Now we need to determine which data series to use:
            MetricSeries seriesToTrack = null;

            if (this.MaxDependencyTypesToDiscover == 0)
            {
                // (MaxDependencyTypesToDiscover == 0) means we do not group by Dependency Type.
                // Then, always use "Other" as Dependency Type:

                dependencyCallMetric.TryGetDataSeries(
                    out seriesToTrack,
                    MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                    dependnecySuccessString,
                    MetricTerms.Autocollection.DependencyCall.TypeNames.Other);
            }
            else
            {
                // We group by Dependency Type and if dim limit is reached fall back to using "Other":

                string dependencyType = dependencyCall.Type;

                //// If dependency type is not set, we use "Unknown":
                if (dependencyType == null || dependencyType.Equals(String.Empty, StringComparison.OrdinalIgnoreCase))
                {
                    dependencyType = MetricTerms.Autocollection.DependencyCall.TypeNames.Unknown;
                }

                bool canTrack = dependencyCallMetric.TryGetDataSeries(
                    out seriesToTrack,
                    MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                    dependnecySuccessString,
                    dependencyType);

                if (false == canTrack)
                {
                    // If dimension cap was reached, use "Other" as dependency type:
                    // (that series has been pre-created, so cap will not apply)
                    dependencyCallMetric.TryGetDataSeries(
                        out seriesToTrack,
                        MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                        dependnecySuccessString,
                        MetricTerms.Autocollection.DependencyCall.TypeNames.Other);
                }
            }

            seriesToTrack.TrackValue(dependencyCall.Duration.TotalMilliseconds);
            isItemProcessed = true;
        }
        async Task SendWithTelemetry(PublishContext <T> context, IPipe <PublishContext <T> > next)
        {
            var telemetry = new DependencyTelemetry()
            {
                Name = $"{StepName} {TypeMetadataCache<T>.ShortName}",
                Type = DependencyType,
                Data = $"{StepName} {context.DestinationAddress}"
            };

            using (IOperationHolder <DependencyTelemetry> operation = _telemetryClient.StartOperation(telemetry))
            {
                _configureOperation?.Invoke(operation, context);

                context.Headers.Set(_telemetryHeaderRootKey, operation.Telemetry.Context.Operation.Id);
                context.Headers.Set(_telemetryHeaderParentKey, operation.Telemetry.Id);

                operation.Telemetry.Properties[MessageType] = TypeMetadataCache <T> .ShortName;

                if (context.MessageId.HasValue)
                {
                    operation.Telemetry.Properties[MessageId] = context.MessageId.Value.ToString();
                }

                if (context.ConversationId.HasValue)
                {
                    operation.Telemetry.Properties[ConversationId] = context.ConversationId.Value.ToString();
                }

                if (context.CorrelationId.HasValue)
                {
                    operation.Telemetry.Properties[CorrelationId] = context.CorrelationId.Value.ToString();
                }

                if (context.DestinationAddress != null)
                {
                    operation.Telemetry.Properties[DestinationAddress] = context.DestinationAddress.ToString();
                }

                if (context.RequestId.HasValue)
                {
                    operation.Telemetry.Properties[RequestId] = context.RequestId.Value.ToString();
                }

                try
                {
                    await next.Send(context).ConfigureAwait(false);

                    operation.Telemetry.Success = true;
                }
                catch (Exception e)
                {
                    _telemetryClient.TrackException(e, operation.Telemetry.Properties);

                    operation.Telemetry.Success = false;
                    throw;
                }
                finally
                {
                    _telemetryClient.StopOperation(operation);
                }
            }
        }
示例#28
0
        private void ValidateTelemetry(
            bool diagnosticSource,
            DependencyTelemetry item,
            Uri url,
            WebRequest requestMsg,
            bool success,
            string resultCode,
            bool w3CHeadersExpected,
            bool responseExpected        = true,
            bool headersDetailExpected   = false,
            bool legacyHeadersExpected   = false,
            bool requestIdHeaderExpected = true)
        {
            Assert.AreEqual(url, item.Data);

            if (url.Port == 80 || url.Port == 443)
            {
                Assert.AreEqual($"{url.Host}", item.Target);
            }
            else
            {
                Assert.AreEqual($"{url.Host}:{url.Port}", item.Target);
            }

            Assert.IsTrue(item.Duration > TimeSpan.FromMilliseconds(0), "Duration has to be positive");
            Assert.AreEqual(RemoteDependencyConstants.HTTP, item.Type, "HttpAny has to be dependency kind as it includes http and azure calls");
            Assert.IsTrue(
                DateTime.UtcNow.Subtract(item.Timestamp.UtcDateTime).TotalMilliseconds <
                TimeSpan.FromMinutes(1).TotalMilliseconds,
                "timestamp < now");
            Assert.IsTrue(
                item.Timestamp.Subtract(DateTime.UtcNow).TotalMilliseconds >
                -TimeSpan.FromMinutes(1).TotalMilliseconds,
                "now - 1 min < timestamp");
            Assert.AreEqual(resultCode, item.ResultCode);
            Assert.AreEqual(success, item.Success);

            var parentActivity = Activity.Current;

            if (parentActivity != null)
            {
                if (parentActivity.IdFormat == ActivityIdFormat.W3C)
                {
                    Assert.AreEqual(parentActivity.TraceId.ToHexString(), item.Context.Operation.Id);
                    Assert.AreEqual($"|{parentActivity.TraceId.ToHexString()}.{parentActivity.SpanId.ToHexString()}.", item.Context.Operation.ParentId);
                    if (parentActivity.TraceStateString != null)
                    {
                        Assert.IsTrue(item.Properties.ContainsKey("tracestate"));
                        Assert.AreEqual(parentActivity.TraceStateString, item.Properties["tracestate"]);
                    }
                    else
                    {
                        Assert.IsFalse(item.Properties.ContainsKey("tracestate"));
                    }
                }
                else
                {
                    Assert.AreEqual(parentActivity.RootId, item.Context.Operation.Id);
                    Assert.AreEqual(parentActivity.Id, item.Context.Operation.ParentId);
                }
            }
            else
            {
                Assert.IsNotNull(item.Context.Operation.Id);
                Assert.IsNull(item.Context.Operation.ParentId);
            }

            Assert.IsTrue(item.Id.StartsWith('|' + item.Context.Operation.Id + '.'));

            if (diagnosticSource)
            {
                this.operationDetailsInitializer.ValidateOperationDetailsDesktop(item, responseExpected, headersDetailExpected);
                this.ValidateTelemetryForDiagnosticSource(item, url, requestMsg, legacyHeadersExpected, w3CHeadersExpected, requestIdHeaderExpected);
            }
            else
            {
                this.ValidateTelemetryForEventSource(item, url, requestMsg);
            }
        }
示例#29
0
        //// netcoreapp 2.0 event

        /// <summary>
        /// Handler for Activity stop event (response is received for the outgoing request).
        /// </summary>
        internal void OnActivityStop(HttpResponseMessage response, HttpRequestMessage request, TaskStatus requestTaskStatus)
        {
            // Even though we have the IsEnabled filter to reject ApplicationInsights URLs before any events are fired, if there
            // are multiple subscribers and one subscriber returns true to IsEnabled then all subscribers will receive the event.
            if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(request.RequestUri))
            {
                return;
            }

            Activity currentActivity = Activity.Current;

            if (currentActivity == null)
            {
                DependencyCollectorEventSource.Log.CurrentActivityIsNull(HttpOutStopEventName);
                return;
            }

            if (Activity.DefaultIdFormat == ActivityIdFormat.W3C &&
                request.Headers.TryGetValues(W3C.W3CConstants.TraceParentHeader, out var parents) &&
                parents.FirstOrDefault() != currentActivity.Id)
            {
                DependencyCollectorEventSource.Log.HttpRequestAlreadyInstrumented();
                return;
            }

            DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerStop(currentActivity.Id);

            Uri requestUri   = request.RequestUri;
            var resourceName = request.Method.Method + " " + requestUri.AbsolutePath;

            DependencyTelemetry telemetry = new DependencyTelemetry();

            telemetry.SetOperationDetail(RemoteDependencyConstants.HttpRequestOperationDetailName, request);

            // properly fill dependency telemetry operation context: OperationCorrelationTelemetryInitializer initializes child telemetry
            if (currentActivity.IdFormat == ActivityIdFormat.W3C)
            {
                var traceId = currentActivity.TraceId.ToHexString();
                telemetry.Context.Operation.Id = traceId;
                if (currentActivity.ParentSpanId != default)
                {
                    telemetry.Context.Operation.ParentId = W3CUtilities.FormatTelemetryId(traceId, currentActivity.ParentSpanId.ToHexString());
                }

                telemetry.Id = W3CUtilities.FormatTelemetryId(traceId, currentActivity.SpanId.ToHexString());
            }
            else
            {
                telemetry.Context.Operation.Id       = currentActivity.RootId;
                telemetry.Context.Operation.ParentId = currentActivity.ParentId;
                telemetry.Id = currentActivity.Id;
            }

            foreach (var item in currentActivity.Baggage)
            {
                if (!telemetry.Properties.ContainsKey(item.Key))
                {
                    telemetry.Properties[item.Key] = item.Value;
                }
            }

            // TODO[tracestate]: remove, this is done in base SDK
            if (!string.IsNullOrEmpty(currentActivity.TraceStateString) && !telemetry.Properties.ContainsKey(W3CConstants.TracestatePropertyKey))
            {
                telemetry.Properties.Add(W3CConstants.TracestatePropertyKey, currentActivity.TraceStateString);
            }

            this.client.Initialize(telemetry);

            // If we started auxiliary Activity before to override the Id with W3C compatible one,
            // now it's time to set end time on it
            if (currentActivity.Duration == TimeSpan.Zero)
            {
                currentActivity.SetEndTime(DateTime.UtcNow);
            }

            telemetry.Timestamp = currentActivity.StartTimeUtc;
            telemetry.Name      = resourceName;
            telemetry.Target    = DependencyTargetNameHelper.GetDependencyTargetName(requestUri);
            telemetry.Type      = RemoteDependencyConstants.HTTP;
            telemetry.Data      = requestUri.OriginalString;
            telemetry.Duration  = currentActivity.Duration;
            if (response != null)
            {
                this.ParseResponse(response, telemetry);
                telemetry.SetOperationDetail(RemoteDependencyConstants.HttpResponseOperationDetailName, response);
            }
            else
            {
                if (this.pendingExceptions.TryRemove(currentActivity.Id, out Exception exception))
                {
                    telemetry.Properties[RemoteDependencyConstants.DependencyErrorPropertyKey] = exception.GetBaseException().Message;
                }

                telemetry.ResultCode = requestTaskStatus.ToString();
                telemetry.Success    = false;
            }

            this.client.TrackDependency(telemetry);
        }
        /// <summary>
        /// Common helper for all End Callbacks.
        /// </summary>
        /// <param name="exception">The exception object if any.</param>
        /// <param name="thisObj">This object.</param>
        /// <param name="returnValue">Return value of the function if any.</param>
        private void OnEnd(object exception, object thisObj, object returnValue)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return;
                }

                DependencyCollectorEventSource.Log.EndCallbackCalled(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));

                Tuple <DependencyTelemetry, bool> telemetryTuple = this.TelemetryTable.Get(thisObj);

                if (telemetryTuple == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));
                    return;
                }

                if (telemetryTuple.Item1 == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));
                    return;
                }

                // Not custom created
                if (!telemetryTuple.Item2)
                {
                    this.TelemetryTable.Remove(thisObj);
                    DependencyTelemetry telemetry = telemetryTuple.Item1;

                    int statusCode = -1;

                    var responseObj = returnValue as HttpWebResponse;

                    if (responseObj == null && exception != null)
                    {
                        var webException = exception as WebException;

                        if (webException != null)
                        {
                            responseObj = webException.Response as HttpWebResponse;
                        }
#if !NET40
                        if (responseObj == null)
                        {
                            var httpException = exception as HttpException;

                            if (httpException != null)
                            {
                                statusCode = httpException.GetHttpCode();
                            }
                        }
#endif
                    }

                    if (responseObj != null)
                    {
                        try
                        {
                            statusCode = (int)responseObj.StatusCode;

                            if (responseObj.Headers != null)
                            {
                                var targetIkeyHash = responseObj.Headers[RequestResponseHeaders.TargetInstrumentationKeyHeader];

                                // We only add the cross component correlation key if the key does not remain the current component.
                                if (!string.IsNullOrEmpty(targetIkeyHash) && targetIkeyHash != InstrumentationKeyHashLookupHelper.GetInstrumentationKeyHash(telemetry.Context.InstrumentationKey))
                                {
                                    telemetry.Type    = RemoteDependencyConstants.AI;
                                    telemetry.Target += " | " + targetIkeyHash;
                                }
                            }
                        }
                        catch (ObjectDisposedException)
                        {
                            // ObjectDisposedException is expected here in the following sequence: httpWebRequest.GetResponse().Dispose() -> httpWebRequest.GetResponse()
                            // on the second call to GetResponse() we cannot determine the statusCode.
                        }
                    }

                    telemetry.ResultCode = statusCode > 0 ? statusCode.ToString(CultureInfo.InvariantCulture) : string.Empty;
                    telemetry.Success    = (statusCode > 0) && (statusCode < 400);

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginHttp", ex);
            }
        }
示例#31
0
        public Task ExportAsync(IEnumerable <SpanData> spanDataList)
        {
            foreach (var span in spanDataList)
            {
                this.ExtractGenericProperties(
                    span,
                    out var resultKind,
                    out var timestamp,
                    out var name,
                    out var resultCode,
                    out var props,
                    out var traceId,
                    out var spanId,
                    out var parentId,
                    out var tracestate,
                    out var success,
                    out var duration);

                string data      = null;
                string target    = null;
                string type      = null;
                string userAgent = null;

                string spanKindAttr       = null;
                string errorAttr          = null;
                string httpStatusCodeAttr = null;
                string httpMethodAttr     = null;
                string httpPathAttr       = null;
                string httpHostAttr       = null;
                string httpUrlAttr        = null;
                string httpUserAgentAttr  = null;
                string httpRouteAttr      = null;
                string httpPortAttr       = null;

                foreach (var attr in span.Attributes.AttributeMap)
                {
                    var key = attr.Key;
                    switch (attr.Key)
                    {
                    case "span.kind":
                        spanKindAttr = attr.Value.ToString();
                        break;

                    case "error":
                        errorAttr = attr.Value.ToString();
                        break;

                    case "http.method":
                        httpMethodAttr = attr.Value.ToString();
                        break;

                    case "http.path":
                        httpPathAttr = attr.Value.ToString();
                        break;

                    case "http.host":
                        httpHostAttr = attr.Value.ToString();
                        break;

                    case "http.url":
                        httpUrlAttr = attr.Value.ToString();
                        break;

                    case "http.status_code":
                        httpStatusCodeAttr = attr.Value.ToString();
                        break;

                    case "http.user_agent":
                        httpUserAgentAttr = attr.Value.ToString();
                        break;

                    case "http.route":
                        httpRouteAttr = attr.Value.ToString();
                        break;

                    case "http.port":
                        httpPortAttr = attr.Value.ToString();
                        break;

                    default:
                        var value = attr.Value.ToString();

                        AddPropertyWithAdjustedName(props, attr.Key, value);

                        break;
                    }
                }

                var linkId = 0;
                foreach (var link in span.Links.Links)
                {
                    AddPropertyWithAdjustedName(props, "link" + linkId + "_traceId", link.Context.TraceId.ToHexString());
                    AddPropertyWithAdjustedName(props, "link" + linkId + "_spanId", link.Context.SpanId.ToHexString());

                    foreach (var attr in link.Attributes)
                    {
                        AddPropertyWithAdjustedName(props, "link" + linkId + "_" + attr.Key, attr.Value.ToString());
                    }

                    ++linkId;
                }

                foreach (var t in span.Events.Events)
                {
                    var log = new TraceTelemetry(t.Event.Name);

                    if (t.Timestamp != null)
                    {
                        log.Timestamp = t.Timestamp;
                    }

                    foreach (var attr in t.Event.Attributes)
                    {
                        var value = attr.Value.ToString();

                        AddPropertyWithAdjustedName(log.Properties, attr.Key, value);
                    }

                    log.Context.Operation.Id       = traceId;
                    log.Context.Operation.ParentId = string.Concat("|", traceId, ".", spanId, ".");

                    this.telemetryClient.Track(log);
                }

                this.OverwriteSpanKindFromAttribute(spanKindAttr, ref resultKind);
                this.OverwriteErrorAttribute(errorAttr, ref success);
                this.OverwriteFieldsForHttpSpans(
                    httpMethodAttr,
                    httpUrlAttr,
                    httpHostAttr,
                    httpPathAttr,
                    httpStatusCodeAttr,
                    httpUserAgentAttr,
                    httpRouteAttr,
                    httpPortAttr,
                    ref name,
                    ref resultCode,
                    ref data,
                    ref target,
                    ref type,
                    ref userAgent);

                // BUILDING resulting telemetry
                OperationTelemetry result;
                if (resultKind == SpanKind.Client || resultKind == SpanKind.Producer)
                {
                    var resultD = new DependencyTelemetry
                    {
                        ResultCode = resultCode,
                        Data       = data,
                        Target     = target,
                        Type       = type,
                    };

                    result = resultD;
                }
                else
                {
                    var resultR = new RequestTelemetry();
                    resultR.ResponseCode = resultCode;
                    Uri.TryCreate(data, UriKind.RelativeOrAbsolute, out var url);
                    resultR.Url = url;
                    result      = resultR;
                }

                result.Success = success;

                result.Timestamp              = timestamp;
                result.Name                   = name;
                result.Context.Operation.Id   = traceId;
                result.Context.User.UserAgent = userAgent;

                foreach (var prop in props)
                {
                    AddPropertyWithAdjustedName(result.Properties, prop.Key, prop.Value);
                }

                if (parentId != null)
                {
                    result.Context.Operation.ParentId = string.Concat("|", traceId, ".", parentId, ".");
                }

                // TODO: I don't understant why this concatanation is required
                result.Id = string.Concat("|", traceId, ".", spanId, ".");

                foreach (var ts in tracestate.Entries)
                {
                    result.Properties[ts.Key] = ts.Value;
                }

                result.Duration = duration;

                // TODO: deal with those:
                // span.ChildSpanCount
                // span.Context.IsValid;
                // span.Context.TraceOptions;

                this.telemetryClient.Track(result);
            }

            return(Task.CompletedTask);
        }
示例#32
0
        /// <summary>
        /// Implemented by the derived class for adding the tuple to its specific cache.
        /// </summary>
        /// <param name="webRequest">The request which acts the key.</param>
        /// <param name="telemetry">The dependency telemetry for the tuple.</param>
        /// <param name="isCustomCreated">Boolean value that tells if the current telemetry item is being added by the customer or not.</param>
        protected override void AddTupleForWebDependencies(WebRequest webRequest, DependencyTelemetry telemetry, bool isCustomCreated)
        {
            var telemetryTuple = new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated);

            this.TelemetryTable.Store(ClientServerDependencyTracker.GetIdForRequestObject(webRequest), telemetryTuple);
        }
示例#33
0
        internal static DependencyTelemetry ExtractDependencyTelemetry(DiagnosticListener diagnosticListener, Activity currentActivity)
        {
            DependencyTelemetry telemetry = new DependencyTelemetry();

            telemetry.Id       = currentActivity.Id;
            telemetry.Duration = currentActivity.Duration;
            telemetry.Name     = currentActivity.OperationName;

            Uri    requestUri          = null;
            string component           = null;
            string queryStatement      = null;
            string httpMethodWithSpace = string.Empty;
            string httpUrl             = null;
            string peerAddress         = null;
            string peerService         = null;

            foreach (KeyValuePair <string, string> tag in currentActivity.Tags)
            {
                // interpret Tags as defined by OpenTracing conventions
                // https://github.com/opentracing/specification/blob/master/semantic_conventions.md
                switch (tag.Key)
                {
                case "component":
                {
                    component = tag.Value;
                    break;
                }

                case "db.statement":
                {
                    queryStatement = tag.Value;
                    break;
                }

                case "error":
                {
                    bool failed;
                    if (bool.TryParse(tag.Value, out failed))
                    {
                        telemetry.Success = !failed;
                        continue;         // skip Properties
                    }

                    break;
                }

                case "http.status_code":
                {
                    telemetry.ResultCode = tag.Value;
                    continue;         // skip Properties
                }

                case "http.method":
                {
                    httpMethodWithSpace = tag.Value + " ";
                    break;
                }

                case "http.url":
                {
                    httpUrl = tag.Value;
                    if (Uri.TryCreate(tag.Value, UriKind.RelativeOrAbsolute, out requestUri))
                    {
                        continue;         // skip Properties
                    }

                    break;
                }

                case "peer.address":
                {
                    peerAddress = tag.Value;
                    break;
                }

                case "peer.hostname":
                {
                    telemetry.Target = tag.Value;
                    continue;         // skip Properties
                }

                case "peer.service":
                {
                    peerService = tag.Value;
                    break;
                }
                }

                // if more than one tag with the same name is specified, the first one wins
                // TODO verify if still needed once https://github.com/Microsoft/ApplicationInsights-dotnet/issues/562 is resolved
                if (!telemetry.Properties.ContainsKey(tag.Key))
                {
                    telemetry.Properties.Add(tag);
                }
            }

            if (string.IsNullOrEmpty(telemetry.Type))
            {
                telemetry.Type = peerService ?? component ?? diagnosticListener.Name;
            }

            if (string.IsNullOrEmpty(telemetry.Target))
            {
                // 'peer.address' can be not user-friendly, thus use only if nothing else specified
                telemetry.Target = requestUri?.Host ?? peerAddress;
            }

            if (string.IsNullOrEmpty(telemetry.Name))
            {
                telemetry.Name = currentActivity.OperationName;
            }

            if (string.IsNullOrEmpty(telemetry.Data))
            {
                telemetry.Data = queryStatement ?? requestUri?.OriginalString ?? httpUrl;
            }

            return(telemetry);
        }
        private static void SerializeTelemetryItem(ITelemetry telemetryItem, JsonWriter jsonWriter)
        {
            if (telemetryItem is EventTelemetry)
            {
                EventTelemetry eventTelemetry = telemetryItem as EventTelemetry;
                SerializeEventTelemetry(eventTelemetry, jsonWriter);
            }
            else if (telemetryItem is ExceptionTelemetry)
            {
                ExceptionTelemetry exceptionTelemetry = telemetryItem as ExceptionTelemetry;
                SerializeExceptionTelemetry(exceptionTelemetry, jsonWriter);
            }
            else if (telemetryItem is MetricTelemetry)
            {
                MetricTelemetry metricTelemetry = telemetryItem as MetricTelemetry;
                SerializeMetricTelemetry(metricTelemetry, jsonWriter);
            }
            else if (telemetryItem is PageViewTelemetry)
            {
                PageViewTelemetry pageViewTelemetry = telemetryItem as PageViewTelemetry;
                SerializePageViewTelemetry(pageViewTelemetry, jsonWriter);
            }
            else if (telemetryItem is DependencyTelemetry)
            {
                DependencyTelemetry remoteDependencyTelemetry = telemetryItem as DependencyTelemetry;
                SerializeDependencyTelemetry(remoteDependencyTelemetry, jsonWriter);
            }
            else if (telemetryItem is RequestTelemetry)
            {
                RequestTelemetry requestTelemetry = telemetryItem as RequestTelemetry;
                SerializeRequestTelemetry(requestTelemetry, jsonWriter);
            }
#pragma warning disable 618
            else if (telemetryItem is SessionStateTelemetry)
            {
                EventTelemetry telemetry = (telemetryItem as SessionStateTelemetry).Data;
                SerializeEventTelemetry(telemetry, jsonWriter);
            }
#pragma warning restore 618
            else if (telemetryItem is TraceTelemetry)
            {
                TraceTelemetry traceTelemetry = telemetryItem as TraceTelemetry;
                SerializeTraceTelemetry(traceTelemetry, jsonWriter);
            }
#pragma warning disable 618
            else if (telemetryItem is PerformanceCounterTelemetry)
            {
                MetricTelemetry telemetry = (telemetryItem as PerformanceCounterTelemetry).Data;
                SerializeMetricTelemetry(telemetry, jsonWriter);
            }
            else if (telemetryItem is AvailabilityTelemetry)
            {
                AvailabilityTelemetry availabilityTelemetry = telemetryItem as AvailabilityTelemetry;
                SerializeAvailability(availabilityTelemetry, jsonWriter);
            }
            else
            {
                string msg = string.Format(CultureInfo.InvariantCulture, "Unknown telemtry type: {0}", telemetryItem.GetType());
                CoreEventSource.Log.LogVerbose(msg);
            }
        }
        /// <summary>
        /// Implemented by the derived class for adding the tuple to its specific cache.
        /// </summary>
        /// <param name="webRequest">The request which acts the key.</param>
        /// <param name="telemetry">The dependency telemetry for the tuple.</param>
        /// <param name="isCustomCreated">Boolean value that tells if the current telemetry item is being added by the customer or not.</param>
        protected override void AddTupleForWebDependencies(WebRequest webRequest, DependencyTelemetry telemetry, bool isCustomCreated)
        {
            var telemetryTuple = new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated);

            this.TelemetryTable.Store(webRequest, telemetryTuple);
        }