1
votes

My application has a central log4net definition in its web.config, which I read with xmlConfigurator. Apart from that central logger, I need to define some other loggers that will write to various log files/DBs. The definitions for those loggers sit in my DB in xml format, and at runtime my attempt is to read them from DB, write them to a stream, configure them with XmlConfigurator as well and store them in an ILog collection (sb is a StringBuilder that contains the xml, logConfig.Type is the name of the logger as appears in xml):

byte[] byteArray = Encoding.UTF8.GetBytes(sb.ToString());
MemoryStream stream = new MemoryStream(byteArray);
log4net.Config.XmlConfigurator.Configure(stream);
ILog ilogRes = log4net.LogManager.GetLogger(logConfig.Type);
stream.Close();
return ilogRes;

ilogRes does not come configured as I expected (with the appenders defined in sb), but as the central logger. What am I doing wrong?

UPDATE: The initial problem was in my XML, once I removed a redundant element a new logger with a new appender was created. The problem now is that the new logger writes with both appenders, previous one and new one, while I want the new logger to write with the new appender only. Is there a way to tell LogManager.GetLogger(X) to bring only appenders that wee configured together with appender X?

1
Log4net configuration is not additive - i.e. every time you call Configure you replace the existing repository, you don't add to it. Your options include storing all the config in the database, merging the two sources at runtime, or perhaps combining the two by keeping a template in the database which you populate with values from config at runtime.stuartd
Actually, the non additive behavior is exactly what I need but for some reason do not get. When I reconfigure log4net (and expect to get a logger with a new appender) I get a logger with the same appender that was configured earlier on.sinai
Loggers are cached by log4net - call LogManager.ResetConfiguration() before reloading as it will "remove all appenders from all loggers, and set the level of all non-root loggers to null"stuartd
Won't that harm my other loggers? Imagine I have logger1 already defined with appender that writes to DB1, now I'm trying to add a new logger2 that wrtites to DB2, not to replace logger1.sinai
Thx Stuartd, the problem was in XML. But now the new logger logger2 has both appendrs - to DB2 AND DB1. How can I make it write with DB2 only without hurting the logger that writes to DB1?sinai

1 Answers

1
votes

I have configured each dynamic logger to a separate repository, this way the logger contained only the appenders that were defined in the current config:

byte[] byteArray = Encoding.UTF8.GetBytes(sb.ToString());
MemoryStream stream = new MemoryStream(byteArray);
log4net.Repository.ILoggerRepository repository = log4net.LogManager.CreateRepository(logConfig.Type);
log4net.Config.XmlConfigurator.Configure(repository, stream);
ILog ilogRes = log4net.LogManager.GetLogger(repository.Name, logConfig.Type);