-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Introducing Log buffering abstraction #104129
Comments
Tagging subscribers to this area: @dotnet/area-extensions-logging |
I'm not following how the system is composed. Where can I see what implementations and consumers of IBufferedLogger look like? |
For example, I don't understand how the cited pooling of BufferedLogRecord is supposed to work. I implement a logger that implements that interface. Someone hands me a bunch of these record objects transferring ownership to be. How is it that I communicate when I'm done with them? Or how does this relate to all the existing use of methods like LogInformation? |
You may look at the PR #103138 showing how the ConsoleLogger is going to implement the interface. The implementation in |
After returning from |
Ok
That is a long issue and it's not clear to me what aspects of it address this. This issue needs to be fleshed out with more details, or a link provided to a finalized design, as otherwise we can't really comment on the how appropriate or not the interface is. If consumption of the interface is being implemented in dotnet/extensions, how does buffering work when someone uses the support in dotnet/runtime? There are lots of very popular extension methods here, and even though we have analyzers that suggest folks use the source generator, the vast majority of code I see that uses ILogger still just uses the extension methods like LogInformation, LogDebug, etc. Those don't light-up with IBufferedLogger? |
|
Good questions :-) The The proposed enhancement involves adding log buffering functionality. When When it's time to flush the buffered logs, Extension methods like
I assume you meant
We anticipate that buffering will generate many |
Would these types be shipped in the Microsoft.Extensions.Logging.Abstractions package? If so, it would then have to depend on the System.Diagnostics.DiagnosticSource package on .NET Framework and .NET Standard, in order to get the definitions of ActivitySpanId, ActivityTraceId, and ActivityTraceFlags. Not an objection; I'd just like to understand the plan. Does BufferedLogRecord.FormattedMessage include BufferedLogRecord.Exception, or is it separate? |
Yes. The dependency on
It makes sense to be separate and let the logger provider decide how to log the exception. |
How does How does it support structured logging? |
Structured logging seems to be supported via BufferedLogRecord.Attributes. I presume the I'd expect ILogger.Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState,Exception?,string> formatter) to call |
These types might be better placed in the Microsoft.Extensions.Logging.Abstractions namespace) than in Microsoft.Extensions.Logging because, like NullLogger and LogEntry<TState>, they are more relevant to authors of logger providers and logging infrastructure than to applications that configure logging and write log entries. |
No, the logging provider exposes the non-generic ILogger interface, and the infrastructure provides an ILogger<TCategoryName> wrapper. |
How does buffering work with ILogger.BeginScope<TState>(TState state)? I don't see a scope-list property in BufferedLogRecord. Does the logging infrastructure have to embed the scope information into BufferedLogRecord.FormattedMessage and BufferedLogRecord.Attributes? (That would not work with logger providers such as TraceSourceLoggerProvider that have to forward the BeginScope calls to some other API, but I guess those would just not implement IBufferedLogger, like they already don't implement ISupportExternalScope.) Or, do all BufferedLogRecord instances in the same IBufferedLogger.LogRecords call belong to the same logger scope? In which case, the logging infrastructure would have to either flush the buffer whenever a scope ends, or copy the logger scope TState objects so that it can safely buffer the scope changes too. |
Right. This was just a typo. It makes sense the new types be next to |
@tarekgh It is not clear for me, how to control this time to flash? Are you going to add more api to control when it should be flushed, and should it be flushed at all? |
@Ilchert there will be a whole feature implemented in the extension's library next to extended logger there. This will include APIs and configurations support for buffering. The proposal here is only scoped to the abstraction needed in the runtime to support implemented the feature. |
namespace Microsoft.Extensions.Logging.Abstractions;
public interface IBufferedLogger
{
void LogRecords(IEnumerable<BufferedLogRecord> records);
}
public abstract class BufferedLogRecord
{
public abstract DateTimeOffset Timestamp { get; }
public abstract LogLevel LogLevel { get; }
public abstract EventId EventId { get; }
public virtual string? Exception { get; }
public virtual ActivitySpanId? ActivitySpanId { get; }
public virtual ActivityTraceId? ActivityTraceId { get; }
public virtual ActivityTraceFlags? ActivityTraceFlags { get; }
public virtual int? ManagedThreadId { get; }
public virtual string? FormattedMessage { get; }
public virtual string? MessageTemplate { get; }
public virtual IReadOnlyList<KeyValuePair<string, object?>>? Attributes { get; }
} |
Background and motivation
Currently, apps publish logs to capture telemetry data for monitoring the system's health. Typically, the logged data is sent to a backend for analysis. Often, these logs become useful only when an issue arises, necessitating a review to identify the problem. When the system is functioning normally, the logs are discarded, but the cost of collecting and transmitting them has already been incurred.
Log buffering addresses this by storing logs in memory instead of immediately sending them to the backend. This allows a decision to be made later on whether to send the buffered logs to their destination or discard them, thereby avoiding unnecessary costs.
This log buffering feature will be implemented in the upstream
dotnet/extensions
library as part of the existingExtendedLogger
design. To enable this feature to work with any logger provider, we need to introduce a buffering abstraction. Logger providers can opt to implement this buffering abstraction interface, which will enable buffering functionality automatically for those providers.The proposal here focuses on the abstraction types needed in the runtime:
IBufferedLogger
: an interface that logger providers must implement to support buffering.BufferedLogRecord
: a proposed class used by the infrastructure to hold buffered state in memory. When ready to be flushed out, this object is passed to logging providers without copying.BufferedLogRecord
is designed to be extendable over time.BufferedLogRecord
objects that are recycled over time. This is an implementation detail forExtendedLogger
.API Proposal
API Usage
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: