Une façon Simple d'effectuer la journalisation des erreurs?
j'ai créé une petite application c# winforms, en tant que fonctionnalité supplémentaire, j'envisageais d'ajouter une forme de journalisation d'erreur. Quelqu'un a-t-il des suggestions à faire? C'est une fonctionnalité que je n'ai jamais cherché à ajouter à des projets précédents, donc je suis ouvert aux suggestions de développeurs qui ont plus d'expérience.
je considérais quelque chose dans le sens d'écrire des exceptions à un fichier texte spécifié, ou peut-être une table de base de données. Ceci est une application qui sera utilisé pendant quelques mois et puis supprimées quand un grand produit est terminé.
8 réponses
Je ne creuserais pas trop sur les bibliothèques externes puisque vos besoins de journalisation sont simples.
.net Framework fournit déjà cette fonctionnalité dans le système namespace.Diagnostics, vous pouvez écrire toute la journalisation dont vous avez besoin en appelant simplement les méthodes sous le Trace catégorie:
Trace.TraceInformation("Your Information");
Trace.TraceError("Your Error");
Trace.TraceWarning("Your Warning");
Et ensuite configurer tous les trace auditeurs qui correspondent à vos besoins sur votre application.fichier de configuration:
<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>
ou si vous préférez, vous pouvez également configurer votre auditeurs dans votre application, sans dépendre d'un fichier de configuration:
Trace.Listeners.Add(new TextWriterTraceListener("MyTextFile.log"));
n'oubliez pas de régler la Trace.Propriété AutoFlush à true, pour que le journal de texte fonctionne correctement.
Vous pouvez utiliser SimpleLog.
c'est une solution de journalisation simple, mais robuste et puissante, facile à comprendre, facile à intégrer et à utiliser. Pas besoin de passer des jours pour configurer et personnaliser log4Net, avec cette classe, vous êtes en quelques minutes.
Bien qu'elle se connecte à un fichier, il devrait être facilement personnalisable pour vous connecter à une base de données.
Une solution optimale, à mon avis, serait d'utiliser des NLog: http://nlog-project.org/
installez simplement le paquet de configuration de NuGet:http://www.nuget.org/packages/NLog.Config/ et vous finirez avec la bibliothèque et un enregistreur de fichiers préconfiguré...
Ensuite, dans votre code, vous avez juste besoin:
// 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.
Dans le fichier de configuration que vous obtenez, vous devez décommenter les sections dont vous avez besoin:
<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>
éditer le propriétés de l' nlog.config
le fichier
Copy to Output Directory: Copy always
Bien log4net fonctionne comme une brique. Il peut être un peu difficile à configurer, mais sa vaut le coup. Il vous permet également de configurer le fichier de verrouillage de ces fichiers journaux etc.
Heres exemple pour log4net:
- créer un nouveau projet de console appelé Log4NetTest
- ajouter log4net [1.2.13] paquet nuget dans le projet
Écrire le programme suivant:
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(); } } }
changez votre application.la configuration suivante:
<!-- 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.Exécutez l'application et vous devriez trouver le fichier suivant de bin\Debug dossier:
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
il Vous suffit d'écrire vos erreurs d'exception dans un fichier texte. Écrire dans un Fichier Texte. Une suggestion est de mettre le fichier que vous créez dans un userdata ou répertoire appdata bien, vous n'avez pas à lutter avec les autorisations.
comme ceci n'est nécessaire que pour quelques mois et sera jeté, il n'y a aucune raison d'aller par-dessus bord avec DB. Un simple fichier texte devrait suffire.
Créer une classe appelée Journal.cs Je suis à l'aide de Linq to SQl pour enregistrer dans la base de données
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)
{
}
}
}
}
Créer le tableau suivant
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
le niveau D'Impact est essentiellement Enum
public enum ImpactLevel
{
High = 0,
Medium = 1,
Low = 2,
}
Vous pouvez l'utiliser comme suivant
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 ");
}
après avoir lu les suggestions ici, j'ai fini par utiliser ce qui suit:
private void LogSystemError(string message)
{
EventLog.WriteEntry("YourAppName", message, EventLogEntryType.Error);
}
La classe EventLog est disponible en utilisant le système.Diagnostic.
j'ai évité les options de connexion dans les fichiers (par exemple " yourLogFile.txt") pour éviter les problèmes de simultanéité de plusieurs threads journalisation des erreurs, l'emplacement du fichier et la sécurité d'accès, et les problèmes que d'avoir un fichier qui devient trop importante.