Click here to Skip to main content
15,041,391 members
Articles / Programming Languages / C#
Tip/Trick
Posted 10 Dec 2014

Tagged as

Stats

56.3K views
34 bookmarked

Easy C# Exception (Or Whatever) Logging Service

Rate me:
Please Sign up or sign in to vote.
3.65/5 (18 votes)
15 Dec 2014CPOL3 min read
Add a singleton exception logger to your app for easy logging of interesting occurrences in your app

Singular Exception Logger

There are many logging solutions available, and some of them are awesome (such as Log4Net), but I doubt you'll find one that's easier to set up and use than this one.

All you have to do to start logging messages from your app (whether it be for debugging where the app "goes" or just logging exceptions, or whatever) is to add a class to your project named "ExceptionLoggingService" (or whatever name floats your boat).

Note: Although I named it "ExceptionLoggingService", you can use it for anything - not just exceptions. Anyway, here's the entire class:

C#
using System;

namespace Platypusophile
{
    using System.IO;
    using System.Text;

    public class ExceptionLoggingService
    {
        // </ Singleton code
        // private fields
        private readonly FileStream _fileStream;
        private readonly StreamWriter _streamWriter;
        private static ExceptionLoggingService _instance;
        // public property
        public static ExceptionLoggingService Instance
        {
            get
            {
                return _instance ?? (_instance = new ExceptionLoggingService());
            }
        }
        //private constructor
        private ExceptionLoggingService()
        {
            _fileStream = File.OpenWrite(GetExecutionFolder() + "\\EasyAsFallingOffA.log");
            _streamWriter = new StreamWriter(_fileStream);
        }
        // <!-- Singleton code

        public void WriteLog(string message)
        {
            if (!HHSConst.Logging)return;
            StringBuilder formattedMessage = new StringBuilder();
            formattedMessage.AppendLine("Date: " + DateTime.Now.ToString());
            formattedMessage.AppendLine("Message: " + message);
            _streamWriter.WriteLine(formattedMessage.ToString());
            _streamWriter.Flush();
        }

        private string GetExecutionFolder()
        {
            return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);<span style="font-size: 9pt;"> </span>          }
    }
}

Note the "if not logging return" logic at the start of the WriteLog() method; To use this, add a global bool somewhere, such as in a Consts class, so that you can toggle logging:

