packages feed

fast-logger 2.4.11 → 2.4.12

raw patch · 7 files changed

+143/−102 lines, 7 filesdep +unix-compatdep −Win32dep −old-localedep −timedep ~unix-timePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: unix-compat

Dependencies removed: Win32, old-locale, time, unix

Dependency ranges changed: unix-time

API changes (from Hackage documentation)

- System.Log.FastLogger.Date: type FormattedTime = ByteString
- System.Log.FastLogger.Date: type TimeFormat = ByteString
+ System.Log.FastLogger: LogFileTimedRotate :: TimedFileLogSpec -> BufSize -> LogType
+ System.Log.FastLogger.File: TimedFileLogSpec :: FilePath -> TimeFormat -> (FormattedTime -> FormattedTime -> Bool) -> (FilePath -> IO ()) -> TimedFileLogSpec
+ System.Log.FastLogger.File: [timed_log_file] :: TimedFileLogSpec -> FilePath
+ System.Log.FastLogger.File: [timed_post_process] :: TimedFileLogSpec -> FilePath -> IO ()
+ System.Log.FastLogger.File: [timed_same_timeframe] :: TimedFileLogSpec -> FormattedTime -> FormattedTime -> Bool
+ System.Log.FastLogger.File: [timed_timefmt] :: TimedFileLogSpec -> TimeFormat
+ System.Log.FastLogger.File: data TimedFileLogSpec
+ System.Log.FastLogger.File: prefixTime :: FormattedTime -> FilePath -> FilePath
+ System.Log.FastLogger.Types: type FormattedTime = ByteString
+ System.Log.FastLogger.Types: type TimeFormat = ByteString
- System.Log.FastLogger: LogCallback :: (LogStr -> IO ()) -> (IO ()) -> LogType
+ System.Log.FastLogger: LogCallback :: (LogStr -> IO ()) -> IO () -> LogType

Files

