Building a log class is a simple matter:
public static class Logger
{
private static List
private static bool _isActive = false;
public static bool IsActive
{
get
{
return _isActive;
}
set
{
if (_isActive != value)
{
if (value)
{
_isActive = true;
}
else
{
_isActive = false;
lock (Entries)
{
Entries.Clear();
}
}
}
}
}
public static int MinLogLevel { get; set; }
public static List
{
List
lock (Entries)
{
tmp = Entries;
Entries = new List
}
return tmp;
}
public static void AddEntry(int level, string message)
{
if ((IsActive) && (level >= MinLogLevel))
{
LogEntry entry = new LogEntry(level, message);
lock (Entries)
{
Entries.Add(entry);
}
}
}
}
The first thing to note is "GetLogEntries" clears the list. I did it in order to send the entries to the server only once, even if the server did not receive them. You might need to implement it in a different way.
The second thing is I relay on a helper class LogEntry. I provide my implementation of it, feel free to change it, the logic wouldn't change. Maybe a minor change to the constructor is needed. Or using the Server's LogEntry class and setting the properties inside {}.
public class LogEntry
{
public DateTime Stamp { get; private set; }
public int Level { get; private set; }
public string Message { get; private set; }
public Guid UserID { get; private set; }
public Guid TenantID { get; private set; }
public string Operation { get; private set; }
public LogEntry(int p_Level, string p_Message)
{
Stamp = DateTime.Now;
Level = p_Level;
Message = p_Message;
StringBuilder sb = new StringBuilder();
StackTrace stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames();
foreach (StackFrame stackFrame in stackFrames)
{
sb.AppendLine(stackFrame.GetMethod().Name);
}
Operation = sb.ToString();
if (WebContext.Current.WFUser == null)
{
TenantID = Guid.Empty;
UserID = Guid.Empty;
}
else
{
TenantID = WebContext.Current.WFUser.TenantID;
UserID = WebContext.Current.WFUser.UserID;
}
}
public override string ToString()
{
return Stamp.ToString() + " " + Message + " - " + Level.ToString() + ": " + Message;
}
}
Now we'll have to add a background sending utility. This implementation is the most naive one, but it works great, so we didn't bother to change it.
private bool IsActive = true;
private void SendLog()
{
while (IsActive)
{
int CountDown = 300;
while (IsActive && CountDown>0)
{
System.Threading.Thread.Sleep(1000);
CountDown--;
}
SendToServer(Logger.GetLogEntries());
}
}
public App()
{
InitializeComponent();
Application.Current.Exit += Application_Exit;
System.Threading.Thread th = new System.Threading.Thread(SendLog);
th.Start();
}
private void Application_Exit(object sender, EventArgs e)
{
IsActive = false;
System.Threading.Thread.Sleep(5000);
}
This code goes to the application class. SendToServer is supposed to be a server side function (using WCF or RIA or whatever is at hand).
That's all, now add the debug lines as Logger.AddEntry(debugLevel, message) whenever you feel like it. Just remember to set the logging level and to activate/deactivate when you need it.