Failure listeners and fallback sinks#2108
Conversation
|
Making a note that Serilog.Sinks.Async will need an update to support this if/when merged. |
|
@nblumhardt thanks for the effort that's gone into this, it's greatly appreciated. If I understand correctly, would there essentially be 2 kinds of sinks that can be wrapped with a fallback chain:
Is there also support for state capture? Is that the goal of the |
| LoggingFailureKind kind, | ||
| string message, | ||
| IReadOnlyCollection<LogEvent>? events, | ||
| Exception? exception); |
There was a problem hiding this comment.
Is there a reason that Exception is preferred over ExceptionDispatchInfo to preserve the stack trace?
There was a problem hiding this comment.
Thanks for taking a look!
If the failure is to be forwarded on to another Serilog sink, an Exception will be needed; ExceptionDispatchInfo is useful for re-throwing, but can't expose enough information to be useful for logging, unfortunately.
|
Hi @nblumhardt, Will it be possible to configure the Fallback sinks through configuration? Will it require a change in the Serilog.Settings.Configuration? Cheers, |
|
Thanks for taking a look @ArieGato. The API used in the PR should work with the current feature set of Serilog.Settings.Configuration 👍 As an intermediate step, it should also be possible to configure fallbacks internally within your own sink configuration method, if you want to preserve configuration/API compatibility. |
|
Planning to merge this after #2118 so we can try it out more broadly. It's a nice benefit of the switch to a built-in batching implementation that this should work with most of the existing ecosystem without any changes :-) |
| { | ||
| public void OnLoggingFailed(object sender, LoggingFailureKind kind, string message, IReadOnlyCollection<LogEvent>? events, Exception? exception) | ||
| { | ||
| if (events is not null && kind is LoggingFailureKind.Final or LoggingFailureKind.Permanent) |
There was a problem hiding this comment.
For batched sinks this will only occur after retries have been performed, causing a delay before the fallback sink will see the events.
By default I think this is okay, but we may wish to add a RetryCount or DisableRetries type of setting to BatchingOptions so that fallbacks are tried immediately when this behavior is required.
hi @nblumhardt: I'm trying to configure the fallback/fallback chain sinks through |
|
Hi @ArieGato; I suspect I got this wrong, and the |
|
@nblumhardt I did some investigating and I think the problem with configuring the FallackChain is partly due to the fact that the WriteTo.FallbackChain is not an extension method. This can be resolved in two ways:
What are your thoughts on this? |
|
Thanks for taking a look @ArieGato. There's already a mechanism in Serilog.Settings.Configuration to deal with these: I'm a bit short on time for the next few weeks unfortunately, but it looks like it should be a fairly quick addition. |
|
What would adding support for this to |
|
@davidkarlsson I think the current mapping of C# configuration onto JSON means that the |
@nblumhardt I finally got round adding support for FallbackChain and Fallable to Serilog.Settings.Configuration. serilog/serilog-settings-configuration#474 Can you take a look at it? |
Implements #1791.
The core addition is a new interface,
ILoggingFailureListener, through which sinks can report temporary or permanent logging failures.The most direct way to consume this is hooked up as
WriteTo.Fallible(), which installs a provided failure listener for a given sink:Failure listeners get enough information about failures that monitoring/metrics use cases should be well handled.
The common batching infrastructure has been updated to support failure listeners, so existing sinks that either a) throw exceptions synchronously on failure, or b) use the common batching infrastructure, will automatically support failure listeners.
Sinks that don't fall into either category can implement
ISetLoggingFailureListenerand receive a failure listener at start-up.The second, higher-level way to consume the new functionality is through fallback chains: the
WriteTo.FallbackChain()method accepts an ordered sequence of sinks to try, and using failure listeners, will pass failed writes on to the next sink in the chain:A few APIs get added and so the feature needs some careful scrutiny. It's possible to construe this as bloat, but it's also proven very hard to implement anything similar in a general/cross-cutting way outside the core, so I'm leaning towards pushing ahead with this. Keen to streamline and refine it as much as we can.