如何将自定义属性传递给NLOG并输出到文件? [英] can I pass a custom property to NLOG and output to file?

查看:136
本文介绍了如何将自定义属性传递给NLOG并输出到文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

"From"似乎是NLog中的保留字.将其更改为"FromID"即可.这是一种将变量传递给NLog并仍然保持代码干净的绝妙方法!谢谢迈克!!!

编辑3.我真的很喜欢这个主意.

按照Mike的建议,实施了一个辅助课程:

public class NLogHelper
{
    //
    // Class Properties
    //
    private Logger m_logger;
    private Dictionary<string, object> m_properties;


    //
    // Constructor
    //
    public NLogHelper(Logger logger)
    {
        m_logger = logger;
        m_properties = new Dictionary<string, object>();
    }

    //
    // Setting Logger properties per instancce
    //
    public void Set(string key, object value)
    {
        m_properties.Add(key, value);
    }

    //
    // Loggers
    //
    public void Debug(string format, params object[] args)
    {
        m_logger.Debug()
            .Message(format, args)
            .Properties(m_properties)
            .Write();
    }

在我的主要代码中,我有:

    private NLogHelper m_logger;
    public void Start() 
    {
        m_logger = new NLogHelper(LogManager.GetCurrentClassLogger());
        m_logger.Set("From", "QRT123");  // Class setting.
        m_logger.Debug("Hello ");
    }

在配置文件中设置目标,如下所示:

<target xsi:type="File"
    name ="LogFile" fileName="C:\QRT\Logs\QRTLog-${shortdate}.log"
    layout ="${date}|${level}|${event-properties:item=From}|${message} "/>

但是输出的'from'属性中有一个空白???

所以我几乎在那...但是它似乎不起作用?

我现在正在尝试创建自己的NLog调用版本:

private void Log_Debug (string Message) 
{
   LogEventInfo theEvent = new LogEventInfo(LogLevel.Debug, "What is this?", Message);
   theEvent.Properties["EmployeeID"] = m_employeeID;
   m_logger.Log(theEvent);
}

问题是我必须格式化调用的字符串(但这是一项巨大的性能问题)……但这看起来像是一个黑客??

理想情况下,我将在自定义布局渲染器中声明属性,而不是在配置文件中设置这些属性,我的类的每个实例都将设置属性...类似于整个类的[ID = m_ID].这样,每当从该类调用NLog时,就会设置ID属性,并且NLog的自定义布局渲染器可以使用此属性来输出它.我说得通吗?

我是NLog的新手,并且一直在研究自定义渲染器. 基本上,我的目标是使我的日志语句为: _logger.Debug ("My Name is {0}", "Ed", ID=87);

,我希望渲染的图像如下所示: layout = ${ID} ${date} ${Level} ${Message}

就是这样. $ {ID}的默认值为0.但理想情况下,我希望每个呼叫都能够指定ID,而无需每次登录都需要3行.

我看过自定义渲染器,可以自定义输出的内容,但是我不确定如何自定义传递给它的属性而无需

https://github.com/NLog/NLog/wiki/Wiki/Extending%20NLog 显示了如何添加属性,但我不知道如何调用它们.

此外, https://github.com/NLog/NLog/Wiki/Event-Context-Layout-Renderer 显示了如何设置自定义属性,但是每次我要记录某些内容时,都会涉及创建LogEventInfo对象.

Nlog自定义layoutrenderer 显示了如何自定义输出.输入.

这是针对使用VS2013的.NET 4.0的C#控制台应用程序

谢谢 -埃德(Ed)

解决方案

事件属性(以前称为事件上下文)将是执行所需操作的内置方法.如果您使用的是NLog 3.2+,则可以使用流利的api,这可能比创建LogEventInfo对象更具吸引力.您可以使用名称空间NLog.Fluent来访问此api.

您的布局将这样定义:

${event-properties:item=ID} ${date} ${Level} ${Message}

然后使用流畅的api,像这样记录:

_logger.Debug()
    .Message("My name is {0}", "Ed")
    .Property("ID", 87)
    .Write();

除了如上所述设置每个事件的属性外,唯一的其他选择是使用 MDC MDLS .

NLog无法设置每个记录器属性(我发现).在内部,NLog通过记录器名称缓存Logger实例,但不保证对于给定的记录器名称始终返回相同的Logger实例.因此,例如,如果您在类的构造函数中调用LogManager.GetCurrentClassLogger(),大多数时候 ,您将为类的所有实例取回相同的Logger实例.在这种情况下,您将无法针对类的每个实例在记录器上使用单独的值.

也许您可以创建一个可以在您的类中实例化的日志记录帮助程序类.可以使用每个实例的属性值初始化帮助程序类,以随每条消息一起记录. helper类还将提供方便的方法来记录上述消息,但使用一行代码.像这样:

// Example of a class that needs to use logging
public class MyClass
{
    private LoggerHelper _logger;

    public MyClass(int id)
    {
        _logger = new LoggerHelper(LogManager.GetCurrentClassLogger());

        // Per-instance values
        _logger.Set("ID", id);
    }

    public void DoStuff()
    {
        _logger.Debug("My name is {0}", "Ed");
    }
}


// Example of a "stateful" logger
public class LoggerHelper
{
    private Logger _logger;
    private Dictionary<string, object> _properties;


    public LoggerHelper(Logger logger)
    {
        _logger = logger;
        _properties = new Dictionary<string, object>();
    }

    public void Set(string key, object value)
    {
        _properties.Add(key, value);
    }

