filterLogging 不适用于 Database.Persist.Sql 的 runSqlPool 函数
filterLogging not working on Database.Persist.Sql's runSqlPool function
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 调用没有抑制输出?
由于该问题收到了两个反对票,我将补充一点,上面显示的模式(即 运行StdoutLoggingT .filterLogger)在许多 GitHub 项目中使用,但我看不到我的申请有何不同。在没有解释或追索手段的情况下被否决有点令人沮丧。
Persistent 的架构有点迂回且文档不足:
withSqlPool
需要一个建造者。构建器能够从任何 "logging function"(基本上是 MonadLogger 使用的内部类型)中构建一个 SqlBackend
。该函数然后创建一个资源池 SqlBackend
s,供您获取和释放和使用。这是你传入的延续参数 Pool SqlBackend -> m a
。在 return 中,withSqlPool
承诺会给你带来一堆副作用,输入为 (MonadIO m, MonadBaseControl IO m, MonadLogger m) => m a
.
另一方面,runSqlPool
需要 MonadBaseControl IO m => ReaderT SqlBackend m a
和 Pool SqlBackend
以及 return 和 m a
。从这里我们可以推断,它基本上是从资源池中获取一个SqlBackend
,用它来构造和运行一个SQL查询,然后returns MonadBaseControl IO => m a
.实际上,它的文档是 "Get a connection from the pool, run the given action, and then return the connection to the pool."
尽管名称相似,但它们做的是两件截然不同的事情。第一个函数构造资源池,第二个函数使用它。大多数持久性 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 ())
当第三个约束消失时,我们可以通过实现 m ~ IO
.
来统一 IO ()
和 (MonadIO m, MonadBaseControl IO m) => m ()
现在,在这个阶段,我们可以插入我们的 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
只是继承了 withSqlPool
生成的 MonadLogger
约束的日志记录行为。只有在 withSqlPool
级别,我们才能插入所需的 filterLogger
调用。
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 调用没有抑制输出?
由于该问题收到了两个反对票,我将补充一点,上面显示的模式(即 运行StdoutLoggingT .filterLogger)在许多 GitHub 项目中使用,但我看不到我的申请有何不同。在没有解释或追索手段的情况下被否决有点令人沮丧。
Persistent 的架构有点迂回且文档不足:
withSqlPool
需要一个建造者。构建器能够从任何 "logging function"(基本上是 MonadLogger 使用的内部类型)中构建一个SqlBackend
。该函数然后创建一个资源池SqlBackend
s,供您获取和释放和使用。这是你传入的延续参数Pool SqlBackend -> m a
。在 return 中,withSqlPool
承诺会给你带来一堆副作用,输入为(MonadIO m, MonadBaseControl IO m, MonadLogger m) => m a
.
另一方面,runSqlPool
需要MonadBaseControl IO m => ReaderT SqlBackend m a
和Pool SqlBackend
以及 return 和m a
。从这里我们可以推断,它基本上是从资源池中获取一个SqlBackend
,用它来构造和运行一个SQL查询,然后returnsMonadBaseControl IO => m a
.实际上,它的文档是 "Get a connection from the pool, run the given action, and then return the connection to the pool."
尽管名称相似,但它们做的是两件截然不同的事情。第一个函数构造资源池,第二个函数使用它。大多数持久性 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 ())
当第三个约束消失时,我们可以通过实现 m ~ IO
.
IO ()
和 (MonadIO m, MonadBaseControl IO m) => m ()
现在,在这个阶段,我们可以插入我们的 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
只是继承了 withSqlPool
生成的 MonadLogger
约束的日志记录行为。只有在 withSqlPool
级别,我们才能插入所需的 filterLogger
调用。