【问题标题】:Logger provider: How can I implement a custom formatter记录器提供程序:如何实现自定义格式化程序
【发布时间】:2017-10-26 12:28:26
【问题描述】:

我实现了一个自定义记录器提供程序。我的自定义记录器有这个签名:

public void Log<TState>(LogLevel logLevel, EventId eventId, 
    TState state, Exception exception, Func<TState, Exception, string> formatter)

formatter 是如何传递的?

如何实现自定义formatter?说,如果我希望它以 JSON 格式格式化所有内容

我是 Net Core 的新手,我不完全了解它是如何工作的。

【问题讨论】:

    标签: c# logging asp.net-core


    【解决方案1】:

    传递给您的函数的Func&lt;TState, Exception, string&gt; formatter 函数基本上只是一个实用函数,用于将状态转换为单个字符串消息。在您的记录器中,您基本上只需要调用formatter(state, exception) 来获取应该记录的格式化消息。

    通常,除了调用它来获取格式化的消息之外,您不需要真正关心该函数,因此所有记录器通常都会这样做。对于 JSON 记录器,您可以完全忽略它,或者至少也导出格式化的消息,以便它作为可读字符串存在。

    快速而肮脏的 JSON 记录器的 Log 方法实际上可能如下所示:

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        var jsonLine = JsonConvert.SerializeObject(new {
            logLevel,
            eventId,
            parameters = (state as IEnumerable<KeyValuePair<string, object>>)?.ToDictionary(i => i.Key, i => i.Value),
            message = formatter(state, exception),
            exception = exception?.GetType().Name
        });
    
        // store the JSON log message somewhere
        Console.WriteLine(jsonLine);
    }
    

    如您所见,在这里生成 JSON 对象并没有那么神奇。

    【讨论】:

    • 实际上,您不应该传递exception 参数,因为默认格式化程序完全忽略了它。见github.com/aspnet/Logging/issues/442
    • @Métoule 如果默认格式化程序忽略它,我不明白为什么这意味着您不应该通过它。它被忽略了,所以不管你是否通过它都没有关系。无论如何传递它使其与所有其他记录器保持一致。
    • 好吧,应该不会有点强,但是我在墙上撞了这么久,因为我不明白为什么我的日志中没有出现异常。不将异常传递给格式化程序可以清楚地表明它不处理它,因此不会造成混淆。
    • 这个演员阵容真是天赐之物! (状态为 IEnumerable>)
    【解决方案2】:

    首先,这与 .NET Core 没有任何关系。看起来您正在使用 Microsoft.Extensions.Logging,它只是一个通用的日志记录外观,您几乎可以在任何地方使用,无论是否是 .NET Core 应用程序。它恰好是 ASP.NET Core 应用程序使用的默认值;就是这样。

    其次,如果您不知道如何实现此方法,那么创建自己的日志记录提供程序可能不是一个好主意。如果没有现有的适配器,您要尝试做什么?

    也就是说,Func&lt;TState, Exception, string&gt; 类型意味着它需要一个函数,该函数接受 TState 类型的参数和 Exception 类型的参数之一并返回一个字符串。本质上:

    public string MyFormatter<TState>(TState state, Exception exception)
    {
        // create some string
        return someString;
    }
    

    或者,它可以通过 lambda 实现:

    (state, exception) => exception?.Message ?? state.ToString();
    

    【讨论】:

    • 我正在尝试以某种方式格式化我的日志。包括以特定的 json 格式格式化状态。我见过的适配器可以工作,但就像我说的那样,我正在尝试遵循特定的日志格式。这是否意味着我每次调用 logmessage 时都必须通过格式化程序?有没有办法在我的 iLoger 中注入默认格式化程序?
    猜你喜欢
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 2018-12-29
    相关资源
    最近更新 更多