Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

NET Core 2.0.0-preview2 Log filtering #654

Closed
akarimovbytewerk opened this issue Jun 29, 2017 · 14 comments
Closed

NET Core 2.0.0-preview2 Log filtering #654

akarimovbytewerk opened this issue Jun 29, 2017 · 14 comments

Comments

@akarimovbytewerk
Copy link

Hello, after upgrade to version 2.0.0-preview2 LoggerFactory filtering is broken and there is no method AddFilter anymore. Can you suggest how to filter built in event sources in new version or did i miss something?
Here is my ConfigureServices part:

            loggerFactory.AddFilter(new Dictionary<string, LogLevel>
            {
                { "Microsoft", LogLevel.Warning },
                { "System", LogLevel.Error },
                { "Engine", LogLevel.Debug }
            });
            loggerFactory.AddLog4Net();
@smbecker
Copy link

See aspnet/Announcements#238

@akarimovbytewerk
Copy link
Author

There is the same code in article aspnet/Announcements#238

var loggerFactory = new LoggerFactory();
loggerFactory.AddFilter(new Dictionary<string, LogLevel>
{
    { "Microsoft", LogLevel.Warning },
    { "System", LogLevel.Error }
});
loggerFactory.AddConsole();

It work perfect in NET Core 2.0.0-preview1 but
the question is why method .AddFilter is no longer available in NET Core 2.0.0-preview2, or there is some additional settings?

@akarimovbytewerk
Copy link
Author

I'm using the following packages:

    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="2.0.0-preview1-final" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.0-preview2-final" />

@poke
Copy link

poke commented Jun 29, 2017

The LoggerFactory.AddFilter(IDictionary<string, LogLevel> filter) overload was removed as part of #626. I’m not sure if this was intentional or not.

The new AddFilter methods (as extensions) are in FilterLoggingBuilderExtensions and do not accept a dictionary anymore. Instead, you would do this:

loggerFactory
    .AddFilter("Microsoft", LogLevel.Warning)
    .AddFilter("System", LogLevel.Error)
    .AddFilter("Engine", LogLevel.Debug)
    .AddConsole();

@pakrym Was the removal of the dictionary configuration intended? If so, the announcement post should probably be updated to reflect that.

@akarimovbytewerk
Copy link
Author

akarimovbytewerk commented Jun 29, 2017

loggerFactory
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Error)
.AddFilter("Engine", LogLevel.Debug)
.AddConsole();

Ok but these methods accept only ILoggingBuilder, how can i get instance of this type?

I've found that these methods can be called inside IServiceCollection's extension AddLogging

services.AddLogging(loggingBuilder =>
            {
                loggingBuilder
                    .AddFilter("Microsoft", LogLevel.Warning)
                    .AddFilter("System", LogLevel.Error)
                    .AddFilter("Engine", LogLevel.Debug);
            });

but if i'll create new LoggerFactory(); than these filters are ignored and i see full log.
If the creation of LoggerFactory is deprecated, than how can i get an intance of factory or logger?

@poke
Copy link

poke commented Jun 29, 2017

Hmm, you’re right, I missed that part.

Looking at the source, it seems that those AddFilter calls just configure the LoggerFilterOptions to add a rule. So if you create a LoggerFactory explicitly, you would have to use the constructor that allows you to pass the options directly:

var loggerProviders =;
var options = new LoggerFilterOptions();
options.AddRule(new LoggerFilterRule(null, "Microsoft", LogLevel.Warning, null));
options.AddRule(new LoggerFilterRule(null, "System", LogLevel.Error, null));
options.AddRule(new LoggerFilterRule(null, "Engine", LogLevel.Debug, null));
var loggerFactory = new LoggerFactory(loggerProviders, options);

I would agree that this is a terrible interface though to construct a logger factory. While I welcome the changes from the announcement to make this all a bit nicer, I think there should still be a good way to construct (and set up) logger factories without a working DI environment. The way everything is built now, it does not seem like there is a nice way to construct a logger factory outside of DI, which is a shame because I personally started using the logging stuff in a lot of smaller projects that do not use DI.

@akarimovbytewerk
Copy link
Author

Thanks that works. Main difference is that you must use LoggerFilterOptions collection instead of AddFilter(new Dictionary<string, LogLevel>)
The result code is

var options = new LoggerFilterOptions();
options.Rules.Add(new LoggerFilterRule(null, "Microsoft", LogLevel.Warning, null));
options.Rules.Add(new LoggerFilterRule(null, "System", LogLevel.Error, null));
options.Rules.Add(new LoggerFilterRule(null, "Engine", LogLevel.Debug, null));
var loggerFactory = new LoggerFactory(new List<ILoggerProvider>(), options);
loggerFactory.AddLog4Net();

@poke
Copy link

poke commented Jun 29, 2017

While it works, I don’t really consider it a solution. So I’d still be interested in reasons for this change and suggestions how to properly consume logging outside of DI.

@divega divega reopened this Jun 29, 2017
@divega
Copy link

divega commented Jun 29, 2017

Reopening based on last comment.

@pakrym
Copy link
Contributor

pakrym commented Jun 29, 2017

Reason for using dependency injection to compose logging is described in #626 (comment)

As for configuring logging filters outside DI, creating LoggerFilterOptions object is the way to go.
One of things we can do to make it easier is to have same set of WithFilter extension methods as we have for ILoggerBuilder be exposed on LoggerFilterOptions. This will make rule addition look a bit nicer.

@poke
Copy link

poke commented Jun 30, 2017

Thanks for the link to the explanations and updating the announcements on this. Btw. there are two typos I’ve spotted: You wrote Micrososft once, and in one code example, there is ConfigureLoggin (missing a g).

As for having extensions for LoggerFilterOptions, that would work for me. Would you accept a pull request for that (or are you already on it)? I’d also like to see an overloaded constructor to LoggerFactory that just accepted the LoggerFilterOptions since the interface allows you to add providers later, so you do not have to specify them on construction.

Alternatively, what would you think about also exposing the LoggerFilterOptions as a property on the LoggerFactory, so you wouldn’t have to pass them in to the factory? This would allow things like this:

var loggerFactory = new LoggerFactory();
loggerFactory.AddConsole();
loggerFactory.Options.AddFilter("Microsoft", LogLevel.Warning);
loggerFactory.Options.AddFilter("System", LogLevel.Error);
loggerFactory.Options.AddFilter("Engine", LogLevel.Debug);

Although I’m not perfectly sure how we could properly expose the options while keeping the options monitor working properly.

@muratg muratg added this to the Discussions milestone Aug 16, 2017
@mabakay
Copy link

mabakay commented Sep 26, 2017

Is it possible to filter single controller action or whole controller from being logged?

@poke
Copy link

poke commented Sep 26, 2017

@mabakay You can set up filters with more specific namespaces or full type names, as explained in the documentation. So you could easily filter out a specific controller like MyApplication.Controllers.FooController. You cannot filter down to the action though since the whole controller will use the same logger.

@aspnet-hello
Copy link

We periodically close 'discussion' issues that have not been updated in a long period of time.

We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.

@aspnet-hello aspnet-hello removed this from the Discussions milestone Sep 24, 2018
@aspnet aspnet locked and limited conversation to collaborators Sep 24, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants