简体   繁体   English

设计应用程序范围的日志系统有哪些指导原则?

[英]What are the guidelines for designing an application-wide logging system?

I'm learning about layered architecture at the moment and I'm wondering how to add a logging system to such a design. 我正在学习分层架构,我想知道如何在这样的设计中添加日志系统。

Now let's say we have three layers: 现在让我们说我们有三层:

  1. Presentation Layer 表达层
  2. Business Layer 业务层
  3. Data Access Layer 数据访问层

And assume that only a higher level layer is aware of the layer one level below. 并假设只有更高级别的层知道下面一层的层。 For example, the Presentation Layer is aware of the Business Layer but not the other way around. 例如,表示层知道业务层,但不是相反。

Where should you implement a general logger class? 你应该在哪里实现一般记录器类?

  1. If I implement it in a different project, it means all the layers have a dependency on a common assembly, which may or may not be good. 如果我在不同的项目中实现它,则意味着所有层都依赖于公共程序集,这可能是也可能不是。 Though this can be overcome with dependency injection. 虽然这可以通过依赖注入来克服。
  2. If I implement it in the highest level (in our case the Presentation Layer), it will defy the Single Responsibility Principle. 如果我在最高级别(在我们的例子中是表示层)中实现它,它将违反单一责任原则。

What is a good place to implement a logging mechanism? 实施日志记录机制的好地方是什么?

And after implementing it, what is a way to use such a system? 在实施之后,使用这样一个系统的方法是什么?

  1. It should ideally be able to catch uncaught exceptions and save the exception description somewhere. 理想情况下,它应该能够捕获未捕获的异常并在某处保存异常描述。
  2. Where should you catch exceptions? 你应该在哪里捕获例外? Should they be caught in the highest layer (the Presentation Layer)? 它们应该被捕获在最高层(表示层)吗? Or should they be caught somewhere else? 或者他们应该被别人抓到?
  3. And what is the way to use to pass a logger to a class? 用于将记录器传递给类的方法是什么? Does it make sense to add a method/constructor overload to everything in the project that accepts an interface like ILogger ? 将方法/构造函数重载添加到项目中接受ILogger接口的所有内容是否有意义?

As you can see I'm pretty confused about the subject, and in my current job there's no one that has any knowledge about enterprise application design / layered design, even though they are designing enterprise applications. 正如您所看到的,我对这个主题非常困惑,在我目前的工作中,没有人对企业应用程序设计/分层设计有任何了解,即使他们正在设计企业应用程序。 So any help showing me the right direction will be appreciated. 所以任何帮助向我展示正确的方向将不胜感激。

Logging is a cross-cutting concern. 记录是一个贯穿各领域的问题。 This means that it encompasses all layers of your architecture, and it makes sense to implement it as a separate library. 这意味着它包含您的体系结构的所有层,并且将其实现为单独的库是有意义的。 However, this would only make sense as an exercise, since there are already very good solutions like Log4Net, NLog, and even .NET's own TraceSources. 但是,这只是一个练习,因为已经有很好的解决方案,如Log4Net,NLog,甚至.NET自己的TraceSources。

I tend to prefer those which support hierarchical logging (eg log4net). 我更倾向于那些支持分层日志记录的东西(例如log4net)。 This make it much easier to configure the desired tracing level in production systems. 这使得在生产系统中配置所需的跟踪级别变得更加容易。 Eg you could set general tracing level for MyApp.SomeNamespace to Warning , but also have set a specific type like MyApp.SomeNamespace.AnInterestingClass to Debug . 例如,您可以将MyApp.SomeNamespace常规跟踪级别设置为Warning ,但也将MyApp.SomeNamespace.AnInterestingClass等特定类型设置为Debug

I am not sure I understood the "what is a way to use such a system" part. 我不确定我是否理解“使用这种系统是什么方法”的一部分。

You use logging everywhere it is needed, in all layers of your app, in each method which needs it. 您可以在应用程序的所有层中,在需要它的每个方法中的任何位置使用日志记录。 I am under impression that you have an idea of centralized place where all errors are handled and logged, but these are separate things. 我的印象是你有一个集中的地方,处理和记录所有错误,但这些都是分开的。

It should ideally be able to catch uncaught exceptions and save the exception description somewhere. 理想情况下,它应该能够捕获未捕获的异常并在某处保存异常描述。

No, it shouldn't. 不,它不应该。 Loggers write stuff to logs, they don't handle exceptions. 记录器将东西写入日志,它们不处理异常。 Logging is not used only for reporting errors. 记录不仅用于报告错误。 You also want to log the execution of your application and many internal information (but with varying tracing levels), for the sake of troubleshooting the system in production or post mortem analysis. 您还需要记录应用程序的执行和许多内部信息(但具有不同的跟踪级别),以便在生产或事后分析中对系统进行故障排除。

Where should you catch exceptions? 你应该在哪里捕获例外?

At all levels. 在各个层面。 Many methods in your code will be handling the exceptions relevant to current context. 代码中的许多方法都将处理与当前上下文相关的异常。 I suppose that you really want to know where to handle the exceptions which were not caught elsewhere - some kind of catch-all handler. 我想你真的想知道在哪里处理其他地方没有发现的异常 - 某种全能的处理程序。 For this, often it makes sense to do it in the topmost layer, ie in your .exe or, more generally, in the layer which contains the types which represent the application itself. 为此,通常在最顶层(即.exe中)或更常见地在包含表示应用程序本身的类型的层中执行此操作是有意义的。 There are many ways to do it - from simply registering the handlers for the unhandled exceptions ( ThreadException/UnhandledException ) to HandleError/Application_Error in ASP.NET MVC to using something like exception handling application block , which I personally dislike (as most of Enterprise Library). 有很多方法可以做到这一点 - 从简单地将未处理异常( ThreadException / UnhandledException )的处理程序注册到ASP.NET MVC中的HandleError / Application_Error到使用异常处理应用程序块之类的东西,我个人不喜欢(因为大多数企业库) )。

And what is the way to use to pass a logger to a class? 用于将记录器传递给类的方法是什么? Does it make sense to add a method/constructor overload to everything in the project that accepts an interface like ILogger? 将方法/构造函数重载添加到项目中接受ILogger之类接口的所有内容是否有意义?

It depends on your implementation. 这取决于您的实施。 It seems that you want to go down the dependency injection path. 您似乎想要沿着依赖注入路径走下去。 Since logger is not an essential dependency (ie it is not related to functional behavior of types, but to the implementation), I would prefer to handle it via property injection as an optional dependency, instead of doing it via constructor which, IMO, should be used only for primary dependencies - those which are required for the type to function properly. 由于logger不是必需的依赖项(即它与类型的函数行为无关,而是与实现有关),我宁愿通过属性注入作为可选依赖项处理它,而不是通过构造函数来实现它,IMO应该仅用于主要依赖项 - 类型正常运行所需的依赖项。

However, you might not want to use DI. 但是,您可能不想使用DI。 Then you need some other way to get to logger. 然后你需要一些其他方式来获取记录器。 One option is discussed here . 这里讨论一个选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM