is there a way (NDC, Properties, ...?) to have a name/id per form that is included in all log4net messages, so I can distinguish between the forms in all log messages?
I have many service methods etc. that are used in all my forms, and I'd like to see e.g. that a service was called as a result of user input in what form (think multiple nonmodal similar forms (same class), running in the same UI thread, containing a button, and in the button's Click-Event, a service method is called. Inside the service method, there are logging calls. In the log messages, I'd like to have a property containing the information of in exactly which form instance the button was clicked in).
I don't want to modify ALL logging calls. The examples in the web for log contexts / NDC all only talk about multiple clients / asp.net requests / etc., not multiple forms in 1 thread.
Thanks, Tim
To do this, set the properties in the form's Activated event to what you want to log:
private void Form1_Activated(object sender, System.EventArgs e)
{
// for example
log4net.GlobalContext.Properties["Name"] = this.GetType().Name;
log4net.GlobalContext.Properties["Id"] = this.Id;
}
The in your logging configuration, you can reference the properties in the PatternLayout for each appender:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{Name} : %property{Id} : [%level]- %message%newline" />
</layout>
Edit: to preserve multiple values, use a stack, as in this unit test which outputs:
Now in TestClass1 Now in TestClass2
using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using NUnit.Framework;
namespace log4net.Tests
{
[TestFixture] // A NUnit test
public class log4net_Stacks
{
[SetUp]
public void Setup()
{
ConsoleAppender ca = new ConsoleAppender
{
Layout = new PatternLayout("%property{demo}"),
Threshold = Level.All
};
ca.ActivateOptions();
BasicConfigurator.Configure(ca);
}
[Test]
public void Stacks_Demo()
{
new TestClass1().Method1();
LogManager.GetLogger("logger").Debug("");
ThreadContext.Stacks["demo"].Clear();
}
private abstract class BaseTestClass
{
protected static void AddToStack(string message)
{
ThreadContext.Stacks["demo"].Push(message);
}
}
private class TestClass1 : BaseTestClass
{
public void Method1()
{
AddToStack("Now in " + GetType().Name);
var tc2 = new TestClass2();
tc2.Method2();
}
}
private class TestClass2 : BaseTestClass
{
public void Method2()
{
AddToStack("Now in " + GetType().Name);
}
}
}
}