Dynamic loading of log4net.Config for separate threads? C#/.NET
My application has a number of parallel separate threads running indefinitely. I'm using log4net for logging of information.
I'd like to instrument the logging configuration information for log4net dynamically. (ie: one of the threads is doing something weird, I can "inject" a more verbose configuration on the fly into it). I'm using the log4net.Config method t开发者_开发知识库o load an XML configuration file on the fly in one of the threads. Unfortunately, it seems to impact every other thread.
Is there a way to isolate configurations for each thread when using log4net?
Thank you!
Create a new logger for each thread that will be running, using LogManager.GetLogger("MyApp.Thread1"). This method can take a string, so just give each one a different name. Then you should be able to use the log level for each one individually.
<!-- Set root logger level to DEBUG and its only appender to A1 -->
<root>
<level value="DEBUG" />
<appender-ref ref="A1" />
</root>
<!-- Print only messages of level WARN or above in the package Com.Foo -->
<logger name="MyApp.Thread1">
<level value="WARN" />
</logger>
More information: http://logging.apache.org/log4net/release/manual/configuration.html
Also, if you're just getting started, check out Log4View . I don't have any affiliation, just a satisfied customer.
I've only barely started using log4net myself, so I apologize if this isn't useful, but I think this problem may be solvable using the Contexts feature.
You may be able to get your specific thread via a combination of that, and using a context filter:
- http://logging.apache.org/log4net/release/sdk/log4net.Filter.MdcFilter.html
- http://logging.apache.org/log4net/release/sdk/log4net.Filter.NdcFilter.html
Edit:
Looking at these closer, it seems that Mdc/Ndc are legacy features, so maybe this isn't the best option. So, here's another idea.
Depending on how you can identify your threads (if you aren't farming totally black-box tasks out of a thread pool), you might simply name your loggers, and use a filter to match on the logger name.
http://logging.apache.org/log4net/release/sdk/log4net.Filter.LoggerMatchFilter.html
You can configure the filters at runtime as long as you loaded your config in a way that it will auto-reload: Configuration Attributes (in particular, Watch = true
).
You can also keep your perf up when not logging by using blocks like if(log.IsDebugEnabled) { /* do logging here */ }
.
What do you mean by "Unfortunately, it seems to impact every other thread"?
I'm thinking about performance or locking.
If your threads get locked (ie. the first thread logs but the other hang in the logging call) then you need MinimalLocking
option for FileAppender
. This way, once a logger writes to the log file, it releases the file handle to other threads. Unfortunately, this affects performance (but the performance still depends on the kernel: if Mac or Linux kernels, when you go to mono, are faster or slower in handling open/close operations, you get different results) because of continuous close/flush/open.
Final solution is to declare different appenders and different loggers. For each logger you instantiate (know them before!), declare a dedicated FileAppender
for exclusive usage, so threads won't go into concurrency issues.
精彩评论