log-base 0.7.1 → 0.7.1.1
raw patch · 6 files changed
+58/−24 lines, 6 files
Files
- CHANGELOG.md +10/−0
- README.md +6/−0
- log-base.cabal +3/−2
- src/Log.hs +1/−1
- src/Log/Data.hs +1/−1
- src/Log/Logger.hs +37/−20
+ CHANGELOG.md view
@@ -0,0 +1,10 @@+# log-base-0.7.2 (2017-06-19)+* mkBulkLogger now uses a bounded queue to interact with the logger thread.++# log-base-0.7.1 (2017-03-16)+* Added a few MTL class instances (#28).++# log-base-0.7 (2016-11-25)+* Initial release (split from the log package).+* Improved documentation (#22).+* Implement 'toEncoding' directly in 'ToJSON' instances (#21).
+ README.md view
@@ -0,0 +1,6 @@+# log-base [](https://hackage.haskell.org/package/log-base) [](http://travis-ci.org/scrive/log)++Base package for the `log` library. Includes only the standard output+back end. Use this package in conjunction with `log-elasticsearch` or+`log-postgres`, depending on which back end you need. Use the `log`+library if you need all back ends.
log-base.cabal view
@@ -1,5 +1,5 @@ name: log-base-version: 0.7.1+version: 0.7.1.1 synopsis: Structured logging solution (base package) description: A library that provides a way to record structured log@@ -21,7 +21,8 @@ category: System build-type: Simple cabal-version: >=1.10-tested-with: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1+extra-source-files: CHANGELOG.md, README.md+tested-with: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2 Source-repository head Type: git
src/Log.hs view
@@ -27,7 +27,7 @@ module Log.Class -- | 'Log.Data.LogMessage' and 'Log.Data.LogLevel' data definitions. , module Log.Data- -- | 'Log.Logger.Logger' objects used to perform logging operations in ''Log.Monad.LogT'.+ -- | 'Log.Logger.Logger' objects used to perform logging operations in 'Log.Monad.LogT'. , module Log.Logger -- | 'Log.Monad.LogT' monad transformer that adds logging capabilities to -- the underlying monad.
src/Log/Data.hs view
@@ -55,7 +55,7 @@ data LogMessage = LogMessage { -- | Component of an application. lmComponent :: !T.Text- -- | Aplication log domain.+ -- | Application log domain. , lmDomain :: ![T.Text] -- | Time of the logged event. , lmTime :: !UTCTime
src/Log/Logger.hs view
@@ -28,11 +28,12 @@ name exec (return ()) -- | Start an asynchronous logger thread that consumes all queued--- messages once per second. To make sure that the messages get--- written out in the presence of exceptions, use high-level wrappers--- like 'withLogger', 'Log.Backend.ElasticSearch.withElasticSearchLogger' or--- 'Log.Backend.StandardOutput.Bulk.withBulkStdOutLogger'--- instead of this function directly.+-- messages once per second. Uses a bounded queue internally to avoid+-- space leaks. To make sure that the messages get written out in the+-- presence of exceptions, use high-level wrappers like 'withLogger',+-- 'Log.Backend.ElasticSearch.withElasticSearchLogger' or+-- 'Log.Backend.StandardOutput.Bulk.withBulkStdOutLogger' instead of+-- this function directly. -- -- Note: some messages can be lost when the main thread shuts down -- without making sure that all logger threads have written out all@@ -76,32 +77,48 @@ -- @ mkBulkLogger :: T.Text -> ([LogMessage] -> IO ()) -> IO () -> IO Logger mkBulkLogger = mkLoggerImpl- newSQueueIO isEmptySQueue readSQueue writeSQueue (threadDelay 1000000)+ (newSBQueueIO sbDefaultCapacity) isEmptySBQueue readSBQueue writeSBQueue+ (threadDelay 1000000) ---------------------------------------- --- | A simple STM based queue.-newtype SQueue a = SQueue (TVar [a])+-- | A simple STM based bounded queue.+data SBQueue a = SBQueue !(TVar [a]) !(TVar Int) !Int --- | Create an instance of 'SQueue'.-newSQueueIO :: IO (SQueue a)-newSQueueIO = SQueue <$> newTVarIO []+-- | Default capacity of a 'SBQueue'. This corresponds to+-- approximately 200 MiB memory residency when the queue is full.+sbDefaultCapacity :: Int+sbDefaultCapacity = 1000000 --- | Check if an 'SQueue' is empty.-isEmptySQueue :: SQueue a -> STM Bool-isEmptySQueue (SQueue queue) = null <$> readTVar queue+-- | Create an instance of 'SBQueue' with a given capacity.+newSBQueueIO :: Int -> IO (SBQueue a)+newSBQueueIO capacity = SBQueue <$> newTVarIO [] <*> newTVarIO 0 <*> pure capacity --- | Read all the values stored in an 'SQueue'.-readSQueue :: SQueue a -> STM [a]-readSQueue (SQueue queue) = do+-- | Check if an 'SBQueue' is empty.+isEmptySBQueue :: SBQueue a -> STM Bool+isEmptySBQueue (SBQueue queue count _capacity) = do+ isEmpty <- null <$> readTVar queue+ numElems <- readTVar count+ assert (if isEmpty then numElems == 0 else numElems > 0) $+ return isEmpty++-- | Read all the values stored in an 'SBQueue'.+readSBQueue :: SBQueue a -> STM [a]+readSBQueue (SBQueue queue count _capacity) = do elems <- readTVar queue when (null elems) retry writeTVar queue []+ writeTVar count 0 return $ reverse elems --- | Write a value to an 'SQueue'.-writeSQueue :: SQueue a -> a -> STM ()-writeSQueue (SQueue queue) a = modifyTVar queue (a :)+-- | Write a value to an 'SBQueue'.+writeSBQueue :: SBQueue a -> a -> STM ()+writeSBQueue (SBQueue queue count capacity) a = do+ numElems <- readTVar count+ if numElems < capacity+ then do modifyTVar queue (a :)+ modifyTVar count (+1)+ else return () ----------------------------------------