J'ai créé une petite application WinForms C #, en tant que fonctionnalité supplémentaire que je souhaitais ajouter à une certaine forme d'erreur de connexion. Quelqu'un a-t-il des suggestions pour de bons moyens d'y parvenir? C’est une fonctionnalité que je n’ai jamais envisagée d’ajouter aux projets précédents. Je suis donc ouvert aux suggestions de développeurs plus expérimentés.
J'envisageais de créer des exceptions à un fichier texte spécifié, voire à une table de base de données. Il s'agit d'une application qui sera utilisée pendant quelques mois, puis supprimée lorsqu'un produit plus volumineux sera terminé.
Je ne voudrais pas trop creuser les bibliothèques externes car vos besoins en journalisation sont simples.
.NET Framework est déjà livré avec cette fonctionnalité dans l'espace de noms System.Diagnostics. Vous pouvez écrire toute la journalisation dont vous avez besoin en appelant simplement des méthodes dans la classe Trace :
Trace.TraceInformation("Your Information");
Trace.TraceError("Your Error");
Trace.TraceWarning("Your Warning");
Et puis configurez tous les écouteurs de trace qui répondent à vos besoins sur votre fichier app.config:
<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 vos écouteurs dans votre application, sans dépendre d'un fichier de configuration:
Trace.Listeners.Add(new TextWriterTraceListener("MyTextFile.log"));
N'oubliez pas de définir la propriété Trace.AutoFlush sur true pour que le journal de texte fonctionne correctement.
Une solution optimale, à mon avis, serait d'utiliser NLog: http://nlog-project.org/
Installez simplement le paquet de configuration depuis NuGet: http://www.nuget.org/packages/NLog.Config/ et vous obtiendrez la bibliothèque et un enregistreur de fichier préconfiguré ...
Ensuite, dans votre code, il vous suffit de:
// 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 supprimer les commentaires 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>
Editez les propriétés du nlog.config
fichier à
Copy to Output Directory: Copy always
Vous pouvez utiliser SimpleLog .
Il s'agit d'une solution de journalisation à une classe simple, robuste et puissante, facile à comprendre, à intégrer et à utiliser. Pas besoin de passer des jours à configurer et personnaliser log4Net, avec cette classe, vous avez terminé en quelques minutes.
Bien qu'il se connecte actuellement à un fichier, il devrait être facilement personnalisable de se connecter à une base de données.
Log4net fonctionne comme une brique. C'est peut-être un peu difficile à configurer, mais ça en vaut la peine. Il vous permet également de configurer le verrouillage de fichier de ces fichiers journaux, etc.
Créez une classe appelée Log.cs J'utilise 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 fondamentalement Enum
public enum ImpactLevel
{
High = 0,
Medium = 1,
Low = 2,
}
Vous pouvez l'utiliser comme suit
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 ");
}
Voici un exemple pour log4net:
É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 app.config comme suit:
<!-- 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.Lancez l’application et vous devriez trouver le fichier suivant à partir du dossier bin\Debug:
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
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 à l'aide de System.Diagnostics.
J'ai évité les options de connexion aux fichiers (par exemple, "yourLogFile.txt") pour éviter les problèmes de concomitance d'erreurs de journalisation de plusieurs threads, l'emplacement du fichier et la sécurité d'accès, ainsi que les problèmes éventuels liés à un fichier trop volumineux.
Vous venez d'écrire vos erreurs d'exception dans un fichier texte. Écrire dans un fichier texte . Une suggestion est de placer le fichier que vous créez dans un répertoire userdata ou appdata afin de ne pas avoir à vous soucier des autorisations.
Comme cela n’est nécessaire que pendant quelques mois et qu’il sera jeté, il n’ya aucune raison d’exagérer avec DB. Un simple fichier texte devrait suffire.