C# NLog为类的每个实例创建新日志文件

C# NLog为类的每个实例创建新日志文件,c#,.net,logging,nlog,C#,.net,Logging,Nlog,我有一个已经使用NLog的项目。应用程序创建一个给定类的实例,将ILogger的实例传递给它,然后在实例中调用“execute”方法-系统是多线程的,最多可以同时运行200个实例,日志文件可能会变大,难以读取 我们需要为类的每个实例创建一个新的日志文件,并将其与该实例的输出一起存储(每个实例都有一个唯一的标识符) 我的问题是:是否可以让NLog为类的每个实例创建一个新文件?我知道不同的类可以有不同的日志文件,我想要的是一个类的每个实例都有一个不同的日志文件 我在网上查过,但找不到太多关于这方面的

我有一个已经使用NLog的项目。应用程序创建一个给定类的实例,将ILogger的实例传递给它,然后在实例中调用“execute”方法-系统是多线程的,最多可以同时运行200个实例,日志文件可能会变大,难以读取

我们需要为类的每个实例创建一个新的日志文件,并将其与该实例的输出一起存储(每个实例都有一个唯一的标识符)

我的问题是:是否可以让NLog为类的每个实例创建一个新文件?我知道不同的类可以有不同的日志文件,我想要的是一个类的每个实例都有一个不同的日志文件

我在网上查过,但找不到太多关于这方面的信息,我不想通过创建自己的日志类来重新发明轮子,如果它已经适合NLog

下面是我制作的一个控制台应用程序,它演示了重新配置现有记录器时会发生什么情况——实际上它更改了记录器的所有实例

class Program
{
    static void Main(string[] args)
    {
        BackgroundWorker bw1 = new BackgroundWorker();
        bw1.DoWork += Bw1_DoWork;
        bw1.RunWorkerAsync();

        BackgroundWorker bw2 = new BackgroundWorker();
        bw2.DoWork += Bw2_DoWork;
        bw2.RunWorkerAsync();

        Console.ReadLine();
    }

    private static void Bw1_DoWork(object sender, DoWorkEventArgs e)
    {
        workLoad one = new workLoad("One");
        one.execute();
    }

    private static void Bw2_DoWork(object sender, DoWorkEventArgs e)
    {
        workLoad one = new workLoad("Two");
        one.execute();
    }

}

public class workLoad
{
    private ILogger _logger { get; set; }
    private string _number { get; set; }
    public workLoad(string number)
    {
        _logger = LogManager.GetCurrentClassLogger();
        _number = number;

        var target = (FileTarget) LogManager.Configuration.FindTargetByName("DebugFile");
        target.FileName = $"c:\\temp\\File{number}.txt";
        LogManager.ReconfigExistingLoggers();
    }

    public void execute()
    {
        for (int i = 0; i < 1000; i++)
        {
            _logger.Info(_number + " LOOPING" + i);        
        }

    }
}
类程序
{
静态void Main(字符串[]参数)
{
BackgroundWorker bw1=新的BackgroundWorker();
bw1.DoWork+=bw1_DoWork;
bw1.RunWorkerAsync();
BackgroundWorker bw2=新的BackgroundWorker();
bw2.DoWork+=bw2_DoWork;
bw2.RunWorkerAsync();
Console.ReadLine();
}
私有静态无效Bw1_DoWork(对象发送方,DoWorkEventArgs e)
{
工作量一=新工作量(“一”);
一.execute();
}
私有静态无效Bw2_DoWork(对象发送方,DoWorkEventArgs e)
{
工作量1=新工作量(“两”);
一.execute();
}
}
公开课工作量
{
专用ILogger_记录器{get;set;}
私有字符串_编号{get;set;}
公共工作负载(字符串编号)
{
_logger=LogManager.GetCurrentClassLogger();
_数字=数字;
var target=(FileTarget)LogManager.Configuration.FindTargetByName(“调试文件”);
target.FileName=$“c:\\temp\\File{number}.txt”;
LogManager.ReconfigeExistingLoggers();
}
public void execute()
{
对于(int i=0;i<1000;i++)
{
_记录器信息(_编号+“循环”+i);
}
}
}
这将导致所有输出都指向一个文件(two.txt)。下面是日志文件的示例

