-
Notifications
You must be signed in to change notification settings - Fork 245
Should BeginScopeImpl be a generic method #366
Comments
Yes; or better lazy-factory based e.g. interface ILogScope : IReadOnlyList<KeyValuePair<string, object>>
{
...
}
IDisposable BeginScopeImpl<T>(Func<T, ILogScope> scopeFactory, T state); |
Yes, please! |
Yeah, scope where T is value typed is the probably the last place to squeeze an allocation out of the logging system |
Also class types https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNetCore.Hosting/Internal/HostingLoggerExtensions.cs#L20 If that could change from public static IDisposable RequestScope(this ILogger logger, HttpContext httpContext)
{
return logger.BeginScopeImpl(new HostingLogScope(httpContext));
} to public static IDisposable RequestScope(this ILogger logger, HttpContext httpContext)
{
return logger.BeginScopeImpl<HostingLogScope, HttpContext>(
(state) => new HostingLogScope(state),
httpContext);
} and https://github.com/aspnet/Logging/blob/dev/src/Microsoft.Extensions.Logging/Logger.cs#L103-L115 from public IDisposable BeginScopeImpl(object state)
{
if (_loggers == null)
{
return _nullScope;
}
if (_loggers.Length == 1)
{
return _loggers[0].BeginScopeImpl(state);
}
var loggers = _loggers; to public IDisposable BeginScopeImpl<TState, TScope>(Func<TState, TScope> scopeFactory, TState state)
{
if (_loggers == null)
{
return _nullScope;
}
return BeginScopeImpl( scopeFactory(state) );
}
public IDisposable BeginScopeImpl<T>(T state)
{
if (_loggers == null)
{
return _nullScope;
}
if (_loggers.Length == 1)
{
return _loggers[0].BeginScopeImpl(state);
}
var loggers = _loggers; Or similar... |
Hmm; first could be an extension method IDisposable BeginScopeImpl<TState, TScope>(this ILogger logger,
Func<TState, TScope> scopeFactory,
TState state) Though |
Does it really matter that much if we made |
And if you use WebSockets currently as they create lots of e.g. aspnet/WebSockets#63 |
This change is really more about consistency of a simple interface that is going to be used by a LOT of libs and probably become the new Common.Logging. So please keep that in mind and get these changes in to simplify the interface now before we are stuck with it for a LONG time. Personally, I also hate that the method got renamed because the signature conflicted with an extension method that was added. If you change the method to @benaadams suggestion then you wouldn't have that conflict and we could go back to the nice simple and logical BeginScope method name. I vote for this signature:
Then there can be extension methods that sit on top of it for all the common easy simple use cases. |
I agree with @ejsmith |
Having TState which may be a value-type, without a Func callback, is better. Having a Func to avoid execution only makes sense if the TState is more expensive to construct than the TScope - and at the end of the say if the TState is a caller defined value-type with multiple fields, the TScope will also be a caller defined value-type with multiple fields. So this would boil down to |
The |
Yes, I just went through this exercise and if you use the scope factory approach it makes it easier to create extension methods on top of the interface. |
Guys, frankly unless you can think of a reason that TScope as a value-type doesn't give you zero allocations when you have no providers, I'm going to be honest and say there's almost no chance we'll add a method that with double-generic signature and extra Func argument when a single-generic signature without the Func does the job. |
Yes, it would give zero alloc when you have no providers; and it would resolve the issue I keep complaining about 👍 However, when there are loggers it might make it worse? Just some observations There is an interest in Logging for a much wider .net use case than just aspnet - which likely also mean people will end up doing weird and wonderful things. While you can easily create a valuetype shim that's mostly no cost. You can't use it to defer expensive execution since its a valuetype its not shared and if you had multiple loggers its deferred cost would now be incurred multiple times. Looking at a specific examples (and it may be an exceptions rather than the rule)
Currently |
I do very similar things in my logging for scopes. It is very common to create logging scopes with collections of property names and values that can be added to the logging output. If you use the scope factory approach then we can avoid doing any data transforms when the scope isn't actually used. Also, if the method signature is just |
Yeah, but if there's a |
Fixed via 8387adb |
For all the same reasons that
Log<T>
is generic https://github.com/aspnet/Logging/blob/dev/src/Microsoft.Extensions.Logging.Abstractions/ILogger.cs#L36./cc @lodejard @rynowak @Eilon
The text was updated successfully, but these errors were encountered: