我目前正在运行一个创建多个类实例的Windows服务。
在我的解决方案的服务类和其他所有类的顶部,我有类似的东西:
private static readonly ILog _log = LogManager.GetLogger(typeof(SomeClassTypeHere));
在我的App.config中,我为单个文件配置了Log4Net:
<log4net debug="true">
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs\SomeLogFileName.xml" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<countDirection value="1" />
<maxSizeRollBackups value="30" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.XmlLayoutSchemaLog4j">
<locationInfo value="true" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
这在大多数方面都很有效,并且所有内容都记录到单个文件中。但是,我真的想为我的服务创建的特定类的每个实例创建一个单独的日志文件 这是一个我们经常需要监控以获得支持的类,我们可以在同一时间运行少数实例 我们不知道在给定时间将运行哪些实例,因此它使得在配置中创建静态文件有点痛苦。
我尝试取消readonly修饰符并在类构造函数中设置以下内容:
_log = LogManager.GetLogger("DataCollectionClass_" + deviceName + "_" + DateTime.Now.ToString("MMddyyyy"), typeof(SomeClassTypeHere));
但是这需要我在配置中手动定义一个appender,这很麻烦,很难跟上。
有关在L4N中这样做的任何想法吗?我见过链接here,但不知道是否需要这么多框架。
答案 0 :(得分:14)
下面的代码显示了如何在不使用配置文件的情况下以编程方式配置log4Net以实现您正在寻找的效果。基本上,它只涉及创建一个命名的记录器并添加到层次结构中。
我将here的答案作为起点之一。
using log4net;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository.Hierarchy;
namespace LoggerTest
{
class Program
{
static void Main(string[] args)
{
DeviceConnection dev1 = new DeviceConnection("Device1");
DeviceConnection dev2 = new DeviceConnection("Device2");
dev1.DoSomething();
dev2.DoSomething();
}
}
public class DeviceConnection
{
private string name;
private readonly ILog logger;
public DeviceConnection(string _name)
{
name = _name;
logger = TestLogger.AddNamedLogger(name);
logger.Info("---- Begin Logging for DeviceConnection: " + name);
}
public void DoSomething()
{
logger.Info("Doing something for device connection " + name);
}
}
public static class TestLogger
{
private static PatternLayout _layout = new PatternLayout();
private const string LOG_PATTERN = "%d [%t] %-5p %m%n";
public static string DefaultPattern
{
get { return LOG_PATTERN; }
}
static TestLogger()
{
_layout.ConversionPattern = DefaultPattern;
_layout.ActivateOptions();
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
hierarchy.Configured = true;
}
public static PatternLayout DefaultLayout
{
get { return _layout; }
}
public static ILog AddNamedLogger(string name)
{
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
Logger newLogger = hierarchy.GetLogger(name) as Logger;
PatternLayout patternLayout = new PatternLayout();
patternLayout.ConversionPattern = LOG_PATTERN;
patternLayout.ActivateOptions();
RollingFileAppender roller = new RollingFileAppender();
roller.Layout = patternLayout;
roller.AppendToFile = true;
roller.RollingStyle = RollingFileAppender.RollingMode.Size;
roller.MaxSizeRollBackups = 4;
roller.MaximumFileSize = "100KB";
roller.StaticLogFileName = true;
roller.File = name + ".log";
roller.ActivateOptions();
newLogger.AddAppender(roller);
return LogManager.GetLogger(name);
}
}
}
答案 1 :(得分:1)
使用ADO.Net appender并登录到SQL Server数据库,只查询所需信息。
另一个替代方案是log4net仪表板:http://www.l4ndash.com/。它可以很好地集成来自各种来源的日志,然后以不同的方式对它们进行切片和切割。价格合理。
答案 2 :(得分:1)
log4net有一个名为logger hierarchy的概念。
据说是记录器 如果它是另一个记录器的祖先 名称后跟一个点是前缀 后代记录器名称。记录器 据说是一个孩子的父母 记录器,如果没有祖先 在它自己和后代之间 记录仪。层次结构非常有用 与命名空间和。相同 .NET中的类层次结构。这是非常的 方便,我们很快就会看到。
因此,您确实应该使用.
个字符而不是_
字符创建特定于实例的记录器。
_log = LogManager.GetLogger("DataCollectionClass." + deviceName + "." + DateTime.Now.ToString("MMddyyyy"), typeof(SomeClassTypeHere));
然后在配置文件中引用记录器层次结构,如下所示。
<log4net>
<!-- Other log4net configuration omitted for brevity -->
<logger name="DataCollectionClass">
<!-- Put your appender-ref entries here -->
</logger>
</log4net>
请注意记录器名称引用如何不包含代码中使用的完全限定名称。它只引用名称的根。可以像想象名称空间一样考虑它。
答案 3 :(得分:0)
我有一篇文章可能会有所帮助:
这是关于在运行时更改日志文件。您可以做的是将每个实例的文件名传递到log4net文件中。这样,您就可以为类的每个实例创建一个日志文件。这样您的配置文件很简单,但您可以灵活地为每个类实例创建一个新的日志文件。
上面提到过,您可以使用每个实例的指示器登录数据库。如果您不想购买任何东西,请使用允许10GB数据库的SQL Express。您甚至可以直接写入MDF文件,而不是安装SQL。