Question: In my application, I work on several thousand of document a day. I'd like, in some cases some logs, one log by document. Then I'd like for a specific target change the output filename (and only the filename) at runtime.

Around the web I found how to create a target by programming me I'd like just update a the filename by programming. I tried the code below. The error I receive is "LayoutRender cannot be found 'logDirectory'.

Any idea ?

Thanks,

```
var target = (FileTarget)LogManager.Configuration.FindTargetByName("logfile");
target.FileName = "${logDirectory}/file2.txt";

LoggingConfiguration config = new LoggingConfiguration();
var asyncFileTarget = new AsyncTargetWrapper(target);
config.AddTarget("logfile", asyncFileTarget);

LogManager.Configuration = config;

```

The config file is :

```
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <variable name="logDirectory" value="C:/MyLogs"/>
    <targets>
      <target name="logfile" xsi:type="File" layout="${date:format=dd/MM/yyyy HH\:mm\:ss.fff}|${level}|${stacktrace}|${message}" fileName="${logDirectory}/file.txt" />
    </targets>

    <rules>
      <logger name="*" minlevel="Info" writeTo="logfile" />
    </rules>    
  </nlog>

```

Answer: 
[Tony's](https://stackoverflow.com/a/20757494/2009197) solution doesn't seem to work if you use NLog Async (`<targets async="true">`). I had to use the wrapper target to get my FileTarget, otherwise I get a lot of errors. I'm using NLog 2.1.

```
if (LogManager.Configuration != null && LogManager.Configuration.ConfiguredNamedTargets.Count != 0)
{
    Target target = LogManager.Configuration.FindTargetByName("yourFileName");
    if (target == null)
    {
        throw new Exception("Could not find target named: " + "file");
    }

    FileTarget fileTarget = null;
    WrapperTargetBase wrapperTarget = target as WrapperTargetBase;

    // Unwrap the target if necessary.
    if (wrapperTarget == null)
    {
        fileTarget = target as FileTarget;
    }
    else
    {
        fileTarget = wrapperTarget.WrappedTarget as FileTarget;
    }

    if (fileTarget == null)
    {
        throw new Exception("Could not get a FileTarget from " + target.GetType());
    }

    fileTarget.FileName = "SetFileNameHere";
    LogManager.ReconfigExistingLoggers();
}

```

This also doesn't change the config file, it just changes the runtime value. So I also manually edit the config file to my new value using the code below:

```
var nlogConfigFile = "NLog.config";
var xdoc = XDocument.Load(nlogConfigFile);
var ns = xdoc.Root.GetDefaultNamespace();
var fTarget = xdoc.Descendants(ns + "target")
         .FirstOrDefault(t => (string)t.Attribute("name") == "yourFileName");
fTarget.SetAttributeValue("fileName", "SetFileNameHere");
xdoc.Save(nlogConfigFile);

```
[I happen to have written an answer that fits your question as well](https://stackoverflow.com/questions/37327129/nlog-dynamically-change-filename-using-nlog-config/52734579#52734579).

In essence, instead of trying to *rewrite* the configuration, you'd be better off simply creating a configuration that allows you to dynamically choose the filename you want.

---

An adapted example for your use case:

```
Logger myLog = LogManager.GetLogger(name);
LogLevel level = LogLevel.Error;
string message = "This is an error message!";

```

You turn this information into a `LogEventInfo` object:

```
LogEventInfo logEvent = new LogEventInfo(level , myLog.Name, message);

```

You can then add properties to this event (the string indexes are free to choose): 

```
logEvent.Properties["CustomFileName"] = "mycustomfilename";

```

And then you write to the log:

```
myLog.Log(logEvent);

```

---

The interesting thing here is that in your NLog configuration, **you can use this custom property in any field that the Nlog documentation refers to as a "Layout" value**. 

You use `${event-properties:item=CustomFileName}` in the layout to access the property. For example:

```
<target xsi:type="File" 
        name="file" 
        fileName="${basedir}/logs/${event-properties:item=CustomFileName}.log"
        layout="${message}" />

```

Following the posted example, this message will be logged in the `mycustomfilename.log` file. This enables you to dynamically switch your targeted file as you please by setting the `logEvent.Properties["CustomFileName"]` value to whatever filename you want to use.

*Note that you can further optimize this, and e.g. only be able to choose part of the file name.*

The additional benefit is that you only need **one target and one rule** in your config file to make this work.