Where can I setup logging?

Topics: Web Api
May 20, 2011 at 7:11 PM

I would like to log the entire request and response for a call.  When our clients are having problems using the new API we are developing (on this framework), we would like to trace the entire request.

Is there a way to get the Content of the request and response at the same time so we can log both on the same "db row"?
My first attempt looks like the following but doesn't work where there are comments.

namespace WebAPIWebApp {
    
    public class LoggingHandler : HttpOperationHandler<HttpResponseMessage, HttpResponseMessage> {

        public LoggingHandler() : base("response") { }

        public override HttpResponseMessage OnHandle(HttpResponseMessage input) {

            string requestString = getRequest(input.RequestMessage);
            string responseString = getResponse(input);

            // Log request and response

            return input;

        }

        private string getResponse(HttpResponseMessage response) {

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("HTTP/" + response.Version.Major.ToString() + "." + response.Version.Minor + " " + ((int)response.StatusCode).ToString() + " " + response.ReasonPhrase);
            sb.AppendLine("Date: " + DateTime.Now.ToString("r"));

            foreach (var key in response.Headers)
                sb.AppendLine(key.Key + ": " + string.Join(", ", key.Value));

            foreach (var key in response.Content.Headers)
                sb.AppendLine(key.Key + ": " + string.Join(", ", key.Value));

            // -----------------------------------------------------------
            // Conent stream is read or disposed
            string bodyContent = response.Content.ReadAsString();
            sb.AppendLine("Content-Length: " + bodyContent.Length.ToString());
            sb.AppendLine(Environment.NewLine + bodyContent);
            // -----------------------------------------------------------

            return sb.ToString();

        }

        private string getRequest(HttpRequestMessage request) {

            StringBuilder sb = new StringBuilder();

            sb.AppendLine(request.Method.ToString() + " " + request.RequestUri.ToString() + " HTTP/" + request.Version.Major.ToString() + "." + request.Version.Minor);

            foreach (var key in request.Headers)
                sb.AppendLine(key.Key + ": " + string.Join(", ", key.Value));

            foreach (var key in request.Content.Headers)
                sb.AppendLine(key.Key + ": " + string.Join(", ", key.Value));

            // -----------------------------------------------------------
            // Conent stream is read or disposed
            sb.AppendLine(Environment.NewLine + request.Content.ReadAsString());
            // -----------------------------------------------------------

            return sb.ToString();

        }

        
    }

}

Any pointers would be greatly appreciated. 

May 26, 2011 at 4:50 PM

Does anyone have any idea how I can accomplish something like this?  Am I looking at this wrong?

May 26, 2011 at 10:41 PM

And there's a NETFx for that! ;)

http://kzu.to/mwAr9P

And a sample on how to use it at http://kzu.to/kEPMtt. It uses System.Diagnostics to trace (through the Tracer nuget), so you can configure listeners and sources with standard web.config stuff. You can also add listeners and set tracing level dynamically on a running app using the Tracer API.

 

/kzu

May 27, 2011 at 3:14 AM

Perfect, thanks.  It looks like I was on the right track but my JsonMediaTypeFormatter was closing the stream.

Thanks again.