Click here to Skip to main content
Licence CPOL
First Posted 8 Apr 2008
Views 30,713
Downloads 259
Bookmarked 32 times

Error logging techniques using Database

By | 8 Apr 2008 | Article
Logging the error in the database and sending email to the respective person

Introduction

Nowadays error logging becomes mandatory and there has been lots of techniques/API's to log the errors. We develop a ASP.NET application and it works fine on your development machine, and when we deploy the application to the production we set the <compilation debug="false" ...> element in your web.config , of course it is the best practice, which makes the error not visible to the end users.
Well, now, we got some exception and we wonder what is that error and you don't have any clue about error since we have not logged the exception and we were left at no man’s land and makes the developer job very tough without any clue about the error and hence we expect is to log the error and a notification mail to sent to the development so that we make the developer job much easier which is even best practice.

In following article we are going to cover the topics on how to log the error in a simple way and of course in a efficient manner.

I personally feel logging the errors either in text files or eventviewer would not make sense, since there is a possibility of losing the data.

Storing them in database would be a better way and easily managable and reports can be generated based on the logging date.

This article is focused to make the logging very simple and customisible based on your needs.

How to add error logging technique to any Application?

To add this logging framework to any ASP.NET web application you only need to do the following:
1) Execute the script(DBExceptionHandler\DBErrorLog.sql in any database
2) Add the following or copy paste (DBExceptionHandler\WebConfigKey.txt)to your web.config and modify the conn. string and other key values based on your settings:

<appSettings>
<add key="EnableLog" value="true"></add>
<add key="EnableLogEmail" value="true"></add>
<add key="LogToEmail" value="yourname1@domain.com|yourname2@domain.com"/>
<add key="smtpServer" value="smtpserverAddress"/>
<add key="LogFromEmail" value="demoadmin@iotap.com"/>
<add key="dbErrorLog" value="Data Source=.\SQLExpress;Integrated Security=True;User Instance=True;AttachDBFilename=|DataDirectory|DemoDatabase.mdf;"/>
</appSettings>


3) Drop the " DBExceptionHandler.dll" into the /bin folder of your app.
4) Jus call the static method YourCompany.ExceptionHandler.dbErrorLogging.LogError(ex) in the catch block.
That's it! Once you have set up the database, please do appropriate changes in the web.config based on the application settings.

How it works?

When there is an exception in the code, it checks for boolean string where the Logging is enabled to our application and calls the method HandleException which takes cares of the logging the exception into the database.

we can also set whether a notification mail of the exception to be sent to the concern person by jus setting EnableLogEmail = True in the web.config.

