Search code examples
asp.net-corenlog

How to configure nlog to use IHostingEnvironment.ContentRootPath in FileTarget


I am trying to add NLog for my asp.net core application. So I configured it exactly as described here https://github.com/NLog/NLog.Extensions.Logging . Also I added https://github.com/NLog/NLog.Web with default configuration too. So far so good, everything working as expected.

Now I want to store my log files not in harcoded folder specified in example c:\temp\nlog-own-${shortdate}.log but in folder which depends on current project. In my previous ASP.NET project I used something like this ${basedir}\App_Data\Logs\nlog-own-${shortdate}.log. Now It is also worked but placed files in bin directory. But I want to configure to place those files in IHostingEnvironment.ContentRootPath folder. Basically I want something like this

    private static Logger Logger = LogManager.GetCurrentClassLogger();
    private IHostingEnvironment _HostingEnvironment;
    public UserController(IHostingEnvironment env)
    {
        _HostingEnvironment = env;
    }

    public IActionResult Index()
    {
        var fileTarget = Logger.Factory.Configuration.FindTargetByName<NLog.Targets.FileTarget>("ownFile-web");
        fileTarget.FileName = new SimpleLayout(
            @"${basedir}\App_Data\Logs\nlog-own-${shortdate}.log"
                .Replace("${basedir}", _HostingEnvironment.ContentRootPath)
        );
        Logger.Info("Index page says hello");

        return View(new UserListArgs());
    }

but in more elegant way.


Solution

  • Something like this:

    Update: in NLog 4.4 this is possible in one line (LayoutRenderer.Register)

    Since NLog 4.4

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
                          ILoggerFactory loggerFactory)
    {
    
        //add NLog to ASP.NET Core
        loggerFactory.AddNLog(); 
    
        //needed for non-NETSTANDARD platforms: configure nlog.config in your project root
        env.ConfigureNLog("nlog.config");
    
        LayoutRenderer.Register("basedir", (logEvent) => env.ContentRootPath);
    
        ...
     }
    

    Before NLog 4.4

    [LayoutRenderer("basedir")]
    public class AspNetCoreBaseDirLayoutRenderer : LayoutRenderer
    {
        public static IHostingEnvironment Env {get;set;}
    
        protected override void Append(StringBuilder builder, LogEventInfo logEvent)
        {
            builder.Append(env.ContentRootPath);
        }
    }
    

    Register:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
      {
          //add NLog to ASP.NET Core
          loggerFactory.AddNLog();
    
    
          //needed for non-NETSTANDARD platforms: configure nlog.config in your project root
          env.ConfigureNLog("nlog.config");
          ...
    
          //overwrite ${basedir}
          AspNetCoreBaseDirLayoutRenderer.Env = env;
          ConfigurationItemFactory.Default.LayoutRenderers
              .RegisterDefinition("basedir", typeof(AspNetCoreBaseDirLayoutRenderer ));
          ...