Cara menggunakan ELMAH untuk mencatat kesalahan secara manual

259

Apakah mungkin melakukan hal berikut menggunakan ELMAH?

logger.Log(" something");

Saya melakukan sesuatu seperti ini:

try 
{
    // Code that might throw an exception 
}
catch(Exception ex)
{
    // I need to log error here...
}

Pengecualian ini tidak akan secara otomatis dicatat oleh ELMAH, karena ditangani.

Omu
sumber
1
Untuk referensi di masa mendatang, saya menulis posting tentang hal itu: Kesalahan pencatatan program . Tutorial ELMAH saya juga memiliki beberapa informasi tentang ini.
ThomasArdal

Jawaban:

412

Metode penulisan log langsung, bekerja sejak ELMAH 1.0:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
}

ELMAH 1.2 memperkenalkan API yang lebih fleksibel:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}

Ada perbedaan antara dua solusi:

  • RaiseMetode berlaku aturan penyaringan ELMAH pengecualian. Logmetode tidak.
  • Raise berbasis langganan dan dapat mencatat satu pengecualian ke beberapa penebang.
Andrey Kamaev
sumber
1
apa perbedaan antara metode Anda dan yang lainnya?
Omu
3
Ini mencatat kesalahan dalam Elmah tanpa menyebabkan aplikasi berhenti bekerja. Ini memungkinkan Anda untuk menangkap pengecualian umum, menanganinya dengan benar, tetapi masih bisa mencatatnya.
PCasagrande
7
Saya menemukan bahwa Elmah.ErrorSignal tidak masuk ketika POST kembali berisi Html tidak aman untuk Mvc4. Net 4.5, dalam contoh saya POST kembali dari Layanan Kontrol Akses Windows dengan SignInResponseMessage. Elmah.ErrorLog.GetDefault berhasil dalam skenario itu
Adam
1
Saya memiliki masalah yang sama dengan Html yang tidak aman. ErrorLog.GetDefault melakukan trik
hgirish
4
Satu peringatan besar ketika menggunakan Elmah.ErrorLog.Log(): ia melempar seandainya panggilan log itu sendiri gagal, mungkin menjatuhkan seluruh aplikasi web. Raise()gagal diam-diam. Misalnya: jika ada masalah kesalahan konfigurasi di sisi server (mis. Elmah dikonfigurasi untuk menyimpan kesalahan ke disk, tetapi tidak memiliki akses yang benar ke folder log), .Log()metode ini akan melempar. (Ini bagus untuk debugging, misalnya mengapa tidak .Raise()mencatat apa pun?)
Cristian Diaconescu
91

Saya akan merekomendasikan membungkus panggilan ke Elmah dalam kelas pembungkus sederhana Anda sendiri.

using Elmah;

public static class ErrorLog
{
    /// <summary>
    /// Log error to Elmah
    /// </summary>
    public static void LogError(Exception ex, string contextualMessage=null)
    {
        try
        {
            // log error to Elmah
            if (contextualMessage != null) 
            {
                // log exception with contextual information that's visible when 
                // clicking on the error in the Elmah log
                var annotatedException = new Exception(contextualMessage, ex); 
                ErrorSignal.FromCurrentContext().Raise(annotatedException, HttpContext.Current);
            }
            else 
            {
                ErrorSignal.FromCurrentContext().Raise(ex, HttpContext.Current);
            }

            // send errors to ErrorWS (my own legacy service)
            // using (ErrorWSSoapClient client = new ErrorWSSoapClient())
            // {
            //    client.LogErrors(...);
            // }
        }
        catch (Exception)
        {
            // uh oh! just keep going
        }
    }
}

Kemudian panggil saja setiap kali Anda perlu mencatat kesalahan.

try {
   ...
} 
catch (Exception ex) 
{
    // log this and continue
    ErrorLog.LogError(ex, "Error sending email for order " + orderID);
}

