web-dev-qa-db-fra.com

c # Meilleure méthode pour créer un fichier journal

J'écris un outil qui va vérifier la santé des postes de travail sur un réseau et qui va corriger en fonction des problèmes rencontrés. Je souhaite créer un fichier journal au fur et à mesure que l'application exécute ses tâches/vérifications sur chaque ordinateur. Je veux juste que cela fonctionne sur une seule machine pour le moment, mais avec le temps, il analysera plus de 100 machines en une fois (filé).

Quel est le meilleur moyen de créer un fichier journal?

Je pensais utiliser un List<string> pour créer le fichier journal en mémoire, puis le sortir dans un fichier une fois terminé.

Je pense juste qu'il y a peut-être une meilleure façon de faire ça?

32
Derek

Je n'utiliserais pas de bibliothèques tierces, je me connecterais à un fichier xml. 

Voici un exemple de code permettant de se connecter à un fichier xml à partir de différents threads:

private static readonly object Locker = new object();
private static XmlDocument _doc = new XmlDocument();

static void Main(string[] args)
{
    if (File.Exists("logs.txt"))
        _doc.Load("logs.txt");
    else
    {
        var root = _doc.CreateElement("hosts");
        _doc.AppendChild(root);
    }

    for (int i = 0; i < 100; i++)
    {
        new Thread(new ThreadStart(DoSomeWork)).Start();
    }
}

static void DoSomeWork()
{
    /*
     * Here you will build log messages
     */
    Log("192.168.1.15", "alive");
}

static void Log(string hostname, string state)
{
    lock (Locker)
    {
        var el = (XmlElement)_doc.DocumentElement.AppendChild(_doc.CreateElement("Host"));
        el.SetAttribute("Hostname", hostname);
        el.AppendChild(_doc.CreateElement("State")).InnerText = state;
        _doc.Save("logs.txt");
    }
}
7
croisharp

Je recommanderais log4net .

Vous auriez besoin de plusieurs fichiers journaux. Donc, plusieurs fichiers annexes. De plus, vous pouvez créer les ajouts de fichiers de manière dynamique.

Exemple de code:

using log4net;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository.Hierarchy;

// Set the level for a named logger
public static void SetLevel(string loggerName, string levelName)
{
    ILog log = LogManager.GetLogger(loggerName);
    Logger l = (Logger)log.Logger;

    l.Level = l.Hierarchy.LevelMap[levelName];
    }

// Add an appender to a logger
public static void AddAppender(string loggerName, IAppender appender)
{
    ILog log = LogManager.GetLogger(loggerName);
    Logger l = (Logger)log.Logger;

    l.AddAppender(appender);
}

// Create a new file appender
public static IAppender CreateFileAppender(string name, string fileName)
{
    FileAppender appender = new
        FileAppender();
    appender.Name = name;
    appender.File = fileName;
    appender.AppendToFile = true;

    PatternLayout layout = new PatternLayout();
    layout.ConversionPattern = "%d [%t] %-5p %c [%x] - %m%n";
    layout.ActivateOptions();

    appender.Layout = layout;
    appender.ActivateOptions();

    return appender;
}

// In order to set the level for a logger and add an appender reference you
// can then use the following calls:
SetLevel("Log4net.MainForm", "ALL");
AddAppender("Log4net.MainForm", CreateFileAppender("appenderName", "fileName.log"));

// repeat as desired

Sources/bons liens:

Log4Net: spécifier par programme plusieurs enregistreurs (avec plusieurs appenders)

Ajout d'appenders par programmation

Comment configurer log4net par programme à partir de rien (pas de configuration)

De plus, le log4net permet également d'écrire dans le journal des événements. Tout est basé sur la configuration, et la configuration peut également être chargée dynamiquement à partir de XML lors de l'exécution.

Edit 2:

Une façon de changer de fichier journal à la volée: Le fichier de configuration Log4Net prend en charge les variables d’environnement:

Environment.SetEnvironmentVariable("log4netFileName", "MyApp.log");

et dans la configuration log4net:

<param name="File" value="${log4netFileName}".log/>
12
Aseem Gautam

Nous avons fait beaucoup de recherches sur l'exploitation forestière et avons décidé que NLog était le meilleur.

Voir http://nlog-project.org/

Voir aussi log4net vs Nlog Et http://www.dotnetlogging.com/comparison/

5
Matthew Watson

Vous voudrez peut-être utiliser le journal des événements! Voici comment y accéder depuis C # http://support.Microsoft.com/kb/307024/fr

Mais quelle que soit la méthode que vous utiliserez, je vous recommande de générer un fichier chaque fois que quelque chose est ajouté au journal plutôt que de quitter votre processus. Ainsi, vous ne perdrez pas de données en cas de blocage ou si votre processus est tué.

5
Julien

Vous pouvez utiliser la bibliothèque log4net Apache

