[實作練習] Exceptionless - 1.Web API利用Exceptionless紀錄Exception與log

[實作練習] Exceptionless - 1.Web API利用Exceptionless紀錄Exception與log

前言

寫程式寫log與處理Exception,都是必須要處理的項目
log來說可以用Nlog寫在txt檔,Exception 可以用Elmah來記錄
但是這些都是分散和有不好管理的問題
這次就要來介紹公司在推行的Exceptionless 來紀錄log和Exception
Exceptionless 有提供線上服務 或自己架設,這次用線上服務來實做

註冊Exceptionless Web帳號

https://exceptionless.com/
註冊帳號就不多介紹了,登入後依照下圖找到建立專案

接著要輸入Organization Name 與 Project Name 這邊輸入 test 與 ExceptionlessLab

1.選Web API 後 就會出現 說明如何在Web API專案安裝

2.用NuGet安裝Exceptionless.WebApi 套件
3.Web.config 將 API_KEY_HERE 換成 被馬賽克的那些文字
4.WebApiConfig 加入 ExceptionlessClient.Default.RegisterWebApi(config);
知道如何安裝後 就來開新專案吧

PS.免費方案的限制

建立專案

建立 一個Empty 的asp.net web專案 只勾Web API  

依照剛剛的步驟安裝
用NuGet安裝Exceptionless.WebApi 套件

Web.config 將 API_KEY_HERE 換成 被馬賽克的那些文字

WebApiConfig 加入 ExceptionlessClient.Default.RegisterWebApi(config);安裝完成!

測試紀錄Exception

完成上面步驟後就可以有紀錄Exception的功能了
首先建立一個TestController 記得要選web api2,輸入一段會出事的code

public IHttpActionResult Get()
{
    var zero = 0;
    var temp = 1 / zero;
    return Ok();
}

然後執行這段code,就會產生Exception

開起 Exceptionless Web 到 Exceptions的Dashboard 

就會看到一筆資料進來了(若沒有請稍微等一下)

點進去可以有更詳細的資料

這樣就會自動紀錄Exception,是不是很方便呢 

測試紀錄Log

紀錄log用記錄每次的request與response的內容
這邊會用到MessageHandlers 
PS.MessageHandlers 的相關技術可以參考文章
ASP.NET Web API 訊息處理器
http://huan-lin.blogspot.com/2013/01/aspnet-web-api-message-handlers.html

ASP.NET WEB API 心得筆記 (8) HTTP 訊息處理常式(HTTP MESSAGE HANDLERS)
http://blog.kkbruce.net/2012/05/aspnet-web-api-8-http-http-message.html

接下來建立資料夾與LogMessageHandler.cs
LogMessageHandler.cs 的內容為

public class LogMessageHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        var requestContent = await request.Content.ReadAsStringAsync();

        var response = await base.SendAsync(request, cancellationToken);

        var responseContent = await response.Content.ReadAsStringAsync();

        Dictionary<string, string> logData = new Dictionary<string, string>();
        logData.Add("iRequest", request.ToString());
        logData.Add("iRequestContent", requestContent.ToString());
        logData.Add("iResponse", response.ToString());
        logData.Add("iResponseContent", responseContent.ToString());

        ExceptionlessClient.Default.CreateLog(
                                source: request.RequestUri.AbsolutePath,
                                message: GetControllerNameAndActionName(request),
                                level: LogLevel.Info)
                            .AddObject(logData)
                            .Submit();
        return response;
    }

    private static string GetControllerNameAndActionName(HttpRequestMessage request)
    {
        var config = request.GetConfiguration();
        var routeData = config.Routes.GetRouteData(request);
        var controllerContext = new HttpControllerContext(config, routeData, request);

        request.Properties[HttpPropertyKeys.HttpRouteDataKey] = routeData;
        controllerContext.RouteData = routeData;

        // get controller type
        var controllerDescriptor = new DefaultHttpControllerSelector(config).SelectController(request);
        controllerContext.ControllerDescriptor = controllerDescriptor;

        // get controller name
        var controllerName = controllerDescriptor.ControllerName;

        // get action name
        var actionName = request.GetActionDescriptor().ActionName;

        return string.Format("controller name:{0},action name:{1}", controllerName, actionName);
    }
}

重點就是 ExceptionlessClient.Default.CreateLog (string source, string message, LogLevel level)
source 這裡是放網址 (或換成你想放的)
message 這裡是放 ControllerName跟ActionName (或換成你想放的)
LogLevel  是enum 跟Nlog一樣有很多可以記錄 可以選適合的來用

.AddObject(object data, string name = null, int? maxDepth = default(int?), ICollection<string> excludedPropertyNames = null, bool ignoreSerializationErrors = false);
這邊是必要輸入只有第一個object  就放入Dictionary,裡面就是放request與response的內容

.Submit();
完成紀錄log

接下來 WebApiConfig 加上

​config.MessageHandlers.Add(new LogMessageHandler());


回到TestController 加入一段可執行的code

public IHttpActionResult Get(int id)
{
    return Ok(new
        {
            code = 200,
            id = id
        });
}

就執行看看吧正常執行後
再執行看看會有Exception的code

就要去Exceptionless Web 看看有沒有紀錄2筆log


果然有紀錄2筆log
在點進去看/api/test/29 那筆log


資料都正確的顯示 成功

結語

這樣蒐集一些資訊就很方便加上 可以搜尋之後在釐清問題時 也就更快速了
最後在提醒大家Exceptionless 是有開放原始碼的可以架設這自己公司裡面
公司有MVP級的神人已經架好私有Exceptionless 確定是OK了

將程式碼放到github了 記得要去Web.config置換你的key
https://github.com/initialsam/ExceptionlessLab

這篇就先這樣了 下次聊囉 Bye

如果內容有誤請多鞭策謝謝