2017年9月15日金曜日

ASP.NET MVCのエラーをログファイルに出力する

ASP.NET MVCのエラーをログファイルに出力する。

HandleErrorAttribute.OnException

Controller内で起きた例外を処理する集約例外ハンドラを実装します。
Ajaxリクエストの場合はデフォルトの例外処理は何もせず、
ステータスコードを500、応答本文を例外情報を含んだJSONにして、
$.ajax().fail()で例外処理をしやすくしておきます。

using System;
using System.IO;
using System.Net;
using System.Web;
using System.Web.Mvc;

using System.Web.Optimization;
using System.Web.Routing;
using System.Text;


namespace Jobs {
    public class GlobalHandleErrorAttribute : HandleErrorAttribute {
        public override void OnException(ExceptionContext filterContext) {
            if (filterContext == null) {
                throw new ArgumentNullException("filterContext");
            }

            // ルート・パラメータを取得
            var route = filterContext.RouteData;
          
            // 例外発生時は常にログを取っておく
            StreamWriter objSw = new StreamWriter(HttpContext.Current.Server.MapPath("~/WebApp_Err.log"), true, Encoding.GetEncoding("utf-8"));

            StringBuilder objBld = new StringBuilder();

            objBld.Append(DateTime.Now.ToString());
            objBld.Append("\t");
            objBld.Append(filterContext.HttpContext.Request.RawUrl);
            objBld.Append("\t");
            objBld.Append(route.Values["controller"].ToString());
            objBld.Append("\t");
            objBld.Append(route.Values["action"].ToString());
            objBld.Append("\t");
            objBld.Append(filterContext.Exception.StackTrace);

            objSw.WriteLine(objBld.ToString());
            objSw.Close();

            //LogUtil.LogControllerError(filterContext);

            if (filterContext.HttpContext.Request.IsAjaxRequest()) {
                /// Application_Errorは呼ばれない
                HandleAjaxRequestException(filterContext);
            }
            else {
                /// custom errorが有効でなければ
                /// base.OnException()でExceptionHandledがtrueにならないので
                /// Application_Errorも呼ばれる
                base.OnException(filterContext);
            }
        }

        private void HandleAjaxRequestException(ExceptionContext filterContext) {
            if (filterContext.ExceptionHandled) {
                return;
            }

            filterContext.Result = new JsonResult
            {
                Data = new {
                    Message = filterContext.ToString(),
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                }
            };

            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
        }
    }
}


FilterConfig.csのRegisterGlobalFilters()を編集します。
もともとあるfilters.Add(new HandleErrorAttribute());をコメントアウトして、
代わりにGlobalHandleErrorAttributeを登録します。
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    //filters.Add(new HandleErrorAttribute());
    filters.Add(new GlobalHandleErrorAttribute());
} 
 

Application_Error

Controller外で起きた例外を補足するにはApplication_Error()を定義します。
これはGlobal.asax.csを修正する

using System.IO;
using System.Text;

void Application_Error(object sender, EventArgs e) {
            StreamWriter objSw = new StreamWriter(Server.MapPath("~/WebApp_Err.log"), true, Encoding.GetEncoding("utf-8"));
            Exception objErr = Server.GetLastError();
            StringBuilder objBld = new StringBuilder();
            objBld.Append(DateTime.Now.ToString());
            objBld.Append("\t");
            objBld.Append(objErr.Source);
            objBld.Append("\t");
            objBld.Append(objErr.Message);
            objBld.Append("\t");
            objBld.Append(objErr.TargetSite.ToString());
            objSw.WriteLine(objBld.ToString());
            objSw.Close();
        }

元ネタ http://qiita.com/mocha/items/6928870b2d02d4c1ac37

0 件のコメント:

コメントを投稿