c#创建日志文件的最佳方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10242061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
c# Best Method to create a log file
提问by Derek
I'm writing a tool that's going to be check the health of workstations across a network, and will fix according to the issues it finds. I want to create a log file as the app is running through its tasks / checks on each machine. I just want to get this working on a single machine for now, but in time it will be scanning 100+ machines in one go (Threaded out).
我正在编写一个工具来检查网络上工作站的健康状况,并将根据它发现的问题进行修复。我想创建一个日志文件,因为应用程序正在每台机器上运行它的任务/检查。我现在只想在一台机器上完成这项工作,但随着时间的推移,它将一次性扫描 100 多台机器(线程化)。
What is the best way to create a log file?
创建日志文件的最佳方法是什么?
I was thinking of using a List<string>to build up the log file in memory and then output it to a file once it had finished.
我正在考虑使用 aList<string>在内存中构建日志文件,然后在完成后将其输出到文件中。
I'm just thinking there may be a better way of doing this?
我只是在想可能有更好的方法来做到这一点?
采纳答案by croisharp
I would not use third party libraries, I would log to an xml file.
我不会使用第三方库,我会登录到一个 xml 文件。
This is a code sample that do logging to a xml file from different threads:
这是一个从不同线程记录到 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");
}
}
回答by Julien
You might want to use the Event Log ! Here's how to access it from C# http://support.microsoft.com/kb/307024/en
您可能想要使用事件日志!以下是从 C# 访问它的方法 http://support.microsoft.com/kb/307024/en
But whatever is the method that you will use, I'd recommend to output to a file every time something is appended to the log rather than when your process exits, so you won't lose data in the case of crash or if your process is killed.
但是无论您将使用什么方法,我建议每次将某些内容附加到日志时而不是在您的进程退出时输出到文件,这样您就不会在崩溃的情况下或您的进程丢失数据被杀了。
回答by Chris Li
You can use http://logging.apache.org/library and use a database appender to collect all your log info together.
您可以使用http://logging.apache.org/库并使用数据库附加程序将所有日志信息收集在一起。
回答by David Z.
You can also take a look at the built-in .NET tracing facilities too. There's a set of trace listeners that allow you to output to a log file, but you can configure it to log into the Event viewer, or to a database (or all of them simultaneously).
您还可以查看内置的 .NET 跟踪工具。有一组跟踪侦听器可让您输出到日志文件,但您可以将其配置为登录到事件查看器或数据库(或同时登录到所有这些)。
http://www.codeguru.com/csharp/.net/net_debugging/tracing/article.php/c5919/NET-Tracing-Tutorial.htm
http://www.codeguru.com/csharp/.net/net_debugging/tracing/article.php/c5919/NET-Tracing-Tutorial.htm
回答by Alex Blokha
Use the Nlog http://nlog-project.org/. It is free and allows to write to file, database, event log and other 20+ targets. The other logging framework is log4net - http://logging.apache.org/log4net/(ported from java Log4j project). Its also free.
使用 Nlog http://nlog-project.org/。它是免费的,允许写入文件、数据库、事件日志和其他 20 多个目标。另一个日志框架是 log4net - http://logging.apache.org/log4net/(从 java Log4j 项目移植)。它也是免费的。
Best practices are to use common logging - http://commons.apache.org/logging/So you can later change NLog or log4net to other logging framework.
最佳实践是使用通用日志记录 - http://commons.apache.org/logging/这样您以后可以将 NLog 或 log4net 更改为其他日志记录框架。
回答by Matthew Watson
We did a lot of research into logging, and decided that NLog was the best one to use.
我们对日志记录进行了大量研究,并认为 NLog 是最好的使用方法。
Also see log4net vs. Nlogand http://www.dotnetlogging.com/comparison/
回答by Aseem Gautam
I would recommend log4net.
我会推荐log4net。
You would need multiple log files. So multiple file appenders. Plus you can create the file appenders dynamically.
您将需要多个日志文件。所以多个文件附加程序。另外,您可以动态创建文件附加程序。
Sample 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/Good links:
来源/良好链接:
Log4Net: Programmatically specify multiple loggers (with multiple file appenders)
Log4Net:以编程方式指定多个记录器(具有多个文件附加器)
Adding appenders programmatically
How to configure log4net programmatically from scratch (no config)
Plus the log4net also allows to write into event log as well. Everything is configuration based, and the configuration can be loaded dynamically from xml at runtime as well.
此外,log4net 还允许写入事件日志。一切都是基于配置的,并且配置也可以在运行时从 xml 动态加载。
Edit 2:
编辑2:
One way to switch log files on the fly: Log4Net configuration file supports environment variables:
一种动态切换日志文件的方法:Log4Net 配置文件支持环境变量:
Environment.SetEnvironmentVariable("log4netFileName", "MyApp.log");
and in the log4net config:
并在 log4net 配置中:
<param name="File" value="${log4netFileName}".log/>
回答by Narottam Goyal
You could use the Apache log4net library:
您可以使用Apache log4net 库:
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.........");
}
}
回答by Narottam Goyal
add this config file
添加这个配置文件
*************************************************************************************
<!--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>
回答by Mendi Barel
I'm using thread safe staticclass. Main idea is to queue the message on list and then save to log file each period of time, or each counter limit.
我正在使用线程安全的静态类。主要思想是将消息列在列表中,然后将每个时间段或每个计数器限制保存到日志文件中。
Important: You should force save file ( DirectLog.SaveToFile();) when you exit the program. (in case that there are still some items on the list)
重要提示:DirectLog.SaveToFile();退出程序时应强制保存文件 ( )。(以防清单上还有一些项目)
The use is very simple: DirectLog.Log("MyLogMessage", 5);
使用非常简单: DirectLog.Log("MyLogMessage", 5);
This is my 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();
}
}
}
}

