I have been looking for a way to log class names and method names as part of my logging infrastructure. Obviously I'd like to make it simple to use and fast at runtime. I've done a lot of reading about logging class names and method names, but I've run across 2 themes.
- That log4net uses an internally throws exception to generate a stack frame and that gets expensive if you use that generally for all logging.
- Confusion. There is a lot of literature out there. I've tried a bunch of it and not gotten to something useful.
If you humor me for a second, I'd like to reset.
I created a class like this in my project
public static class Log {
private static Dictionary<Type, ILog> _loggers = new Dictionary<Type, ILog>();
private static bool _logInitialized = false;
private static object _lock = new object();
public static string SerializeException(Exception e) {
return SerializeException(e, string.Empty);
}
private static string SerializeException(Exception e, string exceptionMessage) {
if (e == null) return string.Empty;
exceptionMessage = string.Format(
"{0}{1}{2}\n{3}",
exceptionMessage,
(exceptionMessage == string.Empty) ? string.Empty : "\n\n",
e.Message,
e.StackTrace);
if (e.InnerException != null)
exceptionMessage = SerializeException(e.InnerException, exceptionMessage);
return exceptionMessage;
}
private static ILog getLogger(Type source) {
lock (_lock) {
if (_loggers.ContainsKey(source)) {
return _loggers[source];
}
ILog logger = log4net.LogManager.GetLogger(source);
_loggers.Add(source, logger);
return logger;
}
}
public static void Debug(object source, object message) {
Debug(source.GetType(), message);
}
public static void Debug(Type source, object message) {
getLogger(source).Debug(message);
}
public static void Info(object source, object message) {
Info(source.GetType(), message);
}
public static void Info(Type source, object message) {
getLogger(source).Info(message);
}
...
private static void initialize() {
XmlConfigurator.Configure();
}
public static void EnsureInitialized() {
if (!_logInitialized) {
initialize();
_logInitialized = true;
}
}
}
(If this code looks familiar it's because it is borrowed from the examples!)
In any case, throughout my project I use lines like this to log:
Log.Info(typeof(Program).Name, "System Start");
Well, this kind of works. Most importantly, I get the class name but no method name. Less, importantly, I am polluting my code with this "typeof" junk. If I copy and paste a snippet of code between files, etc. the logging framework will be lying!
I tried playing with the PatternLayout (%C{1}.{M}) but that didn't work (all it did was write "Log.Info" to the log--because everything is routing through the Log.X static methods!). Besides, that's supposed to be slow.
So, what is the best way, given my setup and my desire to be simple and fast?
Appreciate any help in advance.