akka.net
akka.net copied to clipboard
Akka.Event: add log filtering system to prevent Akka.NET logs from being emitted in first place
Changes
Fixes #7097 and probably lots of other usability issues.
The goal behind this system is to prevent Akka.NET LogEvents from being emitted in the first place in the event that their data is not useful. This should allow developers to do things like akka.LOGLEVEL=DEBUG without getting absolutely flooded with noise from busy parts of the system like Akka.Remote, Akka.Streams, and so on.
The general idea is to pass in a new Setup class:
/// <summary>
/// Used to specify filters that can be used to curtail noise from sources in the Akka.NET log stream.
/// </summary>
public sealed class LogFilterSetup : Setup
{
public LogFilterBase[] Filters { get; }
public LogFilterEvaluator CreateEvaluator() => new(Filters);
public LogFilterSetup(LogFilterBase[] filters)
{
Filters = filters;
}
}
These LogFilterBase types are intended to be simple functions, but while taking into account some easy performance considerations:
public abstract class LogFilterBase : INoSerializationVerificationNeeded, IDeadLetterSuppression
{
/// <summary>
/// Which part of the log message this filter is evaluating?
/// </summary>
/// <remarks>
/// This actually has a performance implication - if we're filtering on the source, which
/// is already fully "expanded" into its final string representation, we can try to fail fast
/// on that without any additional allocations.
///
/// If we're filtering on the message, we have to fully expand the log message first which
/// involves allocations. Users on really tight performance budgets should be aware of this.
/// </remarks>
public abstract LogFilterType FilterType { get; }
/// <summary>
/// Returns <c>true</c> if the message should be kept, <c>false</c> if it should be dropped.
/// </summary>
/// <param name="evt">The <see cref="LogEvent"/> being evaluated.</param>
/// <remarks>
/// If there are multiple filters, all of them must return <c>true</c> for the message to be kept.
/// </remarks>
public abstract bool ShouldKeepMessage(LogEvent evt);
/// <summary>
/// Fast path designed to avoid allocating strings if we're filtering on the message content.
/// </summary>
/// <param name="part">The part of the message to evaluate.</param>
/// <param name="content">Usually the fully expanded message content.</param>
public abstract LogFilterDecision ShouldKeepMessage(LogFilterType part, string content);
}
I'm even including a LogFilterBuilder that should make it easy to construct these using a simple builder pattern. For a log to be printed, all filters must evaluate to true. Will include some examples of this below.
Checklist
For significant changes, please ensure that the following have been completed (delete if not relevant):
- [x] This change follows the Akka.NET API Compatibility Guidelines.
- [x] This change follows the Akka.NET Wire Compatibility Guidelines.
- [x] I have reviewed my own pull request.
- [x] Design discussion issue #7097
- [ ] Changes in public API reviewed, if any.
- [ ] I have added website documentation for this feature.
Going to leave this PR open for comments for a while before it gets merged in
Also: documentation. Will add it once I get review comments.
I still need to do API approvals here