NLog: disable/enable multiple log files - c#

I have 2 loggers: one for Info messages, and another for other ones.
<logger name="ErrLogger" levels="Trace,Debug,Warn,Fatal,Error" writeTo="logfile_w" />
<logger name="InfoLogger" level="Info" writeTo="logfile_i" />
Each one write information to his own file.
Is it possible in runtime turn off and on certain loggers?
Btw, for each class I'm using code like this:
private static Logger _logger = LogManager.GetCurrentClassLogger();
And then in functions I use _logger.Info("message");. Should I modify class loggers too?

You can use filtering for that.
Example
<rules>
<logger name="*" writeTo="file">
<filters>
<when condition="${logger}==loggername" action="Ignore" />
</filters>
</logger>
</rules>
See filtering on NLog wiki and the ${logger} layout renderer.
Hint: not sure what the (full) name of the logger is? Just log something with ${logger} and check the logs.

Related

NLog, how to execute code on logging ERROR and higher?

I'm quite new to NLog and I wanted to execute some code when logs are done.
Basically, I got a RichTextBoxTarget. The RichTextBox is hidden by default. I want to display it when a Error log or higher is done.
How could I do this, if it's possible ?
Sounds like you would like to have 2 targets listening for events:
RichTextBox-Target for capturing all events in the error-window.
MethodCall-Target for reacting to error-events and show the error-window.
So the trick is just to setup the two targets:
<nlog>
<targets>
<target name="richtext" xsi:type="RichTextBox" />
<target name="showrichtext" xsi:type="MethodCall" className="SomeNamespace.MyClass, MyAssembly" methodName="LogMethod" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="richtext" />
<logger name="*" minlevel="Error" writeTo="showrichtext" />
</rules>
</nlog>
And implement a suitable static method for the MethodCall-Target to call.
See also: https://github.com/NLog/NLog/wiki/MethodCall-target
See also: https://github.com/NLog/NLog/wiki/RichTextBox-target
What is the purpose of this RichTextBox exactly?
If you want to show errors on input error then the ErrorProvider is better for that.
If you want to capture Error Logging also into this RTB as well as to say file, then you can write your own target, register it, and then it can process the events.
See:
https://github.com/NLog/NLog/wiki/Extending-NLog

Generic Logging and Specific Logging (using NLOG), Duplication of Logging

