-
Notifications
You must be signed in to change notification settings - Fork 390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rerun logging setup on NLog config change #6051
Conversation
{ | ||
Setup(logFileName, logDirectory, logRules); | ||
// Required since 'NLog.config' could change during runtime, we need to re-apply the configuration | ||
LogManager.ConfigurationChanged += (sender, args) => Setup(logFileName, logDirectory, logRules); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the best practices when dealing with this kind of event handler?
I've read that you could use LogManager.ConfigurationChanged = null
to remove all handlers, but what if we attach a new one on other parts of the code?
Ideally, we would only remove this handler during Shutdown
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is that a static event? and do we want to attach a handler to it every time we create a new NLogManager ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is:
public static event EventHandler<LoggingConfigurationChangedEventArgs> ConfigurationChanged;
NLogManager
is created in two scenarios (ignoring tests):
return new NLogManager("logs.txt").GetClassLogger(); |
NLogManager logManager = new(initConfig.LogFileName, initConfig.LogDirectory, initConfig.LogRules); |
IMO, it should be treated as a singleton (does it even make sense to have two NLog instances?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make IDisposable and make sure it unregisters them later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to unregister it at all if you want it to live throughout the whole application lifecycle?
Or like Tomasz said make NLogManager
or ILogManager
implement IDisposable
unhook there and leave it to user to dispose the manager. (Or if you don't trust your users you can use disposable/finalizer pattern)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to unregister it at all if you want it to live throughout the whole application lifecycle?
That's the thing: I do not know if we want/need to unregister it. We already have a shutdown method that kind of looks like Dispose
, but from reading the source of NLog I don't see that it removes the event handler (https://github.com/NLog/NLog/blob/3ff3d5b2ab091e2171e81c410b4c4aa558aee4ba/src/NLog/LogFactory.cs#L1020).
I think that it should not be problematic to do nothing, but I wanted to double check with someone who has worked with NLog and EventHandlers before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are shutting down you can kind of ignore things that are not crucial for shutting down. But Also you can make it IDisposable and add it to DisposeStack - a stack of things that will be disposed during shutdown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I guess our options are:
- Do nothing with the event handler since it lasts for the whole application lifetime.
- Use
IDisposable
and the dispose pattern to ensure that we remove the event handler. - Change the config to use Configuration-Variables, removing the requirement of running
SetupLogFile
andSetupLogDirectory
(but what aboutSetupLogRules
?).
I think 1.
should be good enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add IDisposable for completeness sake - so 2.- but shouldn't affect the end result,
It is recommended to use Configuration-Variables or GlobalDiagnosticsContext, instead of modifying NLog-configuration at runtime. Ex. using FileTarget.FileName= See also: https://github.com/NLog/NLog/wiki/Environment-specific-NLog-Logging-Configuration See also: https://github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules One could also use NLog-Configuration-Variables: <nlog autoReload="true">
<variable name="BaseDir" value="${basedir}" />
<variable name="AppLevel" value="Info" />
<targets>
<target name="logfile" xsi:type="file" filename="${basedir}/logfile.txt" />
</targets>
<minlevel>
<logger minlevel="${AppLevel}" writeTo="logfile" />
</minlevel>
</nlog> Then during application startup: NLog.LogManager.Configuration.Variables["BaseDir"] = appBaseDir; // Will survieve future config-reloads
NLog.LogManager.Configuration = NLog.LogManager.Configuration.Reload(); |
{ | ||
Setup(logFileName, logDirectory, logRules); | ||
// Required since 'NLog.config' could change during runtime, we need to re-apply the configuration | ||
LogManager.ConfigurationChanged += (sender, args) => Setup(logFileName, logDirectory, logRules); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add IDisposable for completeness sake - so 2.- but shouldn't affect the end result,
Notice that
This has been handled here: if (LogManager.Configuration?.AllTargets is not null) But here it can throw with NullReferenceException: IList<LoggingRule> configurationLoggingRules = LogManager.Configuration.LoggingRules; Maybe consider changing the logic to only patch the NLog-configuration when assigned:
|
Fixes #5847
Changes
NLog.config
file.Types of changes
What types of changes does your code introduce?
Testing
Requires testing
If yes, did you write tests?
Notes on testing
Tested manually on a running Nethermind instance.
Documentation
Requires documentation update
Requires explanation in Release Notes