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만큼 낮은 수준은 아니지만 오류를 모니터링하고 진단하려는 경우 시간을 절약 할 수 있습니다. BugsnagAirBrake 는 제가 아는 두 가지입니다. .NET
Don P

답변:


103

Elmah 를 연결하여 웹 애플리케이션을 단순화하는 것을 고려할 것 입니다.

Elmah 어셈블리를 프로젝트에 추가 한 다음 web.config를 구성합니다. 그런 다음 컨트롤러 또는 페이지 수준에서 생성 된 예외를 기록합니다. 다양한 장소 (SQL Server, 이메일 등)에 기록하도록 구성 할 수 있습니다. 또한 웹 프런트 엔드를 제공하므로 예외 로그를 ​​탐색 할 수 있습니다.

내가 만든 asp.net mvc 앱에 가장 먼저 추가 한 것입니다.

나는 여전히 log4net을 사용하지만 디버그 / 정보 로깅에 사용하는 경향이 있으며 모든 예외는 Elmah에 남겨 둡니다.

ASP.NET 앱에서 오류 (예외)를 기록하는 방법 질문에서 자세한 정보를 찾을 수도 있습니다 . .


3
저는 최근에 Elmah를 사용하기 시작했으며 지금까지 사용해 본 것 중 가장 매끄럽고 간단한 예외 로거 중 하나입니다. 나는 MS가 그것을 ASP.net에 포함시켜야한다는 글을 읽었고 동의한다.
dtc

14
앱에 ELMAH와 log4net이 모두 필요한 이유. 벌채 반출? 단일 솔루션이 아닌 이유는 무엇입니까?
VJAI

n 계층 아키텍처가 있어도 작동합니까? 컨트롤러-서비스-저장소?
a.farkas2508

2
ELMAH는 과대 평가되었습니다.
Ronnie Overby

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
이것은 모든 예외를 포착해야합니다. 나는 이것이 최선의 방법이라고 생각합니다.
안드레이 Rînea

4
ReSharper의 가치 분석에 따르면 Server항상 null이 아닙니다.
Drew Noakes 2011 년

6
404를 무시하는 것은 당신이 작성한 방식대로 작동하지 않았습니다. 내가 쓴if (ex is HttpException && ((HttpException)ex).GetHttpCode() == 404) return;
pauloya

21

MVC3
HandleErrorInfoAttribute에서 상속되고 선택한 로깅을 포함하는 속성 만들기

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에는 세 가지 속성이 있습니다. string ActionName string ControllerName Exception Exception

HandleErrorInfo에 액세스 할 수 있어야하므로 뷰 내에서 예외가 발생합니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.