Reputation: 2473
I'm not sure what is the best way to achieve what I am trying to accomplish so let me give you an example.
I am using Azure Functions, which are stateless, with the following signature.
public static Task Run(Message message, ILogger logger)
{
var controller = Main.Container.GetInstance<ConsumerController>();
// How can I attach the passed in logger instance so the rest of
// the services for the current flow re-use this instance?
return controller.Execute(message);
}
As you can see, the azure function framework passes me an instance of the ILogger already configured and initialized for this function call only.
I read through the documentation and I think I need a new scope here but I'm not sure. I only want this ILogger instance to be used during the async execution of this one method call. Each function call will use their own.
And just to be clear, the controller is only one of possibly many services (services, repositories, request handlers) involved in the execution of the task.
Any help would be great?
Upvotes: 1
Views: 905
Reputation: 172646
You can do the following:
ProxyLogger
) implementation that implements ILogger
, contains a ILogger Logger
property, and forwards any call to that property.ILogger
and ProxyLogger
as Lifestyle.Scoped
.ProxyLogger
within your function.ProxyLogger.Logger
using the function's supplied ILogger
.Create a Proxy:
public class ProxyLogger : ILogger
{
public ILogger Logger { get; set; }
public void Log<TState>(LogLevel l, EventId id, TState s, Exception ex,
Func<TState,Exception,String> f) =>
this.Logger.Log<TState>(l, id, s, ex, f);
// Implement other functions
}
Register that Proxy:
container.Register<ProxyLogger>(Lifestyle.Scoped);
container.Register<ILogger, ProxyLogger>(Lifestyle.Scoped);
Resolve ProxyLogger
within your function, set ProxyLogger.Logger
using the function's supplied ILogger
, and resolve the root object and use it.
public static Task Run(Message message, ILogger logger)
{
using (AsyncScopedLifestyle.BeginScope(Main.Container)
{
Main.Container.GetInstance<ProxyLogger>().Logger = logger;
var controller = Main.Container.GetInstance<ConsumerController>();
return controller.Execute(message);
}
}
I do think, however, that this model leads to a very large amount of infrastructural code. Preferably you wish to keep this infrastructure to the absolute minimum. Instead, you could try keeping your Azure Functions small Humble Objects, as described here. That might not completely solve your initial problem, but you might not need to have a method specific logger anyway. But if, on the other hand, you need that, you might be able to mix that Humble Object approach with the use of C#'s CallerMemberName attribute and the ProxyLogger
approach. You don't really need the Azure injected ILogger
to do that for you.
Upvotes: 1