web-dev-qa-db-de.com

Einfache Möglichkeit zur Fehlerprotokollierung?

Ich habe eine kleine C # -winforms-Anwendung erstellt. Als zusätzliche Funktion habe ich erwogen, eine Art Fehler beim Anmelden hinzuzufügen. Hat jemand Vorschläge für eine gute Vorgehensweise? Dies ist eine Funktion, die ich bisher noch nie in Betracht gezogen habe. Daher bin ich offen für Vorschläge von Entwicklern mit mehr Erfahrung.

Ich überlegte, ob ich Ausnahmen zu einer bestimmten Textdatei oder möglicherweise zu einer Datenbanktabelle schreiben sollte. Dies ist eine Anwendung, die einige Monate in Gebrauch sein wird und dann verworfen wird, wenn ein größeres Produkt fertig ist.

40

Ich würde nicht zu viel in externen Bibliotheken suchen, da Ihre Anforderungen an die Protokollierung einfach sind.

.NET Framework wird bereits mit dieser Funktion im Namespace System.Diagnostics ausgeliefert. Sie können die gesamte dort erforderliche Protokollierung schreiben, indem Sie einfach Methoden unter der Klasse Trace aufrufen:

Trace.TraceInformation("Your Information");
Trace.TraceError("Your Error");
Trace.TraceWarning("Your Warning");

Und dann konfigurieren Sie alle Trace-Listener, die Ihren Anforderungen entsprechen, in Ihrer app.config-Datei:

<configuration>
  // other config
  <system.diagnostics>
    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="consoleListener" type="System.Diagnostics.ConsoleTraceListener"/>
        <add name="textWriterListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="YourLogFile.txt"/>
        <add name="eventLogListener" type="System.Diagnostics.EventLogTraceListener" initializeData="YourEventLogSource" />
        <remove name="Default"/>
      </listeners>
    </trace>
  </system.diagnostics>
  // other config
</configuration>

wenn Sie möchten, können Sie Ihre Listener auch in Ihrer Anwendung konfigurieren, ohne von einer Konfigurationsdatei abhängig zu sein:

Trace.Listeners.Add(new TextWriterTraceListener("MyTextFile.log"));

Denken Sie daran, die Trace.AutoFlush-Eigenschaft auf true festzulegen, damit das Textprotokoll ordnungsgemäß funktioniert.

86
Mauro2

Eine meiner Meinung nach optimale Lösung wäre die Verwendung von NLog: http://nlog-project.org/

Installieren Sie einfach das Konfigurationspaket von NuGet: http://www.nuget.org/packages/NLog.Config/ und Sie erhalten die Bibliothek und einen vorkonfigurierten Datei-Logger ...

Dann brauchen Sie in Ihrem Code nur noch:

// A logger member field:

private readonly Logger logger = LogManager.GetCurrentClassLogger(); // creates a logger using the class name

// use it:
logger.Info(...);
logger.Error(...);

// and also:
logger.ErrorException("text", ex); // which will log the stack trace.

In der Konfigurationsdatei, die Sie erhalten, müssen Sie die benötigten Abschnitte auskommentieren:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <!-- 
        See http://nlog-project.org/wiki/Configuration_file 
        for information on customizing logging rules and outputs.
    -->
    <targets>
        <!-- add your targets here -->

        <!-- UNCOMMENT THIS!
        <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
                layout="${longdate} ${uppercase:${level}} ${message}" />
        -->
    </targets>

    <rules>
        <!-- add your logging rules here -->

        <!-- UNCOMMENT THIS!
        <logger name="*" minlevel="Trace" writeTo="f" />
        -->
    </rules>
</nlog>

Bearbeiten Sie die Eigenschaften des nlog.config Datei an

Copy to Output Directory: Copy always
13
Tallmaris

Sie könnten SimpleLog verwenden.

Es ist eine einfache, aber robuste und leistungsstarke Ein-Klassen-Protokollierungslösung, die einfach zu verstehen, einfach zu integrieren und einfach zu verwenden ist. Sie müssen keine Tage für das Einrichten und Anpassen von log4Net aufwenden. Mit dieser Klasse sind Sie in wenigen Minuten fertig.

Obwohl es derzeit in einer Datei protokolliert, sollte es leicht anpassbar sein, um in einer Datenbank zu protokollieren.

http://www.codeproject.com/Tips/585796/Simple-Log

10
Jochen

Nun, log4net funktioniert wie ein Ziegelstein. Es ist zwar etwas schwierig zu konfigurieren, aber es lohnt sich. Außerdem können Sie die Dateisperrung dieser Protokolldateien usw. konfigurieren.