I am trying to create 2 loggers (using NLog)
First logger logs all the desired item to log in the solution
The other one traces specific items (I do it to keep things clean and focused, and only run trace here)
Below is the configuration
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile"
xsi:type="File"
layout="${longdate} ${level} ${threadid} ${callsite} ${message}"
fileName="${basedir}\Logs\GatewayApplicationDebugAndErrorLog.txt"
archiveNumbering="Rolling"
maxArchiveFiles="10"
archiveAboveSize="10000000"/>
<target name="J1939Trace"
xsi:type="File"
layout="${longdate} ${level} ${threadid} ${callsite} ${message}"
fileName="${basedir}\Logs\J1939Trace.txt"
archiveNumbering="Rolling"
maxArchiveFiles="10"
archiveAboveSize="10000000"/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />
<logger name="J1939Trace" maxlevel="Trace" writeTo="J1939Trace" final="true" />
</rules>
and usage is shown below
private readonly Logger logger = LogManager.GetCurrentClassLogger(); // Generic Logger
private readonly Logger j1939Logger = LogManager.GetLogger("J1939Trace"); // Specific Logger.
What I observe is that the specific logger item is also logged in generic log item and I don't want that duplication. Any ideas what am I doing wrong?
Will this work?
From: NLog: How to exclude specific loggers from a specific rule?
Adding final="true" means that no more rules will be executed for the events produced by "SpammyLogger", but it applies only to the specified levels.(see https://github.com/nlog/nlog/wiki/Configuration-file#rules)
Make sure to read through all the comments in the answer.

In NLog, is it possible to use layouts to define the log level?

I would like to use Layouts in NLog to be able to change the minimum log level using an external variable :
<nlog>
<variable name="loglevel" value="Debug"/>
<targets>
<target ... />
</targets>
<rules>
<logger name="*" minlevel="${loglevel}" writeTo="LogFile" />
</rules>
</nlog>
After starting NLog, all log levels (eg : Tracing, Debug, Info, ...) are set to false which indicate NLog failed to parse minlevel attribute properly.
The NLog layout feature seems to works with target attributes only.
What I want to achieve : in my real app, loglevel is not a constant but rather a custom layout renderer.
I have also tried to replace value="Debug" by value="LogLevel.Debug" without success.
** Updated Answer **
NLog ver. 4.6 added support for using NLog-Config-Variables in minLevel. See https://github.com/NLog/NLog/pull/2709
NLog ver. 4.6.7 added support for adjusting minLevel at runtime, by modifying NLog-Config-Variables and calling ReconfigExistingLoggers(). See https://github.com/NLog/NLog/pull/3184
** Original Answer **
The minlevel, maxlevel and level attributes on <logger> should be fixed strings.
In this case you could use a <filter>, e.g.
<nlog>
<variable name="loglevel" value="Debug"/>
<targets>
<target ... />
</targets>
<rules>
<logger name="*" writeTo="LogFile" >
<filter condition="${level} >= ${loglevel}" action="Log">
</logger>
</rules>
</nlog>
See the docs

NLog create log files based on static variable

How can I set NLog file name based on static variable in my application.
I have windows service that performs different tasks. Reads configuration file with task details.
I would like to create log file based on given task name.
NOTE: class name will not work, since all the tasks call the same code.
NOTE: I am already using ${logger} variable as my current class. Since I need to know where I am as well.
-------------UPDATE--------------
Seems like this is not possible to do.
Modified question: How to set variable values at run time?
I am talking about this:
<variable name="logFileName" value="" />
Thank you.
You cannot, I believe. But you can use something like this:
In code:
static NLog.Logger loggerA = NLog.LogManager.GetLogger("nameA");
static NLog.Logger loggerB = NLog.LogManager.GetLogger("nameB");
void Something()
{
loggerA.Error("Something");
}
void SomethingElse()
{
loggerB.Error("SomethingElse");
}
NLog config:
<nlog ...>
<targets>
<target name="Error" xsi:type="AsyncWrapper">
<target name="file" xsi:type="File" fileName="${basedir}/Logs/Error.txt">
<layout ... />
</target>
</target>
</targets>
<!--other targets pointing to different files.-->
<rules>
<logger name="nameA" minlevel="Warn" writeTo="Error" />
<logger name="nameB" minlevel="Trace" maxLevel="Info" writeTo="Log" />-->
<logger name="*" minlevel="Trace" maxLevel="Info" writeTo="CommonLog" />
</rules>
</nlog>
You can also use SomeNamespace.Component.* as name of a logger and than only logs from SomeNamespace.Component will be logged via it. In that case the logger would be obtained like this:
static NLog.Logger loggerA = NLog.LogManager.GetCurrentClassLogger();
Here is the documentation for Nlog: https://github.com/NLog/NLog/wiki/Tutorial
There is a way to edit NLog configuration programmatically: https://github.com/nlog/NLog/wiki/Configuration-API
The easy solution is to use NLog GlobalDiagnosticsContext:
<target name="file" xsi:type="File" fileName="${gdc:logFileName:whenEmpty=DefaultApp}.txt">
Then you can override it like this:
NLog.GlobalDiagnosticsContext.Set("logFileName", "HelloApp");
See also: https://github.com/nlog/nlog/wiki/Gdc-Layout-Renderer

How do I programmatically add logging filters?

I want to add the rule in my NLog. The rule is:
<rules>
<logger name="*" writeTo="file">
<filters>
<when condition="length(message) > 100" action="Ignore" />
<when condition="equals('${logger}','MyApps.SomeClass')" action="Ignore" />
<when condition="(level >= LogLevel.Debug and contains(message,'PleaseDontLogThis')) or level==LogLevel.Warn" action="Ignore" />
<when condition="not starts-with('${message}','PleaseLogThis')" action="Ignore" />
</filters>
</logger>
Now I want to implement it in C# code. I haven't found the sample code online.
I would take a look a look at the Configuration API documentation for NLog. While it doesn't specifically reference filters, it seems like the way to accomplish this programmatically is by using LoggingRules to control how log messages are processed.
Edit
Like I said, the Configuration API is the way to achieve this. This example will replicate the following config programmatically:
Config
<targets>
<target name="console" type="Console" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="console">
<filters>
<when condition="not starts-with('${message})', 'PleaseLogThis')" action="Ignore" />
</filters>
</logger>
</rules>
Code
// Create the filter
var filter = new ConditionBasedFilter();
filter.Condition = "not starts-with('${message}','PleaseLogThis')";
filter.Action = FilterResult.Ignore;
// Create the rule to apply the filter to
var consoleTarget = new ColoredConsoleTarget();
var rule = new LoggingRule("*", LogLevel.Debug, consoleTarget);
rule.Filters.Add(filter);
// Create the config to apply the rule to
var config = new LoggingConfiguration();
config.LoggingRules.Add(rule);
// Update the log manager with the programmatic config
LogManager.Configuration = config;
// Test Your Logging
var log = LogManager.GetCurrentClassLogger();
log.Debug("Test");
log.Debug("Filter");
log.Debug("PleaseLogThis");
Console.ReadLine();

Categories