keter/Keter/LogFile.hs

80 lines
2.4 KiB
Haskell
Raw Normal View History

2012-05-17 08:15:25 +04:00
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
2012-05-17 10:32:11 +04:00
{-# LANGUAGE TemplateHaskell #-}
2012-05-17 08:15:25 +04:00
module Keter.LogFile
( LogFile
, start
, addChunk
, close
) where
2012-05-17 11:59:17 +04:00
import Keter.Prelude hiding (getCurrentTime)
2012-05-17 08:15:25 +04:00
import qualified Data.ByteString as S
import Data.Time (getCurrentTime)
import qualified System.IO as SIO
import qualified Filesystem as F
import qualified Data.Text as T
data Command = AddChunk S.ByteString
| Close
newtype LogFile = LogFile (Command -> KIO ())
addChunk :: LogFile -> S.ByteString -> KIO ()
addChunk (LogFile f) bs = f $ AddChunk bs
close :: LogFile -> KIO ()
close (LogFile f) = f Close
start :: FilePath -- ^ folder to contain logs
-> KIO (Either SomeException LogFile)
start dir = do
res <- liftIO $ do
createTree dir
moveCurrent Nothing
case res of
Left e -> return $ Left e
Right handle -> do
chan <- newChan
forkKIO $ loop chan handle 0
return $ Right $ LogFile $ writeChan chan
where
current = dir </> "current.log"
moveCurrent mhandle = do
maybe (return ()) SIO.hClose mhandle
x <- isFile current
when x $ do
now <- getCurrentTime
rename current $ dir </> suffix now
F.openFile current F.WriteMode
2012-05-17 12:47:54 +04:00
suffix now = fromText (T.concatMap fix $ T.takeWhile (/= '.') $ show now) <.> "log"
fix ' ' = "_"
fix c | '0' <= c && c <= '9' = T.singleton c
fix _ = T.empty
2012-05-17 08:15:25 +04:00
loop chan handle total = do
c <- readChan chan
case c of
AddChunk bs -> do
let total' = total + S.length bs
res <- liftIO $ S.hPut handle bs >> SIO.hFlush handle
2012-05-17 10:32:11 +04:00
either $logEx return res
2012-05-17 08:15:25 +04:00
if total' > maxTotal
then do
res2 <- liftIO $ moveCurrent $ Just handle
case res2 of
Left e -> do
2012-05-17 10:32:11 +04:00
$logEx e
2012-05-17 08:15:25 +04:00
deadLoop chan
Right handle' -> loop chan handle' 0
else loop chan handle total'
Close ->
liftIO (SIO.hClose handle) >>=
2012-05-17 10:32:11 +04:00
either $logEx return
2012-05-17 08:15:25 +04:00
deadLoop chan = do
c <- readChan chan
case c of
AddChunk _ -> deadLoop chan
Close -> return ()
maxTotal = 5 * 1024 * 1024 -- 5 MB