65

ELMAHを使い始めたばかりでファンです。私のチームは多数の Web アプリケーションをサポートしていますが、ELMAH によって各アプリケーションの例外を同じ MS SQL データベース テーブルに保存できることに特に興奮しています。

また、いくつかのコンソール、DLL、およびデスクトップ アプリケーションもサポートしています。ELMAH DLL を使用して、これらのアプリの例外を同じ場所に記録することはできますか?

4

7 に答える 7

77

ASP.NET サイトに加えて、コンソール アプリと Windows サービスからログを記録する機能が必要でした。ErrorLog.GetDefault(null);私もメールが必要になるまでうまくいった答え( )を使用しました。

だから、ここに私の解決策があります。ログ、電子メール、ツイート、およびフィルタリング (構成ファイルとコードの両方) を処理します。また、main 呼び出しを Exception の拡張としてラップしたので、次のように呼び出すことができます。catch(Exception ex) { ex.LogToElmah(); }

コードでフィルタリングするには、対応する .Filtering イベントをフックします。ElmahExtension.ErrorLog.Filtering += new ExceptionFilterEventHandler(ErrorLog_Filtering);

コード:

using System;
using System.Web;
using Elmah;
namespace System
{
    public static class ElmahExtension
    {
        public static void LogToElmah(this Exception ex)
        {
            if (HttpContext.Current != null)
            {
                ErrorSignal.FromCurrentContext().Raise(ex);
            }
            else
            {
                if (httpApplication == null) InitNoContext();
                ErrorSignal.Get(httpApplication).Raise(ex);
            }
        }

            private static HttpApplication httpApplication = null;
            private static ErrorFilterConsole errorFilter = new ErrorFilterConsole();

            public static ErrorMailModule ErrorEmail = new ErrorMailModule();
            public static ErrorLogModule ErrorLog = new ErrorLogModule();
            public static ErrorTweetModule ErrorTweet = new ErrorTweetModule();

            private static void InitNoContext()
            {
                httpApplication = new HttpApplication();
                errorFilter.Init(httpApplication);

                (ErrorEmail as IHttpModule).Init(httpApplication);
                errorFilter.HookFiltering(ErrorEmail);

                (ErrorLog as IHttpModule).Init(httpApplication);
                errorFilter.HookFiltering(ErrorLog);                

                (ErrorTweet as IHttpModule).Init(httpApplication);
                errorFilter.HookFiltering(ErrorTweet);
            }

            private class ErrorFilterConsole : ErrorFilterModule
            {
                public void HookFiltering(IExceptionFiltering module)
                {
                    module.Filtering += new ExceptionFilterEventHandler(base.OnErrorModuleFiltering);
                }
            }
    }
}

System.Web.dllさらに、これを機能させるには、プロジェクトにへの参照を追加する必要があります。

編集: コメントによると、このコードは、構成ファイルに<errorMail async="false"/>. 構成ファイルに保持する必要がある場合は、このコード スニペットを参照してください<errorMail async="true"/>(HttpContext.Current が使用可能な場合に使用されます)。

于 2010-03-18T21:52:50.120 に答える
68

ここでもまったく同じ状況です。すべてのWebアプリケーションでELMAHを実行します。それらのいくつかは、コンソールベースのスケジューラーを持っています。

ソースコードを掘り下げた後、次のコードが機能しているようです。

            ErrorLog errorLog = ErrorLog.GetDefault(null);
            errorLog.ApplicationName = "/LM/W3SVC/1/ROOT/AppName";
            errorLog.Log(new Error(ex));

上記の唯一の実際の問題は、ELMAH.axdビューアでエントリを表示できるように、構成内のどこかにアプリケーション名を保持する必要があることです。

したがって、一般的なエラー処理コードでは、次のようにします。

        if (HttpContext.Current != null)
            ErrorSignal.FromCurrentContext().Raise(ex);
        else
        {
            ErrorLog errorLog = ErrorLog.GetDefault(null);
            errorLog.ApplicationName = ErrorHandling.Application;
            errorLog.Log(new Error(ex));
        }
于 2009-07-01T10:26:18.823 に答える
14

http なしでログを電子メールで送信したい場合は、次のようにします。

    public class MyElmahMail: ErrorMailModule
    {
        public MyElmahMail()
        {
//this basically just gets config from errorMail  (app.config)
            base.OnInit(new HttpApplication());
        }
        public void Log(Error error)
        {
//just send the email pls
            base.ReportError(error);
        }
    }

//to call it
var mail = new MyElmahMail();
mail.Log(new Error(new NullReferenceException()));//whatever exception u want to log

そして app.config に関して