http://www.codeproject.com/Articles/140911/log4net-Tutorial

3
Panu Oksala

Erstellen Sie eine Klasse mit dem Namen Log.cs. Ich verwende Linq To SQl, um in der Datenbank zu speichern

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
public static partial class Log
{
    /// <summary>
    /// Saves the exception details to ErrorLogging db with Low Priority
    /// </summary>
    /// <param name="ex">The exception.</param>
    public static void Save(this Exception ex)
    {
        Save(ex, ImpactLevel.Low, "");
    }

    /// <summary>
    /// Saves the exception details to ErrorLogging db with specified ImpactLevel
    /// </summary>
    /// <param name="ex">The exception.</param>
    /// <param name="impactLevel">The Impact level.</param>
    public static void Save(this Exception ex, ImpactLevel impactLevel)
    {
        Save(ex, impactLevel,"");
    }
    /// <summary>
    /// Saves the exception details to ErrorLogging db with specified ImpactLevel and user message
    /// </summary>
    /// <param name="ex">The exception</param>
    /// <param name="impactLevel">The impact level.</param>
    /// <param name="errorDescription">The error Description.</param>
    public static void Save(this Exception ex, ImpactLevel impactLevel, string errorDescription)
    {
        using (var db = new ErrorLoggingDataContext())
        {
            Log log = new Log();

            if (errorDescription != null && errorDescription != "")
            {
                log.ErrorShortDescription = errorDescription;
            }
            log.ExceptionType = ex.GetType().FullName;
            var stackTrace = new StackTrace(ex, true);
            var allFrames = stackTrace.GetFrames().ToList();
            foreach (var frame in allFrames)
            {
                log.FileName = frame.GetFileName();
                log.LineNumber = frame.GetFileLineNumber();
                var method = frame.GetMethod();
                log.MethodName = method.Name;
                log.ClassName = frame.GetMethod().DeclaringType.ToString();
            }

            log.ImpactLevel = impactLevel.ToString();
            try
            {
                log.ApplicationName = Assembly.GetCallingAssembly().GetName().Name;
            }
            catch
            {
                log.ApplicationName = "";
            }

            log.ErrorMessage = ex.Message;
            log.StackTrace = ex.StackTrace;
            if (ex.InnerException != null)
            {
                log.InnerException = ex.InnerException.ToString();
                log.InnerExceptionMessage = ex.InnerException.Message;
            }
            log.IpAddress = ""; //get the ip address

            if (System.Diagnostics.Debugger.IsAttached)
            {
                log.IsProduction = false;
            }

            try
            {
                db.Logs.InsertOnSubmit(log);
                db.SubmitChanges();
            }
            catch (Exception eex)
            {

            }
        }
    }
}

Erstellen Sie die folgende Tabelle

USE [database Name]
GO

