当前位置: 首页 > 编程语言 > C#

不调试Log4Net消息的构建成本分享

时间:2023-04-10 22:44:45 C#

不调试Log4Net消息的构建成本根据这篇log4net文章,您应该在任何Log.Debug语句之前检查是否启用调试以消除语句构建成本。是否有更好的替代方法来始终必须在任何日志语句之前检查if(Log.IsDebugEnabled)?Log4Net示例:if(log.IsDebugEnabled){log.Debug("这是条目号:"+i);我不想支付语句构建的开销成本,也不想在每个日志语句之前检查。但也不想在每个日志语句之前检查当您发现自己一遍又一遍地重复相同的代码时,听起来像是一个通用的抽象可能是有序的。在这种情况下,您可以为Log4Net创建自定义包装器。很简单:publicstaticclassLogger{privatestaticILog_log;静态Logger(){log4net.Config.XmlConfigurator.Configure();_log=log4net.LogManager.GetLogger("Log4Net");}publicstaticvoidDebug(stringmessage){if(_log.IsDebugEnabled)_log.Debug(message);}publicstaticvoidInfo(stringmessage){_log.Info(message);}publicstaticvoidWarn(stringmessage){_log.Warn(message);}publicstaticvoidError(stringmessage){_log.Error(message);}publicstaticvoidError(stringmessage,Exceptionex){_log.Error(message,ex);}publicstaticvoidFatal(stringmessage){_log.致命的(消息);}publicstaticvoidFatal(stringmessage,Exceptionex){_log.Fatal(message,ex);在这种情况下,我将记录器实例设为静态。我不是100%确定它会始终按预期工作。通常我在依赖注入框架后面使用它,并将记录器依赖项配置为由框架处理的单例。您可以使用实例方法使其成为实例类,并将其放在静态工厂类之后。必要时进行测试和调整。这里有几个额外的好处:您在Log4Net中的依赖项被隔离到一个类中。所以如果你想使用不同的记录器,你只需要更改一个类而不是整个项目中的所有内容。您可以在依赖注入器后面轻松地将其抽象化。您希望包含在所有日志语句中的任何其他通用功能都可以轻松地在此处全局包含。我通常用于第三个好处的示例可能如下所示:privatestaticstringGetLocation(){varframe=newStackTrace(1).GetFrame(1);var方法=frame.GetMethod();returnstring.Format("{0}:{1}.{2}({3})",Environment.MachineName,method.ReflectedType.FullName,method.Name,frame.GetFileLineNumber().ToString());这从运行时系统获得了更有意义的调试信息(虽然可能会有性能损失,但对于高容量系统来说值得测试)。所以我传递的错误记录函数可能看起来像这样:@Grhm和@David都有很棒的想法,但我认为David的包装并没有达到应有的水平。以这种方式包装log4net。只需在包装器上实现Debug、Info等并将它们委托给log4net的Debug、Info等方法即可破解log4net记录调用站点信息的能力。如果你这样包装并告诉log4net记录调用站点信息,log4net将在包装器中写出调用站点,而不是实际代码中的调用站点,这就是你想要的。我个人不喜欢使用单例记录器,因为您无法为程序的不同部分调整记录级别。如果您正在处理多个组件,您可能希望为一个组件启用信息级日志记录,但只为其他组件记录警告(或根本不记录警告)。使用单例记录器,所有应用程序中的所有日志记录都将处于同一级别。当您错误地包装log4net并用单个记录器覆盖整个应用程序时,您就是在否认自己的许多log4net内置(和强大)功能。我在这里回答了一个类似的问题(关于维护调用站点信息):HowtologmethodnameswhenusingawrapperclasswhenusingawrapperclassthatincludesLog4net为了节省时间,我在这里包含了一个代码示例(未编译和未经测试,但应该关闭)...公共类MyLog4NetWrapper{ILog日志;publicMyLog4NetWrapper(stringloggerName){log=LogManager.GetLogger(loggerName)}publicMyLog4NetWrapper(typeloggerType){log=LogManager.GetLogger(loggerType)}publicvoidInfo(stringmessage){if(log.IsInfoEnabled)log.Logger.日志(类型(MyLog4NetWrapper),LogLevel.Info,消息,空);}//除非启用日志记录,否则推迟昂贵的计算——感谢Grhm的示例无效的);}}//Debug、Warn、Trace等留作练习。您可以在代码中创建这些记录器,如下所示:publicclassMyClass{privatestaticreadonlyILoglog=newMyLoggerWrapper(typeof(MyClass));publicvoidDoSomething(){log.Info("Helloworld!");编写保留调用站点信息的log4net包装器的诀窍是使用Log方法并将记录器的类型作为第一个参数传递。如果您要编写一个包装器来实现您询问的功能(延迟日志调用中任何昂贵代码的执行而不明确检查是否启用了所需的日志记录级别),那么您可以将其作为包装器中的代码而不是实现它作为一种扩展方法(它也遇到了我上面描述的相同的调用站点丢失问题)。祝你好运!您可以使用lambda表达式。比如:log.Debug(()=>"这是条目号:"+i);这样,lambda仅在.IsDebugEnabled调用之后进行评估。我们定义一个扩展类(取自http://www.beefycode.com/post/Extension-Methods-for-Deferred-Message-Formatting-in-Log4Net.aspx),其扩展方法如下:publicstaticclassLog4NetExtensionMethods{publicstaticvoidDebug(thisILoglog,FuncformattingCallback){if(log.IsDebugEnabled){log.Debug(formattingCallback());}}//..需要的其他方法...}我不确定log4net是否在最近的版本中添加了lamda类型支持-但这对我有用。最简单和最干净的方法可能是使用DebugFormat方法,它实际上检查是否启用了调试级别(参见log4net的Github代码)。如果包含命名空间log??4net.Util,则可以在log4netILog上调用以下扩展方法:publicstaticvoidErrorExt(thisILoglogger,Funccallback)这只会在启用日志记录错误级别时调用lambda函数。无需编写自己的扩展方法。它还通过将创建包装在trycatch方法中来防止在构造实际日志消息时出现创建错误。我会看一下预处理器(预编译?)指令。#ifDEBUG{yourloggingcodehere}#endif之类的东西应该为你做,然后代码只会在调试模式下编译。您还可以在这样的方法上使用条件属性:[System.Diagnostics.Conditional("DEBUG")]privatevoidYourMethodNameHere(YourMethodSignatureHere)查看这个旧问题以获取有关何时/为什么/如何使用它们的更多信息。http://stackoverflow.com/questions/3788605/if-debug-vs-conditionaldebug以上是C#学习教程:非调试时Log4Net消息的构建开销分享。如果对大家有用,需要进一步了解C#学习教程,希望大家多加关注——本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: