public async Task Invoke(IDictionary <string, object> environment)
        {
            var id = Guid.NewGuid();

            BeforeProcessing(id, environment);

            // Hijack the response stream
            var responseBody = EnvironmentHelper.GetResponseBody(environment);
            var hijackBody   = new RequestTrackerHijackStream(responseBody, 128 * 1024); // 128 KB

            EnvironmentHelper.SetResponseBody(environment, hijackBody);

            try
            {
                var path = EnvironmentHelper.GetRequestPath(environment);
                if (string.Compare(path, "/RequestTracker/B", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    var keyValues = EnvironmentHelper.ParseRequestKeyValues(environment);
                    BrowseRequests(
                        environment,
                        keyValues.ContainsKey("count") ? (int?)int.Parse(keyValues["count"]) : null,
                        keyValues.ContainsKey("ipAddress") ? keyValues["ipAddress"] : null,
                        keyValues.ContainsKey("userAgent") ? keyValues["userAgent"] : null,
                        keyValues.ContainsKey("accessToken") ? keyValues["accessToken"] : null
                        );
                }
                else if (path.StartsWith("/RequestTracker/BR/", StringComparison.OrdinalIgnoreCase))
                {
                    var idString = path.Substring("/RequestTracker/BR/".Length);
                    BrowseRequest(environment, Guid.Parse(idString));
                }
                else
                {
                    await _next(environment);
                }
            }
            catch (Exception ex)
            {
                // Restore the original response stream
                EnvironmentHelper.SetResponseBody(environment, responseBody);

                AfterProcessing(id, environment, hijackBody, ex);
                throw;
            }
            // Restore the original response stream
            EnvironmentHelper.SetResponseBody(environment, responseBody);

            var internalException = EnvironmentHelper.GetApplicationInternalException(environment);

            if (internalException != null)
            {
                AfterProcessing(id, environment, hijackBody, internalException);
            }
            else
            {
                AfterProcessing(id, environment, hijackBody, null);
            }
        }
        private void AfterProcessing(Guid id, IDictionary <string, object> environment, RequestTrackerHijackStream hijackStream, Exception exception)
        {
            RequestTrackerData data;

            lock (_requestMap)
            {
                if (!_requestMap.TryGetValue(id, out data))
                {
                    _logger.Error("Cannot find the RequestTrackerData in _requestMap. Id:" + id.ToString("N"));
                    return;
                }
            }

            DateTime utcNow = DateTime.UtcNow;

            data.ProcessedTime = utcNow;

            if (exception != null)
            {
                data.Exception = exception.ToString();
            }
            else
            {
                data.Exception = string.Empty;

                data.ResponseHttpCode = EnvironmentHelper.GetResponseStatusCode(environment, 0);
                var headers = EnvironmentHelper.GetResponseHeaders(environment);
                foreach (var pair in headers)
                {
                    data.ResponseHeaders[pair.Key] = string.Join(", ", pair.Value);
                }

                var body = EnvironmentHelper.GetResponseBody(environment);
                if ((body == null) || (body == Stream.Null))
                {
                    data.ResponseBody       = new byte[0];
                    data.ResponseBodyLength = data.ResponseBody.Length;
                }
                else
                {
                    data.ResponseBody       = hijackStream.GenerateHijackSnapshot();
                    data.ResponseBodyLength = hijackStream.TotalLength;
                }
            }
        }