C#
public static class HHSConsts
{
    public static bool Logging = true;
    . . .

Easy as Falling off a Log File

Now you can call it like so:

C#
ExceptionLoggingService.Instance.WriteLog("Go, Packers!");

Or, more realistically, from inside an exception block:

C#
catch (Exception ex)
{
    String msgInnerExAndStackTrace = String.Format(
        "{0}; Inner Ex: {1}; 
        Stack Trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);
    ExceptionLoggingService.Instance.WriteLog(String.Format
    ("From frmDelivery.ConditionallyPrint():{0}", msgInnerExAndStackTrace));
}

Note that the logging service implements the Singleton pattern, and so you call its public static property "Instance" which allows for JIT creation/instantiation of the class and ensures that there is never more than one instance in memory. You can then call its "WriteLog()" method, which will automatically add the date for you - all you need to supply it is the string you want to have logged.

The file is then saved in the same directory as the .exe, with the name "EasyAsFallingOffA.log" (unless for some strange reason you want to change it to something else). The file (once written to) will contain entries something like this:

C#
Date: 2/19/2009 11:34:10 PM
Message: From HHSDBUtils.SaveAndGetINVDataAsXMLFromTable: SQL logic error or missing database
no such table: INV_3_20090206200112000.xml; Inner Ex: ; 
Stack Trace:    at System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, . 

. .

Bonus Tip

You can get the skinny on exceptions you neglected by adding an application-wide handler like so, such as in Program.cs:

C#
static void Main()
{
    AppDomain.CurrentDomain.UnhandledException += Unhandled;
    Application.Run(new frmMain());
}

static void Unhandled(object sender, UnhandledExceptionEventArgs exArgs)
{
    ExceptionLoggingService.Instance.WriteLog(String.Format
    ("From application-wide exception handler: {0}", exArgs.ExceptionObject));
}

Yet Another Bonus Tip

If you want to also know who was running the program, you can get their name this way:

C#
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

...and then add that value into the message. That way you can see who is running into which problems, and respond accordingly. You might even have a little fun with it by telling them you see that they did this or that and had such-and-such a problem. If they are ignorant of your programming prowess, they may start looking over their shoulder and searching for hidden cameras, etc.

Now Pay Up!

If you find this tip useful, manifest your undying gratitude by sending me a giant chocolate duckbilled platypus. I will (eventually) forgive you if it's hollow, as I know a solid one might weigh quite a bit and cost you a pretty penny in shipping costs. If more convenient for you, simply send me a 3D printer and a 55-gallon drum of Belgian chocolate, and I'll make the "Choctypus" myself.

Force Augustus Gloop to Morph Into Twiggy

Here's yet another tiplet, free as a bird now (but I'm hoping you're even more moved to supply me my yearned-for Choctypus)*: If you want to prevent your log file from getting too large (it may be a moot point in these days of Gigabytes and Terrabytes for most, but on my Windows CE / Compact Framework every bit counts), you can check its size on startup and delete it at whatever point seems too hefty to you like so (I use 20000 here):

* This is kind of like the snuck-in final scene at the end of a flick, such as the wedding scene in Napoleon Dynamite, that wondrous documentary of Idaho life.

C#
const int MAX_FILESIZE_ALLOWED = 20000;
string uriPath = GetExecutionFolder() + "\\Application.log";
if (System.IO.File.Exists(uriPath))
{
    string logPath = new Uri(uriPath).LocalPath;
    FileInfo f = new FileInfo(logPath);
    long fileSizeInBytes = f.Length;
    if (fileSizeInBytes > MAX_FILESIZE_ALLOWED)
    {
        File.Delete(logPath);
    }
}

License

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

Share

About the Author

B. Clay Shannon
Founder Across Time & Space
United States United States
I am in the process of morphing from a software developer into a portrayer of Mark Twain. My monologue (or one-man play, entitled "The Adventures of Mark Twain: As Told By Himself" and set in 1896) features Twain giving an overview of his life up till then. The performance includes the relating of interesting experiences and humorous anecdotes from Twain's boyhood and youth, his time as a riverboat pilot, his wild and woolly adventures in the Territory of Nevada and California, and experiences as a writer and world traveler, including recollections of meetings with many of the famous and powerful of the 19th century - royalty, business magnates, fellow authors, as well as intimate glimpses into his home life (his parents, siblings, wife, and children).

Peripatetic and picaresque, I have lived in eight states; specifically, besides my native California (where I was born and where I now again reside) in chronological order: New York, Montana, Alaska, Oklahoma, Wisconsin, Idaho, and Missouri.

I am also a writer of both fiction (for which I use a nom de plume, "Blackbird Crow Raven", as a nod to my Native American heritage - I am "½ Cowboy, ½ Indian") and nonfiction, including a two-volume social and cultural history of the U.S. which covers important events from 1620-2006: http://www.lulu.com/spotlight/blackbirdcraven

Comments and Discussions

 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun15-Dec-14 22:43
MemberHumayun Kabir Mamun15-Dec-14 22:43 
SuggestionGood, but I have a suggestion Pin
gavilanch15-Dec-14 3:23
Membergavilanch15-Dec-14 3:23 
SuggestionMake it Async Pin
D Sarthi Maheshwari15-Dec-14 2:16
professionalD Sarthi Maheshwari15-Dec-14 2:16 
GeneralMy vote of 1 Pin
veitmen14-Dec-14 20:25
Memberveitmen14-Dec-14 20:25 
GeneralMy vote of 1 Pin
Saeid Pournejati13-Dec-14 2:57
professionalSaeid Pournejati13-Dec-14 2:57 
GeneralRe: My vote of 1 Pin
B. Clay Shannon13-Dec-14 4:34
professionalB. Clay Shannon13-Dec-14 4:34 
GeneralMy vote of 1 Pin
tom-englert12-Dec-14 22:07
Membertom-englert12-Dec-14 22:07 
Looks like you have just re-invented System.Diagnostics.Trace
GeneralMy vote of 2 Pin
m1o212-Dec-14 14:27
Memberm1o212-Dec-14 14:27 
SuggestionRealy nice and simple logging pattern... Pin
mateo1985112-Dec-14 8:06
Membermateo1985112-Dec-14 8:06 
QuestionPostsharp Pin
RickNash12-Dec-14 2:23
MemberRickNash12-Dec-14 2:23 
AnswerRe: or Log4Net Pin
RickNash12-Dec-14 2:48
MemberRickNash12-Dec-14 2:48 
AnswerRe: Postsharp Pin
B. Clay Shannon12-Dec-14 5:59
professionalB. Clay Shannon12-Dec-14 5:59 
GeneralMy vote of 1 Pin
Steve Drake12-Dec-14 2:08
MemberSteve Drake12-Dec-14 2:08 
SuggestionSorry but thats a BAD exception handling Pin
freakyit12-Dec-14 2:04
Memberfreakyit12-Dec-14 2:04 
GeneralRe: Sorry but thats a BAD exception handling Pin
B. Clay Shannon12-Dec-14 5:54
professionalB. Clay Shannon12-Dec-14 5:54 
SuggestionLogging is complex, leave it to the framework / experts. Pin
Steve Drake12-Dec-14 2:03
MemberSteve Drake12-Dec-14 2:03 
GeneralMy vote of 5 Pin
Maxwolf Goodliffe11-Dec-14 20:12
MemberMaxwolf Goodliffe11-Dec-14 20:12 
GeneralRe: My vote of 5 Pin
B. Clay Shannon12-Dec-14 5:49
professionalB. Clay Shannon12-Dec-14 5:49 
QuestionRe - Release Builds Pin
TSFolkes11-Dec-14 3:42
MemberTSFolkes11-Dec-14 3:42 
GeneralThoughts Pin
PIEBALDconsult10-Dec-14 17:21
professionalPIEBALDconsult10-Dec-14 17:21 
GeneralRe: Thoughts Pin
Bob Crowley12-Dec-14 7:11
MemberBob Crowley12-Dec-14 7:11 
GeneralRe: Thoughts Pin
Bob Van Wagner12-Dec-14 11:21
MemberBob Van Wagner12-Dec-14 11:21 
Questiona bit bizarre ... Pin
Garth J Lancaster10-Dec-14 13:25
mveGarth J Lancaster10-Dec-14 13:25 
AnswerRe: a bit bizarre ... Pin
B. Clay Shannon10-Dec-14 13:29
professionalB. Clay Shannon10-Dec-14 13:29 
GeneralRe: a bit bizarre ... Pin
Garth J Lancaster10-Dec-14 13:36
mveGarth J Lancaster10-Dec-14 13:36 

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

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