ASP.NET MVC'de günlüğe kaydetme hataları


109

Şu anda özel durumları günlüğe kaydetmek için ASP.NET MVC uygulamamda log4net kullanıyorum. Bunu yapmamın yolu, tüm denetleyicilerimin BaseController sınıfından miras almasıdır. BaseController'ın OnActionExecuting olayında, meydana gelmiş olabilecek istisnaları günlüğe kaydediyorum:

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);
    }
}

Bu, bir denetleyici eylemi sırasında işlenmeyen bir istisna meydana gelirse harika çalışır.

404 hatalarına gelince, web.config dosyamda şu şekilde ayarlanmış özel bir hata var:

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

Ve "sayfa bulunamadı" url'sini işleyen denetleyici eyleminde, istenen orijinal url'yi günlüğe kaydediyorum:

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

    return View();
}

Ve bu da işe yarıyor.

Karşılaştığım sorun, .aspx sayfalarında bulunan hataları günlüğe nasıl kaydedeceğim. Diyelim ki sayfalardan birinde bir derleme hatası veya bir istisna atacak bazı satır içi kodlar var:

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

Görünüşe göre HandleError özniteliği bunu Paylaşılan klasördeki Error.aspx sayfama doğru şekilde yeniden yönlendiriyor, ancak kesinlikle BaseController'ın OnActionExecuted yöntemi tarafından yakalanmıyor. Günlük kodunu Error.aspx sayfasına koyabileceğimi düşünüyordum, ancak bu düzeyde hata bilgisini nasıl alacağımdan emin değilim.


ELMAH için +1. İşte başlamanıza yardımcı olmak için yazdığım bir ELMAH Eğitimi . Ayrıca , özel hata sayfalarıyla ilgili sorunları önlemek için ASP.NET MVC kullanırken Elmah.MVC paketini kullanmayı da unutmayın .
ThomasArdal

NET uygulamalarında meydana gelen tüm hataları günlüğe kaydedecek birkaç ürün var. ELMAH veya log4net kadar düşük seviyeli değiller, ancak sadece hataları izlemeye ve teşhis etmeye çalışıyorsanız size bir ton zaman kazandırır: Bugsnag ve AirBrake bildiğim iki tanesidir .NET
Don P

Yanıtlar:


103

Elmah'ı takarak web uygulamanızı basitleştirmeyi düşünürdüm .

Elmah derlemesini projenize eklersiniz ve ardından web.config dosyanızı yapılandırırsınız. Daha sonra denetleyici veya sayfa düzeyinde oluşturulan istisnaları günlüğe kaydeder. Çeşitli farklı yerlerde (SQL Server, E-posta vb.) Oturum açmak için yapılandırılabilir. Ayrıca, istisnaların günlüğüne göz atabilmeniz için bir web ön ucu sağlar.

Oluşturduğum herhangi bir asp.net mvc uygulamasına eklediğim ilk şey.

Hala log4net kullanıyorum, ancak hata ayıklama / bilgi günlüğü için kullanma eğilimindeyim ve tüm istisnaları Elmah'a bırakıyorum.

Ayrıca , ASP.NET uygulamalarınızda hataları (İstisnalar) nasıl günlüğe kaydedersiniz? Sorusunda daha fazla bilgi bulabilirsiniz. .


3
Elmah'ı son zamanlarda kullanmaya başladım ve şimdiye kadar kullandığım en düzgün ve en basit istisna kaydedicilerden biri. MS'nin ASP.net'e dahil etmesi gerektiğini söyleyen bir yazı okudum ve kabul ediyorum.
dtc

14
Neden uygulama için hem ELMAH hem de log4net'e ihtiyacım var? Kerestecilik? Neden tek bir çözüm değil?
VJAI

Bu, n katmanlı mimarim olsa bile çalışacak mı? Denetleyiciler - hizmetler - havuzlar?
a.farkas2508

2
ELMAH aşırı derecelendirilmiştir.
Ronnie Overby

ELMAH ücretsiz mi?
Dallas

38

Global.asax'ta OnError olayına bağlanabilirsiniz.

Bunun gibi bir şey:

/// <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
Bu, tüm istisnaları yakalamalıdır. Bunun en iyi uygulama olduğunu düşünüyorum.
Andrei Rînea

4
ReSharper'ın değer analizine göre, Serverher zaman boş olmayacaktır.
Drew Noakes

6
404'ü görmezden gelmek yazdığın gibi benim için çalışmadı. Yazdığımif (ex is HttpException && ((HttpException)ex).GetHttpCode() == 404) return;
pauloya

21

MVC3
, HandleErrorInfoAttribute'dan devralan ve günlük kaydı seçiminizi içeren Öznitelik Oluşturma

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'a özellik yerleştirin

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

1

HandleError niteliğini genişletmeyi düşündünüz mü? Ayrıca, Scott'ın burada denetleyiciler / eylemler üzerindeki filtre engelleyicileri hakkında iyi bir blog yazısı var .


1

Error.aspx görünümü şu şekilde tanımlanır:

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

HandleErrorInfo üç özelliğe sahiptir: string ActionName string ControllerName Exception Exception

HandleErrorInfo'ya ve dolayısıyla görünümdeki İstisnaya erişebilmelisiniz.


0

HttpContext.Error'ı incelemeyi deneyebilirsiniz, ancak bundan emin değilim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.