/// <summary>
 /// Saves the log somewhere. To a database for instance.
 /// Raw request/response is also given in case other information should be saved.
 /// </summary>
 /// <param name="logEntry">Curated data to save to a database.</param>
 /// <param name="request">Raw request.</param>
 /// <param name="response">Raw response.</param>
 protected abstract void SaveLogEntry(LogEntry logEntry, HttpRequest request, HttpResponse response);
        /// <summary>
        /// Finalizes the log.
        /// </summary>
        /// <param name="sender">Application.</param>
        /// <param name="e">Event.</param>
        private void EndRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication)sender;
            var request = application.Request;
            var response = application.Response;
            var items = request.RequestContext.HttpContext.Items;

            var filter = items[FILTER_KEY] as OutputFilterStream;
            var extra = items[EXTRA_KEY] as Dictionary<string, object>;

            var logEntry = new LogEntry
            {
                Request = new Request
                {
                    Method = request.HttpMethod,
                    RawUrl = request.RawUrl,
                    ServerProtocol = request.ServerVariables["SERVER_PROTOCOL"],
                    Headers = request.Headers,
                    Body = savedRequest,
                },
                Response = new Response
                {
                    StatusCode = response.StatusCode,
                    StatusDescription = response.StatusDescription,
                    Headers = response.Headers,
                    Body = filter != null ? filter.ReadStream() : null
                },
                Extra = extra
            };

            SaveLogEntry(logEntry, request, response);
        }