//Under configSections
    <sectionGroup name="elmah">
      <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
      <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
      <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
      <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    </sectionGroup>

  <elmah>
    <errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="C:\Elmah.Error" applicationName="MyAwesomeApp" />
    <errorMail from="from@email.com" to="to@email.com" />
  </elmah>

そして、あなたの選択したsmtp設定。

すべて完了。:-)

于 2012-06-20T05:22:21.173 に答える
5

編集:これは実行できます-この回答を参照してください。


私はあなたがこれを行うことができないと確信しています。関連資料を掘り下げてみます。

http://groups.google.com/group/elmah/browse_thread/thread/f214c4f782dc2bf4/d96fe43b60765f0c?lnk=gst&q=app#d96fe43b60765f0c

したがって、Googleグループを検索すると、それは不可能であることがわかります...ELMAHはHttpHandlers(asp.netコンストラクト)から離れて動作するため、ASP.NETのみです。

そうは言っても、コンソール アプリケーションでそれを利用する方法はいくつかあります。ELMAH はエラーを発生させるメソッドを提供するため、例外処理で ELMAH をラップし、次の方法でエラーを通知できます。

ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());

これは、アプリケーション全体を例外ハンドラーとシグナルでラップすることを意味します。ダウンさせるには微調整が必​​要かもしれませんが、完全に可能だと思います。

必要な場合は、これがELMAH コード リポジトリへのリンクです。

于 2009-05-08T19:47:23.060 に答える
2

Brian Chance の回答を VB.NET に移植する必要がある場合:

Imports System
Imports System.Web
Imports Elmah
Namespace System
    Public NotInheritable Class ElmahExtension
        Private Sub New()
        End Sub
        <System.Runtime.CompilerServices.Extension> _
        Public Shared Sub LogToElmah(ex As Exception)
            If HttpContext.Current IsNot Nothing Then
                ErrorSignal.FromCurrentContext().Raise(ex)
            Else
                If httpApplication Is Nothing Then
                    InitNoContext()
                End If
                ErrorSignal.[Get](httpApplication).Raise(ex)
            End If
        End Sub

        Private Shared httpApplication As HttpApplication = Nothing
        Private Shared errorFilter As New ErrorFilterConsole()

        Public Shared ErrorEmail As New ErrorMailModule()
        Public Shared ErrorLog As New ErrorLogModule()
        Public Shared ErrorTweet As New ErrorTweetModule()

        Private Shared Sub InitNoContext()
            httpApplication = New HttpApplication()
            errorFilter.Init(httpApplication)

            TryCast(ErrorEmail, IHttpModule).Init(httpApplication)
            errorFilter.HookFiltering(ErrorEmail)

            TryCast(ErrorLog, IHttpModule).Init(httpApplication)
            errorFilter.HookFiltering(ErrorLog)

            TryCast(ErrorTweet, IHttpModule).Init(httpApplication)
            errorFilter.HookFiltering(ErrorTweet)
        End Sub



    Private Class ErrorFilterConsole
        Inherits Elmah.ErrorFilterModule


        Public Sub HookFiltering([module] As Elmah.IExceptionFiltering)
            AddHandler [module].Filtering, New Elmah.ExceptionFilterEventHandler(AddressOf MyBase.OnErrorModuleFiltering)
        End Sub

    End Class


    End Class
End Namespace

ただし、エラーをデータベースに記録するだけであれば、これで十分です。

If System.Web.HttpContext.Current Is Nothing Then
    Dim req As System.Web.HttpRequest = New System.Web.HttpRequest(String.Empty, "https://www.domain.tld", Nothing)
    Dim res As System.Web.HttpResponse = New System.Web.HttpResponse(Nothing)
    System.Web.HttpContext.Current = New System.Web.HttpContext(req, res)

    'Dim request As System.Web.Hosting.SimpleWorkerRequest = New System.Web.Hosting.SimpleWorkerRequest("/blah", "c:\inetpub\wwwroot\blah", "blah.html", Nothing, New System.IO.StringWriter())
    'System.Web.HttpContext.Current = New System.Web.HttpContext(request)

    System.Web.HttpContext.Current.ApplicationInstance = New System.Web.HttpApplication()

    Dim ErrorLog As New Elmah.ErrorLogModule()
    TryCast(ErrorLog, System.Web.IHttpModule).Init(System.Web.HttpContext.Current.ApplicationInstance)
End If

完全なソリューションとして:

Public parent As Elmah.ServiceProviderQueryHandler = Nothing