Ini memiliki manfaat sebagai berikut:

  • Anda tidak perlu mengingat sintaks panggilan Elmah yang sedikit kuno ini
  • Jika Anda memiliki banyak DLL, Anda tidak perlu merujuk Elmah Core dari setiap satu - dan cukup letakkan ini di DLL 'Sistem' Anda sendiri.
  • Jika Anda perlu melakukan penanganan khusus atau hanya ingin memasukkan breakpoint ke kesalahan debug Anda memiliki semuanya satu tempat.
  • Jika Anda pernah pindah dari Elmah Anda hanya dapat mengubah satu tempat.
  • Jika Anda memiliki pendataan kesalahan lama yang ingin Anda pertahankan (Saya kebetulan memiliki mekanisme pendataan kesalahan sederhana yang terkait dengan beberapa UI yang saya tidak segera punya waktu untuk menghapusnya).

Catatan: Saya telah menambahkan properti 'kontekstualMessage' untuk informasi kontekstual. Anda dapat menghilangkan ini jika Anda mau tetapi saya merasa sangat berguna. Elmah secara otomatis membuka bungkus pengecualian sehingga pengecualian yang mendasarinya masih akan dilaporkan dalam log tetapi Pesan kontekstual akan terlihat ketika Anda mengkliknya.

Simon_Weaver
sumber
1
Jawaban yang bagus Mungkin ELMAH harus mengimplementasikan sesuatu yang mirip di luar kotak. Terkadang sangat sulit untuk men-debug kesalahan tanpa konteks.
ra00l
2
Saya suka semua tetapi menelan kesalahan sekunder dengan // uh oh! just keep going. Jika penanganan kesalahan saya gagal saya ingin tahu. Saya ingin membuat kebisingan.
Jeremy Cook
3
@JeremyCook Saya setuju, tetapi dengan peringatan bahwa jika Anda tidak hati-hati, rutinitas penanganan kesalahan yang gagal cenderung berakhir dengan menyebut diri mereka sendiri dan kemudian meledak (oh dan saya juga benar-benar memanggil API pihak ketiga di sini untuk mencatat kesalahan tersebut). Saya mungkin tidak seharusnya membiarkan ini untuk jawaban ini, tetapi saya memiliki pengalaman buruk dengan hal seperti itu terjadi sebelumnya
Simon_Weaver
1
Akan lebih baik lagi sebagai metode ekstensi.
Stephen Kennedy
1
Anda mungkin berpikir: nah, berapa banyak kesalahan manual yang bisa saya coba login? Saya pikir itu, sekitar setahun yang lalu. Singkat cerita: gunakan pembungkus ini!
nmit026
29

Anda bisa menggunakan metode Elmah.ErrorSignal () untuk mencatat masalah tanpa memunculkan pengecualian.

try
{
    // Some code
}
catch(Exception ex)
{
    // Log error
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);

    // Continue
}
bigtv
sumber
19
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
Darin Dimitrov
sumber
14

Ya itu mungkin. ELMAH dirancang untuk mencegat pengecualian yang tidak ditangani. Namun Anda dapat memberi sinyal pengecualian ke ELMAH melalui kelas ErrorSignal. Pengecualian tersebut tidak dibuang (jangan digembungkan), tetapi hanya dikirim ke ELMAH (dan kepada pelanggan acara Naikkan kelas ErrorSignal).

Contoh kecil:

protected void ThrowExceptionAndSignalElmah()
{
    ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
}
Christophe Geers
sumber
13

Saya mencari untuk melakukan hal yang sama di utas saya mulai mengantri surat dari dalam aplikasi MVC4 saya, karena itu saya tidak memiliki HttpContext tersedia ketika pengecualian muncul. Untuk melakukan ini saya berakhir dengan yang berikut berdasarkan pertanyaan ini dan jawaban lain yang ditemukan di sini: elmah: pengecualian tanpa HttpContext?

Dalam file konfigurasi saya tentukan nama aplikasi:

<elmah>
    <security allowRemoteAccess="false" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="myApplication"/>   
</elmah>

