Skip to content
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

Remove filters for ILoggers created by customer DI #4345

Open
brettsam opened this issue Apr 23, 2019 · 17 comments
Open

Remove filters for ILoggers created by customer DI #4345

brettsam opened this issue Apr 23, 2019 · 17 comments
Assignees
Milestone

Comments

@brettsam
Copy link
Member

@brettsam brettsam commented Apr 23, 2019

We need to be less restrictive on filtering logging categories. Today if someone creates a logger that is not in one of our "accepted" lists, we'll filter it away. You can get around this by adding one or more filters to get those categories flowing again, but this shouldn't be necessary.

The below settings will allow any category that starts with "OrderService" to be logged at "Information" and above levels.

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "OrderService": "Information"
    }
  }
}
@sandeepiiit
Copy link

@sandeepiiit sandeepiiit commented Jun 5, 2019

@brettsam Thanks for the host.json workaround. Is there a way to specify log levels differently for development vs production environments?

@bchrisb
Copy link

@bchrisb bchrisb commented Jun 19, 2019

@brettsam when you say: The below settings will allow any category that starts with "OrderService" to be logged at "Information" and above levels. what is a "category"? I am experiencing this bug but I'm not quite sure what the workaround is? See my code below:

private ILogger<ServiceLogger> _logger;
private readonly string _version;
private readonly string _deploymentRegion;

public ServiceLogger(ILogger<ServiceLogger> logger, IAppSettings appSettings)
{
	_logger = logger;
	_version = appSettings.Version;
	_deploymentRegion = appSettings.DeploymentRegion;
}

And then my host.json:

{
  "version": "2.0",
  "logging": {
	"logLevel": {
	  "ServiceLogger": "Information"
	}
  }
}

I still don't get any logs. What am I missing?

@bchrisb
Copy link

@bchrisb bchrisb commented Jun 19, 2019

@brettsam sorry, I've just found the answer to my own question by looking at this: #4425 (comment)

@jamesharling
Copy link

@jamesharling jamesharling commented Jan 30, 2020

You can reset all of the filters with this code in your Startup.cs (put it as late as possible):

builder.Services.RemoveAll<IConfigureOptions<LoggerFilterOptions>>();
builder.Services.ConfigureOptions<LoggerFilterConfigureOptions>();

Where LoggerFilterConfigureOptions is an internal implementation in Microsoft.Extensions.Logging that you'll have to bring in to your project (link).

@jeffhollan jeffhollan added the P2 label Mar 4, 2020
@ilushka85
Copy link

@ilushka85 ilushka85 commented May 9, 2020

Are there any updates to this besides removing all the filters?

@brettsam
Copy link
Member Author

@brettsam brettsam commented May 11, 2020

No updates -- but the workaround above is fairly straightforward: #4345 (comment).

Is this not working for you?

@smokedlinq
Copy link

@smokedlinq smokedlinq commented Sep 29, 2020

In the host.json, the category filtering is not working for the root namespace for my solution.

host.json

{
    "version": "2.0",
    "logging": {
      "logLevel": {
        "default": "Information",
        "MySolution": "Trace"
      }
    }
}

Where I have a class that tries to use it that gets injected into the function...

namespace MySolution.Things {
  public class Thing1 {
    public Thing1(ILogger<Thing1> logger) => logger.LogTrace("this is a trace from thing1");
  }
}

It does work if I use the full namespace + class name for the category in the host.json, e.g. MySolution.Things.Thing1

@brettsam
Copy link
Member Author

@brettsam brettsam commented Sep 30, 2020

@smokedlinq -- is this happening in production, or locally using the core tools?

@smokedlinq
Copy link

@smokedlinq smokedlinq commented Sep 30, 2020

I have only noticed locally while debugging.

@brettsam
Copy link
Member Author

@brettsam brettsam commented Oct 1, 2020

Can you share what version of the core tools and functions host you're running (it should be the first few lines of output in the console when you start your app).

@pragnagopa -- maybe another issue here with the logging setup in core tools.

@IanKemp
Copy link

@IanKemp IanKemp commented Oct 1, 2020

@brettsam It's been 18 months since you filed this - when is it going to be implemented?

Logging is one of the most important parts of any application. Getting it right should thus be the first priority of any framework. I know Microsoft wants new features to sell Azure with, but Functions' logging woes need to get sorted out for once and for all.

@pragnagopa
Copy link
Contributor

@pragnagopa pragnagopa commented Oct 1, 2020

@smokedlinq - Core Tools regression is fixed in the latest version: https://github.com/Azure/azure-functions-core-tools/releases/tag/3.0.2931 - if filter is still not working please open a separate issue here: https://github.com/Azure/azure-functions-core-tools/

@smokedlinq
Copy link

@smokedlinq smokedlinq commented Oct 1, 2020

Just confirmed, 3.0.2931 does behave as expected. Thanks all.

@abjbhat
Copy link

@abjbhat abjbhat commented Dec 14, 2020

I think I'm seeing this problem as well.

I've created an Azure Service Bus function. The function uses a DI container using .NET Core's own DI libraries.

