private void ParseResponse(HttpResponseMessage response, DependencyTelemetry telemetry)
        {
            try
            {
                string targetApplicationId = HttpHeadersUtilities.GetRequestContextKeyValue(response.Headers, RequestResponseHeaders.RequestContextCorrelationTargetKey);
                if (!string.IsNullOrEmpty(targetApplicationId) && !string.IsNullOrEmpty(telemetry.Context.InstrumentationKey))
                {
                    // We only add the cross component correlation key if the key does not represent the current component.
                    string sourceApplicationId;
                    if (this.correlationIdLookupHelper.TryGetXComponentCorrelationId(telemetry.Context.InstrumentationKey, out sourceApplicationId) &&
                        targetApplicationId != sourceApplicationId)
                    {
                        telemetry.Type    = RemoteDependencyConstants.AI;
                        telemetry.Target += " | " + targetApplicationId;
                    }
                }
            }
            catch (Exception e)
            {
                AppMapCorrelationEventSource.Log.UnknownError(ExceptionUtilities.GetExceptionDetailString(e));
            }

            int statusCode = (int)response.StatusCode;

            telemetry.ResultCode = (statusCode > 0) ? statusCode.ToString(CultureInfo.InvariantCulture) : string.Empty;
            telemetry.Success    = (statusCode > 0) && (statusCode < 400);
        }
        /// <summary>
        /// Provides the observer with new data.
        /// <seealso cref="IObserver{T}.OnNext(T)"/>
        /// </summary>
        /// <param name="evnt">The current notification information.</param>
        public void OnNext(KeyValuePair <string, object> evnt)
        {
            const string ErrorTemplateTypeCast   = "Event {0}: cannot cast {1} to expected type {2}";
            const string ErrorTemplateValueParse = "Event {0}: cannot parse '{1}' as type {2}";

            try
            {
                switch (evnt.Key)
                {
                case HttpOutStartEventName:
                {
                    var request = this.startRequestFetcher.Fetch(evnt.Value) as HttpRequestMessage;

                    if (request == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateTypeCast, evnt.Key, "request", "HttpRequestMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnActivityStart(request);
                    }

                    break;
                }

                case HttpOutStopEventName:
                {
                    var        response = this.stopResponseFetcher.Fetch(evnt.Value) as HttpResponseMessage;
                    var        request  = this.stopRequestFetcher.Fetch(evnt.Value) as HttpRequestMessage;
                    var        requestTaskStatusString = this.stopRequestStatusFetcher.Fetch(evnt.Value).ToString();
                    TaskStatus requestTaskStatus;

                    if (response == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateTypeCast, evnt.Key, "response", "HttpResponseMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (request == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateTypeCast, evnt.Key, "request", "HttpRequestMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (!Enum.TryParse(requestTaskStatusString, out requestTaskStatus))
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateValueParse, evnt.Key, requestTaskStatusString, "TaskStatus");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnActivityStop(response, request, requestTaskStatus);
                    }

                    break;
                }

                case HttpExceptionEventName:
                {
                    var exception = this.exceptionFetcher.Fetch(evnt.Value) as Exception;
                    var request   = this.exceptionRequestFetcher.Fetch(evnt.Value) as HttpRequestMessage;

                    if (exception == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateTypeCast, evnt.Key, "exception", "Exception");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (request == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateTypeCast, evnt.Key, "request", "HttpRequestMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnException(exception, request);
                    }

                    break;
                }

                case DeprecatedRequestEventName:
                {
                    var  request = this.deprecatedRequestFetcher.Fetch(evnt.Value) as HttpRequestMessage;
                    var  loggingRequestIdString = this.deprecatedRequestGuidFetcher.Fetch(evnt.Value).ToString();
                    Guid loggingRequestId;

                    if (request == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateTypeCast, evnt.Key, "request", "HttpRequestMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (!Guid.TryParse(loggingRequestIdString, out loggingRequestId))
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateValueParse, evnt.Key, loggingRequestIdString, "Guid");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnRequest(request, loggingRequestId);
                    }

                    break;
                }

                case DeprecatedResponseEventName:
                {
                    var  response = this.deprecatedResponseFetcher.Fetch(evnt.Value) as HttpResponseMessage;
                    var  loggingRequestIdString = this.deprecatedResponseGuidFetcher.Fetch(evnt.Value).ToString();
                    Guid loggingRequestId;

                    if (response == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateTypeCast, evnt.Key, "response", "HttpResponseMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (!Guid.TryParse(loggingRequestIdString, out loggingRequestId))
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, ErrorTemplateValueParse, evnt.Key, loggingRequestIdString, "Guid");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnResponse(response, loggingRequestId);
                    }

                    break;
                }
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(ExceptionUtilities.GetExceptionDetailString(ex));
            }
        }
        private void InjectRequestHeaders(HttpRequestMessage request, string instrumentationKey, bool isLegacyEvent = false)
        {
            try
            {
                var currentActivity = Activity.Current;

                HttpRequestHeaders requestHeaders = request.Headers;
                if (requestHeaders != null && this.setComponentCorrelationHttpHeaders && !this.correlationDomainExclusionList.Contains(request.RequestUri.Host))
                {
                    try
                    {
                        if (!string.IsNullOrEmpty(instrumentationKey) && !HttpHeadersUtilities.ContainsRequestContextKeyValue(requestHeaders, RequestResponseHeaders.RequestContextCorrelationSourceKey))
                        {
                            string sourceApplicationId;
                            if (this.correlationIdLookupHelper.TryGetXComponentCorrelationId(instrumentationKey, out sourceApplicationId))
                            {
                                HttpHeadersUtilities.SetRequestContextKeyValue(requestHeaders, RequestResponseHeaders.RequestContextCorrelationSourceKey, sourceApplicationId);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        AppMapCorrelationEventSource.Log.UnknownError(ExceptionUtilities.GetExceptionDetailString(e));
                    }

                    // Add the root ID
                    string rootId = currentActivity.RootId;
                    if (!string.IsNullOrEmpty(rootId) &&
                        !requestHeaders.Contains(RequestResponseHeaders.StandardRootIdHeader))
                    {
                        requestHeaders.Add(RequestResponseHeaders.StandardRootIdHeader, rootId);
                    }

                    // Add the parent ID
                    string parentId = currentActivity.Id;
                    if (!string.IsNullOrEmpty(parentId) &&
                        !requestHeaders.Contains(RequestResponseHeaders.StandardParentIdHeader))
                    {
                        requestHeaders.Add(RequestResponseHeaders.StandardParentIdHeader, parentId);
                        if (isLegacyEvent)
                        {
                            requestHeaders.Add(RequestResponseHeaders.RequestIdHeader, parentId);
                        }
                    }

                    if (isLegacyEvent)
                    {
                        // we expect baggage to be empty or contain a few items
                        using (IEnumerator <KeyValuePair <string, string> > e = currentActivity.Baggage.GetEnumerator())
                        {
                            if (e.MoveNext())
                            {
                                var baggage = new List <string>();
                                do
                                {
                                    KeyValuePair <string, string> item = e.Current;
                                    baggage.Add(new NameValueHeaderValue(item.Key, item.Value).ToString());
                                }while (e.MoveNext());
                                request.Headers.Add(RequestResponseHeaders.CorrelationContextHeader, baggage);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                AppMapCorrelationEventSource.Log.UnknownError(ExceptionUtilities.GetExceptionDetailString(e));
            }
        }
예제 #4
0
        private void InjectRequestHeaders(HttpRequestMessage request, string instrumentationKey)
        {
            try
            {
                HttpRequestHeaders requestHeaders = request.Headers;
                if (requestHeaders != null && this.setComponentCorrelationHttpHeaders && !this.correlationDomainExclusionList.Contains(request.RequestUri.Host))
                {
                    string sourceApplicationId = null;
                    try
                    {
                        if (!string.IsNullOrEmpty(instrumentationKey) &&
                            !HttpHeadersUtilities.ContainsRequestContextKeyValue(requestHeaders, RequestResponseHeaders.RequestContextCorrelationSourceKey) &&
                            (this.configuration.ApplicationIdProvider?.TryGetApplicationId(instrumentationKey, out sourceApplicationId) ?? false))
                        {
                            HttpHeadersUtilities.SetRequestContextKeyValue(requestHeaders, RequestResponseHeaders.RequestContextCorrelationSourceKey, sourceApplicationId);
                        }
                    }
                    catch (Exception e)
                    {
                        AppMapCorrelationEventSource.Log.UnknownError(ExceptionUtilities.GetExceptionDetailString(e));
                    }

                    var currentActivity = Activity.Current;

                    switch (this.httpInstrumentationVersion)
                    {
                    case HttpInstrumentationVersion.V1:
                        // HttpClient does not add any headers
                        // add W3C or Request-Id depending on Activity format
                        // add correlation-context anyway
                        if (currentActivity.IdFormat == ActivityIdFormat.W3C)
                        {
                            InjectW3CHeaders(currentActivity, requestHeaders);
                            if (this.injectRequestIdInW3CMode)
                            {
                                InjectBackCompatibleRequestId(currentActivity, requestHeaders);
                            }
                        }
                        else
                        {
                            if (!requestHeaders.Contains(RequestResponseHeaders.RequestIdHeader))
                            {
                                requestHeaders.Add(RequestResponseHeaders.RequestIdHeader, currentActivity.Id);
                            }
                        }

                        InjectCorrelationContext(requestHeaders, currentActivity);
                        break;

                    case HttpInstrumentationVersion.V2:
                        // On V2, HttpClient adds Request-Id and Correlation-Context
                        // but not W3C
                        if (currentActivity.IdFormat == ActivityIdFormat.W3C)
                        {
                            // we are going to add W3C and Request-Id (in W3C-compatible format)
                            // as a result HttpClient will not add Request-Id AND Correlation-Context
                            InjectW3CHeaders(currentActivity, requestHeaders);
                            if (this.injectRequestIdInW3CMode)
                            {
                                InjectBackCompatibleRequestId(currentActivity, requestHeaders);
                            }

                            InjectCorrelationContext(requestHeaders, currentActivity);
                        }

                        break;

                    case HttpInstrumentationVersion.V3:
                        // on V3, HttpClient adds either W3C or Request-Id depending on Activity format
                        // and adds Correlation-Context
                        if (currentActivity.IdFormat == ActivityIdFormat.W3C && this.injectRequestIdInW3CMode)
                        {
                            // we are going to override Request-Id to be in W3C compatible mode
                            InjectBackCompatibleRequestId(currentActivity, requestHeaders);
                        }

                        break;
                    }

                    if (this.injectLegacyHeaders)
                    {
                        // Add the root ID (Activity.RootId works with W3C and Hierarchical format)
                        string rootId = currentActivity.RootId;
                        if (!string.IsNullOrEmpty(rootId) && !requestHeaders.Contains(RequestResponseHeaders.StandardRootIdHeader))
                        {
                            requestHeaders.Add(RequestResponseHeaders.StandardRootIdHeader, rootId);
                        }

                        // Add the parent ID
                        string parentId = currentActivity.IdFormat == ActivityIdFormat.W3C ?
                                          W3CUtilities.FormatTelemetryId(rootId, currentActivity.SpanId.ToHexString()) :
                                          currentActivity.Id;

                        if (!string.IsNullOrEmpty(parentId) && !requestHeaders.Contains(RequestResponseHeaders.StandardParentIdHeader))
                        {
                            requestHeaders.Add(RequestResponseHeaders.StandardParentIdHeader, parentId);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                AppMapCorrelationEventSource.Log.UnknownError(ExceptionUtilities.GetExceptionDetailString(e));
            }
        }
예제 #5
0
        /// <summary>
        /// Provides the observer with new data.
        /// <seealso cref="IObserver{T}.OnNext(T)"/>
        /// </summary>
        /// <param name="evnt">The current notification information.</param>
        public void OnNext(KeyValuePair <string, object> evnt)
        {
            try
            {
                // It's possible to host multiple apps (ASP.NET Core or generic hosts) in the same process
                // Each of this apps has it's own DependencyTrackingModule and corresponding Http listener.
                // We should ignore events for all of them except one
                if (!SubscriptionManager.IsActive(this))
                {
                    DependencyCollectorEventSource.Log.NotActiveListenerNoTracking(evnt.Key, Activity.Current?.Id);
                    return;
                }

                const string errorTemplateTypeCast   = "Event {0}: cannot cast {1} to expected type {2}";
                const string errorTemplateValueParse = "Event {0}: cannot parse '{1}' as type {2}";

                switch (evnt.Key)
                {
                case HttpOutStartEventName:
                {
                    var request = this.startRequestFetcher.Fetch(evnt.Value) as HttpRequestMessage;

                    if (request == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateTypeCast, evnt.Key, "request", "HttpRequestMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnActivityStart(request);
                    }

                    break;
                }

                case HttpOutStopEventName:
                {
                    var response = this.stopResponseFetcher.Fetch(evnt.Value) as HttpResponseMessage;
                    var request  = this.stopRequestFetcher.Fetch(evnt.Value) as HttpRequestMessage;
                    var requestTaskStatusString = this.stopRequestStatusFetcher.Fetch(evnt.Value).ToString();

                    if (request == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateTypeCast, evnt.Key, "request", "HttpRequestMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (!Enum.TryParse(requestTaskStatusString, out TaskStatus requestTaskStatus))
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateValueParse, evnt.Key, requestTaskStatusString, "TaskStatus");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnActivityStop(response, request, requestTaskStatus);
                    }

                    break;
                }

                case HttpExceptionEventName:
                {
                    var exception = this.exceptionFetcher.Fetch(evnt.Value) as Exception;
                    var request   = this.exceptionRequestFetcher.Fetch(evnt.Value) as HttpRequestMessage;

                    if (exception == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateTypeCast, evnt.Key, "exception", "Exception");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (request == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateTypeCast, evnt.Key, "request", "HttpRequestMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnException(exception, request);
                    }

                    break;
                }

                case DeprecatedRequestEventName:
                {
                    if (this.httpInstrumentationVersion != HttpInstrumentationVersion.V1)
                    {
                        // 2.0+ publishes new events, and this should be just ignored to prevent duplicates.
                        break;
                    }

                    var request = this.deprecatedRequestFetcher.Fetch(evnt.Value) as HttpRequestMessage;
                    var loggingRequestIdString = this.deprecatedRequestGuidFetcher.Fetch(evnt.Value).ToString();

                    if (request == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateTypeCast, evnt.Key, "request", "HttpRequestMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (!Guid.TryParse(loggingRequestIdString, out Guid loggingRequestId))
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateValueParse, evnt.Key, loggingRequestIdString, "Guid");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnRequest(request, loggingRequestId);
                    }

                    break;
                }

                case DeprecatedResponseEventName:
                {
                    if (this.httpInstrumentationVersion != HttpInstrumentationVersion.V1)
                    {
                        // 2.0+ publishes new events, and this should be just ignored to prevent duplicates.
                        break;
                    }

                    var response = this.deprecatedResponseFetcher.Fetch(evnt.Value) as HttpResponseMessage;
                    var loggingRequestIdString = this.deprecatedResponseGuidFetcher.Fetch(evnt.Value).ToString();

                    if (response == null)
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateTypeCast, evnt.Key, "response", "HttpResponseMessage");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else if (!Guid.TryParse(loggingRequestIdString, out Guid loggingRequestId))
                    {
                        var error = string.Format(CultureInfo.InvariantCulture, errorTemplateValueParse, evnt.Key, loggingRequestIdString, "Guid");
                        DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(error);
                    }
                    else
                    {
                        this.OnResponse(response, loggingRequestId);
                    }

                    break;
                }
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.HttpCoreDiagnosticSourceListenerOnNextFailed(ExceptionUtilities.GetExceptionDetailString(ex));
            }
        }
예제 #6
0
        void IObserver <KeyValuePair <string, object> > .OnNext(KeyValuePair <string, object> evnt)
        {
            try
            {
                switch (evnt.Key)
                {
                case SqlBeforeExecuteCommand:
                {
                    var operationId = (Guid)CommandBefore.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var command = (SqlCommand)CommandBefore.Command.Fetch(evnt.Value);

                    if (this.operationHolder.Get(command) == null)
                    {
                        var           dependencyName = string.Empty;
                        var           target         = string.Empty;
                        SqlConnection connection     = null;

                        if (command.Connection != null)
                        {
                            connection = command.Connection;
                            target     = string.Join(" | ", connection.DataSource, connection.Database);

                            var commandName = command.CommandType == CommandType.StoredProcedure
                                    ? command.CommandText
                                    : string.Empty;

                            dependencyName = string.IsNullOrEmpty(commandName)
                                    ? string.Join(" | ", connection.DataSource, connection.Database)
                                    : string.Join(" | ", connection.DataSource, connection.Database, commandName);
                        }

                        var timestamp = CommandBefore.Timestamp.Fetch(evnt.Value) as long?
                                        ?? Stopwatch.GetTimestamp(); // TODO corefx#20748 - timestamp missing from event data

                        var telemetry = new DependencyTelemetry()
                        {
                            Id      = operationId.ToString("N"),
                            Name    = dependencyName,
                            Type    = RemoteDependencyConstants.SQL,
                            Target  = target,
                            Data    = command.CommandText,
                            Success = true
                        };

                        // Populate the operation details for intializers
                        telemetry.SetOperationDetail(RemoteDependencyConstants.SqlCommandOperationDetailName, command);

                        InitializeTelemetry(telemetry, operationId, timestamp);

                        this.operationHolder.Store(command, Tuple.Create(telemetry, /* isCustomCreated: */ false));
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                    }

                    break;
                }

                case SqlAfterExecuteCommand:
                {
                    var operationId = (Guid)CommandAfter.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var command = (SqlCommand)CommandAfter.Command.Fetch(evnt.Value);
                    var tuple   = this.operationHolder.Get(command);

                    if (tuple != null)
                    {
                        this.operationHolder.Remove(command);

                        var telemetry = tuple.Item1;

                        var timestamp = (long)CommandAfter.Timestamp.Fetch(evnt.Value);

                        telemetry.Stop(timestamp);

                        this.client.TrackDependency(telemetry);
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(operationId.ToString("N"));
                    }

                    break;
                }

                case SqlErrorExecuteCommand:
                {
                    var operationId = (Guid)CommandError.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var command = (SqlCommand)CommandError.Command.Fetch(evnt.Value);
                    var tuple   = this.operationHolder.Get(command);

                    if (tuple != null)
                    {
                        this.operationHolder.Remove(command);

                        var telemetry = tuple.Item1;

                        var timestamp = (long)CommandError.Timestamp.Fetch(evnt.Value);

                        telemetry.Stop(timestamp);

                        var exception = (Exception)CommandError.Exception.Fetch(evnt.Value);

                        ConfigureExceptionTelemetry(telemetry, exception);

                        this.client.TrackDependency(telemetry);
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(operationId.ToString("N"));
                    }

                    break;
                }

                case SqlBeforeOpenConnection:
                {
                    var operationId = (Guid)ConnectionBefore.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var connection = (SqlConnection)ConnectionBefore.Connection.Fetch(evnt.Value);

                    if (this.operationHolder.Get(connection) == null)
                    {
                        var operation = (string)ConnectionBefore.Operation.Fetch(evnt.Value);
                        var timestamp = (long)ConnectionBefore.Timestamp.Fetch(evnt.Value);

                        var telemetry = new DependencyTelemetry()
                        {
                            Id      = operationId.ToString("N"),
                            Name    = string.Join(" | ", connection.DataSource, connection.Database, operation),
                            Type    = RemoteDependencyConstants.SQL,
                            Target  = string.Join(" | ", connection.DataSource, connection.Database),
                            Data    = operation,
                            Success = true
                        };

                        InitializeTelemetry(telemetry, operationId, timestamp);

                        this.operationHolder.Store(connection, Tuple.Create(telemetry, /* isCustomCreated: */ false));
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                    }

                    break;
                }

                case SqlAfterOpenConnection:
                {
                    var operationId = (Guid)ConnectionAfter.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var connection = (SqlConnection)ConnectionAfter.Connection.Fetch(evnt.Value);
                    var tuple      = this.operationHolder.Get(connection);

                    if (tuple != null)
                    {
                        this.operationHolder.Remove(connection);
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(operationId.ToString("N"));
                    }

                    break;
                }

                case SqlErrorOpenConnection:
                {
                    var operationId = (Guid)ConnectionError.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var connection = (SqlConnection)ConnectionError.Connection.Fetch(evnt.Value);
                    var tuple      = this.operationHolder.Get(connection);

                    if (tuple != null)
                    {
                        this.operationHolder.Remove(connection);

                        var telemetry = tuple.Item1;

                        var timestamp = (long)ConnectionError.Timestamp.Fetch(evnt.Value);

                        telemetry.Stop(timestamp);

                        var exception = (Exception)ConnectionError.Exception.Fetch(evnt.Value);

                        ConfigureExceptionTelemetry(telemetry, exception);

                        this.client.TrackDependency(telemetry);
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(operationId.ToString("N"));
                    }

                    break;
                }

                case SqlBeforeCommitTransaction:
                {
                    var operationId = (Guid)TransactionCommitBefore.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var connection = (SqlConnection)TransactionCommitBefore.Connection.Fetch(evnt.Value);

                    if (this.operationHolder.Get(connection) == null)
                    {
                        var operation      = (string)TransactionCommitBefore.Operation.Fetch(evnt.Value);
                        var timestamp      = (long)TransactionCommitBefore.Timestamp.Fetch(evnt.Value);
                        var isolationLevel = (IsolationLevel)TransactionCommitBefore.IsolationLevel.Fetch(evnt.Value);

                        var telemetry = new DependencyTelemetry()
                        {
                            Id      = operationId.ToString("N"),
                            Name    = string.Join(" | ", connection.DataSource, connection.Database, operation, isolationLevel),
                            Type    = RemoteDependencyConstants.SQL,
                            Target  = string.Join(" | ", connection.DataSource, connection.Database),
                            Data    = operation,
                            Success = true
                        };

                        InitializeTelemetry(telemetry, operationId, timestamp);

                        this.operationHolder.Store(connection, Tuple.Create(telemetry, /* isCustomCreated: */ false));
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                    }

                    break;
                }

                case SqlBeforeRollbackTransaction:
                {
                    var operationId = (Guid)TransactionRollbackBefore.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var connection = (SqlConnection)TransactionRollbackBefore.Connection.Fetch(evnt.Value);

                    if (this.operationHolder.Get(connection) == null)
                    {
                        var operation      = (string)TransactionRollbackBefore.Operation.Fetch(evnt.Value);
                        var timestamp      = (long)TransactionRollbackBefore.Timestamp.Fetch(evnt.Value);
                        var isolationLevel = (IsolationLevel)TransactionRollbackBefore.IsolationLevel.Fetch(evnt.Value);

                        var telemetry = new DependencyTelemetry()
                        {
                            Id      = operationId.ToString("N"),
                            Name    = string.Join(" | ", connection.DataSource, connection.Database, operation, isolationLevel),
                            Type    = RemoteDependencyConstants.SQL,
                            Target  = string.Join(" | ", connection.DataSource, connection.Database),
                            Data    = operation,
                            Success = true
                        };

                        InitializeTelemetry(telemetry, operationId, timestamp);

                        this.operationHolder.Store(connection, Tuple.Create(telemetry, /* isCustomCreated: */ false));
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                    }

                    break;
                }

                case SqlAfterCommitTransaction:
                case SqlAfterRollbackTransaction:
                {
                    var operationId = (Guid)TransactionAfter.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var connection = (SqlConnection)TransactionAfter.Connection.Fetch(evnt.Value);
                    var tuple      = this.operationHolder.Get(connection);

                    if (tuple != null)
                    {
                        this.operationHolder.Remove(connection);

                        var telemetry = tuple.Item1;

                        var timestamp = (long)TransactionAfter.Timestamp.Fetch(evnt.Value);

                        telemetry.Stop(timestamp);

                        this.client.TrackDependency(telemetry);
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(operationId.ToString("N"));
                    }

                    break;
                }

                case SqlErrorCommitTransaction:
                case SqlErrorRollbackTransaction:
                {
                    var operationId = (Guid)TransactionError.OperationId.Fetch(evnt.Value);

                    DependencyCollectorEventSource.Log.SqlClientDiagnosticSubscriberCallbackCalled(operationId, evnt.Key);

                    var connection = (SqlConnection)TransactionError.Connection.Fetch(evnt.Value);
                    var tuple      = this.operationHolder.Get(connection);

                    if (tuple != null)
                    {
                        this.operationHolder.Remove(connection);

                        var telemetry = tuple.Item1;

                        var timestamp = (long)TransactionError.Timestamp.Fetch(evnt.Value);

                        telemetry.Stop(timestamp);

                        var exception = (Exception)TransactionError.Exception.Fetch(evnt.Value);

                        ConfigureExceptionTelemetry(telemetry, exception);

                        this.client.TrackDependency(telemetry);
                    }
                    else
                    {
                        DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(operationId.ToString("N"));
                    }

                    break;
                }
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log
                .SqlClientDiagnosticSourceListenerOnNextFailed(ExceptionUtilities.GetExceptionDetailString(ex));
            }
        }
#pragma warning disable 612, 618
        private void InjectRequestHeaders(HttpRequestMessage request, string instrumentationKey, bool isLegacyEvent = false)
        {
            try
            {
                HttpRequestHeaders requestHeaders = request.Headers;
                if (requestHeaders != null && this.setComponentCorrelationHttpHeaders && !this.correlationDomainExclusionList.Contains(request.RequestUri.Host))
                {
                    string sourceApplicationId = null;
                    try
                    {
                        if (!string.IsNullOrEmpty(instrumentationKey) &&
                            !HttpHeadersUtilities.ContainsRequestContextKeyValue(requestHeaders, RequestResponseHeaders.RequestContextCorrelationSourceKey) &&
                            (this.configuration.ApplicationIdProvider?.TryGetApplicationId(instrumentationKey, out sourceApplicationId) ?? false))
                        {
                            HttpHeadersUtilities.SetRequestContextKeyValue(requestHeaders, RequestResponseHeaders.RequestContextCorrelationSourceKey, sourceApplicationId);
                        }
                    }
                    catch (Exception e)
                    {
                        AppMapCorrelationEventSource.Log.UnknownError(ExceptionUtilities.GetExceptionDetailString(e));
                    }

                    var currentActivity = Activity.Current;
                    if (isLegacyEvent)
                    {
                        if (!requestHeaders.Contains(RequestResponseHeaders.RequestIdHeader))
                        {
                            requestHeaders.Add(RequestResponseHeaders.RequestIdHeader, currentActivity.Id);
                        }

                        InjectCorrelationContext(requestHeaders, currentActivity);
                    }

                    if (this.injectLegacyHeaders)
                    {
                        // Add the root ID
                        string rootId = currentActivity.RootId;
                        if (!string.IsNullOrEmpty(rootId) && !requestHeaders.Contains(RequestResponseHeaders.StandardRootIdHeader))
                        {
                            requestHeaders.Add(RequestResponseHeaders.StandardRootIdHeader, rootId);
                        }

                        // Add the parent ID
                        string parentId = currentActivity.Id;
                        if (!string.IsNullOrEmpty(parentId) && !requestHeaders.Contains(RequestResponseHeaders.StandardParentIdHeader))
                        {
                            requestHeaders.Add(RequestResponseHeaders.StandardParentIdHeader, parentId);
                        }
                    }

                    if (this.injectW3CHeaders)
                    {
                        currentActivity.UpdateContextOnActivity();
                        string traceParent = currentActivity.GetTraceparent();
                        if (traceParent != null && !requestHeaders.Contains(W3CConstants.TraceParentHeader))
                        {
                            requestHeaders.Add(W3CConstants.TraceParentHeader, traceParent);
                        }

                        string traceState = currentActivity.GetTracestate();
                        if (!requestHeaders.Contains(W3CConstants.TraceStateHeader))
                        {
                            if (sourceApplicationId != null)
                            {
                                // TODO: there could be another az in the state.
                                // last updated state should appear first in the tracestate
                                string appIdPair = StringUtilities.FormatAzureTracestate(sourceApplicationId);
                                if (traceState == null)
                                {
                                    traceState = appIdPair;
                                }
                                else
                                {
                                    traceState = appIdPair + "," + traceState;
                                }
                            }

                            if (traceState != null)
                            {
                                requestHeaders.Add(W3CConstants.TraceStateHeader, traceState);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                AppMapCorrelationEventSource.Log.UnknownError(ExceptionUtilities.GetExceptionDetailString(e));
            }
        }
        void IObserver <KeyValuePair <string, object> > .OnNext(KeyValuePair <string, object> evnt)
        {
            try
            {
                // It's possible to host multiple apps (ASP.NET Core or generic hosts) in the same process
                // Each of this apps has it's own DependencyTrackingModule and corresponding SQL listener.
                // We should ignore events for all of them except one
                if (!SubscriptionManager.IsActive(this))
                {
                    DependencyCollectorEventSource.Log.NotActiveListenerNoTracking(evnt.Key, Activity.Current?.Id);
                    return;
                }

                switch (evnt.Key)
                {
                case SqlBeforeExecuteCommand:
                {
                    this.BeforeExecuteHelper(evnt, CommandBefore.OperationId,
                                             CommandBefore.Command,
                                             CommandBefore.CommandText,
                                             CommandBefore.Connection,
                                             CommandBefore.DataSource,
                                             CommandBefore.Database,
                                             CommandBefore.CommandType,
                                             CommandBefore.Timestamp);
                    break;
                }

                case SqlMicrosoftBeforeExecuteCommand:
                {
                    this.BeforeExecuteHelper(evnt, CommandBeforeMicrosoft.OperationId,
                                             CommandBeforeMicrosoft.Command,
                                             CommandBeforeMicrosoft.CommandText,
                                             CommandBeforeMicrosoft.Connection,
                                             CommandBeforeMicrosoft.DataSource,
                                             CommandBeforeMicrosoft.Database,
                                             CommandBeforeMicrosoft.CommandType,
                                             CommandBeforeMicrosoft.Timestamp);
                    break;
                }

                case SqlAfterExecuteCommand:
                {
                    this.AfterExecuteHelper(evnt, CommandAfter.OperationId, CommandAfter.Command, CommandAfter.Timestamp);
                    break;
                }

                case SqlMicrosoftAfterExecuteCommand:
                {
                    this.AfterExecuteHelper(evnt, CommandAfterMicrosoft.OperationId,
                                            CommandAfterMicrosoft.Command, CommandAfterMicrosoft.Timestamp);
                    break;
                }

                case SqlErrorExecuteCommand:
                {
                    this.ErrorExecuteHelper(evnt, CommandError.OperationId, CommandError.Command, CommandError.Timestamp,
                                            CommandError.Exception, CommandError.Number);
                    break;
                }

                case SqlMicrosoftErrorExecuteCommand:
                {
                    this.ErrorExecuteHelper(evnt, CommandErrorMicrosoft.OperationId, CommandErrorMicrosoft.Command,
                                            CommandErrorMicrosoft.Timestamp, CommandErrorMicrosoft.Exception, CommandErrorMicrosoft.Number);
                    break;
                }

                case SqlBeforeOpenConnection:
                {
                    this.BeforeOpenConnectionHelper(evnt, ConnectionBefore.OperationId,
                                                    ConnectionBefore.Connection,
                                                    ConnectionBefore.Operation,
                                                    ConnectionBefore.Timestamp,
                                                    ConnectionBefore.DataSource,
                                                    ConnectionBefore.Database);
                    break;
                }

                case SqlMicrosoftBeforeOpenConnection:
                {
                    this.BeforeOpenConnectionHelper(evnt, ConnectionBeforeMicrosoft.OperationId,
                                                    ConnectionBeforeMicrosoft.Connection,
                                                    ConnectionBeforeMicrosoft.Operation,
                                                    ConnectionBeforeMicrosoft.Timestamp,
                                                    ConnectionBeforeMicrosoft.DataSource,
                                                    ConnectionBeforeMicrosoft.Database);
                    break;
                }

                case SqlAfterOpenConnection:
                {
                    this.AfterOpenConnectionHelper(evnt, ConnectionAfter.OperationId, ConnectionAfter.Connection);
                    break;
                }

                case SqlMicrosoftAfterOpenConnection:
                {
                    this.AfterOpenConnectionHelper(evnt, ConnectionAfterMicrosoft.OperationId, ConnectionAfterMicrosoft.Connection);
                    break;
                }

                case SqlErrorOpenConnection:
                {
                    this.ErrorOpenConnectionHelper(evnt, ConnectionError.OperationId, ConnectionError.Connection,
                                                   ConnectionError.Timestamp, ConnectionError.Exception, ConnectionError.Number);
                    break;
                }

                case SqlMicrosoftErrorOpenConnection:
                {
                    this.ErrorOpenConnectionHelper(evnt, ConnectionErrorMicrosoft.OperationId, ConnectionErrorMicrosoft.Connection,
                                                   ConnectionErrorMicrosoft.Timestamp, ConnectionErrorMicrosoft.Exception, ConnectionErrorMicrosoft.Number);
                    break;
                }

                case SqlBeforeCommitTransaction:
                {
                    this.BeforeCommitHelper(evnt, TransactionCommitBefore.OperationId,
                                            TransactionCommitBefore.Connection,
                                            TransactionCommitBefore.Operation,
                                            TransactionCommitBefore.Timestamp,
                                            TransactionCommitBefore.IsolationLevel,
                                            TransactionCommitBefore.DataSource,
                                            TransactionCommitBefore.Database);
                    break;
                }

                case SqlMicrosoftBeforeCommitTransaction:
                {
                    this.BeforeCommitHelper(evnt, TransactionCommitBeforeMicrosoft.OperationId,
                                            TransactionCommitBeforeMicrosoft.Connection,
                                            TransactionCommitBeforeMicrosoft.Operation,
                                            TransactionCommitBeforeMicrosoft.Timestamp,
                                            TransactionCommitBeforeMicrosoft.IsolationLevel,
                                            TransactionCommitBeforeMicrosoft.DataSource,
                                            TransactionCommitBeforeMicrosoft.Database);
                    break;
                }

                case SqlBeforeRollbackTransaction:
                {
                    this.BeforeRollbackHelper(evnt, TransactionRollbackBefore.OperationId,
                                              TransactionRollbackBefore.Connection,
                                              TransactionRollbackBefore.Operation,
                                              TransactionRollbackBefore.Timestamp,
                                              TransactionRollbackBefore.IsolationLevel,
                                              TransactionRollbackBefore.DataSource,
                                              TransactionRollbackBefore.Database);
                    break;
                }

                case SqlMicrosoftBeforeRollbackTransaction:
                {
                    this.BeforeRollbackHelper(evnt, TransactionRollbackBeforeMicrosoft.OperationId,
                                              TransactionRollbackBeforeMicrosoft.Connection,
                                              TransactionRollbackBeforeMicrosoft.Operation,
                                              TransactionRollbackBeforeMicrosoft.Timestamp,
                                              TransactionRollbackBeforeMicrosoft.IsolationLevel,
                                              TransactionRollbackBeforeMicrosoft.DataSource,
                                              TransactionRollbackBeforeMicrosoft.Database);
                    break;
                }

                case SqlAfterCommitTransaction:
                {
                    this.AfterCommitHelper(evnt, TransactionCommitAfter.OperationId,
                                           TransactionCommitAfter.Connection, TransactionCommitAfter.Timestamp);
                    break;
                }

                case SqlMicrosoftAfterCommitTransaction:
                {
                    this.AfterCommitHelper(evnt, TransactionCommitAfterMicrosoft.OperationId,
                                           TransactionCommitAfterMicrosoft.Connection, TransactionCommitAfterMicrosoft.Timestamp);
                    break;
                }

                case SqlAfterRollbackTransaction:
                {
                    this.AfterRollBackHelper(evnt, TransactionRollbackAfter.OperationId,
                                             TransactionRollbackAfter.Connection,
                                             TransactionRollbackAfter.Timestamp);
                    break;
                }

                case SqlMicrosoftAfterRollbackTransaction:
                {
                    this.AfterRollBackHelper(evnt, TransactionRollbackAfterMicrosoft.OperationId,
                                             TransactionRollbackAfterMicrosoft.Connection,
                                             TransactionRollbackAfterMicrosoft.Timestamp);
                    break;
                }

                case SqlErrorCommitTransaction:
                {
                    this.ErrorCommitHelper(evnt, TransactionCommitError.OperationId,
                                           TransactionCommitError.Connection,
                                           TransactionCommitError.Timestamp,
                                           TransactionCommitError.Exception,
                                           TransactionCommitError.Number);
                    break;
                }

                case SqlMicrosoftErrorCommitTransaction:
                {
                    this.ErrorCommitHelper(evnt, TransactionCommitErrorMicrosoft.OperationId,
                                           TransactionCommitErrorMicrosoft.Connection,
                                           TransactionCommitErrorMicrosoft.Timestamp,
                                           TransactionCommitErrorMicrosoft.Exception,
                                           TransactionCommitErrorMicrosoft.Number);
                    break;
                }

                case SqlErrorRollbackTransaction:
                {
                    this.ErrorRollbackHelper(evnt, TransactionRollbackError.OperationId,
                                             TransactionRollbackError.Connection,
                                             TransactionRollbackError.Timestamp,
                                             TransactionRollbackError.Exception,
                                             TransactionRollbackError.Number);
                    break;
                }

                case SqlMicrosoftErrorRollbackTransaction:
                {
                    this.ErrorRollbackHelper(evnt, TransactionRollbackErrorMicrosoft.OperationId,
                                             TransactionRollbackErrorMicrosoft.Connection,
                                             TransactionRollbackErrorMicrosoft.Timestamp,
                                             TransactionRollbackErrorMicrosoft.Exception,
                                             TransactionRollbackErrorMicrosoft.Number);
                    break;
                }
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log
                .SqlClientDiagnosticSourceListenerOnNextFailed(ExceptionUtilities.GetExceptionDetailString(ex));
            }
        }