System/Log/FastLogger.hs view
@@ -43,6 +43,8 @@   , module System.Log.FastLogger.Date   -- * File rotation   , module System.Log.FastLogger.File+  -- * Types+  , module System.Log.FastLogger.Types   ) where  #if __GLASGOW_HASKELL__ < 709@@ -53,6 +55,7 @@ import Control.Exception (handle, SomeException(..), bracket) import Control.Monad (when, replicateM) import Data.Array (Array, listArray, (!), bounds)+import Data.Foldable (forM_) import Data.Maybe (isJust) import System.EasyFile (getFileSize) import System.Log.FastLogger.File@@ -62,6 +65,7 @@ import System.Log.FastLogger.LogStr import System.Log.FastLogger.Logger import System.Log.FastLogger.Date+import System.Log.FastLogger.Types  ---------------------------------------------------------------- @@ -175,6 +179,15 @@ type FastLogger = LogStr -> IO () -- | 'TimedFastLogger' pass 'FormattedTime' to callback and simply log its result. -- this can be used to customize how to log timestamp.+-- +-- Usually, one would write a wrapper on top of 'TimedFastLogger', for example:+--+-- @+-- {-# LANGUAGE OverloadedStrings #-}+--+-- log :: TimedFastLogger -> LogStr -> IO ()+-- log logger msg = logger (\time -> toLogStr (show time) <> " " <> msg <> "\n")+-- @ type TimedFastLogger = (FormattedTime -> LogStr) -> IO ()  -- | Logger Type.@@ -194,6 +207,11 @@                                   --   'BufSize' is a buffer size                                   --   for each capability.                                   --   File rotation is done on-demand.+    | LogFileTimedRotate TimedFileLogSpec BufSize -- ^ Logging to a file.+                                  --   'BufSize' is a buffer size+                                  --   for each capability.+                                  --   Rotation happens based on check specified+                                  --   in 'TimedFileLogSpec'.     | LogCallback (LogStr -> IO ()) (IO ()) -- ^ Logging with a log and flush action.                                                -- run flush after log each message. @@ -201,12 +219,13 @@ -- a tuple of logger and clean up action are returned. newFastLogger :: LogType -> IO (FastLogger, IO ()) newFastLogger typ = case typ of-    LogNone                  -> return (const noOp, noOp)-    LogStdout bsize          -> newStdoutLoggerSet bsize >>= stdLoggerInit-    LogStderr bsize          -> newStderrLoggerSet bsize >>= stdLoggerInit-    LogFileNoRotate fp bsize -> newFileLoggerSet bsize fp >>= fileLoggerInit-    LogFile fspec bsize      -> rotateLoggerInit fspec bsize-    LogCallback cb flush     -> return (\str -> cb str >> flush, noOp)+    LogNone                        -> return (const noOp, noOp)+    LogStdout bsize                -> newStdoutLoggerSet bsize >>= stdLoggerInit+    LogStderr bsize                -> newStderrLoggerSet bsize >>= stdLoggerInit+    LogFileNoRotate fp bsize       -> newFileLoggerSet bsize fp >>= fileLoggerInit+    LogFile fspec bsize            -> rotateLoggerInit fspec bsize+    LogFileTimedRotate fspec bsize -> timedRotateLoggerInit fspec bsize+    LogCallback cb flush           -> return (\str -> cb str >> flush, noOp)   where     stdLoggerInit lgrset = return (pushLogStr lgrset, rmLoggerSet lgrset)     fileLoggerInit lgrset = return (pushLogStr lgrset, rmLoggerSet lgrset)@@ -219,6 +238,18 @@                 pushLogStr lgrset str                 when (cnt <= 0) $ tryRotate lgrset fspec ref mvar         return (logger, rmLoggerSet lgrset)+    timedRotateLoggerInit fspec bsize = do+        cache <- newTimeCache $ timed_timefmt fspec+        now <- cache+        lgrset <- newFileLoggerSet bsize $ prefixTime now $ timed_log_file fspec+        ref <- newIORef now+        mvar <- newMVar lgrset+        let logger str = do+                ct <- cache+                updated <- updateTime (timed_same_timeframe fspec) ref ct+                when updated $ tryTimedRotate fspec ct mvar+                pushLogStr lgrset str+        return (logger, rmLoggerSet lgrset)  -- | 'bracket' version of 'newFastLogger' withFastLogger :: LogType -> (FastLogger -> IO a) -> IO a@@ -231,12 +262,13 @@                         -- "System.Log.FastLogger.Date" provide cached formatted time.     -> LogType -> IO (TimedFastLogger, IO ()) newTimedFastLogger tgetter typ = case typ of-    LogNone                  -> return (const noOp, noOp)-    LogStdout bsize          -> newStdoutLoggerSet bsize >>= stdLoggerInit-    LogStderr bsize          -> newStderrLoggerSet bsize >>= stdLoggerInit-    LogFileNoRotate fp bsize -> newFileLoggerSet bsize fp >>= fileLoggerInit-    LogFile fspec bsize      -> rotateLoggerInit fspec bsize-    LogCallback cb flush     -> return (\f -> tgetter >>= cb . f >> flush, noOp)+    LogNone                        -> return (const noOp, noOp)+    LogStdout bsize                -> newStdoutLoggerSet bsize >>= stdLoggerInit+    LogStderr bsize                -> newStderrLoggerSet bsize >>= stdLoggerInit+    LogFileNoRotate fp bsize       -> newFileLoggerSet bsize fp >>= fileLoggerInit+    LogFile fspec bsize            -> rotateLoggerInit fspec bsize+    LogFileTimedRotate fspec bsize -> timedRotateLoggerInit fspec bsize+    LogCallback cb flush           -> return (\f -> tgetter >>= cb . f >> flush, noOp)   where     stdLoggerInit lgrset = return ( \f -> tgetter >>= pushLogStr lgrset . f, rmLoggerSet lgrset)     fileLoggerInit lgrset = return (\f -> tgetter >>= pushLogStr lgrset . f, rmLoggerSet lgrset)@@ -250,6 +282,19 @@                 pushLogStr lgrset (f t)                 when (cnt <= 0) $ tryRotate lgrset fspec ref mvar         return (logger, rmLoggerSet lgrset)+    timedRotateLoggerInit fspec bsize = do+        cache <- newTimeCache $ timed_timefmt fspec+        now <- cache+        lgrset <- newFileLoggerSet bsize $ prefixTime now $ timed_log_file fspec+        ref <- newIORef now+        mvar <- newMVar lgrset+        let logger f = do+                ct <- cache+                updated <- updateTime (timed_same_timeframe fspec) ref ct+                when updated $ tryTimedRotate fspec ct mvar+                t <- tgetter+                pushLogStr lgrset (f t)+        return (logger, rmLoggerSet lgrset)  -- | 'bracket' version of 'newTimeFastLogger' withTimedFastLogger :: IO FormattedTime -> LogType -> (TimedFastLogger -> IO a) -> IO a@@ -263,6 +308,10 @@ decrease :: IORef Int -> IO Int decrease ref = atomicModifyIORef' ref (\x -> (x - 1, x - 1)) +-- updateTime returns whether the timeframe has changed+updateTime :: (FormattedTime -> FormattedTime -> Bool) -> IORef FormattedTime -> FormattedTime -> IO Bool+updateTime cmp ref newTime = atomicModifyIORef' ref (\x -> (newTime, not $ cmp x newTime))+ tryRotate :: LoggerSet -> FileLogSpec -> IORef Int -> MVar () -> IO () tryRotate lgrset spec ref mvar = bracket lock unlock rotateFiles   where@@ -292,3 +341,17 @@         Just . fromIntegral <$> getFileSize file     -- 200 is an ad-hoc value for the length of log line.     estimate x = fromInteger (x `div` 200)+++tryTimedRotate :: TimedFileLogSpec -> FormattedTime -> MVar LoggerSet -> IO ()+tryTimedRotate spec now mvar = bracket lock unlock rotateFiles+  where+    lock           = tryTakeMVar mvar+    unlock Nothing = return ()+    unlock (Just (LoggerSet current_path a b c)) = do+        putMVar mvar $ LoggerSet (Just new_file_path) a b c+        forM_ current_path (timed_post_process spec)+    rotateFiles Nothing  = return ()+    rotateFiles (Just (LoggerSet _ a b c)) = renewLoggerSet $ LoggerSet (Just new_file_path) a b c+    new_file_path = prefixTime now $ timed_log_file spec+
System/Log/FastLogger/Date.hs view
@@ -4,56 +4,27 @@ -- | -- Formatting time is slow. -- This package provides mechanisms to cache formatted date.-module System.Log.FastLogger.Date (-  -- * Types-    TimeFormat-  , FormattedTime-  -- * Date cacher-  , newTimeCache+module System.Log.FastLogger.Date+  ( -- * Date cacher+    newTimeCache   , simpleTimeFormat   , simpleTimeFormat'   ) where  import Control.AutoUpdate (mkAutoUpdate, defaultUpdateSettings, updateAction)-import Data.ByteString (ByteString)-#if WINDOWS-import qualified Data.ByteString.Char8 as BS-import Data.Time (UTCTime, formatTime, getCurrentTime, utcToLocalZonedTime)-# if MIN_VERSION_time(1,5,0)-import Data.Time (defaultTimeLocale)-# else-import System.Locale (defaultTimeLocale)-# endif-#else+import System.Log.FastLogger.Types (TimeFormat, FormattedTime) import Data.UnixTime (formatUnixTime, fromEpochTime)-import System.Posix (EpochTime, epochTime)-#endif---------------------------------------------------------------------- | Type aliaes for date format and formatted date.-type FormattedTime = ByteString-type TimeFormat = ByteString+import System.PosixCompat.Types (EpochTime)+import System.PosixCompat.Time (epochTime)  ---------------------------------------------------------------- -#if WINDOWS--- | Get date using UTC.-getTime :: IO UTCTime-getTime = getCurrentTime--- | Format UTC date.-formatDate :: TimeFormat -> UTCTime -> IO FormattedTime-formatDate fmt ut = do-  zt <- utcToLocalZonedTime ut-  return $ BS.pack $ formatTime defaultTimeLocale (BS.unpack fmt) zt-#else -- | Get date using UnixTime. getTime :: IO EpochTime getTime = epochTime -- | Format unix EpochTime date. formatDate :: TimeFormat -> EpochTime -> IO FormattedTime formatDate fmt = formatUnixTime fmt . fromEpochTime-#endif  ---------------------------------------------------------------- 
System/Log/FastLogger/File.hs view
@@ -1,10 +1,18 @@ {-# LANGUAGE Safe #-} -module System.Log.FastLogger.File where+module System.Log.FastLogger.File+    ( FileLogSpec(..)+    , TimedFileLogSpec (..)+    , check+    , rotate+    , prefixTime+    ) where  import Control.Monad (unless, when)+import Data.ByteString.Char8 (unpack) import System.Directory (doesFileExist, doesDirectoryExist, getPermissions, writable, renameFile)-import System.FilePath (takeDirectory)+import System.FilePath (takeDirectory, dropFileName, takeFileName, (</>))+import System.Log.FastLogger.Types (TimeFormat, FormattedTime)  -- | The spec for logging files data FileLogSpec = FileLogSpec {@@ -13,6 +21,31 @@   , log_backup_number :: Int -- ^ Max number of rotated log files to keep around before overwriting the oldest one.   } +-- | The spec for time based rotation. It supports post processing of log files. Does+-- not delete any logs. Example:+--+-- @+-- timeRotate fname = LogFileTimedRotate+--                (TimedFileLogSpec fname timeFormat sametime compressFile)+--                defaultBufSize+--    where+--        timeFormat = "%FT%H%M%S"+--        sametime = (==) `on` C8.takeWhile (/='T')+--        compressFile fp = void . forkIO $+--            callProcess "tar" [ "--remove-files", "-caf", fp <> ".gz", fp ]+-- @+data TimedFileLogSpec = TimedFileLogSpec {+    timed_log_file :: FilePath              -- ^ base file path+  , timed_timefmt  :: TimeFormat            -- ^ time format to prepend+  , timed_same_timeframe  :: FormattedTime -> FormattedTime -> Bool+                                            -- ^ function that compares two+                                            --   formatted times as specified by+                                            --   timed_timefmt and decides if a+                                            --   new rotation is supposed to+                                            --   begin+  , timed_post_process :: FilePath -> IO () -- ^ processing function called asynchronously after a file is added to the rotation+  }+ -- | Checking if a log file can be written. check :: FilePath -> IO () check file = do@@ -40,3 +73,7 @@     move (src,dst) = do         exist <- doesFileExist src         when exist $ renameFile src dst++-- | Prefix file name with formatted time+prefixTime :: FormattedTime -> FilePath -> FilePath+prefixTime time path = dropFileName path </> unpack time ++ "-" ++ takeFileName path
System/Log/FastLogger/FileIO.hs view
@@ -1,49 +1,10 @@-{-# LANGUAGE CPP #-}- module System.Log.FastLogger.FileIO where -import Foreign.Ptr (Ptr) import Data.Word (Word8)--#ifdef mingw32_HOST_OS-import System.Win32.Types (HANDLE, UINT)-import System.Win32.File-import Graphics.Win32.Misc (getStdHandle, sTD_OUTPUT_HANDLE, sTD_ERROR_HANDLE)-import Data.Bits ((.|.))--type FD = HANDLE-#if !MIN_VERSION_Win32(2,4,0)--- This flag is not defined in System.Win32.File-fILE_APPEND_DATA :: UINT-fILE_APPEND_DATA = 0x0004-#endif--closeFD :: FD -> IO ()-closeFD = closeHandle--openFileFD :: FilePath -> IO FD-openFileFD f = createFile f-                         fILE_APPEND_DATA-                         (fILE_SHARE_READ .|. fILE_SHARE_DELETE)-                         Nothing-                         oPEN_ALWAYS-                         fILE_ATTRIBUTE_NORMAL-                         Nothing--getStderrFD :: IO FD-getStderrFD = getStdHandle sTD_ERROR_HANDLE--getStdoutFD :: IO FD-getStdoutFD = getStdHandle sTD_OUTPUT_HANDLE--writeRawBufferPtr2FD :: FD -> Ptr Word8 -> Int -> IO Int-writeRawBufferPtr2FD h bf len = fromIntegral `fmap` win32_WriteFile h bf (fromIntegral len) Nothing--#else-+import Foreign.Ptr (Ptr) import GHC.IO.Device (close)-import qualified GHC.IO.FD as POSIX (FD(..)) import GHC.IO.FD (openFile, stderr, stdout,  writeRawBufferPtr)+import qualified GHC.IO.FD as POSIX (FD(..)) import GHC.IO.IOMode (IOMode(..))  type FD = POSIX.FD@@ -62,5 +23,3 @@  writeRawBufferPtr2FD :: FD -> Ptr Word8 -> Int -> IO Int writeRawBufferPtr2FD fd bf len = fromIntegral `fmap` writeRawBufferPtr "write" fd bf 0 (fromIntegral len)--#endif
System/Log/FastLogger/LogStr.hs view
@@ -76,6 +76,8 @@     toLogStr bs = LogStr (BS.length bs) (toBuilder bs) instance ToLogStr BL.ByteString where     toLogStr = toLogStr . S8.concat . BL.toChunks+instance ToLogStr Builder where+    toLogStr x = let b = B.toLazyByteString x in LogStr (fromIntegral (BL.length b)) (B.lazyByteString b) instance ToLogStr String where     toLogStr = toLogStr . TL.pack instance ToLogStr T.Text where
+ System/Log/FastLogger/Types.hs view
@@ -0,0 +1,13 @@+module System.Log.FastLogger.Types (+  -- * Types+    TimeFormat+  , FormattedTime+  ) where++import Data.ByteString (ByteString)++----------------------------------------------------------------+  +-- | Type aliaes for date format and formatted date.+type FormattedTime = ByteString+type TimeFormat = ByteString
fast-logger.cabal view
@@ -1,5 +1,5 @@ Name:                   fast-logger-Version:                2.4.11+Version:                2.4.12 Author:                 Kazu Yamamoto <kazu@iij.ad.jp> Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp> License:                BSD3@@ -10,13 +10,15 @@ Category:               System Cabal-Version:          >= 1.8 Build-Type:             Simple-extra-source-files:     README.md ChangeLog.md+Extra-Source-Files:     README.md ChangeLog.md+Tested-With:            GHC ==7.8.4 || ==7.10.3 || ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.3  Library   GHC-Options:          -Wall   Exposed-Modules:      System.Log.FastLogger                         System.Log.FastLogger.File                         System.Log.FastLogger.Date+                        System.Log.FastLogger.Types   Other-Modules:        System.Log.FastLogger.IO                         System.Log.FastLogger.FileIO                         System.Log.FastLogger.IORef@@ -30,16 +32,10 @@                       , directory                       , filepath                       , text+                      , unix-time >= 0.4.3+                      , unix-compat   if impl(ghc < 7.8)       Build-Depends:    bytestring-builder-  if os(windows)-      Cpp-Options:      -DWINDOWS-      Build-Depends:    time-                      , Win32-                      , old-locale-  else-      Build-Depends:    unix-                      , unix-time >= 0.2.2  Test-Suite spec     Main-Is:         Spec.hs