为什么hslogger会给出此错误消息? :hPutStr:非法操作(句柄关闭)

时间:2014-02-27 22:36:39

标签: haskell logging

我一定不知道如何正确使用hslogger。我收到此错误消息:

hsloggerTest1: test.log: hPutStr: illegal operation (handle is closed)

当我在hsloggerTest1.hs

中运行此代码时
-- hslogger
import System.Log.Logger         ( Priority(ERROR), addHandler
                                 , errorM, updateGlobalLogger
                                 )
import System.Log.Handler        (close)
import System.Log.Handler.Simple (fileHandler)


main :: IO ()
main = do
  let logger   = "main"
      fileName = "test.log"

  h1 <- fileHandler fileName ERROR
  putStrLn "opened file1"
  updateGlobalLogger logger $ addHandler h1
  putStrLn "will write1"
  errorM logger "writing 1"
  putStrLn "did write1"
  close h1
  putStrLn "closed file1"

  h2 <- fileHandler fileName ERROR
  putStrLn "opened file2"
  updateGlobalLogger logger $ addHandler h2
  putStrLn "will write2"
  errorM logger "writing 2"
--  putStrLn "did write2"
--  close h2
--  putStrLn "closed file2"

test.log的内容是:

writing 1
writing 2

我做错了什么? (或者这是一个hslogger错误?)谢谢。

顺便说一句,我已经通过一些重组修复了我的实际代码中的问题。但是,我仍然很好奇为什么我上面做的是错误的。

1 个答案:

答案 0 :(得分:1)

我没有看到删除处理程序的接口,因此为了使上面的代码工作,我使用了setHandlers并覆盖了之前的处理程序,如果这有助于你的用例。

import System.Log.Logger         ( Priority(ERROR), addHandler, setHandlers
                             , errorM, updateGlobalLogger
                             )
import System.Log.Handler        (close)
import System.Log.Handler.Simple (fileHandler)
import Data.Time.Clock

main :: IO ()
main = do
let logger   = "main"
   fileName = "test.log"
h1 <- fileHandler fileName ERROR
putStrLn "opened file1"
updateGlobalLogger logger $ setHandlers[h1]
putStrLn "will write1"
c1 <- getCurrentTime
errorM logger $ "writing 1 " ++ (show c1)
putStrLn "did write1"
close h1
putStrLn "closed file1"

h2 <- fileHandler fileName ERROR
putStrLn "opened file2"
updateGlobalLogger logger $ setHandlers[h2]
putStrLn "will write2"
c <- getCurrentTime
errorM logger ("writing 2 " ++ (show c))
putStrLn "did write2"
--  close h2  
--  putStrLn "closed file2"

日志文件的内容:      writing 12014-02-27 23:03:35.0594493 UTC writing 2 2014-02-27 23:03:35.0754502 UTC

更新: 这就是我解释http://hackage.haskell.org/package/hslogger-1.0.7/docs/System-Log-Logger.html doc的方法:如果根层次结构相同,则搜索相同的处理程序集。为了让我理解api,这是另一个版本:

-- hslogger
import System.Log.Logger         ( Priority(ERROR), addHandler
                             , errorM, updateGlobalLogger
                             )
import System.Log.Handler        (close)
import System.Log.Handler.Simple (fileHandler)


main :: IO ()
main = 
 do
    putStrLn("This will work because the hierarchies are different")
    mainWithLoggerPair ("main", "main2")
    putStrLn("______________________________________________________")
    putStrLn("This will fail because the root logger is returned from the tree map")
    mainWithLoggerPair ("main", "main.sub")


mainWithLoggerPair (logger1, logger2) = do
  let  fileName = "test.log"
  h1 <- fileHandler fileName ERROR
  putStrLn "opened file1"
  updateGlobalLogger logger1 $ addHandler h1
  putStrLn "will write1"
  errorM logger1 "writing 1"
  putStrLn "did write1"
  close h1
  putStrLn "closed file1"

  h2 <- fileHandler fileName ERROR
  putStrLn "opened file2"
  updateGlobalLogger logger2 $ addHandler h2
  putStrLn "will write2"
  errorM logger2 "writing 2"
  putStrLn "did write2"
  close h2
  putStrLn "closed file2"

` 在上述情况下,当使用相同的记录器层次结构时,写入失败,因为我们仍然遇到在关闭基础文件句柄时未删除处理程序的问题。

我尝试浏览网站上的代码,以便更好地了解该库:

type LogTree = Map.Map String Logger

例如,该树基于记录器字符串进行维护 “a.b.c”属于“a”下的树,但记录器“l1”和“l2”是不同的记录器。我希望这有助于为api增加一些额外的亮点。 现在,让我们考虑当前的测试用例: 记录器的名称从未改变,这意味着映射将找到较早的记录器并返回现有的记录器实例(等效的haskell术语?),并在处理程序列表中引用已关闭的文件句柄。

提供一个removeHandler接口来处理上述测试用例是非常直观的。