can I pass a custom property to NLOG and output to file?

大兔子大兔子 提交于 2019-12-03 07:09:40

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 4.5 supports structured logging using message templates:

logger.Info("Logon by {user} from {ip_address}", "Kenny", "127.0.0.1");

See also https://github.com/NLog/NLog/wiki/How-to-use-structured-logging

Use MDLC Layout Renderer

MappedDiagnosticsLogicalContext.Set("PropertyName", "PropertyValue"); MappedDiagnosticsLogicalContext.Set("PropertyName2", "AnotherPropertyValue");

In your nlog config:

${mdlc:item=PropertyName} ${mdlc:item=PropertyName2}

https://github.com/NLog/NLog/wiki/MDLC-Layout-Renderer

Jürgen Steinblock

This is propably not the best way to do this and not even thread safe but a quick and dirty solution: You could use Environment variables:

Environment.SetEnvironmentVariable("NLogOptionID", "87");
logger.Debug("My Name id Ed");
Environment.SetEnvironmentVariable("NLogOptionID", null);

In your layout, you can use environment variables.

${environment:variable=NLogOptionID}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!