ELMAHを使用して手動でエラーを記録する方法


259

ELMAHを使用して次のことを行うことはできますか?

logger.Log(" something");

私はこのようなことをしています:

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

この例外は処理されたため、ELMAHによって自動的にログに記録されません。


1
将来の参考のために、私はそれについて正確に投稿しました:プログラムによるエラーのロギング。私のELMAHチュートリアルにも、これに関するいくつかの情報があります。
ThomasArdal 2016

回答:


412

ELMAH 1.0以降で機能する直接ログ書き込み方法:

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

ELMAH 1.2では、より柔軟なAPIが導入されています。

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

2つのソリューションには違いがあります。

  • Raiseメソッドは、ELMAHフィルタリングルールを例外に適用します。Logメソッドにはありません。
  • Raise サブスクリプションベースであり、1つの例外を複数のロガーに記録できます。

1
あなたの方法と他の方法の違いは何ですか?
オム2011

3
これらは、アプリケーションの動作を停止させることなくElmahでエラーを記録します。これにより、一般的な例外をキャッチして適切に処理しながら、ログに記録することができます。
PCasagrande 2013年

7
POSTバックにMvc4 .Net 4.5の安全でないHtmlが含まれている場合、Elmah.ErrorSignalがログに記録されないことがわかりました。私の例では、SignInResponseMessageを使用したWindowsアクセスコントロールサービスからのPOSTバックです。Elmah.ErrorLog.GetDefaultはこのシナリオで機能しました
アダム

1
安全でないHTMLでも同じ問題が発生しました。ErrorLog.GetDefaultがトリックを実行しました
2013

4
使用時の1つの大きな警告Elmah.ErrorLog.Log():ログの呼び出し自体が失敗した場合にスローされ、Webアプリ全体がダウンする可能性があります。Raise()静かに失敗します。たとえば、サーバー側で構成の問題がある場合(たとえば、Elmahはエラーをディスクに保存するように構成されているが、ログフォルダーへの正しいアクセス権がない場合)、.Log()メソッドはスローします。(ただし、これはデバッグに適しています。たとえば、.Raise()何もログに記録しないのはなぜですか?)
Cristian Diaconescu

91

Elmahへの呼び出しを、独自の単純なラッパークラスでラップすることをお勧めします。

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

その後、エラーをログに記録する必要があるときはいつでも呼び出します。

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

これには次の利点があります。

  • Elmah呼び出しのこの少し古い構文を覚えておく必要はありません
  • 多くのDLLがある場合、すべてのDLLからElmah Coreを参照する必要はありません。これを独自の「システム」DLLに置くだけです。
  • 特別な処理を行う必要がある場合、またはエラーをデバッグするためにブレークポイントを設定する場合は、すべて1か所にあります。
  • Elmahから離れる場合は、1つの場所を変更できます。
  • 保持したいレガシーのエラーロギングがある場合(たまたま、すぐに削除する時間がない一部のUIに関連付けられている単純なエラーロギングメカニズムがあります)。

注:コンテキスト情報の「contextualMessage」プロパティを追加しました。必要に応じてこれを省略できますが、非常に便利です。Elmahは自動的に例外をアンラップするため、基になる例外は引き続きログに報告されますが、contextualMessageはクリックすると表示されます。


1
すばらしい答えです。ELMAHは、箱から出してすぐに同様の何かを実装する必要があります。コンテキストなしでエラーをデバッグすることは本当に難しい場合があります。
ra00l 2013

2
二次的エラーをで飲み込む以外はすべて好き// uh oh! just keep goingです。エラー処理が失敗した場合、知りたいです。音を立てて欲しい。
ジェレミークック

3
@JeremyCook私は同意しますが、注意しないと、エラー処理ルーチンが失敗すると、自分自身が呼び出されて爆発する傾向があります(ああ、私は実際にここにサードパーティのAPIを呼び出してエラーをログに記録していました)。私はおそらく、この回答のためにこれを残しておくべきではありませんでしたが、以前にそのようなことで悪い経験がありました
Simon_Weaver

1
それは、拡張メソッドとしてはさらに良いでしょう。
スティーブンケネディ

1
あなたは考えているかもしれません:いや、ログに記録しようとする手動エラーの数はいくつでしょうか?1年ほど前だと思いました。要するに、このラッパーを使用してください!
nmit026 2017年

29

Elmah.ErrorSignal()メソッドを使用して、例外を発生させずに問題をログに記録できます。

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

    // Continue
}


14

はい、可能です。ELMAHは、未処理の例外をインターセプトするように設計されています。ただし、ErrorSignalクラスを介してELMAHに例外を通知できます。これらの例外はスローされません(バブルアップしません)が、ELMAH(およびErrorSignalクラスのRaiseイベントのサブスクライバー)にのみ送信されます。

小さな例:

protected void ThrowExceptionAndSignalElmah()
{
    ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
}

13

例外が発生したときにHttpContextを使用できなかったため、MVC4アプリケーション内からメールをキューに入れ始めたスレッドでこれと同じことを実行しようとしていました。これを行うために、私はこの質問とここにある別の答えに基づいて次のようになりました:elmah:HttpContextなしの例外?

設定ファイルでアプリケーション名を指定しました:

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

次に、コードで(上記の回答のように、HttpContextなしで)、HttpContextの代わりにnullを渡すことができます。

ThreadPool.QueueUserWorkItem(t => {
     try {
         ...
         mySmtpClient.Send(message);
     } catch (SomeException e) {
         Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(e));
     }
 });

私はあなたの解決策が好きです。しかし、「エルマ」を解決することはできません。私のプロジェクトで。「Elmahを使って」を追加してみました。私のコードでは、それは私の現在のコンテキストには存在しません。
13

@Taersiousあなたはpackages.configどのように見えますか?次のようなものが表示され<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" />'ますか?NuGETでインストールしましたか?
Matthew

はいと言いたいのですが、私のプロジェクトは現在ソース管理でロックされています。プロジェクトのサンプル構成ファイルからelmahを手動で実装しました。
13

@Taersious手動で行う場合、使用を呼び出す前にプロジェクトにElmah参照を追加しましたか?私はそれがどちらの方法でも機能すると予想しますが、nugetを追加すると、上記の行がpackages.config
Matthew

3

時々CurrentHttpContext利用できない場合があります。

定義する

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 { }
    }
}

使用する

public class MyClass
{
    readonly ILogger _logger;

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

    public void MethodOne()
    {
        try
        {

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

2

私はASP.NETコアを使用していて、ElmahCoreを使用しています

(コントローラー内の)HttpContextでエラーを手動でログに記録するには、次のように記述します。

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

アプリケーションの別の部分でHttpContextなし

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

0

Signal.FromCurrentContext()。Raise(ex);を使用してelmahログにカスタムメッセージを書き込もうとしていました。そして、これらの例外が浮き彫りになることがわかりました。

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

その上、elmahがさまざまなレベルのロギングをサポートする方法がわかりません-web.config設定によって詳細なロギングをオフにすることは可能ですか?


1
例外をキャッチして再びスローしない場合、例外は発生しません。多分私は誤解していますか?ELMAHはさまざまなレベルのロギングをサポートしていません。エラー専用です。
ThomasArdal 2017年

ありがとう、トーマス。それがまさに私が確認しようとしていたことです
Valery Gavrilov

0

このラインを使用すると、完全に正常に動作します。

 try{
            //Code which may throw an error
    }
    catch(Exception ex){
            ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.