Below is the code snippet used for logging the error

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Diagnostics;
using System.Data.SqlClient;
using System.Web.Mail;
using System.Text;
namespace YourCompany.ExceptionHandler
{
    /// <summary>
    /// This file Handles the Exception and logging them into the database.
    /// </summary>
    public class dbErrorLogging
    {
        public dbErrorLogging()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        public static void LogError(Exception oEx)
        {
            bool blLogCheck = Convert.ToBoolean(System.Configuration.ConfigurationSettings.AppSettings["EnableLog"]);
            bool blLogEmailCheck = Convert.ToBoolean(System.Configuration.ConfigurationSettings.AppSettings["EnableLogEmail"]);
            if (blLogCheck)
            {
                HandleException(oEx);
            }
            if (blLogEmailCheck)
            {
                SendExceptionMail(oEx);
            }
        }
        public static void HandleException(Exception ex)
        {
            HttpContext ctxObject = HttpContext.Current;
            string strLogConnString = System.Configuration.ConfigurationSettings.AppSettings["dbErrorLog"].ToString();
            string logDateTime = DateTime.Now.ToString("g");
            string strReqURL = (ctxObject.Request.Url != null) ? ctxObject.Request.Url.ToString() : String.Empty; 
            string strReqQS = (ctxObject.Request.QueryString != null) ? ctxObject.Request.QueryString.ToString() : String.Empty;
            string strServerName = String.Empty;
            if (ctxObject.Request.ServerVariables["HTTP_REFERER"] != null)
            {
                strServerName = ctxObject.Request.ServerVariables["HTTP_REFERER"].ToString();
            }
            string strUserAgent = (ctxObject.Request.UserAgent != null) ? ctxObject.Request.UserAgent : String.Empty;
            string strUserIP = (ctxObject.Request.UserHostAddress != null) ? ctxObject.Request.UserHostAddress : String.Empty;
            string strUserAuthen = (ctxObject.User.Identity.IsAuthenticated.ToString() != null) ? ctxObject.User.Identity.IsAuthenticated.ToString() : String.Empty;
            string strUserName = (ctxObject.User.Identity.Name != null) ? ctxObject.User.Identity.Name : String.Empty;
            string strMessage = string.Empty, strSource = string.Empty, strTargetSite = string.Empty, strStackTrace = string.Empty;
            while (ex != null)
            {
                strMessage = ex.Message;
                strSource = ex.Source;
                strTargetSite = ex.TargetSite.ToString();
                strStackTrace = ex.StackTrace;
                ex = ex.InnerException;
            }
            if (strLogConnString.Length > 0)
            {
                SqlCommand strSqlCmd = new SqlCommand();
                strSqlCmd.CommandType = CommandType.StoredProcedure;
                strSqlCmd.CommandText = "sp_LogExceptionToDB";
                SqlConnection sqlConn = new SqlConnection(strLogConnString);
                strSqlCmd.Connection = sqlConn;
                sqlConn.Open();
                try
                {
                    strSqlCmd.Parameters.Add(new SqlParameter("@Source", strSource));
                    strSqlCmd.Parameters.Add(new SqlParameter("@LogDateTime", logDateTime));
                    strSqlCmd.Parameters.Add(new SqlParameter("@Message", strMessage));
                    strSqlCmd.Parameters.Add(new SqlParameter("@QueryString", strReqQS));
                    strSqlCmd.Parameters.Add(new SqlParameter("@TargetSite", strTargetSite));
                    strSqlCmd.Parameters.Add(new SqlParameter("@StackTrace", strStackTrace));
                    strSqlCmd.Parameters.Add(new SqlParameter("@ServerName", strServerName));
                    strSqlCmd.Parameters.Add(new SqlParameter("@RequestURL", strReqURL));
                    strSqlCmd.Parameters.Add(new SqlParameter("@UserAgent", strUserAgent));
                    strSqlCmd.Parameters.Add(new SqlParameter("@UserIP", strUserIP));
                    strSqlCmd.Parameters.Add(new SqlParameter("@UserAuthentication", strUserAuthen));
                    strSqlCmd.Parameters.Add(new SqlParameter("@UserName", strUserName));
                    SqlParameter outParm = new SqlParameter("@EventId", SqlDbType.Int);
                    outParm.Direction = ParameterDirection.Output;
                    strSqlCmd.Parameters.Add(outParm);
                    strSqlCmd.ExecuteNonQuery();
                    strSqlCmd.Dispose();
                    sqlConn.Close();
                }
                catch (Exception exc)
                {
                    EventLog.WriteEntry(exc.Source, "Database Error From Exception Log!", EventLogEntryType.Error, 65535);
                }
                finally
                {
                    strSqlCmd.Dispose();
                    sqlConn.Close();
                }
            }
        }
        protected static string FormatExceptionDescription(Exception e)
        {
            StringBuilder sb = new StringBuilder();
            HttpContext context = HttpContext.Current;
            sb.Append("<b>Time of Error: </b>" + DateTime.Now.ToString("g") + "<br />");
            sb.Append("<b>URL:</b> " + context.Request.Url + "<br />");
            sb.Append("<b>QueryString: </b> " + context.Request.QueryString.ToString() + "<br />");
            sb.Append("<b>Server Name: </b> " + context.Request.ServerVariables["SERVER_NAME"]+ "<br />");
            sb.Append("<b>User Agent: </b>" + context.Request.UserAgent + "<br />");
            sb.Append("<b>User IP: </b>" + context.Request.UserHostAddress + "<br />");
            sb.Append("<b>User Host Name: </b>" + context.Request.UserHostName + "<br />");
            sb.Append("<b>User is Authenticated: </b>" + context.User.Identity.IsAuthenticated.ToString() + "<br />");
            sb.Append("<b>User Name: </b>" + context.User.Identity.Name + "<br />");
            while (e != null)
            {
                sb.Append("<b>Message: </b>" + e.Message + "<br />");
                sb.Append("<b> Source: </b>" + e.Source + "<br />");
                sb.Append("<b>TargetSite: </b>" + e.TargetSite + "<br />");
                sb.Append("<b>StackTrace: </b>" + e.StackTrace + "<br />");
                sb.Append(Environment.NewLine + "<br />");
                e = e.InnerException;
            }
            sb.Append("--------------------------------------------------------" + "<br />");
            sb.Append("Regards," + "<br />");
            sb.Append("Admin");
            return sb.ToString();
        }
        public static void SendExceptionMail(Exception e)
        {
            string strEmails = ConfigurationSettings.AppSettings["LogToEmail"].ToString();
            if (strEmails.Length > 0)
            {
                string[] arEmails = strEmails.Split(Convert.ToChar("|"));
                MailMessage strMessage = new MailMessage();
                strMessage.BodyFormat = MailFormat.Html;
                strMessage.To = arEmails[0];
                for (int i = 1; i < arEmails.Length; i++)
                    strMessage.Cc = arEmails[i];
                string strFromEmail = ConfigurationSettings.AppSettings["LogFromEmail"].ToString();
                strMessage.From = strFromEmail;
                strMessage.Subject = "AMR Research: Exception dated "+DateTime.Now+ " !";
                string sExceptionDescription = FormatExceptionDescription(e);
                strMessage.Body = sExceptionDescription;
                SmtpMail.SmtpServer = System.Configuration.ConfigurationSettings.AppSettings["smtpServer"].ToString();
                try
                {
                    SmtpMail.Send(strMessage);
                }
                catch (Exception excm)
                {
                    Debug.WriteLine(excm.Message);
                    throw;
                }
            }
            else
            {
                return;
            }
        }
    }        

Below is the Preview of the Email Message

EmailMessage.JPG

Additional Notes:

I've attached the source with a sample web application which gives you clear idea about how to use them in your application.

If you have any queries or suggestions, please email to kkumar@iotap.com

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Kishore Kumar.N

Architect
TATA CONSULTANCY SERVICES
India India

Member

ROLE: SDL Tridion Consultant
 
Background:
Over 8+ Years of Experience working in various Web Content Management System like SDL Tridion,Sharepoint, Interwoven and few other OpenSource CMS.
 
Core WCM product strength is on SDLTridion.
 
Current Profile: Product Specialist
 
Email: kishorekumar.nandagopal@tcs.com

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralGood Article PinmemberAvind Mewara19:24 2 Jul '08  
GeneralThank you - useful way of logging custom information PinmemberDavidjwong14:17 13 Apr '08  
GeneralRe: Thank you - useful way of logging custom information PinmemberKishore Kumar.N2:41 14 Apr '08  
Questionhow about using gmail smtp server ? PinmemberQuachNguyen9:46 9 Apr '08  
AnswerRe: how about using gmail smtp server ? PinmemberNirosh15:22 12 Apr '08  
GeneralPossibilities of losing the logs PinmemberEniac02:19 9 Apr '08  
GeneralRe: Possibilities of losing the logs PinmemberKishore Kumar.N2:39 14 Apr '08  
GeneralYou do not need this Pinmember leppie 3:38 8 Apr '08  
GeneralRe: You do not need this PinmemberKishore Kumar.N3:51 8 Apr '08  
GeneralRe: You do not need this Pinmemberr_anand_kumar4:18 8 Apr '08  
GeneralRe: You do not need this PinmemberMadhur Ahuja19:59 8 Apr '08  
GeneralRe: You do not need this PinmemberAshfield0:22 9 Apr '08  
GeneralRe: You do not need this PinmemberDavidjwong14:02 13 Apr '08  
GeneralRe: You do not need this Pinmember leppie 19:50 13 Apr '08  
GeneralRe: You do not need this PinmemberDavidjwong21:00 13 Apr '08  
GeneralRe: You do not need this PinmemberKishore Kumar.N2:31 14 Apr '08  
GeneralRe: You do not need this PinmemberRichard Deeming6:33 14 Apr '08  
The IP address and username are included in health monitoring reports by default. Looking at a typical error message, the information includes:
  • Application domain;
  • Trust level;
  • Application Virtual Path;
  • Application Path;
  • Machine name;
  • Event code;
  • Event message;
  • Event time;
  • Event time (UTC);
  • Event ID;
  • Event sequence;
  • Event occurrence;
  • Event detail code;
  • Process ID;
  • Process name;
  • Account name;
  • Exception type;
  • Exception message;
  • Request URL;
  • Request path;
  • User host address;
  • User;
  • Is authenticated;
  • Authentication Type;
  • Thread account name;
  • Thread ID;
  • Thread account name;
  • Is impersonating;
  • Stack trace;
 
It's a very powerful system, so it can be quite daunting trying to set it up. As an example, here's the typical configuration I use as a starting point:
<configuration>
    <system.net>
        <mailSettings>
            <smtp 
                deliveryMethod="PickupDirectoryFromIis" 
                from="Default sender's email address"
            />
        </mailSettings>
    </system.net>
    
    <system.web>
        <healthMonitoring enabled="true">
        <providers>
            <add 
                name="errorMailWebEventProvider" 
                type="System.Web.Management.SimpleMailWebEventProvider"
                buffer="true" bufferMode="Critical Notification"
                from="Sender's email address"
                to="Your email address"
            />
        </providers>
        <rules>
            <add 
                name="Error Email Event Provider"
                eventName="All Errors" 
                provider="errorMailWebEventProvider"
                profile="Default"
                minInstances="1"
                maxLimit="Infinite"
                minInterval="00:00:30"
                custom="" 
            />
        </rules>
        </healthMonitoring>
    </system.web>
</configuration>

 



"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer


GeneralRe: You do not need this PinmemberDavidjwong10:50 14 Apr '08  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120529.1 | Last Updated 8 Apr 2008
Article Copyright 2008 by Kishore Kumar.N
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid