logging - 如何使用 NLog 以功能方式登录 F#

标签 logging f# nlog

我一直在研究日志记录选项并选择了 NLog 并记录到数据库

我是函数式编程的新手,有 C# OOP 背景。

我如何在 F# 中以功能方式实现日志记录?
我会吗

  • 在顶层创建记录器,然后将它传递给每个函数
  • 根据需要通过静态方法访问记录器(显然每次实例化记录器都会有一些开销 - 但也许这不是什么大问题)
  • 还有别的吗?

我想避免使用商业日志记录选项,因为我的项目很小。

感谢您的宝贵时间。

最佳答案

Access the logger through a static method

这种方法适用于实验性应用,但一般来说它是 Service Locator 的实例这通常被认为是反模式。

更可靠的替代方案是依赖注入(inject) (DI)。由于 F# 是混合语言,您可以使用 OOP 概念并以 OOP 的通用方式应用 DI 模式。但是,如果您想使用函数式风格,F# 中的 DI 没有单一的通用函数式模式。

Create the logger at the top level and just pass it in to every function

这只是在功能代码中使用 DI 的最直接方式。这种方法可能适用于小型应用程序,但是如果除了日志记录之外还有其他横切关注点(例如配置),您可能会以参数爆炸而告终,这会使代码变得困惑。 有不同的方法来解决这个问题。我已经解决了描述的方法 here .

您可以通过以下方式应用此方法。

您的业务逻辑函数可能如下所示:

let doSomething env = 
    let logger = getLogger env
    logger.Debug("Do something")
    // Do something

这意味着logger 引用通过env 参数提供,并通过函数getLogger 访问。

此代码应引用公共(public)日志记录模块,它可能如下所示:

[<Interface>]
type ILoggerProvider =
    abstract Logger: ILogger

let getLogger (env: #ILoggerProvider) = env.Logger

注意 doSomethingenv 参数类型被自动推断为 #ILoggerProvider (即继承 ILoggerProvider ).

设想稍后在相同的业务逻辑中我们需要访问配置(以及日志记录)。在这种情况下,我们不需要新参数,而是以类似的方式从相同的 env 参数访问配置:let configuration = getConfiguration env,前提是用于配置的通用模块是也创建了:

[<Interface>]
type IConfigurationProvider =
    abstract Configuration: IConfiguration

let getConfiguration (env: #IConfigurationProvider) = env.Configuration

在这种情况下,doSomethingenv 参数类型会自动重新推断为 'a(需要 'a :> ILoggerProvider 和 'a :> IConfigurationProvider) 这意味着它应该同时继承 ILoggerProviderIConfigurationProvider

在应用程序级别,您需要创建环境实例并将其传递给业务逻辑,以便提供对日志记录和配置(以及可能的其他服务)的访问。您可以通过以下方式进行:

[<Interface>] 
type IEnvironment = 
    inherit ILoggerProvider 
    inherit IConfigurationProvider
    
let createEnvironment (logger, configuration) = 
    { new IEnvironment with
        member self.Logger = logger 
        member self.Configuration = configuration }

let createLogger () = // create logger...
    
let createConfiguration () = // create configuration...

let logger = createLogger ()
let configuration = createConfiguration ()
let env = createEnvironment (logger, configuration)

// Call business logic
doSomething env

请注意,使用新的横切关注点很容易扩展此代码,因为每个业务逻辑功能只知道使用过的服务(例如日志记录、配置),而对 IEnvironment 界面及其所有内容。

您可以找到我的示例的完整版本 here .

您可能会发现 F# 中 DI 方法的更全面概述 here .

关于logging - 如何使用 NLog 以功能方式登录 F#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70040464/

相关文章:

java - Log4j + OpenJPA = NoClassDefFoundError : javax/persistence/AttributeConverter

f# - 如何在执行异步任务时保持按钮启用

f# - 如何使用单根对简单层次结构进行建模

c# - 如何正确从 appsettings.json 中提取 NLog DB ConnectionString

python - 如何使用 Cherrypy 设置日志记录?

sharepoint - 使用日志解析器解析不同文件夹中的大量日志

asynchronous - C# 中的 httpclient postasync

.net - NLog每日归档大小限制

.net - NLog:在类里面传递记录器是一种好习惯吗?

logging - 需要 OWASP-ESAPI 记录器帮助