We made some progress for beta but we'll keep this item active to track further work.
Please keep me, @SonjaKhan, @davidfowl, and @lodejard in the loop on this because I would like @SonjaKhan to produce some guidance for the team as a whole as part of the core Logging work. We'd like to learn where each sub-team sees value in logging, and generalize it.
We had an all up aspnet brownbag on this the other day
We're not 100% happy with where we have landed - so we want to revisit this in 2.0. Next step is for @ajcvickers to prepare something for a design meeting.
Principle: logging is something that is setup and configured for the application, not per context instance.
To achieve this we introduce some new configuration APIs that are associated with the service provider. This is effectively application-level, or EF-global level configuration, although bound to the service provider so as not to be truly global.
We run the code to set configuration for this only once when we first use a new service provider.
This existing configuration would move:
This means that ILogger no longer needs to be a scoped service, which solves the problem of logging forcing other services to be scoped.
Consequence/limitation: we cannot log for only one context instance and not another. This is something that we support with EF6, but does not work well with the logger abstractions we have. It would likely be ugly to implement and need something like:
It's probably not worth doing all of this, especially given that most code just logs everything to one log anyway. For things that need correlation, we can do it in a way that is more natural to the logging abstractions, such as the work that was already done for connections.
We could introduce a new "On..." method for this API, but this is probably not necessary. Instead we could hang it off of "OnConfiguring". The logging sugar API (Issue #1199) would also go here, since it is application/global configuration. Maybe something like this:
C#
optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Demo;")
.GlobalConfiguration(b => b
.EnableSensitiveDataLogging()
.Log(message => Console.WriteLine(message)));
As stated above, this new builder would only be run once the first time a new service provider is used. This could be confusing in a similar way to OnModelCreating, but then creating a new "On..." method could also be confusing in the same way.
From the Logging docs:
Create a hierarchy of categories that we think best matches the semantics of what people will want to filter on. For example:
Now filtering can be done with a simple "StartsWith" call in a LoggerProvider. We can also add nice sugar for this when using our Log API.
The range from 0-9999 is not used so that code (most likely provider code) that does not follow this convention will still likely not cause collisions.
@ajcvickers Would you explain "not per context instance."? Thanks.
@MaherJendoubi I mean you can't register logging for a single instance of a DbContext but rather must register logging for all instances of DbContext that are associated with a given IServiceProvider.
Notes from design meeting discussion:
Notes:
Categories:
Updated categories above based on design meeting discussion. Only change was to remove the .Design subcategory since it was deemed unnecessary.
Most helpful comment
Logging Proposal for 2.0
Scoping and sugar
Principle: logging is something that is setup and configured for the application, not per context instance.
To achieve this we introduce some new configuration APIs that are associated with the service provider. This is effectively application-level, or EF-global level configuration, although bound to the service provider so as not to be truly global.
We run the code to set configuration for this only once when we first use a new service provider.
This existing configuration would move:
This means that ILogger no longer needs to be a scoped service, which solves the problem of logging forcing other services to be scoped.
Consequence/limitation: we cannot log for only one context instance and not another. This is something that we support with EF6, but does not work well with the logger abstractions we have. It would likely be ugly to implement and need something like:
It's probably not worth doing all of this, especially given that most code just logs everything to one log anyway. For things that need correlation, we can do it in a way that is more natural to the logging abstractions, such as the work that was already done for connections.
API
We could introduce a new "On..." method for this API, but this is probably not necessary. Instead we could hang it off of "OnConfiguring". The logging sugar API (Issue #1199) would also go here, since it is application/global configuration. Maybe something like this:
C# optionsBuilder .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Demo;") .GlobalConfiguration(b => b .EnableSensitiveDataLogging() .Log(message => Console.WriteLine(message)));As stated above, this new builder would only be run once the first time a new service provider is used. This could be confusing in a similar way to OnModelCreating, but then creating a new "On..." method could also be confusing in the same way.
Logger names and event IDs
From the Logging docs:
Proposal for names/categories
Create a hierarchy of categories that we think best matches the semantics of what people will want to filter on. For example:
Now filtering can be done with a simple "StartsWith" call in a LoggerProvider. We can also add nice sugar for this when using our Log API.
Proposal for event IDs
The range from 0-9999 is not used so that code (most likely provider code) that does not follow this convention will still likely not cause collisions.