2017-06-13 17:00:42.4156测试负载两个循环0 2017-06-13 17:00:42.4156测试负载一个循环0 2017-06-13 17:00:42.4806测试一次循环1 2017-06-13 17:00:42.4746测试负载两个循环1 2017-06-13 17:00:42.4806测试日志工作负载一个循环2 2017-06-13 17:00:42.4806测试日志工作量二循环2 2017-06-13 17:00:42.4946测试负载一个循环3 2017-06-13 17:00:42.4946测试负载两个循环3 2017-06-13 17:00:42.4946测试负载一个循环4 2017-06-13 17:00:42.4946测试负载两个循环4 2017-06-13 17:00:42.5132测试负载一个循环5 2017-06-13 17:00:42.5132测试负载两个循环5 2017-06-13 17:00:42.5132测试负载一个循环6 2017-06-13 17:00:42.5257测试负载两个循环 2017-06-13 17:00:42.5257测试一次循环 2017-06-13 17:00:42.5257测试负载两个循环 2017-06-13 17:00:42.5407测试负载两个循环 2017-06-13 17:00:42.5407测试一个循环的工作量 2017-06-13 17:00:42.5407测试负载两个循环 2017-06-13 17:00:42.5407测试一次循环 2017-06-13 17:00:42.5577测试负载两个循环10 2017-06-13 17:00:42.5577测试负载一个循环10


理想情况下,我会查找从实例1到one.TXT的所有内容,以及从实例2到two.TXT的所有内容(您可以看到,像这样运行200+可能是一个问题!)

也许你可以让类的构造函数初始化一个新日志

也许你可以让类的构造函数初始化一个新日志

试试
重新配置现有的记录器
,这可能是你最好的选择

<targets>
    <target xsi:type="File"
        name="Foo"
        fileName="${basedir}/logs/logfile.txt"
        keepFileOpen="false"
        encoding="iso-8859-2" />
</targets>
从这里的答案可以看出:

尝试
重新配置现有的记录器
,这可能是您最好的选择

<targets>
    <target xsi:type="File"
        name="Foo"
        fileName="${basedir}/logs/logfile.txt"
        keepFileOpen="false"
        encoding="iso-8859-2" />
</targets>
从这里的答案可以看出:

可以尝试在文件名中使用
${logger}
(需要NLog 4.5才能使NLog文件归档逻辑正常工作):

然后这样做:

_logger = LogManager.GetCurrentClassLogger(typeof(workLoad).ToString() + "." + number);
或者,您可以这样创建记录器(如果可行,则不进行测试):


可能尝试在文件名中使用
${logger}
(需要NLog 4.5才能使NLog文件归档逻辑正常工作):

然后这样做:

_logger = LogManager.GetCurrentClassLogger(typeof(workLoad).ToString() + "." + number);
或者,您可以这样创建记录器(如果可行,则不进行测试):


您可以在运行时创建自己的目标,也可以向布局中添加参数并传递它

创建自定义日志文件

    /// <summary>
    /// Creates the custom log file.
    /// Logging of Info and Warning Message Only.
    /// </summary>
    /// <param name="TargetName">Name of the target.</param>
    /// <param name="TargetFileName">Name of the target file.</param>
    /// <param name="LoggerName">Name of the logger.</param>
    public void CreateCustomLogFile(String TargetName, String TargetFileName, String LoggerName = "*")
    {
        try
        {
            var NLogTarget = LogManager.Configuration.FindTargetByName(TargetName);

            if (NLogTarget == null) //Don't Re Add the Target
            {
                NLogTarget = new FileTarget()
                {
                    Name = TargetName,
                    FileName = TargetFileName,
                    Layout = @"[${date:format=yyyy-MM-dd HH\:mm\:ss}] ${message}"
                };

                LogManager.Configuration.AddTarget(TargetName, NLogTarget);
            }

            var NLogRule = new LoggingRule(LoggerName, NLogTarget);
            NLogRule.EnableLoggingForLevel(LogLevel.Info);
            NLogRule.EnableLoggingForLevel(LogLevel.Warn);
            LogManager.Configuration.LoggingRules.Add(NLogRule);

            LogManager.ReconfigExistingLoggers();
        }
        catch { }
    }

    /// <summary>
    /// Removes the custom log file.
    /// </summary>
    /// <param name="TargetName">Name of the target.</param>
    public void RemoveCustomLogFile(String TargetName)
    {
        try
        {
            if (LogManager.Configuration.FindTargetByName(TargetName) != null)
            {
                var Target = LogManager.Configuration.FindTargetByName(TargetName);

                foreach (var rule in LogManager.Configuration.LoggingRules)
                {
                    rule.Targets.Remove(Target);
                }
                LogManager.Configuration.RemoveTarget(TargetName);
                Target.Dispose();
                LogManager.ReconfigExistingLoggers();
            }
        }
        catch { }
    }
