webentwicklung-frage-antwort-db.com.de

c # Beste Methode zum Erstellen einer Protokolldatei

Ich schreibe ein Tool, das den Zustand von Workstations in einem Netzwerk überprüft und je nach den gefundenen Problemen korrigiert. Ich möchte eine Protokolldatei erstellen, während die App ihre Aufgaben/Prüfungen auf jedem Rechner ausführt. Ich möchte, dass dies für einen Moment auf einer einzigen Maschine funktioniert, aber mit der Zeit werden 100+ Maschinen in einem Durchgang gescannt (Threaded out).

Wie lässt sich eine Protokolldatei am besten erstellen?

Ich dachte daran, einen List<string> zu verwenden, um die Protokolldatei im Speicher aufzubauen und sie anschließend in eine Datei auszugeben, sobald sie fertig war.

Ich denke nur, dass es einen besseren Weg gibt, dies zu tun?

32
Derek

Ich würde keine Bibliotheken von Drittanbietern verwenden, ich würde mich in eine XML-Datei einloggen. 

Dies ist ein Codebeispiel, in dem von verschiedenen Threads aus eine XML-Datei protokolliert wird:

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

Ich würde log4net empfehlen.

Sie benötigen mehrere Protokolldateien. Also mehrere Datei-Appenders. Außerdem können Sie die Datei-Appenders dynamisch erstellen.

Beispielcode:

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

Quellen/gute Links:

Log4Net: Programmgesteuert mehrere Logger angeben (mit mehreren Datei-Appendern)

Appender programmgesteuert hinzufügen

Wie programmiere ich log4net von Grund auf neu (keine Konfiguration)

Außerdem können Sie mit log4net auch in das Ereignisprotokoll schreiben. Alles ist konfigurationsbasiert und die Konfiguration kann zur Laufzeit auch dynamisch aus xml geladen werden.

Edit 2:

Eine Möglichkeit, die Protokolldateien schnell zu wechseln: Die Log4Net-Konfigurationsdatei unterstützt Umgebungsvariablen:

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

und in der log4net config:

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

Wir haben viel über das Logging geforscht und entschieden, dass NLog das Beste ist.

Siehe http://nlog-project.org/

Siehe auch log4net vs. Nlog Und http://www.dotnetlogging.com/comparison/

5
Matthew Watson

Möglicherweise möchten Sie das Ereignisprotokoll verwenden! So greifen Sie unter C # http://support.Microsoft.com/kb/307024/de darauf zu.

Was auch immer die Methode ist, die Sie verwenden möchten. Ich würde empfehlen, jedes Mal eine Datei auszugeben, wenn etwas an das Protokoll angehängt wird, und nicht, wenn Ihr Prozess beendet ist, damit Sie bei einem Absturz oder bei einem Prozess keine Daten verlieren wurde getötet.

5
Julien

Verwenden Sie das Nlog http://nlog-project.org/ . Es ist kostenlos und ermöglicht das Schreiben in Dateien, Datenbanken, Ereignisprotokolle und andere 20+ Ziele. Das andere Protokollierungs-Framework ist log4net - http://logging.Apache.org/log4net/ (von Java portiert) Log4j-Projekt). Es ist auch kostenlos.

Bewährte Methoden sind die Verwendung der allgemeinen Protokollierung - http://commons.Apache.org/logging/ Sie können später NLog oder log4net in ein anderes Protokollierungs-Framework ändern.

5
Alex Blokha

Sie können die Bibliothek Apache log4net verwenden

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

fügen Sie diese Konfigurationsdatei hinzu


*************************************************************************************
<!--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

Sie können sich auch die integrierten .NET-Ablaufverfolgungsfunktionen ansehen. Es gibt eine Reihe von Ablaufverfolgungslistenern, die die Ausgabe in eine Protokolldatei ermöglichen. Sie können sie jedoch so konfigurieren, dass sie sich bei der Ereignisanzeige oder bei einer Datenbank (oder allen gleichzeitig) anmeldet.

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

3
David Z.

Sie können http://logging.Apache.org/ library verwenden und einen Datenbank-Appender verwenden, um alle Ihre Protokollinformationen zusammen zu sammeln. 

2
Chris Li

Ich verwende threadsicher static class. Die Hauptidee besteht darin, die Nachricht in die Warteschlange zu stellen und dann für jeden Zeitraum oder jedes Zählerlimit in der Protokolldatei zu speichern.

Wichtig: Beim Beenden des Programms sollten Sie die Sicherungsdatei (DirectLog.SaveToFile();) erzwingen. (falls noch einige Artikel auf der Liste stehen)

Die Verwendung ist sehr einfach: DirectLog.Log("MyLogMessage", 5);

Das ist mein 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

Ich fand das SimpleLogger from heiswayi auf GitHub gut.

0
Tim