I have a logger attached to an ASP.NET project. In test environments, the logger always works. In production (much higher user load), the logger stops after a few hours and won’t restart until the app is cycled. I made modifications to make the logger
thread-safe, but that didn’t fix the problem. I’m at a loss for how to troubleshoot since it only stops under high user load.
In production, there are around 30 web servers and one database. I don’t know if that makes a difference. It’s not a problem when I run other stored procedures.
I have years of experience with log4net, but before I’ve always used it in a server application, not on a web server.
I don’t have any idea of where to start debugging this, so I’m attaching most of the relevant code, with some names changed:
Web.config:
<log4net>
<appender name="XDbAppender" type="X.CustomAdoNetAppender">
<bufferSize value="1"/>
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=[server]; initial catalog=[dbname]"/>
<commandText value="exec dbo.spSetLogMessage <at> date, <at> level, <at> msg, <at> exc"/>
<parameter>
<parameterName value=" <at> date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value=" <at> level" />
<dbType value="String" />
<size value="10" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value=" <at> msg" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value=" <at> exc" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="XDbAppender"/>
</root>
</log4net>
Global.asax:
<% <at> Application Language="C#" Inherits="Microsoft.Practices.CompositeWeb.WebClientApplication"
%>
<% <at> Import Namespace="Y"
%>
<script Language="C#" RunAt="server">
private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger("AppName");
private static readonly object Locker = new object();
protected override void Application_Start(object sender, EventArgs
e)
{
lock (Locker)
{
log4net.Config.XmlConfigurator.Configure();
Logger.Info("Started");
}
base.Application_Start(sender, e);
}
protected void Application_Error(object sender, EventArgs e)
{
lock (Locker)
{
var ex = Server.GetLastError();
// exception has already been handled
if (ex == null) return;
string pageName = string.Empty;
try
{
pageName = Request.CurrentExecutionFilePath;
}
catch (HttpException exc)
{
Logger.Warn(exc.Message);
}
var innermostEx = ex;
while (innermostEx.InnerException != null) innermostEx = innermostEx.InnerException;
string exceptionMessage = innermostEx.GetType().Name + ": " + innermostEx.Message;
UserLogin ul = null;
try
{
ul = (UserLogin) Session["LoggedInUser"];
}
catch (HttpException exc)
{
if (exc.Message != "Session state is not available in this context.")
{
Logger.Warn(exc.Message);
}
}
string message = string.Empty;
if (ul != null)
{
message += "User:" + ul.Anumber;
}
if (pageName != string.Empty)
{
message += " Page:" + pageName;
}
if (exceptionMessage != string.Empty)
{
message += " Msg:" + exceptionMessage;
}
Logger.Error(message, ex);
}
}
</script>
Custom DB appender (gets the correct connection string for the environment):
using Commons;
using log4net.Appender;
namespace X
{
public class CustomAdoNetAppender : AdoNetAppender
{
public new string ConnectionString
{
get
{
return base.ConnectionString;
}
set
{
base.ConnectionString = (Common.GetConnectionString());
}
}
}
}
Can anyone suggest where log4net is failing under high load, and why it stops entirely?
Stephanie Giovannini