Monday, March 3, 2008

Error logging

I'm currently working on hardening an ASP.NET web site, so I'll be posting on error-handling and security issues for a little while.

One of the basics for this task is good error handling, so I'll start with event logging. You don't ever want your production web site to post error data (not even in comments, so don't think about hiding them in your HTML source, either). So what to do? Use the Windows event logs.

Here's a simple event logger that does the job. Put it in your App_Code directory.


public class Logger
{
/// <summary>
/// Application name
/// </summary>
private static string LogName = "MyApp";
/// <summary>
/// Default constructor.
/// </summary>
public Logger()
{
}

/// <summary>
/// Set up EventSource for logging
/// </summary>
public static void InitLogger()
{
if (!EventLog.Exists(LogName))
{
EventLog.CreateEventSource("MyApp Web Tools", LogName);
}
}

/// <summary>
/// Log any error data sent this way.
/// </summary>
/// <param name="LogData">Exception to be logged.</param>
public static void Log(Exception LogData)
{
string LogMessage = LogData.GetType().ToString() + ": " +
LogData.Message + System.Environment.NewLine +
LogData.StackTrace;
EventLog.WriteEntry(LogName, LogMessage, EventLogEntryType.Error);
}

/// <summary>
/// Log an exception, plus additional data
/// </summary>
/// <param name="LogData">Exception to be logged</param>
/// <param name="LogInfo">Dictionary of string-string name-value pairs to
/// be included in the log entry</param>
public static void Log(Exception LogData, Dictionary<string,> LogInfo)
{
StringBuilder _LogText = new StringBuilder();
_LogText.Append(LogData.GetType().ToString() + ": ");
_LogText.Append(LogData.Message + System.Environment.NewLine);
foreach(string Name in LogInfo.Keys)
{
_LogText.Append(String.Format("Name: {0}, Value{1}{2}",
Name, LogInfo[Name], System.Environment.NewLine));
}
_LogText.Append(LogData.StackTrace + System.Environment.NewLine);
EventLog.WriteEntry(LogName, _LogText.ToString(), EventLogEntryType.Error);
}
}

Note that the logger takes an exception as a parameter. There are a couple of nice things about this. One is that the exception contains a call stack, so your log can point you to the place where the exception occurred. Second, you can set up your application to catch unhandled exceptions, and log those, too, so you can get logs on errors that you didn't anticipate. (My next post will cover unhandled exceptions in detail.)

Using this logging class is very easy. Somewhere in your initialization code, you need to call

Logger.InitLogger();

Then, to log an event, throw an exception, catch it, and log it.

try
{
throw new Exception("Surprise!");
}
catch (Exception ex)
{
Logger.Log(ex);
}

How hard is that? You can find your log using either the Windows Event Viewer (in Computer -> Manage) or in the Server Explorer in Visual Studio.

Also note that the Log method is overloaded. The second version adds a dictionary as a second parameter; you can load up the dictionary with name-value pairs (both as strings) so your event log will contain data values that you'd like to save with the exception message and call stack. Make your logs as informative as possible!

Tuesday, February 12, 2008

Slides posted

The slides are now available as well, in both PowerPoint 2007 format (zipped) and PDF format (2MB). There may be minor tweaks again before the presentation, but this is pretty much the script.

ETA: Slides have been updated for the Raleigh Code Camp.

Sample code posted

The sample code is available for my LINQ presentation.

This requires Visual Studio 2008, SQL Server 2000 or 2005, as well as the Northwind database. I used the "extended" Northwind that was temporarily distributed for LINQ, but I don't think anything in the sample actually requires it. It's available here; just look down the page.

The samples include a lot of good stuff! Complex queries, N-tier application prototypes (including compiled queries, caching, isolating the presentation layer, full CRUD operations, and optimistic concurrency support), queries to DataSet objects, stored procedure examples, non-flat result sets, and more.

Slides to follow "soon", for appropriate values of "soon."

ETA: One sample program does require the "extended" Northwind. It's SprocTwoResults.aspx, which calls a stored procedure that's not in the "standard" Northwind.

Monday, February 11, 2008

Getting Started

This is a first post, just getting things started for this blog. I'll be giving a presentation on LINQ at the local .NET user group this week. I'll be posting links for the presentation and sample code in a few days. Then I'll go into details on some of the sample code, and get into the bits and bytes of it all.

LINQ is an exciting new technology; it has really changed how I think about writing software. Already, I'm finding that I think about solutions in terms of how LINQ can do it. When LINQ is not available, it really feels like a restraint! (And not in a good way...)

More to come!