5

我通常在每个类中声明以下内容:

private static readonly log4net.ILog log = log4net.LogManager.GetLogger(
            System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

并使用每个类中的静态成员在不同级别(信息、调试等)进行日志记录

我在某处看到它并且一直在不知不觉地使用它,理由是设置足够灵活,可以帮助我按名称空间过滤并记录单个类型,如果我想解决生产问题等等。

但我很少需要使用精细日志记录的“级别”。所以,我想看看其他人在使用什么。你使用上面的,因为我感觉很多人都在使用,或者你创建命名记录器,如“debug”、“trace”、“error”、“moduleA”等,并在不同类型之间共享记录器,组件?

4

4 回答 4

11

我基本上用

public class MyClass
{
    private static readonly ILog log = Log.Get<MyClass>();
}

其中 Log.Get 是一个基本上在内部执行此操作的类

return LogManager.GetLogger(typeof(T));

启动成本比反射方式还要小,而且更干净。

更新:鉴于我晚年在依赖注入、单元测试和伪造方面的经验,我不能再说我纵容上述方法。该方法(我的和 OP 的方法)的问题在于代码对如何创建日志实例有明确的了解。

一方面,这种增加的耦合使得测试变得更加困难:没有简单的方法可以用ILog假实例替换实例。另一方面,对我的Log班级所做的更改将导致更改波及所有使用它的班级。

因此,我通常通过构造函数注入来注入实例ILog,并将如何构建记录器外包给我选择的 DI 框架

public class MyClass
{
    readonly ILog _log;

    public class MyClass(ILog log)
    {
        _log = log;
    }
}

这允许适当的去耦。代码不再需要知道记录器是如何构造的。大多数依赖注入框架都可以查看被注入的类型,然后使用它来构造日志实例。这是 log4net 和 Autofac 的一种方法

于 2009-05-19T16:38:46.713 回答
2

以原始方式执行此操作的成本是 ILog 实现的实例以及在启动时运行“System.Reflection.MethodBase.GetCurrentMethod().DeclaringType”所需的时间。

我记得几年前研究过它,我们的启动成本大约是每 10000 个类 1 秒,而每 10k 个类不到 1 兆字节。

鉴于如此低的成本,鉴于 log4net 提供的难以置信的灵活性,我从未回头。

注意:我不能在这里评论其他解决方案,因为我是新人.. 但是这一行:

方法 = 新 System.Diagnostics.StackTrace().GetFrame(1).GetMethod();

昂贵,尤其是在为每条日志消息调用时。

于 2009-02-05T15:30:59.450 回答
0

您可以使用日志记录的工具是 PostSharp ( http://www.postsharp.org/ )。有付费和免费(Express)版本。我只用它来记录方法边界,但我知道你也可以用它来处理错误。在两者之间,这将满足您的大部分日志记录需求,而无需在每个类中编写代码。

于 2009-05-17T23:29:24.427 回答
-1

Lately, i created something like this:

public static class Logger
{
    private static bool isLoaded = false;       

    public static ILog Log
    {
        get
        {
            System.Reflection.MethodBase method;
            method = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod();
            StringBuilder loggerName = new StringBuilder();
            loggerName.AppendFormat("{0}.{1}(", method.ReflectedType.FullName, method.Name);

            ParameterInfo[] parameters = method.GetParameters();
            string[] parametersStr = new string[parameters.Length];

            if (parameters.Length > 0)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    parametersStr[i] = parameters[i].ToString();
                }
                loggerName.Append(String.Join(", ", parametersStr));
            }

            loggerName.Append(")");

            return GetLogger(loggerName.ToString());
        }
    }


    private static ILog GetLogger(string loggerName)
    {
        if (!isLoaded)
        {
            log4net.Config.XmlConfigurator.Configure();
        }
        return LogManager.GetLogger(loggerName);
    }
}

it lets me use log4net without creating its instance in every class i need to use it, and i still get class name and method where i logged the action.

Sample usage:

Logger.Log.DebugFormat("Response [{0}]", xmlResponse);
于 2009-01-22T13:07:52.600 回答