/****** Object:  Table [dbo].[Log]    Script Date: 9/27/2016 11:52:32 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Log](
    [LogId] [INT] IDENTITY(1,1) NOT NULL,
    [ErrorDate] [DATETIME] NOT NULL CONSTRAINT [DF_Log_Date]  DEFAULT (GETDATE()),
    [ErrorShortDescription] [VARCHAR](1000) NULL,
    [ExceptionType] [VARCHAR](255) NULL,
    [FileName] [VARCHAR](1000) NULL,
    [LineNumber] [INT] NULL,
    [MethodName] [VARCHAR](255) NULL,
    [ClassName] [VARCHAR](150) NULL,
    [ImpactLevel] [VARCHAR](50) NOT NULL,
    [ApplicationName] [VARCHAR](255) NULL,
    [ErrorMessage] [VARCHAR](4000) NULL,
    [StackTrace] [VARCHAR](MAX) NULL,
    [InnerException] [VARCHAR](2000) NULL,
    [InnerExceptionMessage] [VARCHAR](2000) NULL,
    [IpAddress] [VARCHAR](150) NULL,
    [IsProduction] [BIT] NOT NULL CONSTRAINT [DF_Log_IsProduction]  DEFAULT ((1)),
    [LastModified] [DATETIME] NOT NULL CONSTRAINT [DF_Log_LastModified]  DEFAULT (GETDATE()),
 CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED 
(
    [LogId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'This table holds all the exceptions. 
ErrorData = when error happened
,[ErrorShortDescription] == short desc about the error entered by the developers
      ,[FileName] = file where error happened full path
      ,[LineNumber] = line number where code failed
      ,[MethodName] = method name where exception happened
      ,[ClassName] = class where exception happened
      ,[ImpactLevel] = high, medium, low
      ,[ApplicationName] = name of the application where error came from
      ,[ErrorMessage] = exception error messge
      ,[StackTrace] = C# stack trace
      ,[InnerException] = inner exception of strack trace
      ,[InnerExceptionMessage] = inner message
      ,[IpAddress]
      ,[IsProduction]' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Log'
GO

Die Auswirkungsstufe ist im Grunde genommen Enum

 public enum ImpactLevel
    {
        High = 0,
        Medium = 1,
        Low = 2,
    }

Sie können es wie folgt verwenden

try
{


}
catch(Exception ex)
{
    //this will save the exception details and mark exception as low priority
    ex.Save();
}


try
{


}
catch(Exception ex)
{
    //this will save the exception details with  priority you define: High, Medium,Low
    ex.Save(ImpactLevel.Medium);
}

try
{


}
catch(Exception ex)
{
    //this will save the exception details with  priority you define: High, Medium,Low
    ex.Save(ImpactLevel.Medium, "You can enter an details you want here ");
}
2
kdnerd

Hier ein Beispiel für log4net:

  1. Erstellen Sie ein neues Konsolenprojekt mit dem Namen Log4NetTest
  2. Fügen Sie das log4net [1.2.13] -Nuget-Paket zum Projekt hinzu
  3. Schreiben Sie folgendes Programm:

    using System.Threading.Tasks;
    using log4net;
    using System.Text;
    using System.CollectionsGeneric;
    using System;
    namespace Log4NetTest
    {
        class Program
        {
    
            private static readonly ILog _logger = LogManager.GetLogger("testApp.LoggingExample");
    
            static void Main(string[] args)
            {
                // Configure from App.config. This is marked as obsolete so you can also add config into separate config file
                // and use log4net.Config.XmlConfigurator method to configure from xml file.            
                log4net.Config.DOMConfigurator.Configure(); 
    
                _logger.Debug("Shows only at debug");
                _logger.Warn("Shows only at warn");
                _logger.Error("Shows only at error");
    
                Console.ReadKey();
            }
        }
    }
    
  4. Ändern Sie Ihre app.config wie folgt:

    <!-- language: xml -->
    <?xml version="1.0" encoding="utf-8" ?> 
    <configuration> 
        <configSections> 
            <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> 
        </configSections> 
            <startup> 
                    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
            </startup> 
        <log4net debug="false"> 
            <appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" > 
                <param name="File" value="myLog.log" /> 
                <param name="AppendToFile" value="true" /> 
                <layout type="log4net.Layout.PatternLayout,log4net"> 
                    <param name="ConversionPattern" value="%date [%thread] %-5level %logger %ndc - %message%newline" /> 
                </layout>      
            </appender> 
            <root> 
                <priority value="ALL" /> 
                <appender-ref ref="LogFileAppender" /> 
            </root> 
            <category name="testApp.LoggingExample"> 
                <priority value="ALL" /> 
            </category> 
        </log4net> 
    </configuration>
    

5. Führen Sie die Anwendung aus und Sie sollten die folgende Datei aus dem Ordner bin\Debug finden:

2013-12-13 13:27:27,252 [8] DEBUG testApp.LoggingExample (null) - Shows only at debug
2013-12-13 13:27:27,280 [8] WARN  testApp.LoggingExample (null) - Shows only at warn
2013-12-13 13:27:27,282 [8] ERROR testApp.LoggingExample (null) - Shows only at error
2
Panu Oksala

Nachdem ich die Vorschläge hier gelesen habe, habe ich Folgendes verwendet:

private void LogSystemError(string message)
{
    EventLog.WriteEntry("YourAppName", message, EventLogEntryType.Error);
}

Die EventLog-Klasse ist über System.Diagnostics verfügbar.

Ich habe die Anmeldemöglichkeiten für Dateien (z. B. "yourLogFile.txt") vermieden, um Probleme mit der gleichzeitigen Protokollierung mehrerer Threads, dem Speicherort der Datei und der Zugriffssicherheit sowie die möglichen Probleme mit einer zu großen Datei zu vermeiden.

1
integrative.io

Sie schreiben einfach Ihre Ausnahmefehler in eine Textdatei. In Textdatei schreiben . Ein Vorschlag ist, die von Ihnen erstellte Datei in ein Benutzerdaten- oder AppData-Verzeichnis zu legen, damit Sie nicht mit Berechtigungen zu kämpfen haben.

Da dies nur für einige Monate benötigt wird und verworfen wird, gibt es keinen Grund, mit DB über Bord zu gehen. Eine einfache Textdatei sollte ausreichen.

1
KSdev