' http://stackoverflow.com/questions/5981750/configuring-elmah-with-sql-server-logging-with-encrypted-connection-string
Public Function Elmah_MS_SQL_Callback(objContext As Object) As System.IServiceProvider
    Dim container As New System.ComponentModel.Design.ServiceContainer(parent(objContext))
    Dim strConnectionString As String = COR.SQL.MS_SQL.GetConnectionString()

    Dim log As Elmah.SqlErrorLog = New Elmah.SqlErrorLog(strConnectionString)
    'Dim strApplicationName = System.Web.Compilation.BuildManager.GetGlobalAsaxType().BaseType.Assembly().FullName
    Dim strApplicationName As String = System.Reflection.Assembly.GetExecutingAssembly().FullName
    If Not String.IsNullOrEmpty(strApplicationName) Then
        log.ApplicationName = strApplicationName.Substring(0, strApplicationName.IndexOf(","))
    End If

    container.AddService(GetType(Elmah.ErrorLog), log)
    Return container
End Function ' Elmah_MS_SQL_Callback




Public Function Elmah_PG_SQL_Callback(objContext As Object) As System.IServiceProvider
    Dim container As New System.ComponentModel.Design.ServiceContainer(parent(objContext))
    Dim strConnectionString As String = COR.SQL.MS_SQL.GetConnectionString()

    Dim log As Elmah.PgsqlErrorLog = New Elmah.PgsqlErrorLog(strConnectionString)
    'Dim strApplicationName = System.Web.Compilation.BuildManager.GetGlobalAsaxType().BaseType.Assembly().FullName
    Dim strApplicationName As String = System.Reflection.Assembly.GetExecutingAssembly().FullName
    If Not String.IsNullOrEmpty(strApplicationName) Then
        log.ApplicationName = strApplicationName.Substring(0, strApplicationName.IndexOf(","))
    End If

    container.AddService(GetType(Elmah.ErrorLog), log)
    Return container
End Function ' Elmah_PG_SQL_Callback


' http://weblogs.asp.net/stevewellens/archive/2009/02/01/debugging-a-deployed-site.aspx
Public Sub Initialize()

    If System.Web.HttpContext.Current Is Nothing Then
        Dim req As System.Web.HttpRequest = New System.Web.HttpRequest(String.Empty, "https://www.domain.tld", Nothing)
        Dim res As System.Web.HttpResponse = New System.Web.HttpResponse(Nothing)
        System.Web.HttpContext.Current = New System.Web.HttpContext(req, res)

        'Dim request As System.Web.Hosting.SimpleWorkerRequest = New System.Web.Hosting.SimpleWorkerRequest("/blah", "c:\inetpub\wwwroot\blah", "blah.html", Nothing, New System.IO.StringWriter())
        'System.Web.HttpContext.Current = New System.Web.HttpContext(request)

        System.Web.HttpContext.Current.ApplicationInstance = New System.Web.HttpApplication()

        Dim ErrorLog As New Elmah.ErrorLogModule()
        TryCast(ErrorLog, System.Web.IHttpModule).Init(System.Web.HttpContext.Current.ApplicationInstance)
    End If



    parent = Elmah.ServiceCenter.Current

    If SQL.IsMsSql Then
        Elmah.ServiceCenter.Current = AddressOf Elmah_MS_SQL_Callback
    End If

    If SQL.IsPostGreSql Then
        Elmah.ServiceCenter.Current = AddressOf Elmah_PG_SQL_Callback
    End If
End Sub ' InitializeElmah

Elmah.ErrorSignal.FromCurrentContext().Raise(New NotImplementedException("Test"))

Initialize() の後に呼び出された場合に機能します

于 2013-01-08T15:01:30.627 に答える
1

コメントできないので、ここに投稿します。誰かがそれを見るかもしれません。

ブライアンの方法とコメンターに従った後、電子メールを機能させることができましたが、applicationName を設定したにもかかわらず、SQL メッセージがログに記録されていませんでした。私が気付いていなかったのは、それらが実際にログに記録されているということです

私のweb.configにはapplicationNameが指定されていなかったため、デフォルトで「/LM/W3SVC/2/ROOT」になりました。これは基本的に「asgeo1」がコメントしたものですが、同じでなければならないことに気づきませんでした。

気になるエラーは実際にはなかったので、web.config と app.config で applicationName を同じになるように構成すると、すべてがチャンピオンのように表示されるようになりました。

<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="MyAppName" />
于 2013-01-23T03:19:47.473 に答える
-6

ELMAH は Error Logging Modules and Handlers の略で、もちろん と を指しIHttpModuleますIHttpHandler

コンソール アプリケーションは HTTP を使用しないため、通常、HTTP 用に構築されたモジュールとハンドラーから多くのメリットを得ることができません。

于 2009-07-01T13:17:06.890 に答える