简体   繁体   English

如何将完整的对象添加到 Serilog Azure Tablestorage 接收器,该对象未在消息中写出?

[英]How can I add a complete object to Serilog Azure Tablestorage sink, which is not written out in the message?

So, I'm attempting to include Serilog in my application at the moment, and was wondering about the following:所以,我现在正在尝试将 Serilog 包含在我的应用程序中,并且想知道以下内容:

Is it possible to add an object so my Azure Tablestorage sink will pick it up and write it out completely to JSON in the respective "Data" column, without adding it to the plain text message?是否可以添加一个对象,以便我的 Azure Tablestorage 接收器将其提取并在相应的“数据”列中将其完全写入 JSON,而不将其添加到纯文本消息中?

My initial approach was this:我最初的方法是这样的:

m_logger.Information("{message} @{context}", message, context);

And this is what my question originates from.这就是我的问题的来源。 This worked, but I'd like to keep the message itself human readable and keep metadata from the context in a separate column.这行得通,但我想让消息本身保持人类可读性,并将上下文中的元数据保存在单独的列中。

So, my second attempt now looks like this:所以,我的第二次尝试现在看起来像这样:

using (LogContext.PushProperty("context", context))
{
    m_logger.Information("{message}", message);
}

Given, I added this to my logger config: .Enrich.FromLogContext()鉴于,我将此添加到我的记录器配置中: .Enrich.FromLogContext()

Now this kind of works, the object does not appear in the message anymore and is actually added to the Data, but instead of completely writing it out to JSON, this is what I end up with in my Data column on the Tablestorage endpoint:现在这种工作,该对象不再出现在消息中,而是实际添加到数据中,但不是将其完全写出到 JSON,这就是我在 Tablestorage 端点上的数据列中得到的结果:

{"Timestamp":"2019-09-01T08:52:29.4835746+02:00","Level":"Information","MessageTemplate":"{message}","Properties":{"message":"Login happened","context":"MooMed.Core.DataTypes.Session.Context"}}

So, it seems like this internally merely calls .ToString() .所以,看起来这在内部只是调用.ToString()

I'd now like to know whether there is a built in way to recursively jsonify the object, or if I have to (seemingly) just override .ToString() in my Context class?我现在想知道是否有内置的方法来递归地对对象进行 jsonify,或者我是否必须(似乎)只是在我的Context类中覆盖.ToString()

Unless you explicitly tell Serilog to destructure your context data it will simply use the ToString representation.除非您明确告诉 Serilog 解构您的上下文数据,否则它只会使用ToString表示。 In your initial approach you're telling Serilog to destructure by using the @ symbol (although I assume you used it inside the curly braces rather than outside, ie {@context} rather than @{context} otherwise this shouldn't have worked).在您最初的方法中,您告诉 Serilog 使用@符号进行解构(尽管我假设您在花括号内而不是在外使用它,即{@context}而不是@{context}否则这不应该起作用) .

When using LogContext you can tell Serilog to destructure the object by passing a flag when pusing a property:使用LogContext您可以通过在推送属性时传递标志来告诉 Serilog 解构对象:

using (LogContext.PushProperty("context", context, destructureObjects: true))
{
    // ...
}

I assume you're aware that this will add the context to all messages logged inside the using block, including any that occur further down the call stack.我假设您知道这会将上下文添加到using块内记录的所有消息中,包括发生在调用堆栈下方的任何消息。 As an alternative, you can also create a temporary logger enriched with this context data if you want more control over which messages the context gets added to.作为替代方案,如果您想更好地控制将上下文添加到哪些消息,您还可以创建一个临时记录器,其中包含此上下文数据。 This is done using the ILogger.ForContext method:这是使用ILogger.ForContext方法完成的:

var enrichedLogger = m_logger.ForContext("context", context, destructureObjects: true);

// Use `enrichedLogger` instead of `m_logger` whenever you want context data included.
enrichedLogger.Information("This message has context data attached!");
m_logger.Information("This message does not have context data attached.");

You can also use the same approach above to add context to a single message:您还可以使用上述相同的方法向单个消息添加上下文:

m_logger.ForContext("context", context, destructureObjects: true)
    .Information("This message has context data attached!")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM