Question

Je viens de commencer à utiliser ELMAH et je suis un fan. Mon équipe prend en charge un grand nombre d'applications Web et je suis particulièrement heureux que ELMAH nous permette de sauvegarder les exceptions de chaque application dans la même table de base de données MS SQL.

Nous prenons également en charge quelques applications de console, de DLL et de bureau. Est-il possible d'utiliser la DLL ELMAH pour consigner les exceptions dans ces applications au même endroit?

Était-ce utile?

La solution

Nous avons exactement la même situation ici. Exécuter ELMAH pour toutes nos applications Web. Certains d'entre eux ont des planificateurs basés sur la console.

Après avoir fouillé dans le code source, le code suivant semble fonctionner:

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

Le seul problème réel avec ce qui précède est que vous devez conserver le nom de l'application quelque part dans votre configuration pour pouvoir voir les entrées sur le visualiseur ELMAH.axd.

Donc, dans notre code de traitement d'erreur générique, nous faisons:

        if (HttpContext.Current != null)
            ErrorSignal.FromCurrentContext().Raise(ex);
        else
        {
            ErrorLog errorLog = ErrorLog.GetDefault(null);
            errorLog.ApplicationName = ErrorHandling.Application;
            errorLog.Log(new Error(ex));
        }

Autres conseils

Nous avions besoin de pouvoir nous connecter à partir d'une application console et d'un service Windows en plus de notre site ASP.NET. J’ai utilisé la réponse (ErrorLog.GetDefault(null);) qui a bien fonctionné jusqu’à ce que j’ai eu besoin d’envoyer un e-mail également.

Donc, voici ma solution. Il gère le journal, email, tweet et filtrage (à la fois dans le fichier de configuration et dans le code). J'ai également enveloppé l'appel principal en tant qu'extension à Exception afin qu'il puisse être appelé comme suit: catch(Exception ex) { ex.LogToElmah(); }

Pour filtrer dans le code, décrochez l'événement .Filtering correspondant: ElmahExtension.ErrorLog.Filtering += new ExceptionFilterEventHandler(ErrorLog_Filtering);

Code:

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

De plus, vous devrez ajouter une référence au System.Web.dll dans votre projet pour que cela fonctionne.

MODIFIER : selon les commentaires, ce code n'enverra des e-mails que si votre fichier de configuration contient <errorMail async="false"/>. Reportez-vous à cet extrait de code si vous souhaitez conserver <errorMail async="true"/> dans votre fichier de configuration (à utiliser lorsque HttpContext.Current est disponible).

Si vous souhaitez simplement envoyer le journal par courrier électronique sans http, procédez comme suit:

    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

Et en termes d'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>

Et

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

Et les paramètres smtp de votre choix.

Tout est fait. : -)

Modifier : cela PEUT être réalisé - Voir this . répondre.

Je suis sûr que vous ne pouvez pas faire ça. Je vais essayer de trouver le matériel pertinent.

Référentiel de code ELMAH .

Pour ceux qui ont besoin que la réponse de Brian Chance soit transférée sur 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

Toutefois, pour consigner uniquement les erreurs dans la base de données, cela suffira:

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

En tant que solution complète:

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

Et

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

fonctionnera s'il est appelé après Initialize ()

Eh bien, comme je ne peux pas commenter, je vais poster ceci ici et peut-être que quelqu'un le verra.

Après avoir suivi la méthode de Brian et les commentateurs, j'ai réussi à faire fonctionner l'e-mail, mais je ne voyais toujours pas les messages SQL en cours de journalisation, même si j'avais défini le nom d'application. Ce que je ne savais pas, c’est qu’ils étaient en train d’être enregistrés. Je ne les voyais tout simplement pas, car le nom de l’application doit être identique à votre fichier web.config pour pouvoir le visualiser.

Mon nom de domaine n'a pas été spécifié dans nom.config. Le nom par défaut était donc & "; / LM / W3SVC / 2 / ROOT &" ;, ce qui est essentiellement ce que & "; asgeo1 quot; a commenté, bien que je n’aie pas réalisé que ça devait être pareil.

Comme je ne rencontrais pas vraiment d'erreurs, j'ai configuré applicationName dans mon web.config et mon app.config est identique, et maintenant tout se présente comme un champion.

<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="MyAppName" />

ELMAH signifie "Logging Modules and Handlers" (Gestion et consignation des erreurs), faisant référence à IHttpModule et à IHttpHandler .

Les applications de console n'utilisant pas HTTP, elles ne pourraient donc généralement pas tirer grand profit des modules et des gestionnaires conçus pour HTTP.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top