Kemudian dalam kode (seperti jawaban yang diberikan di atas, tetapi tanpa HttpContext) Anda dapat melewatkan nol alih-alih HttpContext:

ThreadPool.QueueUserWorkItem(t => {
     try {
         ...
         mySmtpClient.Send(message);
     } catch (SomeException e) {
         Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(e));
     }
 });
Matius
sumber
Saya suka solusi Anda; Namun, saya tidak dapat menyelesaikan "Elmah." dalam proyek saya. Saya mencoba menambahkan "menggunakan Elmah;" dalam kode saya, tetapi tidak ada dalam konteks saya saat ini.
Taersious
@Taersious Seperti apa packages.configpenampilan Anda ? Apakah Anda melihat sesuatu seperti <package id="elmah" version="1.2.2" targetFramework="net45" /> <package id="elmah.corelibrary" version="1.2.2" targetFramework="net45" /> <package id="elmah.sqlserver" version="1.2" targetFramework="net45" />':? Apakah Anda menginstal dengan NuGET?
Matius
Saya ingin mengatakan ya, tetapi proyek saya saat ini terkunci di kontrol sumber. Saya menerapkan elmah secara manual dari file config sampel dalam proyek.
Taersious
@Taersious Jika melakukannya secara manual, apakah Anda menambahkan referensi Elmah ke proyek sebelum memohon penggunaan ... Saya akan berharap itu bekerja dengan cara baik, tapi saya tahu bahwa ketika nuget menambahkannya, baris di atas ditambahkan kepackages.config
Matthew
3

Terkadang CurrentHttpContextmungkin tidak tersedia.

Menetapkan

public class ElmahLogger : ILogger
{
    public void LogError(Exception ex, string contextualMessage = null, bool withinHttpContext = true)
    {
        try
        {
            var exc = contextualMessage == null 
                      ? ex 
                      : new ContextualElmahException(contextualMessage, ex);
            if (withinHttpContext)
                ErrorSignal.FromCurrentContext().Raise(exc);
            else
                ErrorLog.GetDefault(null).Log(new Error(exc));
        }
        catch { }
    }
}

Menggunakan

public class MyClass
{
    readonly ILogger _logger;

    public MyClass(ILogger logger)
    {
        _logger = logger;
    }

    public void MethodOne()
    {
        try
        {

        }
        catch (Exception ex)
        {
            _logger.LogError(ex, withinHttpContext: false);
        }
    }
}
tchelidze
sumber
2

Saya menggunakan inti ASP.NET dan saya menggunakan ElmahCore .

Untuk secara manual mencatat kesalahan dengan HttpContext (di controller) cukup tulis:

using ElmahCore;
...
HttpContext.RiseError(new Exception("Your Exception"));

Di bagian lain aplikasi Anda tanpa HttpContext :

using ElmahCore;
...
ElmahExtensions.RiseError(new Exception("Your Exception"));
A. Morel
sumber
0

Saya mencoba untuk menulis pesan khusus ke dalam log elmah menggunakan Signal.FromCurrentContext (). Naikkan (ex); dan menemukan bahwa pengecualian ini menggelembung, misalnya:

try
{
    ...
}
catch (Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
    // this will write to the log AND throw the exception
}

Selain itu saya tidak melihat bagaimana elmah mendukung berbagai level logging - apakah mungkin untuk mematikan logging verbose dengan pengaturan web.config?

Valery Gavrilov
sumber
1
Jika Anda menangkap pengecualian dan tidak melemparnya lagi, pengecualian tidak muncul. Mungkin saya salah paham? ELMAH tidak mendukung level logging yang berbeda. Ini hanya untuk kesalahan.
ThomasArdal
Terima kasih, Thomas. Itulah tepatnya yang saya coba konfirmasi
Valery Gavrilov
0

Digunakan baris ini dan itu berfungsi dengan baik.

 try{
            //Code which may throw an error
    }
    catch(Exception ex){
            ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
    }
Prajakta Kale
sumber