ASP.NET MVCでのエラーのロギング


109

現在、ASP.NET MVCアプリケーションでlog4netを使用して、例外をログに記録しています。これを行う方法は、すべてのコントローラーにBaseControllerクラスを継承させることです。BaseControllerのOnActionExecutingイベントで、発生した可能性のある例外をログに記録します。

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
    // Log any exceptions
    ILog log = LogManager.GetLogger(filterContext.Controller.GetType());

    if (filterContext.Exception != null)
    {
        log.Error("Unhandled exception: " + filterContext.Exception.Message +
            ". Stack trace: " + filterContext.Exception.StackTrace, 
            filterContext.Exception);
    }
}

これは、コントローラーのアクション中に未処理の例外が発生した場合に適切に機能します。

404エラーについては、web.configで次のようにカスタムエラーを設定しています。

<customErrors mode="On">
    <error statusCode="404" redirect="~/page-not-found"/>
</customErrors>

そして、「page-not-found」URLを処理するコントローラーアクションで、リクエストされた元のURLをログに記録します。

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult PageNotFound()
{
    log.Warn("404 page not found - " + Utils.SafeString(Request.QueryString["aspxerrorpath"]));

    return View();
}

そして、これも機能します。

私が抱えている問題は、.aspxページ自体にあるエラーをログに記録する方法です。例外をスローするページまたはインラインコードのいずれかにコンパイルエラーがあるとします。

<% ThisIsNotAValidFunction(); %>
<% throw new Exception("help!"); %>

HandleError属性は、これをSharedフォルダーのError.aspxページに正しく再ルーティングしているようですが、BaseControllerのOnActionExecutedメソッドによって確実にキャッチされていません。Error.aspxページ自体にログコードを配置できると考えていましたが、そのレベルでエラー情報を取得する方法がわかりません。


ELMAHの場合は+1。これは私があなたが始めるのを助けるために書いたELMAHチュートリアルです。また、使用することを忘れないでくださいElmah.MVCの ASP.NET MVCを使用するときにカスタムエラーページなどの問題を回避するために、パッケージを
ThomasArdal

.NETアプリで発生するすべてのエラーをログに記録する製品がいくつかあります。あなただけのエラーを監視&診断しようとしているなら、彼らはELMAHまたはlog4netのような低レベルとしてじゃない、しかし、あなたの時間のトンを保存します。Bugsnagエアブレーキは、私は.NET知っていることの2つです
ドン・P

回答:


103

Elmahをプラグインすることで、Webアプリケーションを簡略化することを検討します。

Elmahアセンブリをプロジェクトに追加し、web.configを構成します。次に、コントローラーまたはページレベルで作成された例外をログに記録します。さまざまな場所(SQL Server、電子メールなど)にログを記録するように構成できます。また、例外のログを参照できるように、Webフロントエンドも提供します。

作成したasp.net mvcアプリに最初に追加するものです。

私は今でもlog4netを使用していますが、デバッグ/情報のロギングに使用する傾向があり、すべての例外をElmahに任せています。

また、問題のより多くの情報を見つけることができ、あなたのASP.NETアプリケーションでエラー(例外)をログに記録するにはどうすればよいですか?


3
私は最近Elmahを使い始めました、そしてそれは私が今まで使った中で最も滑らかで最も単純な例外ロガーの1つです。MSがASP.netに含める必要があるという投稿を読み、同意します。
dtc

14
アプリにELMAHとlog4netの両方が必要な理由 ロギング?なぜ単一のソリューションではないのですか?
VJAI 2012

これは、n層アーキテクチャーでも機能しますか?コントローラー-サービス-リポジトリ?
a.farkas2508 2015

2
ELMAHは過大評価されています。
ロニーオーバーバイ

ELMAHは無料ですか?
ダラス

38

Global.asaxのOnErrorイベントにフックできます。

このようなもの:

/// <summary>
/// Handles the Error event of the Application control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Application_Error(object sender, EventArgs e)
{
    if (Server != null)
    {
        Exception ex = Server.GetLastError();

        if (Response.StatusCode != 404 )
        {
            Logging.Error("Caught in Global.asax", ex);
        }

    }


}

3
これですべての例外がキャッチされます。私はこれをベストプラクティスと考えています。
AndreiRînea2010年

4
ReSharperの値分析によると、Serverは常にnull以外になります。
Drew Noakes、2011年

6
404を無視しても、あなたが書いた方法ではうまくいきませんでした。私が書いたif (ex is HttpException && ((HttpException)ex).GetHttpCode() == 404) return;
pauloya 2011

21

HandleErrorInfoAttribute
から継承し、ログの選択を含むMVC3 Create Attribute

public class ErrorLoggerAttribute : HandleErrorAttribute 
{
    public override void OnException(ExceptionContext filterContext)
    {
        LogError(filterContext);
        base.OnException(filterContext);
    }

    public void LogError(ExceptionContext filterContext)
    {
       // You could use any logging approach here

        StringBuilder builder = new StringBuilder();
        builder
            .AppendLine("----------")
            .AppendLine(DateTime.Now.ToString())
            .AppendFormat("Source:\t{0}", filterContext.Exception.Source)
            .AppendLine()
            .AppendFormat("Target:\t{0}", filterContext.Exception.TargetSite)
            .AppendLine()
            .AppendFormat("Type:\t{0}", filterContext.Exception.GetType().Name)
            .AppendLine()
            .AppendFormat("Message:\t{0}", filterContext.Exception.Message)
            .AppendLine()
            .AppendFormat("Stack:\t{0}", filterContext.Exception.StackTrace)
            .AppendLine();

        string filePath = filterContext.HttpContext.Server.MapPath("~/App_Data/Error.log");

        using(StreamWriter writer = File.AppendText(filePath))
        {
            writer.Write(builder.ToString());
            writer.Flush();
        }
    }

Global.asax RegisterGlobalFiltersに属性を配置します

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
       // filters.Add(new HandleErrorAttribute());
        filters.Add(new ErrorLoggerAttribute());
    }

1

HandleError属性の拡張について考えましたか?また、Scottは、コントローラー/アクションのフィルターインターセプターについての優れたブログ投稿をここに掲載しています


1

Error.aspxビューは次のように定義されています。

namespace MvcApplication1.Views.Shared
{
    public partial class Error : ViewPage<HandleErrorInfo>
    {
    }
}

HandleErrorInfoには3つのプロパティがあります。string ActionName string ControllerName Exception Exception

HandleErrorInfoにアクセスできるため、ビュー内の例外にアクセスできるはずです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.