AngryHacker
AngryHacker

Reputation: 61606

How to inject NLog with an Azure Function

I have the following code to Dependency Inject the NLog logger:

// startup.cs
[assembly: FunctionsStartup(typeof(MyApp.FunctionApp.Startup))]
namespace MyApp.FunctionApp {
    public class Startup : FunctionsStartup {
        public override void Configure(IFunctionsHostBuilder builder) {
            var nLogConfigPath = GetLogPath("nlog.config");
            
            builder.Services.AddLogging(loggingBuilder =>
            {
                var nLogOptions = new NLogAspNetCoreOptions
                {
                    RegisterHttpContextAccessor = true,
                    IgnoreEmptyEventId = true,
                    IncludeScopes = true,
                    ShutdownOnDispose = true
                };

                var logFactory = NLogBuilder.ConfigureNLog(nLogConfigPath);
                logFactory.AutoShutdown = false;

                var nLogConfig = logFactory.Configuration;
                loggingBuilder.AddNLog(nLogConfig, nLogOptions);
            });
        }
    }
}

// actual function code
public class ActualFunctionClass {
    public ActualFunctionClass (ILogger<ActualFunctionClass> logger) {
        logger.LogInformation("log stuff");
    }
}

In the nlog.config, I have several targets. How do I make sure that the logger parameter to the ActualFunctionClass is configured with the proper target?

These are the contents of the nlog.config. For the record, I would like to log using the locations-dataload-file target.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      throwExceptions="true"
      keepVariablesOnReload="true">

  <variable name="logDirectory" value="${basedir}/logs/locations-dataload" />
  <variable name="commonLayout" value="${longdate}|${logger}|${uppercase:${level}}|${message}, ${all-event-properties:format=[key]=[value]:separator=, } ${exception}" />
  <targets>
    <target xsi:type="ApplicationInsightsTarget"
            name="locations-dataload-ai"
            layout="${commonLayout}" />

    <target xsi:type="File"
            name="locations-dataload-file"
            fileName="${logDirectory}/locations-dataload-file-${shortdate}.log"
            layout="${commonLayout}" />

    <target xsi:type="Null" name="blackhole" />
  </targets>

  <rules>
  <!--All logs, including from Microsoft-->
    <logger name="*" minlevel="Trace" writeTo="locations-dataload-ai" />

    <!--All logs, including from Microsoft-->
    <logger name="locations-dataload-local*" minlevel="Trace" writeTo="locations-dataload-ai,locations-dataload-file" />

    <!-- Skip Microsoft logs and so log only own logs -->
    <logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" />
  </rules>

  <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
    <add assembly="MyApp.Logging" />
  </extensions>
</nlog>

Upvotes: 1

Views: 1123

Answers (1)

Julian
Julian

Reputation: 36710

I think this is wrong:

<logger name="locations-dataload-local*" ...

The logger name is by default Namespace.ClassName

You could test this by:

change the rule it to name="*"

 <logger name="*" minlevel="Trace" writeTo="locations-dataload-ai,locations-dataload-file" />

and add to your layout ${logger}, e.g.

layout="${logger}|${commonLayout}" 

The name filter will be matched against the logger name ${logger). So if the logger name is YourNamespace.ActualFunctionClass then locations-dataload-local* won't match that.

Upvotes: 1

Related Questions