using System;
using log4net;
using log4net.Config;


public class MyApp
{
    // Define a static logger variable so that it references the
    // Logger instance named "MyApp".
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
    static void Main(string[] args)
    {
        XmlConfigurator.Configure(new System.IO.FileInfo(@"..\..\resources\log4net.config"));
        log.Info("Entering application.");
        Console.WriteLine("starting.........");
        log.Info("Entering application.");
        log.Error("Exiting application.");
        Console.WriteLine("starting.........");
    }
}
4
Narottam Goyal

ajouter ce fichier de configuration


*************************************************************************************
<!--Configuration for file appender-->

<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net>
    <appender name="FileAppender" type="log4net.Appender.FileAppender">
      <file value="logfile.txt" />
      <appendToFile value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p [%logger] - %m%n" />
      </layout>
    </appender>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="FileAppender" />
    </root>
  </log4net>
</configuration>

*************************************************************************************

<!--Configuration for console appender-->


<configuration>

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,
        log4net" />
  </configSections>

  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d [%t] %-5p [%logger] - %m%n" />
      </layout>
    </appender>
   <root>
      <level value="ALL" />
      <appender-ref ref="ConsoleAppender" />
    </root>
  </log4net>
</configuration>
4
Narottam Goyal

Vous pouvez également consulter les fonctions de traçage .NET intégrées. Un ensemble d'écouteurs de trace vous permet de générer un fichier journal, mais vous pouvez le configurer pour qu'il se connecte à l'observateur d'événements ou à une base de données (ou à la totalité de ceux-ci simultanément).

http://www.codeguru.com/csharp/.net/net_debugging/tracing/article.php/c5919/NET-Tracing-Tutorial.htm

3
David Z.

Vous pouvez utiliser http://logging.Apache.org/ library et utiliser un appender de base de données pour collecter toutes vos informations de journal. 

2
Chris Li

J'utilise thread safe static class. L'idée principale est de mettre le message en liste, puis de l'enregistrer dans un fichier journal à chaque période ou à chaque compteur.

Important: Vous devez forcer l'enregistrement du fichier (DirectLog.SaveToFile();) lorsque vous quittez le programme. (au cas où il y aurait encore des articles sur la liste)

L'utilisation est très simple: DirectLog.Log("MyLogMessage", 5);

Ceci est mon code:

using System;
using System.IO;
using System.Collections.Generic;

namespace Mendi
{

    /// <summary>
    /// class used for logging misc information to log file
    /// written by Mendi Barel
    /// </summary>
    static class DirectLog
    {
        readonly static int SAVE_PERIOD = 10 * 1000;// period=10 seconds
        readonly static int SAVE_COUNTER = 1000;// save after 1000 messages
        readonly static int MIN_IMPORTANCE = 0;// log only messages with importance value >=MIN_IMPORTANCE

        readonly static string DIR_LOG_FILES = @"z:\MyFolder\";

        static string _filename = DIR_LOG_FILES + @"Log." + DateTime.Now.ToString("yyMMdd.HHmm") + @".txt";

        readonly static List<string> _list_log = new List<string>();
        readonly static object _locker = new object();
        static int _counter = 0;
        static DateTime _last_save = DateTime.Now;

        public static void NewFile()
        {//new file is created because filename changed
            SaveToFile();
            lock (_locker)
            {

                _filename = DIR_LOG_FILES + @"Log." + DateTime.Now.ToString("yyMMdd.HHmm") + @".txt";
                _counter = 0;
            }
        }
        public static void Log(string LogMessage, int Importance)
        {
            if (Importance < MIN_IMPORTANCE) return;
            lock (_locker)
            {
                _list_log.Add(String.Format("{0:HH:mm:ss.ffff},{1},{2}", DateTime.Now, LogMessage, Importance));
                _counter++;
            }
            TimeSpan timeDiff = DateTime.Now - _last_save;

            if (_counter > SAVE_COUNTER || timeDiff.TotalMilliseconds > SAVE_PERIOD)
                SaveToFile();
        }

        public static void SaveToFile()
        {
            lock (_locker)
                if (_list_log.Count == 0)
                {
                    _last_save = _last_save = DateTime.Now;
                    return;
                }
            lock (_locker)
            {
                using (StreamWriter logfile = File.AppendText(_filename))
                {

                    foreach (string s in _list_log) logfile.WriteLine(s);
                    logfile.Flush();
                    logfile.Close();
                }

                _list_log.Clear();
                _counter = 0;
                _last_save = DateTime.Now;
            }
        }


        public static void ReadLog(string logfile)
        {
            using (StreamReader r = File.OpenText(logfile))
            {
                string line;
                while ((line = r.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
                r.Close();
            }
        }
    }
}
1
Mendi Barel

J'ai trouvé le SimpleLogger de heiswayi sur GitHub bon.

0
Tim