Logging

Logs user actions, exceptions and traces easily, tailored specifically for web applications.

Logging in action

Log errors

Log errors encountered during an execution of code. There are 4 overloads available, depending on the variables available during execution.

Page URL, referring URL are recorded automatically if an instance of HttpContext is used. Stack trace is recorded automatically if an instance of Exception is used.

void Page_Load(object sender, EventArgs e)
{
	Logging.LogError("test page", "test error");	
	Logging.LogError(Context, "test error");
	
	try
	{
		DoSomethingThatMayRaiseAnException();
	}
	catch (Exception ex)
	{
		Logging.LogError(Context, ex);
		Logging.LogError("test page", ex);
	}
}

You can also catch all exceptions in the Global.asax file:

void Application_Error(object sender, EventArgs e)
{
	Logging.LogError(Context, Context.Error);
}

Log search

Logs the search term used, the number of results, and the page the search was performed at.

void SearchButton_Click(object sender, EventArgs e)
{
	var searchTerm = SearchTermTextBox.Text;
	var searchResults = SearchEngine.Search(SearchTerm);
	
	LogSearch(searchTerm, searchResults.Count, Context);
}

Log new sessions

Logs any sessions that were created. Properties recorded are session ID, date/time created, IP address, user agent string, referring URL, and whether this session should be marked as "exclude".

Global.asax
void Session_Start(object sender, EventArgs e)
{
	Logging.LogSessionCreate(Context);
}

Log user errors

Track which form fields users have the most problems with an what values they entered in them. This helps you improve the usability of input forms on your website.

void SubmitFormButton_Click(object sender, EventArgs e)
{
	var errorsAndValues = new Dictionary<string, string>;
	
	if (string.IsNullOrEmpty(TextBox1.Text))
		errorsAndValues.Add("TextBox1-Empty", null);
	if (!StringFormat.IsInteger(TextBox1.Text))
		errorsAndValues.Add("TextBox1-InvalidNumber", TextBox1.Text);
		
	Logging.LogUserErrors("Checkout Page", errorsAndValues);
}

Log user steps

Keep track of what user did at what time.

void Page_Load(object sender, EventArgs e)
{
	Logging.LogUserStep(Context, "Homepage");
}

Tracing

Records variable values of your choosing to aid debugging.

void Page_Load(object sender ,EventArgs e)
{
	var result = MysteriousClass.GetResult();
	
	// record the mysterious value to ensure that you are getting the
	// result you're expecting
	Logging.Trace(result.MysteriousValue.ToString(), "MysteriousClass");
	
	// note the location of this trace for more specific information
	Logging.Trace(result.MysteriousValue.ToString(), "MysteriousClass",
		"Checkout");
}

Setting it up

Step 1: Prepare the database. Execute the following command in your command prompt to prepare the database tables in MySQL:

mysql MyDatabase < Setup\MySQL\SetupLog.sql

Step 2: Add a connection string called "SharpNick.LogConnection" into web.config:

<configuration>
	<connectionStrings>
		<add name="SharpNick.LogConnection"
			connectionString="Database=DatabaseName;DataSource=ServerIP"
			providerName="MySql.Data.MySqlClient" />
	</connectionStrings>
</configuration>

Step 3: (Optional) Set up the exclusion cookie. If you're using web analytics solutions like Google Analytics, you can mark sessions as excluded based on a cookie's value.

The sessions will still recorded, but can be excluded based on the value of the "exclude" field in each record.

See configuration reference to use the <sharpNick> node.

<sharpNick>
	<logging>
		<excludeCookie name="__utmv" value="exclude" />
	</logging>
</sharpNick>

Analyzing log data

Here are a couple of (My)SQL queries that you can perform:

Errors: Get the list of errors encountered this month, the number of errors so far, the last time this has happened, the error message, and the stack trace:

SELECT max(timeStamp) as latest, count(*) AS num, message,
	stack, location, max(length(referrer))
FROM Errors
WHERE MONTH(timeStamp)=month(now()) AND YEAR(timeStamp)=year(now())
GROUP BY message, stack
ORDER BY latest DESC

User errors: Get a list of user errors and an example of their values for the most problematic form fields on the page named "Checkout":

SELECT count(*) AS num, error, valueEntered
FROM UserErrors
WHERE location='Checkout'
GROUP BY error
ORDER BY num DESC

Database model

[image:Data Model.png]

FAQ

Why not use log4net?

log4net is extremely flexible. However, its flexibility makes configuration and debugging of the logging system itself difficult.

SharpNick.Logging aims to make logging on ASP.NET applications easy to understand and use. All you have to do to start using it is to set up the database and add one line of code into your web.config file.

SharpNick.Logging automatically extracts useful information from the HttpContext instance to make debugging of ASP.NET applications easier.

Does it support MySQL only?

It is built and tested to work with MySQL for now. Support for other databases has not been implemented, but theoretically can be expanded to use other databases - so long as the database driver supports DbConnectionFactory.

Why not file-based storage instead of databases?

Storing log data in a database makes error analysis easier. Not all errors that occured in a web application can be addressed - bots are known to hack URLs - and we need to prioritize which errors to address. Datamining with SQL is easier than looking through thousands of lines in Notepad.

How can I debug the logging system if it swallows all exceptions?

Specify throwExceptions="true" in the <sharpNick> configuration node:

<sharpNick>
	<logging throwExceptions="true" />
</sharpNick>

Last edited Aug 28, 2010 at 4:18 PM by weiwong, version 8

Comments

No comments yet.