Подтвердить что ты не робот

С# Лучший способ создания файла журнала

Я пишу инструмент, который будет проверять работоспособность рабочих станций по сети, и будет исправляться в соответствии с проблемами, которые он находит. Я хочу создать файл журнала, поскольку приложение выполняет свои задачи/проверки на каждой машине. Я просто хочу, чтобы эта работа работала на одной машине на данный момент, но со временем она будет сканировать более 100 машин за один раз (Threaded out).

Каков наилучший способ создания файла журнала?

Я думал использовать List<string> для создания файла журнала в памяти, а затем вывести его в файл после его завершения.

Я просто думаю, что может быть лучший способ сделать это?

4b9b3361

Ответ 1

Я бы не использовал сторонние библиотеки, я бы входил в xml файл.

Это пример кода, который регистрируется в XML файле из разных потоков:

    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");
        }
    }

Ответ 2

Я бы порекомендовал log4net.

Вам понадобится несколько файлов журнала. Таким образом, несколько файловых приложений. Кроме того, вы можете создавать файловые приложения динамически.

Пример кода:

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

Источники/Хорошие ссылки:

Log4Net: программно укажите несколько журналов (с несколькими файловыми приложениями)

Программная добавка appenders

Как программировать log4net с нуля (без конфигурации)

Кроме того, log4net также позволяет записывать в журнал событий. Все основано на конфигурации, и конфигурация может динамически загружаться из xml во время выполнения.

Изменить 2:

Один из способов переключения журналов на лету: Файл конфигурации Log4Net поддерживает переменные среды:

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

и в конфигурации log4net:

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

Ответ 3

Возможно, вы захотите использовать журнал событий! Здесь, как получить доступ к нему из С# http://support.microsoft.com/kb/307024/en

Но какой бы метод вы ни использовали, я бы рекомендовал выводить его в файл каждый раз, когда что-то добавляется в журнал, а не когда ваш процесс завершается, поэтому вы не потеряете данные в случае сбоя или если ваш процесс убит.

Ответ 4

Используйте Nlog http://nlog-project.org/. Он бесплатный и позволяет писать в файл, базу данных, журнал событий и другие 20+ целей. Другая структура ведения журнала - log4net - http://logging.apache.org/log4net/ (портировано из проекта java Log4j). Это также бесплатно.

Лучшие практики - использовать общий журнал - http://commons.apache.org/logging/ Таким образом, вы можете позже изменить NLog или log4net на другие рамки ведения журнала.

Ответ 6

Вы можете использовать Apache log4net library:

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.........");
    }
}

Ответ 7

добавить этот файл конфигурации


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

Ответ 8

Вы также можете взглянуть на встроенные средства трассировки .NET. Там есть набор слушателей трассировки, которые позволяют вам выводить в файл журнала, но вы можете настроить его для входа в средство просмотра событий или в базу данных (или все из них одновременно).

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

Ответ 9

Вы можете использовать http://logging.apache.org/ библиотеку и использовать приложение базы данных для сбора всей информации о вашем журнале.

Ответ 10

Я использую thread safe static. Основная идея состоит в том, чтобы поставить в очередь сообщение в списке, а затем сохранить в файл журнала каждый период времени или каждый предел счетчика.

Важно: принудительно сохранять файл (DirectLog.SaveToFile();) при выходе из программы. (в случае, если в списке еще есть какие-то элементы)

Использование очень просто: DirectLog.Log("MyLogMessage", 5);

Это мой код:

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();
            }
        }
    }
}