我正在编写一个工具,它将检查网络中工作站的运行状况,并根据发现的问题进行修复。我想创建一个日志文件,因为应用程序正在运行每台计算机上的任务/检查。我只想暂时让它在一台机器上工作,但是它会一次扫描100多台机器(螺纹输出)。
创建日志文件的最佳方法是什么?
我在考虑使用List<string>
在内存中构建日志文件,然后在文件结束后将其输出到文件中。
我只是觉得可能有更好的方法吗?
答案 0 :(得分:12)
我建议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: Programmatically specify multiple loggers (with multiple file appenders)
Adding appenders programmatically
How to configure log4net programmatically from scratch (no config)
另外,log4net也允许写入事件日志。一切都是基于配置的,配置也可以在运行时从xml动态加载。
编辑2:
即时切换日志文件的一种方法: Log4Net配置文件支持环境变量:
Environment.SetEnvironmentVariable("log4netFileName", "MyApp.log");
并在log4net config中:
<param name="File" value="${log4netFileName}".log/>
答案 1 :(得分:7)
我不会使用第三方库,我会登录到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 :(得分:5)
您可能想要使用事件日志!以下是如何从C#访问它 http://support.microsoft.com/kb/307024/en
但无论你要使用哪种方法,我建议每次将某些内容附加到日志而不是进程退出时输出到文件,这样你就不会在崩溃或丢失时丢失数据如果你的进程被杀死了。
答案 3 :(得分:5)
使用Nlog http://nlog-project.org/。它是免费的,允许写入文件,数据库,事件日志和其他20多个目标。 另一个日志框架是log4net - http://logging.apache.org/log4net/(从java Log4j项目移植)。它也是免费的。
最佳做法是使用常见日志记录 - http://commons.apache.org/logging/ 因此,您可以稍后将NLog或log4net更改为其他日志框架。
答案 4 :(得分:5)
我们对日志记录进行了大量研究,并认为NLog是最好用的。
另见log4net vs. Nlog 和http://www.dotnetlogging.com/comparison/
答案 5 :(得分:4)
您可以使用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.........");
}
}
答案 6 :(得分:4)
添加此配置文件
*************************************************************************************
<!--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>
答案 7 :(得分:3)
您也可以查看内置的.NET跟踪工具。有一组跟踪侦听器允许您输出到日志文件,但您可以将其配置为登录事件查看器或数据库(或同时所有数据库)。
http://www.codeguru.com/csharp/.net/net_debugging/tracing/article.php/c5919/NET-Tracing-Tutorial.htm
答案 8 :(得分:2)
您可以使用http://logging.apache.org/库并使用数据库追加器一起收集所有日志信息。
答案 9 :(得分: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();
}
}
}
}
答案 10 :(得分:0)
我在GitHub上找到了来自SimpleLogger的heiswayi。
答案 11 :(得分:0)
我没有使用外部库log4net,而是创建了自己的简单类,高度可定制且易于使用(使用所需的名称空间编辑YOURNAMESPACEHERE
)。
控制台应用程序
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.