packages feed

keter-2.1.5: src/Keter/Logger.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE RankNTypes #-}
module Keter.Logger
    ( Logger(..)
    , createLoggerViaConfig
    , defaultRotationSpec
    , defaultMaxTotal
    , defaultBufferSize
    ) where

import Data.Time
import Debug.Trace
import qualified System.Log.FastLogger as FL
import System.Directory
import System.FilePath
import Control.Monad.Logger
import Control.Monad.Reader
import Control.Monad.IO.Class
import Control.Monad.IO.Unlift
import Keter.Context
import Keter.Config.V10

-- | Record wrapper over a fast logger (log,close) function tuple, just to make it less unwieldy and obscure.
-- The 'LogType' is also tracked, in case formatting depends on it.
data Logger = Logger
  { loggerLog :: forall a. FL.ToLogStr a => a -> IO ()
  , loggerClose :: IO () 
  , loggerType :: FL.LogType
  }

-- | Create a logger based on a 'KeterConfig'.
-- If log rotation is enabled in the config, this will return a rotating file logger;
-- and a stderr logger otherwise.
createLoggerViaConfig :: KeterConfig
                      -> String -- ^ Log file name
                      -> IO Logger
createLoggerViaConfig KeterConfig{..} name = do
  let logFile = kconfigDir </> "log" </> name <.> "log"
  let logType =
       if kconfigRotateLogs
         then FL.LogFile (defaultRotationSpec logFile) defaultBufferSize
         else FL.LogStderr defaultBufferSize
  liftIO $ createDirectoryIfMissing True (takeDirectory logFile)
  mkLogger logType <$> FL.newFastLogger logType
  where
    mkLogger logType (logFn, closeFn) = Logger (logFn . FL.toLogStr) closeFn logType

defaultRotationSpec :: FilePath -> FL.FileLogSpec
defaultRotationSpec dir =
    FL.FileLogSpec
      { log_file = dir
      , log_file_size = defaultMaxTotal
      , log_backup_number = 20
      }

-- | The default total file size before for a log file before it needs to be rotated
defaultMaxTotal :: Integer
defaultMaxTotal = 5 * 1024 * 1024 -- 5 MB

-- | The default log message buffer size
defaultBufferSize :: Int
defaultBufferSize = 256 -- 256 bytes, TODO: Reasonable value?