    public void Debug(string format, params object[] args)
    {
        _logger.Debug()
            .Message(format, args)
            .Properties(_properties)
            .Write();
    }
}

这将与上面的布局相同.

EDIT 4: "From" seems to be a reserved word in NLog. Changing it "FromID" worked. this is an awesome way to pass variables to NLog and still keep your code clean !!!! THANK MIKE!!!

EDIT 3. I really like this idea.:

Implemented a helper class as Mike suggested below:

public class NLogHelper
{
    //
    // Class Properties
    //
    private Logger m_logger;
    private Dictionary<string, object> m_properties;


    //
    // Constructor
    //
    public NLogHelper(Logger logger)
    {
        m_logger = logger;
        m_properties = new Dictionary<string, object>();
    }

    //
    // Setting Logger properties per instancce
    //
    public void Set(string key, object value)
    {
        m_properties.Add(key, value);
    }

    //
    // Loggers
    //
    public void Debug(string format, params object[] args)
    {
        m_logger.Debug()
            .Message(format, args)
            .Properties(m_properties)
            .Write();
    }

and in my main code, I have:

    private NLogHelper m_logger;
    public void Start() 
    {
        m_logger = new NLogHelper(LogManager.GetCurrentClassLogger());
        m_logger.Set("From", "QRT123");  // Class setting.
        m_logger.Debug("Hello ");
    }

And the target set in the config file as follows:

<target xsi:type="File"
    name ="LogFile" fileName="C:\QRT\Logs\QRTLog-${shortdate}.log"
    layout ="${date}|${level}|${event-properties:item=From}|${message} "/>

But the output has a BLANK in the place of the 'from' property ???

So I'm ALMOST THERE... but it does not seem to work??

EDIT 2: I am now trying to create my own version of the NLog call:

private void Log_Debug (string Message) 
{
   LogEventInfo theEvent = new LogEventInfo(LogLevel.Debug, "What is this?", Message);
   theEvent.Properties["EmployeeID"] = m_employeeID;
   m_logger.Log(theEvent);
}

The issue is that I have to format the string for the calls (but a huge performance deal)... but this seems like a hack??

Ideally, I would declare properties in the custom layout renderer and instead of setting those properties in the configuration file, each instance of my class would have the property set... something like [ID = m_ID] for the whole class. This way whenever a NLog is called from that class, the ID property is set and NLog's custom layout renderer can use this property to output it. Am I making sense??

I'm new to NLog and have been looking at custom renderers. Basically, my goal is to have my log statements be: _logger.Debug ("My Name is {0}", "Ed", ID=87);

and I'd like my rendered to be something like: layout = ${ID} ${date} ${Level} ${Message}

That's it. ${ID} can have a default value of 0. fine. But ideally, I'd like every call to have the ability to specify an ID without needing to have 3 lines everytime I want to log.

I've seen custom renderers allowing me to customize what I output but i'm not sure how I can customize the properties I pass to it without

https://github.com/NLog/NLog/wiki/Extending%20NLog shows how I can add properties but I don't know how to call them.

Also, https://github.com/NLog/NLog/wiki/Event-Context-Layout-Renderer shows how I can set custom properties but that involved the creation of a LogEventInfo object every time I want to log something.

Nlog Custom layoutrenderer shows how to customize the output.. again... not how to customize the inputs.

This is for a Console app in C# targeting .NET 4.0 using VS2013

Thanks -Ed

解决方案

Event properties (used to be called event-context) would be the built-in way to do what you want. If you are using NLog 3.2+ you can use the fluent api, which may be a bit more appealing than creating LogEventInfo objects. You can access this api by by using the namespace NLog.Fluent.

Your layout would then be defined like this:

${event-properties:item=ID} ${date} ${Level} ${Message}

Then using the fluent api, log like this:

_logger.Debug()
    .Message("My name is {0}", "Ed")
    .Property("ID", 87)
    .Write();

Other than setting properties per event as above, the only other option would be to set properties per thread using MDC or MDLS.

NLog dosen't have a way (that I have found) of setting per-logger properties. Internally, NLog caches Logger instances by logger name, but does not guarantee that the same instance of Logger will always be returned for a given logger name. So for example if you call LogManager.GetCurrentClassLogger() in the constructor of your class, most of the time you will get back the same instance of Logger for all instances of your class. In which case, you would not be able to have separate values on your logger, per instance of your class.

Perhaps you could create a logging helper class that you can instantiate in your class. The helper class can be initialized with per-instance property values to be logged with every message. The helper class would also provide convenience methods to log messages as above, but with one line of code. Something like this:

// Example of a class that needs to use logging
public class MyClass
{
    private LoggerHelper _logger;

    public MyClass(int id)
    {
        _logger = new LoggerHelper(LogManager.GetCurrentClassLogger());

        // Per-instance values
        _logger.Set("ID", id);
    }

    public void DoStuff()
    {
        _logger.Debug("My name is {0}", "Ed");
    }
}


// Example of a "stateful" logger
public class LoggerHelper
{
    private Logger _logger;
    private Dictionary<string, object> _properties;


    public LoggerHelper(Logger logger)
    {
        _logger = logger;
        _properties = new Dictionary<string, object>();
    }

    public void Set(string key, object value)
    {
        _properties.Add(key, value);
    }

    public void Debug(string format, params object[] args)
    {
        _logger.Debug()
            .Message(format, args)
            .Properties(_properties)
            .Write();
    }
}

This would work with the same layout as above.

这篇关于如何将自定义属性传递给NLOG并输出到文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