tags:

views:

36

answers:

4

I am working with a log file and I have a method which is creating a generic entry in to the log. The generic log entry looks like this:

public StringBuilder GetLogMessage(LogEventType logType, object message)
{
        StringBuilder logEntry = new StringBuilder();
        logEntry.AppendFormat("DATE={0} ", DateTime.Now.ToString("dd-MMM-yyyy", new CultureInfo(CommonConfig.EnglishCultureCode)));
        logEntry.AppendFormat("TIME={0} ", DateTime.Now.ToString("HH:mm:ss", new CultureInfo(CommonConfig.EnglishCultureCode)));
        logEntry.AppendFormat("ERRORNO={0} ", base.RemoteIPAddress.ToString().Replace(".", string.Empty));
        logEntry.AppendFormat("IP={0}", base.RemoteIPAddress.ToString());
        logEntry.AppendFormat("LANG={0} ", base.Culture.TwoLetterISOLanguageName);
        logEntry.AppendFormat("PNR={0} ", this.RecordLocator);
        logEntry.AppendFormat("AGENT={0} ", base.UserAgent);
        logEntry.AppendFormat("REF={0} ", base.Referrer);
        logEntry.AppendFormat("SID={0} ", base.CurrentContext.Session.SessionID);
        logEntry.AppendFormat("LOGTYPE={0} ", logType.ToString() );
        logEntry.AppendFormat("MESSAGE={0} ", message);
        return logEntry;
}

What would be the best approach for adding additional parameters before "MESSAGE="? For example if I wanted to add "MODULE=" from a derived class when the GetLogMessage is being run. Would a delegate be what I am looking for or marking the method as virtual and overriding it or do I need something entirely different?

Any help would be appreciated.

A: 

If you want just append some information related to the subclass overriding a virtual method (and calling base implementation at the beginning) is the best suitable solution ;)

Thomas Wanner
Thanks Thomas, how would I then be able to enter an entry in the StringBuilder before "MESSAGE={0}" and after "LOGTYPE={0}"? Would I have to convert it to a string and look for the substring?
Sammy T
A: 
public StringBuilder GetLogMessage(LogEventType logType, object message)
{
        StringBuilder logEntry = new StringBuilder();
        logEntry.AppendFormat("DATE={0} ", DateTime.Now.ToString("dd-MMM-yyyy", new CultureInfo(CommonConfig.EnglishCultureCode)));
        logEntry.AppendFormat("TIME={0} ", DateTime.Now.ToString("HH:mm:ss", new CultureInfo(CommonConfig.EnglishCultureCode)));
        logEntry.AppendFormat("ERRORNO={0} ", base.RemoteIPAddress.ToString().Replace(".", string.Empty));
        logEntry.AppendFormat("IP={0}", base.RemoteIPAddress.ToString());
        logEntry.AppendFormat("LANG={0} ", base.Culture.TwoLetterISOLanguageName);
        logEntry.AppendFormat("PNR={0} ", this.RecordLocator);
        logEntry.AppendFormat("AGENT={0} ", base.UserAgent);
        logEntry.AppendFormat("REF={0} ", base.Referrer);
        logEntry.AppendFormat("SID={0} ", base.CurrentContext.Session.SessionID);
        logEntry.AppendFormat("LOGTYPE={0} ", logType.ToString() );

        var module_log = GetModuleLog();        
        logEntry.AppendFormat("MODULE={0}", (!String.IsNullOrEmpty(module_log))
                     ?module_log
                     :String.Empty);

        logEntry.AppendFormat("MESSAGE={0} ", message);
        return logEntry;
}

protected virtual string GetModuleLog(){
 // code in the derived class to return the log related to the module...
}

HTH.

Sunny
A: 

Assuming the log message always has the same format you could add a virtual method which subclasses can implement to add their own details to the message:

public StringBuilder GetLogMessage(LogEventType logType, object message)
{
    StringBuilder logEntry = new StringBuilder();
    logEntry.AppendFormat("DATE={0} ", DateTime.Now.ToString("dd-MMM-yyyy", new CultureInfo(CommonConfig.EnglishCultureCode)));
    //...

    this.AddMessageDetail(logEntry);
    logEntry.AppendFormat("MESSAGE={0} ", message);
    return logEntry;
}

protected virtual void AddMessageDetail(StringBuilder logMessage)
{
}

However this breaks down if subclasses need to change the structure of messages.

Lee
This is a really interesting method Lee, thanks very much for your feedback. It will be useful for another part of what I am writing!
Sammy T
+1  A: 

What about this approach:

public StringBuilder GetLogMessage(LogEventType logType, object message)
{
    return GetLogMessage(logType, message, null);
}

public StringBuilder GetLogMessage(LogEventType logType, object message, Dictionary<string,string> extraParameters) 
{ 
        StringBuilder logEntry = new StringBuilder(); 
        logEntry.AppendFormat("DATE={0} ", DateTime.Now.ToString("dd-MMM-yyyy", new CultureInfo(CommonConfig.EnglishCultureCode))); 
        logEntry.AppendFormat("TIME={0} ", DateTime.Now.ToString("HH:mm:ss", new CultureInfo(CommonConfig.EnglishCultureCode))); 
        logEntry.AppendFormat("ERRORNO={0} ", base.RemoteIPAddress.ToString().Replace(".", string.Empty)); 
        logEntry.AppendFormat("IP={0}", base.RemoteIPAddress.ToString()); 
        logEntry.AppendFormat("LANG={0} ", base.Culture.TwoLetterISOLanguageName); 
        logEntry.AppendFormat("PNR={0} ", this.RecordLocator); 
        logEntry.AppendFormat("AGENT={0} ", base.UserAgent); 
        logEntry.AppendFormat("REF={0} ", base.Referrer); 
        logEntry.AppendFormat("SID={0} ", base.CurrentContext.Session.SessionID); 
        logEntry.AppendFormat("LOGTYPE={0} ", logType.ToString() ); 
        if(extraParameters != null)
        {
             foreach(var s in extraParameters.Keys)
             {
                  logEntry.AppendFormat("{0}={1} ", s, extraParameters[s] ); 
             }
        }
        logEntry.AppendFormat("MESSAGE={0} ", message); 
        return logEntry; 
} 
klausbyskov
+1 I like your answer better than mine since it now allows multiple custom messages to be added without needing a method like I wrote (assuming the OP does not have a standard log message format)
Sunny
I really like this approach. Allows for better maintenance of the message format. Thank you!
Sammy T