Forget about instance restarts when you want to switch log4net logging levels. This custom solution let’s you set different value without putting your instance down.
Introduction
Logs are a great source of information when our instance has some problems and we need to figure out what is going on.
Sometimes normal logging levels are not enough and we need to switch to DEBUG
.
Each time you want to change logging levels, you need to edit configuration, which means your application will be restarted.
It is time consuming and makes Sitecore instance unavailable for a while. Don’t miss anything important just because you restarted machine and everything started working normal. Let’s see what we can do to solve that problem.
Implementation
Firstly, I need to extend the default SitecoreLogFileAppender
, so I create new CustomSitecoreLogFileAppender
and override Append
method.
At the beginning I read Level
property which provides me dynamic level (previously values taken from Sitecore.config
).
Then I add extra check to determine whether current logging event should be passed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protected override void Append(LoggingEvent loggingEvent)
{
if (Level != null)
{
var currentLogLevel = loggingEvent.Level;
if (currentLogLevel >= Level)
{
base.Append(loggingEvent);
}
}
else
{
base.Append(loggingEvent);
}
}
What about level defined in Sitecore.config
?
Default Sitecore logging file appender configuration looks like this.
1
2
3
4
5
6
7
8
9
10
11
12
<appender name="LogFileAppender" type="log4net.Appender.SitecoreLogFileAppender, Sitecore.Logging">
<file value="$(dataFolder)/logs/log.{date}.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%4t %d{ABSOLUTE} %-5p %m%n" />
</layout>
<encoding value="utf-8" />
</appender>
<root>
<priority value="INFO" />
<appender-ref ref="LogFileAppender" />
</root>
My goal is to get that priority node value from somwhere else.
As I am going to make a decision in a different place, we need to pass all log messages into my custom logger (set priority value to ALL
).
Here is how patch configuration file should look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<log4net>
<appender name="LogFileAppender">
<patch:attribute name="type">Sitecore.Playground.Logging.CustomSitecoreLogFileAppender, Sitecore.Playground</patch:attribute>
</appender>
<root>
<priority>
<patch:attribute name="value">ALL</patch:attribute>
</priority >
</root>
</log4net>
</sitecore>
</configuration>
The only one thing we need more now is that Level
property implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
public Level Level
{
get
{
var filePath = Path.Combine(Settings.DataFolder, "log4net");
if (System.IO.File.Exists(filePath))
{
var levelStr = System.IO.File.ReadAllText(filePath);
return LogLevelMap.GetLogLevel(levelStr);
}
return null;
}
}
I put log4net
file inside data folder, but you can easily provide your own implementation.
Now you just simply control logging level from that file. Accepted values: ALL
,DEBUG
,INFO
,WARN
,ERROR
,FATAL
,OFF
Warning: Influence on performance is unknown. It is not recommended to keep this solution on live environments. It can be used during integration period but after whole project is deployed we should disable the configuration.
Summary
That’s it. Hope you like it.
Whole solution can be found in my playground project on github: Sitecore.Playground
Here is a link to a specific commit if you are interested in this particular solution.