The function entry point receives an ILogger instance and we see log entries made with this instance. However, any log entries made with any generic instances of ILogger<MyClass> never show up. I can't point to this exact timeframe, but a few months ago when this function was first deployed, log entries did show up correctly. In fact, these entries were used to debug an issue we had. This is how I know it worked at some point in the past.

The current function runtime is 3.0.15185.0

So far, I have tried ...

hosts.json
{
	"version": "2.0",
	"logging": {
		"logLevel": {
			"default": "Error",
			"MySolution.Functions.Tasks": "Trace",
			"MySolution.Functions.Tasks.MyFunction1": "Trace",
			"MySolution.Functions.Tasks.MyFunction2": "Trace",
			"MySolution.Functions.Tasks.Logic.Managers.Tasks.MyServiceClass1": "Information",
			"MySolution.Functions.Tasks.Logic.Services.MyServiceClass2": "Information"
		},
		"applicationInsights": {
			"samplingExcludedTypes": "Request",
			"samplingSettings": {
				"isEnabled": true
			}
		}
	}
}

In my function, I do setup my DI container like so ..

public class MySolution.Functions.Tasks.MyFunction1
{
	private readonly IServiceProvider _serviceProvider;

	
	public ProcessTaskFunction()
	{
		_serviceProvider = Startup.BuildServiceProvider();
	}
	
	[FunctionName("MyFunction1")]
	public async Task Run(
		[ServiceBusTrigger("%TopicName%", "%SubscriptionName%", Connection = "ServiceBusConnectionString")]
		string serviceBusMsg,
		IDictionary<string, object> userProperties,
		ILogger log)
	{
		{
			//this message does show up in AppInsights
			log.LogInformation($"C# ServiceBus topic trigger function processed message: {serviceBusMsg}");
			
			using var scope = _serviceProvider.CreateScope();
			var dep1 = scope.ServiceProvider.GetRequiredService<IMyDependency1>();
			
			 //This dependency takes an instance of ILogger<IMyDependency1>.
			 //Any calles to ILogger<IMyDependency1>.LogInformation() don't show up in AppInsights of the Kudu file system logs
			dep1.DoStuff();
		}
	}
}

public class Startup
{
	public static IServiceProvider BuildServiceProvider()
	{
		var configRoot = GetConfigurationRoot();
		var services = new ServiceCollection();
		AddOptions(services, configRoot);
		AddConfiguration(services, configRoot);
		AddLogging(services, configRoot);
		AddSqlDbContext(services);
		AddScopedServices(services);
		AddHttpClients(services, configRoot);

		//added these three lines of code after viewing comment https://github.com/Azure/azure-functions-host/issues/4345#issuecomment-580211775
		services.AddSingleton<IConfiguration>(sp => configRoot);
		services.RemoveAll<IConfigureOptions<LoggerFilterOptions>>();
		services.ConfigureOptions<Common.Logging.LoggerFilterConfigureOptions>();
		
		return services.BuildServiceProvider(true);
	}

	private static void AddLogging(IServiceCollection services, IConfiguration configRoot)
	{
		services.AddLogging(builder =>
		{
			builder.AddConfiguration(configRoot);
			builder.AddConsole();
			builder.AddDebug();
		});
	}
	
	//other functions omitted
}

At this point, I'm debating rewriting my function and DI container to pass around the ILogger instance received in the function entry method.

Any help would be appreciated.

Thanks.

LXBdev added a commit to LXBdev/Functions-V3-sample that referenced this issue Mar 25, 2021
otherwise it would only be shown in Live Metrics, but not in console or in actual AppInsights logs.
see Azure/azure-functions-host#4345
@jonathanantoine
Copy link

@jonathanantoine jonathanantoine commented Mar 26, 2021

I have the same issue thant @abjbhat and I would love to have a workaround :(

@hachanMSFT
Copy link

@hachanMSFT hachanMSFT commented Dec 21, 2021

I am hitting the same issue, did you find a work around ? @jonathanantoine @abjbhat

@abjbhat
Copy link

@abjbhat abjbhat commented Dec 21, 2021

@hachanMSFT @jonathanantoine

My solution was just to take the ILogger instance passed in when the function is called and then register it in DI. Then every component which needed logging would get an instance of the original ILogger

//YourFunction.cs

public static void Run(/*other parameters*/, ILogger logger){
    
    YourDependencyInjection.Create(logger)
}

//YourDependencyInjection.cs

private void Create(ILogger logger, ServiceCollection services){

   services.AddScoped< ILoggerWrapper, LoggerWrapper>(builder => new LoggerWrapper(logger))
}

//ILoggerWrapper.cs maybe defined in a different project/dll. Add whatever methods you need

public interface ILoggerWrapper{
 void LogInfo();

  void LogError(); 
}


//LoggerWrapper

public class LoggerWrapper : ILoggerWrapper{
  public LoggerWrapper(ILogger logger) {
    //save the reference
  }
}

//DependentComponentService.cs

public class DependentComponentService{
    public DependentComponentService(ILoggerWrapper loggerWrapper){
       //save the reference
   }
}

This worked for me. I can now see logs in AppInsights. I couldn't see them earlier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests