Of the many logging options available around, often the choice comes down to NOT what is the best in the industry but what is currently being used in your organization. And you won’t have an option of looking at alternatives UNLESS you have a very good reason. This post isn’t about choosing a logging component but rather one of my experiences using Log4Net with BizTalk on an integration project.
One thing about using Log4Net with BizTalk is to make sure the assembly you would refer to is serializable. I ended up using Log4Net version 1.2.9 although there was a latest one available but wasn’t a serialized assembly. BizTalk projects offer multiple instances of its artifacts running at the same time and because of this I came across a problem using Log4Net. One thing to note before we continue is that Log4Net swallows any/all exceptions. In my case, one of my BizTalk artifacts was using the Log4Net object. It ended up in an error and as a result all further Biztalk instances that used Log4Net stopped logging.
The success status above represents a log being written in the log repository. While a failure, represent any error that occurred during the logging process. Note that after a failure happens, the Log4Net somehow switches into the error state and all subsequent log entries are represented by failures. Hence, logging is disabled!!.
After, investigating for long hours on this problem, the obvious problem was about thread safety. All my logging was being appended to a file. Behind the scenes Biztalk was referencing the Log4Net assembly, and the log message was being appended to a file. Because the file is being opened and closed multiple times and several instances would try writing to it – therefore some instances would be denied the logging request. This places the Log4Net assembly in the error state (you won’t see any exceptions) and if further BizTalk artefacts tried referencing the object – the failed object never logs (making some sense now).
I still can’t understand why Log4Net won’t throw exceptions when “something” isn’t compatible to its design – phew!!
Solution:
There were two solutions to consider.
1) Batch the messages together and then submit them to the file for logging.
Comment: It sounds good because it would reduce the traffic on my log store (a file in this case). However, it won’t guarantee me that the log object won’t go into the error state. Remember, the problem here is about locking on the log file and not about traffic. Both these concepts are closely related but I would tend to distinguish the two – as locking would still happen, (even if the batch size is increased to a factor n).Load wasn’t a problem as the log file resides on the same machine as the BizTalk host instance and this was moved to another archive share on the network by a schedule at the end of the day.
2) Disable locking on the file
Comment: This was the option I went ahead with. In my design each log object is represented with a particular timestamp (configuration setting used by my BizTalk application). The worst case I could come up with would be the order of the log statements. I was ready to live up with this – but it would guarantee me that my logging won’t be disabled because Log4Net swallows all exceptions.
Setting to add in your Log4Net configuration file:
<lockingModel type = “log4net.Appender.FileAppender + MinimalLock”/>
Happy coding J
