自從學會Self-Hosting ASP.NET Web API,遇到Console Application/Window Form/WPF程式需提供API介面的場合,我都二話不說召喚它出來打怪,開開心心地在EXE裡寫Web,好不快意~

最近有個情境,需要為Web API保留存取Log記錄,查了一下,HttpSelfHostServer似乎沒提供內建的Logging機制。沒想太多,決定利用MessageHandler配合NLog自己寫一個。

LogHandler只需繼承DelegatingHandler實作SendAsync(),攔截Request及Reponse輸出到NLog,程式碼不多:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.ServiceModel.Channels;
using System.Text;
using NLog;
 
namespace MySelfHostWebApi
{
    public class LogHandler : DelegatingHandler
    {
        private static Logger logger = NLog.LogManager.GetCurrentClassLogger();
 
        //REF: http://blog.kkbruce.net/2012/05/aspnet-web-api-8-http-http-message.html
        protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, 
            System.Threading.CancellationToken cancellationToken)
        {
            //取得Method、IP、Url等等,稍後寫入NLog
            string method = request.Method.ToString();
            //REF: http://bit.ly/16lpGKM
            //在Self-Hosted模式,透過RemoteEndpointMessageProperty取得IP
            string ip = "Unknown";
            if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
                ip = ((RemoteEndpointMessageProperty)
                    request.Properties[RemoteEndpointMessageProperty.Name]).Address;
            string url = request.RequestUri.ToString();
            
            return base.SendAsync(request, cancellationToken)
                .ContinueWith((task) =>
                {
                    //Response回傳時,連同StatusCode一起寫入NLog
                    HttpResponseMessage resp = task.Result as HttpResponseMessage;
                    logger.Log(LogLevel.Trace, string.Format("{0} {1} {2} {3}", 
                        ip, method, url, (int)resp.StatusCode));
                    return resp;
                });
        }
    }
}

使用方法很簡單,將LogHandler加進HttpSelfHostConfiguration.MessageHandlers,再設妥NLog.config,就大功告成囉!

            //設定路由
            config.Routes.MapHttpRoute("API", 
                "{id}",
                 new { 
                     controller = "download",
                     action = "index"
                 });
            //加上LogHandler,記錄存取Log
            config.MessageHandlers.Add(new LogHandler());
 
            httpServer = new HttpSelfHostServer(config);

記錄的Log檔範例如下:

2013-08-01 05:14:46.4144 192.168.1.5 GET httq://192.168.1.1:4567/test.jpg 404
2013-08-01 05:18:15.9233 192.168.1.18 GET httq://192.168.1.1:4567/66fd.png 200

【延伸閱讀】


Comments

Be the first to post a comment

Post a comment