使用C#创建日志文件的最佳方法

33

我正在编写一个工具,用于检查网络中所有工作站的健康状况,并根据发现的问题进行修复。我想在应用程序运行时,在每台机器上执行任务/检查时创建日志文件。目前我只想在单台机器上让它工作,但随着时间的推移,它将一次扫描100多台机器(线程化)。

创建日志文件的最佳方式是什么?

我考虑使用 List<string> 在内存中构建日志文件,然后在完成后将其输出到文件中。

我在思考是否有更好的方法来处理这个问题?


1
你的应用程序是在远程扫描所有机器还是会单独部署在每台机器上? - Wouter de Kort
你想要创建一个日志文件还是每台机器一个? - Renatas M.
6
log4net也许值得一看:http://logging.apache.org/log4net/release/features.html - Anders Lindahl
我将远程访问这些机器,并希望为每台机器创建一个日志文件。理想情况下,那些我已经修复的将会进入特定的文件夹,而失败的则会被转储到另一个文件夹中。我只是不确定最佳方法是什么?谢谢大家。 - Derek
12个回答

1
我正在使用线程安全的静态类。主要思路是将消息排队到列表中,然后每隔一段时间或每个计数器限制保存到日志文件中。
重要提示:在退出程序时应强制保存文件(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();
            }
        }
    }
}

锁定文件并不是必要的。Thread.Sleep(1)! 锁定不能写入文件的事实。文件将成为您的锁。这是跨线程、进程、应用程序、服务器等安全的。在对象上进行锁定只是进程安全的。 - TamusJRoyce

0

我创建了一个简单的类,高度可定制且易于使用(请用您需要的命名空间编辑YOURNAMESPACEHERE),而不是使用外部库log4net。

控制台应用程序

using System;
using System.IO;

namespace YOURNAMESPACEHERE
{
    enum LogEvent
    {
        Info = 0,
        Success = 1,
        Warning = 2,
        Error = 3
    }

    internal static class Log
    {
        private static readonly string LogSession = DateTime.Now.ToLocalTime().ToString("ddMMyyyy_HHmmss");
        private static readonly string LogPath = AppDomain.CurrentDomain.BaseDirectory + "logs";

        internal static void Write(LogEvent Level, string Message, bool ShowConsole = true, bool WritelogFile = true)
        {
            string Event = string.Empty;
            ConsoleColor ColorEvent = Console.ForegroundColor;

            switch (Level)
            {
                case LogEvent.Info:
                    Event = "INFO";
                    ColorEvent = ConsoleColor.White;
                    break;
                case LogEvent.Success:
                    Event = "SUCCESS";
                    ColorEvent = ConsoleColor.Green;
                    break;
                case LogEvent.Warning:
                    Event = "WARNING";
                    ColorEvent = ConsoleColor.Yellow;
                    break;
                case LogEvent.Error:
                    Event = "ERROR";
                    ColorEvent = ConsoleColor.Red;
                    break;
            }

            if (ShowConsole)
            {
                Console.ForegroundColor = ColorEvent;
                Console.WriteLine(" [{0}] => {1}", DateTime.Now.ToString("HH:mm:ss"), Message);
                Console.ResetColor();
            }

            if (WritelogFile)
            {
                if (!Directory.Exists(LogPath))
                    Directory.CreateDirectory(LogPath);

                File.AppendAllText(LogPath + @"\" + LogSession + ".log", string.Format("[{0}] => {1}: {2}\n", DateTime.Now.ToString("HH:mm:ss"), Event, Message));
            }
        }
    }
}

没有控制台应用程序(仅日志记录)
using System;
using System.IO;

namespace YOURNAMESPACEHERE
{
    enum LogEvent
    {
        Info = 0,
        Success = 1,
        Warning = 2,
        Error = 3
    }

internal static class Log
{
    private static readonly string LogSession = DateTime.Now.ToLocalTime().ToString("ddMMyyyy_HHmmss");
    private static readonly string LogPath = AppDomain.CurrentDomain.BaseDirectory + "logs";

    internal static void Write(LogEvent Level, string Message)
    {
        string Event = string.Empty;

        switch (Level)
        {
            case LogEvent.Info:
                Event = "INFO";
                break;
            case LogEvent.Success:
                Event = "SUCCESS";
                break;
            case LogEvent.Warning:
                Event = "WARNING";
                break;
            case LogEvent.Error:
                Event = "ERROR";
                break;
        }

        if (!Directory.Exists(LogPath))
            Directory.CreateDirectory(LogPath);

        File.AppendAllText(LogPath + @"\" + LogSession + ".log", string.Format("[{0}] => {1}: {2}\n", DateTime.Now.ToString("HH:mm:ss"), Event, Message));
    }
}

用法:

控制台应用

Log.Write(LogEvent.Info, "Test message"); // It will print an info in your console, also will save a copy of this print in a .log file.
Log.Write(LogEvent.Warning, "Test message", false); // It will save the print as warning only in your .log file.
Log.Write(LogEvent.Error, "Test message", true, false); // It will print an error only in your console.

无控制台应用程序(仅日志)。
Log.Write(LogEvent.Info, "Test message"); // It will print an info in your .log file.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接