Haskell 库 Database.Persist.Sqlite 包含在 LoggingT 上下文中运行的函数,用于控制调试输出。所以我希望能够限制它们产生的调试输出,因此:
runStdoutLoggingT . filterLogger (\_ _ -> False) (runSqlPool (insertBy myData) myPool)
(根据我的实际代码进行压缩和简化)但是,它不会抑制日志记录。 insertBy 的求值在 stdout 上生成一行,格式为
[Debug#SQL] SELECT "id","key","data_source_row_id","loaded" FROM "data_row" WHERE "key"=? AND "data_source_row_id"=?; [PersistText blahblahblah]
那么为什么 filterLogger 调用没有抑制输出呢?
由于该问题已收到两票反对,我将补充一点,上面显示的模式(即 runStdoutLoggingT .filterLogger)已在许多 GitHub 项目中使用,我看不出我的应用程序有何不同。在没有解释或追索手段的情况下被否决有点令人沮丧。
最佳答案
持久化的架构有点迂回且记录不足:
withSqlPool
需要一个建筑商。 builder 能够 build 一个SqlBackend
超出任何“日志记录功能”(基本上是 MonadLogger 使用的内部类型)。然后该函数创建一个SqlBackend
的资源池 s,供您获取、释放和使用。这是延续参数Pool SqlBackend -> m a
作为返回,withSqlPool
promise 会给你带来一堆副作用,输入为(MonadIO m, MonadBaseControl IO m, MonadLogger m) => m a
.runSqlPool
另一方面,需要MonadBaseControl IO m => ReaderT SqlBackend m a
和一个Pool SqlBackend
并返回m a
。由此我们可以推断,它基本上获得了SqlBackend
。从资源池中获取,使用它构建并运行 SQL 查询,然后返回MonadBaseControl IO => m a
。事实上,它的文档是“从池中获取连接,运行给定的操作,然后将连接返回到池中。”
虽然名称相似,但它们做两件截然不同的事情。第一个函数构造资源池,第二个函数使用它。大多数持久 SQL 代码将具有以下形式:
withSqlPool (\logFunc -> do
conn <- makeConnection connectionString
return SqlBackend { ... , connLogFunc = logFunc })
numberOfOpenConnections
(\pool -> do
runSqlPool (insertBy myData) pool
runSqlPool (anotherTransaction moreData) pool)
事实上,如果您使用 persistent-postgresql
,上面只是简单的展开形式
withPostgresqlPool connectionString
numberOfOpenConnections
(\pool -> do
runSqlPool (insertBy myData) pool
runSqlPool (anotherTransaction moreData) pool)
但是等等!我们不能完全将其执行为 IO
行动尚未。 MonadIO m, MonadBaseControl IO m, MonadLogger m
是我们的限制,我们必须解除第三个限制:
main :: IO ()
main =
runStdoutLoggingT $
withPostgresqlPool connectionString
numberOfOpenConnections
(\pool -> do
runSqlPool (insertBy myData) pool
runSqlPool (anotherTransaction moreData) pool
return ())
当第三个约束消失后,我们就能够统一 IO ()
与 (MonadIO m, MonadBaseControl IO m) => m ()
通过实现m ~ IO
.
现在,在这个阶段,我们可以插入 filterLogger
– 就在 runStdoutLoggingT
解除约束之前:
main :: IO ()
main =
runStdoutLoggingT . filterLogger (\_ _ -> False) $
withPostgresqlPool connectionString
numberOfOpenConnections
(\pool -> do
runSqlPool (insertBy myData) pool
runSqlPool (anotherTransaction moreData) pool
return ())
总的来说,糟糕的命名和平淡的记录造成了困惑Database.Persist.Sql
模块。
让我们强调这一点:runSqlPool
只是继承 MonadLogger
的日志记录行为由 withSqlPool
生成的约束。仅在 withSqlPool
我们能够插入所需的 filterLogger
的级别打电话。
关于sql - filterLogging 不适用于 Database.Persist.Sql 的 runSqlPool 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36768459/