序列化对象或集合以进行记录

Yav*_*sta 11 .net c# nlog

我想用我的错误消息保存一些附加信息.例如,它应该是用户查询,或其他.我该怎么办?

是否有任何构建它的方法来记录集合,结构或对象?或者我应该自己序列化?

Ser*_*kiy 22

不,没有内置的序列化对象.当您使用Debug<T>(string message, T argument)内部的格式化方法(您可以看到类NLog.LogEventInfo)时,simple String.Format用于创建格式化消息(即只ToString()在每个参数上调用).

我使用Json.NET将对象和集合序列化为JSON.创建扩展方法很容易

public static string ToJson(this object value)
{
    var settings = new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
    };

    return JsonConvert.SerializeObject(value, Formatting.Indented, settings);
}
Run Code Online (Sandbox Code Playgroud)

然后在日志记录期间使用它:

Logger.Debug("Saving person {0}", person.ToJson());
Run Code Online (Sandbox Code Playgroud)

  • 值得一提的是,无论日志级别如何,都将始终调用ToJson。这可能会损害生产性能 (3认同)
  • @dimaaan 是的,为了提高性能,有接受 `LogMessageGenerator` 委托的记录器方法的重载: `Logger.Debug(() =&gt; $"Saving person {person.ToJson()}");` 我也会移动 `JsonSerializerSettings ` 到静态字段。 (3认同)

fan*_*ory 5

/**
 * class used to optimize loggers
 *
 * Logger.Trace("info "+bigData.ToString());
 * Logger.Trace("info {0}",bigData.ToString());
 * both creates and parses bigData even if Trace is disabled
 * 
 * Logger.Trace("info {0}", LazyJsonizer.Create(bigData));
 * Logger.Trace(LazyJsonizer.Instance, "info {0}", bigData);
 * creates string only if Trace is enabled
 * 
 * http://stackoverflow.com/questions/23007377/nlog-serialize-objects-or-collections-to-log
 */
public class LazyJsonizer<T>
{
    T Value;

    public LazyJsonizer(T value)
    {
        Value = value;
    }

    override public string ToString()
    {
        return LazyJsonizer.Instance.Format(null, Value, null);
    }
}

public class LazyJsonizer : IFormatProvider, ICustomFormatter
{
    static public readonly LazyJsonizer Instance = new LazyJsonizer();

    static public LazyJsonizer<T> Create<T>(T value)
    {
        return new LazyJsonizer<T>(value);
    }

    public object GetFormat(Type formatType)
    {
        return this;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        try
        {
            return JsonConvert.SerializeObject(arg);
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这个简化的例子展示了我在玩 NLog 之后的想法。在我的解决方案中,我使用基于代码的配置来减少每个 asp.net 项目的重复 xml nlog.config 文件。适用于 NLog v4.4.1。

记录器静态助手:

private static readonly Logger DefaultLogger = LogManager.GetLogger("Application");

public static void Debug(Exception exception = null, string message = null, object data = null)
    => Write(DefaultLogger, LogLevel.Debug, message, exception, data);

private static void Write(
    Logger logger,
    LogLevel level,
    string message = null,
    Exception exception = null, 
    object data = null)
{
    var eventInfo = new LogEventInfo()
    {
        Level = level,
        Message = message,
        Exception = exception,
        Parameters = new[] { data, tag }
    };
    if (data != null) eventInfo.Properties["data"] = data.ToJson();
    eventInfo.Properties["level"] = eventInfo.GetLevelCode(); // custom level to int conversion

    logger.Log(eventInfo);
}
Run Code Online (Sandbox Code Playgroud)

文件目标配置:

var jsonFileTarget = new FileTarget()
{
    Name = "file_json",
    Layout = new JsonLayout()
    {
        Attributes =
        {
            new JsonAttribute("level", "${event-context:item=level}"),
            new JsonAttribute("time", "${longdate}"),
            new JsonAttribute("msg", "${message}"),
            new JsonAttribute("error", "${exception:format=tostring}"),
            new JsonAttribute("data", "${event-context:item=data}", false),
        },
        RenderEmptyObject = false,
    },
    FileName = $"{LogFile.Directory}/json_{LogFile.Suffix}", // use settings from static LogFile class 
    ArchiveFileName = $"{LogFile.Directory}/json_{LogFile.ArchiveSuffix}",
    ArchiveAboveSize = LogFile.MaxSize
};
Run Code Online (Sandbox Code Playgroud)

自定义对象的输出:

{ "level": "10", "time": "2017-02-02 16:24:52.3078", "data":{"method":"get","url":"http://localhost:44311/"}}
Run Code Online (Sandbox Code Playgroud)