//
///创建自定义日志文件。
///仅记录信息和警告消息。
/// 
///目标的名称。
///目标文件的名称。
///记录器的名称。
public void CreateCustomLogFile(字符串TargetName、字符串TargetFileName、字符串LoggerName=“*”)
{
尝试
{
var NLogTarget=LogManager.Configuration.FindTargetByName(TargetName);
if(NLogTarget==null)//不要重新添加目标
{
NLogTarget=新文件目标()
{
Name=TargetName,
FileName=TargetFileName,
布局=@“[${date:format=yyyy-MM-dd-HH \:MM \:ss}]${message}”
};
LogManager.Configuration.AddTarget(TargetName,NLogTarget);
}
var NLogRule=新的日志规则(LoggerName,NLogTarget);
NLogRule.EnableLoggingForLevel(LogLevel.Info);
NLogRule.EnableLoggingForLevel(LogLevel.Warn);
LogManager.Configuration.LoggingRules.Add(NLogRule);
日志管理器,重新配置
private static object _lock = new object();

public static NLog.Logger PrepareLogger(string number)
{
        lock (_lock)
        {
            var fileTarget = LogManager.Configuration.FindTargetByName(number);
            if (fileTarget == null)
            {
                var fileTarget = new FileTarget(number);
                fileTarget.FileName = $"c:\\temp\\File{number}.txt";

                var template = LogManager.Configuration.FindTargetByName("DebugFile");
                if (template != null)
                {
                      fileTarget.Layout = template.Layout;
                }
                LogManager.Configuration.AddTarget(fileTarget);
                var rule = new LoggingRule(number, LogLevel.Debug, fileTarget) { Final = true };
                LogManager.Configuration.LoggingRules.Add(rule);
                LogManager.ReconfigExistingLoggers();
            }
        }
    return LogManager.GetLogger(number);
}
    /// <summary>
    /// Creates the custom log file.
    /// Logging of Info and Warning Message Only.
    /// </summary>
    /// <param name="TargetName">Name of the target.</param>
    /// <param name="TargetFileName">Name of the target file.</param>
    /// <param name="LoggerName">Name of the logger.</param>
    public void CreateCustomLogFile(String TargetName, String TargetFileName, String LoggerName = "*")
    {
        try
        {
            var NLogTarget = LogManager.Configuration.FindTargetByName(TargetName);

            if (NLogTarget == null) //Don't Re Add the Target
            {
                NLogTarget = new FileTarget()
                {
                    Name = TargetName,
                    FileName = TargetFileName,
                    Layout = @"[${date:format=yyyy-MM-dd HH\:mm\:ss}] ${message}"
                };

                LogManager.Configuration.AddTarget(TargetName, NLogTarget);
            }

            var NLogRule = new LoggingRule(LoggerName, NLogTarget);
            NLogRule.EnableLoggingForLevel(LogLevel.Info);
            NLogRule.EnableLoggingForLevel(LogLevel.Warn);
            LogManager.Configuration.LoggingRules.Add(NLogRule);

            LogManager.ReconfigExistingLoggers();
        }
        catch { }
    }

    /// <summary>
    /// Removes the custom log file.
    /// </summary>
    /// <param name="TargetName">Name of the target.</param>
    public void RemoveCustomLogFile(String TargetName)
    {
        try
        {
            if (LogManager.Configuration.FindTargetByName(TargetName) != null)
            {
                var Target = LogManager.Configuration.FindTargetByName(TargetName);

                foreach (var rule in LogManager.Configuration.LoggingRules)
                {
                    rule.Targets.Remove(Target);
                }
                LogManager.Configuration.RemoveTarget(TargetName);
                Target.Dispose();
                LogManager.ReconfigExistingLoggers();
            }
        }
        catch { }
    }
<target name="CTSCoreByPortNumber" xsi:type="File" 
     fileName="${logDirectory}/CTS${event-context:item=PortNumber}.log"
     layout="${fulllayout}" />
    /// <summary>
    /// WriteLog - Overloaded Method to write a Message. 
    /// </summary>
    /// <param name="LogType">LogLevel.Trace
    /// LogLevel.Debug,
    /// LogLevel.Info,
    /// LogLevel.Warn,
    /// LogLevel.Error,
    /// LogLevel.Fatal,</param>
    /// <param name="Msg">Message to write</param>
    /// <param name="args">Arguments</param>
    public void WriteLog(LogLevel LogType, String Msg, object[] args)
    {
        try
        {
            if (args == null)
                args = new object[0];

            LogEventInfo logEvent = new LogEventInfo(LogType, GetCallingMethodName(), null, String.Format(Msg, args), null);

            if (PortNumber != 0)
                logEvent.Properties["PortNumber"] = ".Line_" + PortNumber;

            Instance.Log(typeof(Logging), logEvent);

            //Instance.Log((LogLevel)LogType, Msg, args);
        }
        catch (Exception) { throw; }
    }