-
-
Save khle/883d216429e2fdec9fbc0ecfcfbb7c6f to your computer and use it in GitHub Desktop.
Azure Functions with ILogger example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace FunctionApp1 | |
{ | |
using Autofac; | |
using Autofac.Core; | |
using EnsureThat; | |
using Microsoft.Azure.WebJobs; | |
using Microsoft.Azure.WebJobs.Description; | |
using Microsoft.Azure.WebJobs.Host; | |
using Microsoft.Azure.WebJobs.Host.Config; | |
using Microsoft.Extensions.Logging; | |
using System; | |
using System.Collections.Concurrent; | |
using System.Linq; | |
using System.Reflection; | |
using Module = Autofac.Module; | |
public static class Function1 | |
{ | |
[FunctionName("Function1")] | |
public static void Run([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, | |
[Inject(typeof(ISomething))]ISomething something, | |
ILogger log) | |
{ | |
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}"); | |
var value = something.GetSomething(); | |
log.LogInformation("Found value " + value); | |
} | |
} | |
public interface ISomething | |
{ | |
string GetSomething(); | |
} | |
public class Something : ISomething | |
{ | |
private readonly ILogger _logger; | |
public Something(ILogger logger) | |
{ | |
_logger = logger; | |
} | |
public string GetSomething() | |
{ | |
_logger.LogInformation("Hey, we are doing something and dependency injection works!"); | |
return Guid.NewGuid().ToString(); | |
} | |
} | |
[Binding] | |
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] | |
public class InjectAttribute : Attribute | |
{ | |
public InjectAttribute(Type type) | |
{ | |
Type = type; | |
} | |
public Type Type { get; } | |
} | |
public class InjectConfiguration : IExtensionConfigProvider | |
{ | |
private static readonly object _syncLock = new object(); | |
private static IContainer _container; | |
public void Initialize(ExtensionConfigContext context) | |
{ | |
InitializeContainer(context); | |
context | |
.AddBindingRule<InjectAttribute>() | |
.BindToInput<dynamic>(i => _container.Resolve(i.Type)); | |
} | |
private void InitializeContainer(ExtensionConfigContext context) | |
{ | |
if (_container != null) | |
{ | |
return; | |
} | |
lock (_syncLock) | |
{ | |
if (_container != null) | |
{ | |
return; | |
} | |
_container = ContainerConfig.BuildContainer(context.Config.LoggerFactory); | |
} | |
} | |
} | |
public static class ContainerConfig | |
{ | |
public static IContainer BuildContainer(ILoggerFactory factory) | |
{ | |
var builder = new ContainerBuilder(); | |
var assemblyTypes = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Any()).ToArray(); | |
builder.RegisterTypes(assemblyTypes).AsImplementedInterfaces(); | |
builder.RegisterInstance(factory).As<ILoggerFactory>(); | |
builder.RegisterModule<LoggerModule>(); | |
return builder.Build(); | |
} | |
} | |
public class LoggerModule : Module | |
{ | |
private static readonly ConcurrentDictionary<Type, object> _logCache = new ConcurrentDictionary<Type, object>(); | |
private interface ILoggerWrapper | |
{ | |
object Create(ILoggerFactory factory); | |
} | |
protected override void AttachToComponentRegistration( | |
IComponentRegistry componentRegistry, | |
IComponentRegistration registration) | |
{ | |
Ensure.Any.IsNotNull(registration, nameof(registration)); | |
// Handle constructor parameters. | |
registration.Preparing += OnComponentPreparing; | |
} | |
private static object GetLogger(IComponentContext context, Type declaringType) | |
{ | |
return _logCache.GetOrAdd( | |
declaringType, | |
x => | |
{ | |
var factory = context.Resolve<ILoggerFactory>(); | |
var loggerName = "Function." + declaringType.FullName + ".User"; | |
return factory.CreateLogger(loggerName); | |
}); | |
} | |
private static void OnComponentPreparing(object sender, PreparingEventArgs e) | |
{ | |
var t = e.Component.Activator.LimitType; | |
if (t.FullName.IndexOf(nameof(FunctionApp1), StringComparison.OrdinalIgnoreCase) == -1) | |
{ | |
return; | |
} | |
if (t.FullName.EndsWith("[]", StringComparison.OrdinalIgnoreCase)) | |
{ | |
// Ignore IEnumerable types | |
return; | |
} | |
e.Parameters = e.Parameters.Union( | |
new[] | |
{ | |
new ResolvedParameter((p, i) => p.ParameterType == typeof(ILogger), (p, i) => GetLogger(i, t)) | |
}); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<TargetFramework>netstandard2.0</TargetFramework> | |
<AzureFunctionsVersion>v2</AzureFunctionsVersion> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Autofac" Version="4.8.1" /> | |
<PackageReference Include="Ensure.That" Version="8.0.0" /> | |
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.13" /> | |
</ItemGroup> | |
<ItemGroup> | |
<None Update="host.json"> | |
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | |
</None> | |
<None Update="local.settings.json"> | |
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | |
<CopyToPublishDirectory>Never</CopyToPublishDirectory> | |
</None> | |
</ItemGroup> | |
</Project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment