记录器提供程序:如何实现自定义格式化程序?

15

我实现了一个自定义的日志提供程序。我的自定义日志记录器具有以下签名:

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

formatter是如何传递的?

我该如何实现自定义formatter?比如说,如果我想将其格式化为JSON。

我是Net Core的新手,对此不是很了解。

2个回答

18
传递给你的函数的Func<TState, Exception, string> 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 对象并不是很神奇。


2
其实,你不应该传递 exception 参数,因为默认的格式化程序会完全忽略它。请参见 https://github.com/aspnet/Logging/issues/442。 - Métoule
1
@Métoule 如果默认格式化程序忽略它,我不明白为什么这意味着你不应该传递它。它被忽略了,所以传递与否并不重要。而且无论如何传递它都使其与所有其他记录器保持一致。 - poke
1
好的,"OK" 这个词可能有点过于强烈了,但是我因为一直看不到异常在日志中出现而苦恼了很久。如果不将异常传递给格式化程序,就能清楚地表明它没有被处理,这样就不会产生混淆了。 - Métoule
2
那个转换是救星!(以IEnumerable<KeyValuePair<string, object>>的状态表示) - Arnab Chakraborty

-4
首先,这与.NET Core没有什么关系。看起来你正在使用Microsoft.Extensions.Logging,这只是一个通用的日志门面,你可以在任何地方使用它,不管是.NET Core应用还是其他。它只是ASP.NET Core应用程序默认使用的日志门面而已。
其次,如果你不知道如何实现这个方法,创建自己的日志提供程序可能不是一个好主意。你到底想做什么,为什么没有现成的适配器呢?
话虽如此,Func<TState, Exception, string>类型意味着它需要一个接受TState类型参数和一个Exception类型参数,并返回一个字符串的函数。本质上是这样的:
public string MyFormatter<TState>(TState state, Exception exception)
{
    // create some string
    return someString;
}

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

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

2
我正在尝试以特定的方式格式化我的日志,包括以特定的JSON格式格式化状态。我看到的适配器可以工作,但正如我所说,我正在尝试遵循日志的特定格式。这是否意味着每次调用logmessage时都必须传递格式化程序?是否有一种方法在我的iLoger中注入默认格式化程序? - user313551

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接