Veritas Today’s short article is about error handling.  In addition to recording errors to our BlogLog table which we discussed previously, we’ll also program in the capability to log to both email and a text file.  If you controlled the server you were going to host on, you could look at other options (writing to the event log, logging through a MSMQ) but since we’re writing this to work on a shared host, we’ll only use the options that we know (should) work.  To begin with we’ll add some settings to the BlogConfig class to control whether or not we log to each source:

   1:  public string LogEmailAddress { get; set; }
   2:  public string LogFilePath { get; set; }
   3:  public bool LogToDb { get; set; }
   4:  public bool LogToEmail { get; set; }
   5:  public bool LogToFile { get; set; }

3 of these will just control where we’re going to log to and the other two just control to what file or email address we log to.  We’ll also add those fields into all of the load and build xml methods in our BlogConfig class.  Once that’s done, we’ll add a new Logging Handler class into our Business Layer.  The first thing we need is a property to check and see if each type of logging is enabled.  These getters will just reach into our BlogConfig to see if the property above is set to true or false:

   1:  public static bool IsDbLoggingEnabled
   2:  {
   3:       get
   4:       {
   5:            return CacheHandler.GetBlogConfig().LogToDb;
   6:       }
   7:  }

We’re going to create two methods for each type of logging.  One that takes in an exception and one that takes in individual details (in case we’re not logging a specific exception).  Both of these methods will also take in the “logging source” (the method or file calling the logging method).  Before we create those, we’ll create our helper methods to take in those details and create a BlogLog object:

   1:  private static BlogLog GetBlogLog(string message, string details, string level, string logger)
   2:  {
   3:      BlogLog log = new BlogLog()
   4:      {
   5:          BlogConfigId = CacheHandler.BlogConfigId,
   6:          CreateDate = DateTime.Now,
   7:          EventLevel = level,
   8:          Exception = details,
   9:          Message = message,
  10:          Url = HttpContext.Current.Request.Url.ToString(),
  11:          Logger = logger
  12:      };
  13:      return log;
  14:  }
  16:  private static BlogLog GetBlogLog(Exception ex, string logger)
  17:  {
  18:      BlogLog log = new BlogLog()
  19:      {
  20:          BlogConfigId = CacheHandler.BlogConfigId,
  21:          CreateDate = DateTime.Now,
  22:          EventLevel = "Error",
  23:          Exception = GetInfoFromException(ex),
  24:          Message = ex.Message,
  25:          Url = HttpContext.Current.Request.Url.ToString(),
  26:          Logger = logger
  27:      };
  28:      return log;
  29:  }

One last item before we get to the logging methods is the GetInfoFromException method we see called above.  It will simply concatenate a few of the details of the exception:

   1:  private static string GetInfoFromException(Exception ex)
   2:  {
   3:      string stackTrace = ex.StackTrace + "\n\n";
   4:      if (ex.InnerException != null)
   5:          stackTrace += LoggingHandler.GetInfoFromException(ex.InnerException);
   6:      return stackTrace;
   7:  }

Finally we’ll create our two actual logging methods.  As you’ll see, these will both make use of our GetBlogLog methods above:

   1:  public static void LogToDb(string message, string details, string level, string logger)
   2:  {
   3:      if (LoggingHandler.IsDbLoggingEnabled)
   4:      {
   5:          BlogLog log = LoggingHandler.GetBlogLog(message, details, level, logger);
   7:          var repo = VeritasRepository.GetInstance();
   8:          repo.Add(log);
   9:          repo.Save();
  10:      }
  11:  }
  13:  public static void LogToDb(Exception ex, string logger)
  14:  {
  15:      if (LoggingHandler.IsDbLoggingEnabled)
  16:      {
  17:          BlogLog log = LoggingHandler.GetBlogLog(ex, logger);
  19:          var repo = VeritasRepository.GetInstance();
  20:          repo.Add(log);
  21:          repo.Save();
  22:      }
  23:  }

That’s it for logging to the database.  We've got two additional methods that will log to email and log to a file but we won’t show those for brevity’s sake.  If you want, you can check out the code attached to see what those look like.  We’re now able to log any errors or information we might want to from anywhere else in the code and we can do it in several different ways.  However, we need a method that will handle figuring out where and what to log to so we don’t have to pick and choose in other locations:

   1:  public static void Log(string message, string details, string level, string logger)
   2:  {
   3:      if (LoggingHandler.IsDbLoggingEnabled)
   4:          LogToDb(message, details, level, logger);
   5:      if (LoggingHandler.IsEmailLoggingEnabled)
   6:          LogToEmail(message, details, level, logger);
   7:      if (LoggingHandler.IsFileLoggingEnabled)
   8:          LogToFile(message, details, level, logger);
   9:  }
  11:  public static void Log(Exception ex, string logger)
  12:  {
  13:      if (LoggingHandler.IsDbLoggingEnabled)
  14:          LogToDb(ex, logger);
  15:      if (LoggingHandler.IsEmailLoggingEnabled)
  16:          LogToEmail(ex, logger);
  17:      if (LoggingHandler.IsFileLoggingEnabled)
  18:          LogToFile(ex, logger);
  19:  }

So that’s it for our logging.  If you want to download the latest code with all of the unit tests, you can do so here.  You may notice that they’re missing tests for the email logging.  I haven’t decided on the best way to handle those yet so they aren’t there. 

Chris Risner