-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Configure from code
NLog can be also configured programmatically.
All options match with the attribute names in the XML config, so for all config options you could check https://nlog-project.org/config/
There is also a SHFB docs, see https://nlog-project.org/documentation/
NLog 5.0 introduces a Fluent-Configuration-API so you can do this instead:
NLog.LogManager.Setup().LoadConfiguration(builder => {
builder.ForLogger().FilterMinLevel(LogLevel.Info).WriteToConsole();
builder.ForLogger().FilterMinLevel(LogLevel.Debug).WriteToFile(fileName: "file.txt");
});
var config = new NLog.Config.LoggingConfiguration();
// Targets where to log to: File and Console
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "file.txt" };
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
// Rules for mapping loggers to targets
config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole);
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
// Apply config
NLog.LogManager.Configuration = config;
There are many ways to capture current Context and output it to the final target. Simple example:
logger.Info("Message with {myProperty}", "myValue");
Render with ${event-properties:myProperty}
Add this to Layout, e.g.
var fileTarget = new FileTarget("target2")
{
FileName = "${basedir}/file.txt",
Layout = "${longdate} ${level} ${message} ${exception} ${event-properties:myProperty}"
};
For many more examples, see ${event-properties} layout renderer.
NLog Layout will implicitly convert from string-objects. It will automatically parse the string and compile it into the recognized Layout-Renderers.
NLog will perform validation when parsing, but errors detected will be swallowed unless having enabled LogManager.ThrowConfigExceptions
. But one can also force NLog to throw parsing error no matter what:
var layout = NLog.Layouts.Layout.FromString("${evil}", throwConfigExceptions: true); // will throw
NLog 4.7 also allows you to generate a Layout from a simple lambda-method:
var unixTime = NLog.Layouts.Layout.FromMethod(logEvent => ((DateTimeOffset)logEvent.TimeStamp).ToUnixTimeSeconds().ToString());
var jsonLayout = NLog.Layouts.JsonLayout()
{
Attributes = { new NLog.Layouts.JsonAttribute("unixtime", unixTime) { Encode = false } }
};
!! NOTICE !! Ensure that custom method given to Layout.FromMethod
is very simple. Deadlock or StackOverflow can occur if performing complex logic that triggers new logevents or acquiring locks.
It is possible to dive into the NLog LoggingConfiguration
and assign properties directly. But NLog is much happier about using NLog Layout logic when possible. Example:
<target type="file" name="logfile" filename="${gdc:CompanyName:whenEmpty=Default}_${shortdate}.log" />
Then in code one can just update the GDC-item, and it will take effect right away:
NLog.GlobalDiagnosticsContext.Set("CompanyName", "SuperPower");
This removes the need to know the exact NLog-target names in the NLog.config, so it decouples the logic even further and makes it more resilient. This will also work excellent together with autoReload="true"
, as you don't have to re-apply the same settings again, as it will happen automatically. This can also be used for adjusting logging rules dynamically at runtime.
But if you really want to get your hands dirty, then here you go:
var configuration = LogManager.Configuration;
// Update single target
var myFileTarget = configuration.FindTargetByName<FileTarget>("myTargetName");
if (myFileTarget != null)
myFileTarget.FileName = "SuperPower" + "_${shortdate}.log";
LogManager.Configuration = configuration; // re-init
// Update all targets
foreach (var fileTarget = configuration.AllTargets.OfType<FileTarget>())
{
fileTarget.FileName = "SuperPower" + "_${shortdate}.log";
}
LogManager.Configuration = configuration; // re-init
Please note that combining the config file (nlog.config) and changing it in code, the reload of nlog.config could undo your changes. If you combine both, then reapply the changes on the reload event. E.g.
// On start of your program
UpdateConfig();
LogManager.ConfigurationChanged += (sender, e) =>
{
if (e.ActivatedConfiguration != null)
{
//Re apply if config reloaded
UpdateConfig();
}
};
Where UpdateConfig
is
public void UpdateConfig()
{
// Do NOT set LogManager.Configuration because that will cause recursion and stackoverflow
var fileTarget = LogManager.Configuration.FindTargetByName<FileTarget>("myTargetName");
fileTarget.FileName = "${basedir}/file.log";
LogManager.ReconfigExistingLoggers(); // Soft refresh
}
Instead of trying to perform patching of NLog-configuration, then it is recommended to make use of NLog Layouts for Target configuration by forexample using ${gdc}
- Troubleshooting Guide - See available NLog Targets and Layouts: https://nlog-project.org/config
- Getting started
- How to use structured logging
- Troubleshooting
- FAQ
-
All targets, layouts and layout renderers
Popular: - Using NLog with NLog.config
- Using NLog with appsettings.json