monad-metrics 0.2.0.0 → 0.2.1.0
raw patch · 4 files changed
+104/−56 lines, 4 filesdep +exceptionsdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: exceptions
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Control.Monad.Metrics: timedList :: (MonadIO m, MonadMetrics m, MonadMask m) => Resolution -> [Text] -> m a -> m a
- Control.Monad.Metrics: timed :: (MonadIO m, MonadMetrics m) => Text -> m a -> m a
+ Control.Monad.Metrics: timed :: (MonadIO m, MonadMetrics m, MonadMask m) => Text -> m a -> m a
- Control.Monad.Metrics: timed' :: (MonadIO m, MonadMetrics m) => Resolution -> Text -> m a -> m a
+ Control.Monad.Metrics: timed' :: (MonadIO m, MonadMetrics m, MonadMask m) => Resolution -> Text -> m a -> m a
Files
- CHANGELOG.md +20/−0
- monad-metrics.cabal +47/−39
- src/Control/Monad/Metrics.hs +32/−12
- src/Control/Monad/Metrics/Internal.hs +5/−5
+ CHANGELOG.md view
@@ -0,0 +1,20 @@+# Change Log++## Upcoming...++- Introduced `timedList` method, to store the same distribution data under several names at once.++## v0.2.0.0 ++- Make `timed` and `timed'` require a `MonadMask` constraint for bracketing.+- [#7](https://github.com/sellerlabs/monad-metrics/pull/7) Switch `Map` to `HashMap`; [~4x faster to look up](https://github.com/sellerlabs/monad-metrics/pull/8)+- Fix a potential race condition when registering new metrics.++## v0.1.0.2++Fix bug where timed metrics are reported in the negatives.++## ~~v0.1.0.0~~ v0.1.0.1++Initial Release+
monad-metrics.cabal view
@@ -1,42 +1,50 @@-name: monad-metrics-version: 0.2.0.0-synopsis: A convenient wrapper around EKG metrics-description: A convenient wrapper for collecting application metrics. Please see the README.md for more information.-homepage: https://github.com/sellerlabs/monad-metrics#readme-license: MIT-license-file: LICENSE-author: Matthew Parsons-maintainer: matt@sellerlabs.com-copyright: 2017 Seller Labs, 2016 Taylor Fausak-category: Web-build-type: Simple-extra-source-files: README.md-cabal-version: >=1.10+name: monad-metrics+version: 0.2.1.0+cabal-version: >=1.10+build-type: Simple+license: MIT+license-file: LICENSE+copyright: 2017 Seller Labs, 2016 Taylor Fausak+maintainer: matt@sellerlabs.com+homepage: https://github.com/sellerlabs/monad-metrics#readme+synopsis: A convenient wrapper around EKG metrics+description:+ A convenient wrapper for collecting application metrics. Please see the README.md for more information.+category: Web+author: Matthew Parsons+extra-source-files:+ README.md+ CHANGELOG.md -library- hs-source-dirs: src- exposed-modules: Control.Monad.Metrics- , Control.Monad.Metrics.Internal- build-depends: base >= 4.7 && < 5- , clock >= 0.3 && < 0.8- , ekg-core >= 0.1.0.1 && < 0.2- , hashable >= 1.2 && < 1.3- , text < 1.3- , mtl >= 2 && < 2.3- , transformers >= 0.3 && < 0.6- , unordered-containers >= 0.2 && < 0.3- , microlens >= 0.2 && < 0.5- default-language: Haskell2010+source-repository head+ type: git+ location: https://github.com/sellerlabs/monad-metrics -test-suite monad-metrics-test- type: exitcode-stdio-1.0- hs-source-dirs: test- main-is: Spec.hs- build-depends: base >= 4.6 && <= 5.0- , monad-metrics- ghc-options: -threaded -rtsopts -with-rtsopts=-N- default-language: Haskell2010+library+ exposed-modules:+ Control.Monad.Metrics+ Control.Monad.Metrics.Internal+ build-depends:+ base >=4.8 && <5,+ clock >=0.3 && <0.8,+ ekg-core >=0.1.0.1 && <0.2,+ exceptions >=0.6 && <0.9,+ hashable ==1.2.*,+ microlens >=0.2 && <0.5,+ mtl >=2 && <2.3,+ text <1.3,+ transformers >=0.3 && <0.6,+ unordered-containers ==0.2.*+ default-language: Haskell2010+ hs-source-dirs: src+ ghc-options: -Wall -source-repository head- type: git- location: https://github.com/sellerlabs/monad-metrics+test-suite monad-metrics-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ build-depends:+ base >=4.8 && <=5.0,+ monad-metrics -any+ default-language: Haskell2010+ hs-source-dirs: test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N
src/Control/Monad/Metrics.hs view
@@ -39,6 +39,7 @@ , distribution , timed , timed'+ , timedList , label , label' , Resolution(..)@@ -51,7 +52,8 @@ , metricsStore ) where -import Control.Monad (liftM)+import Control.Monad (liftM, forM_)+import Control.Monad.Catch (MonadMask, bracket) import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Reader (MonadReader (..), ReaderT (..)) import Control.Monad.Trans (MonadTrans (..))@@ -63,8 +65,7 @@ import Data.Monoid (mempty) import Data.Text (Text) import qualified Data.Text as Text-import System.Clock (Clock (..), TimeSpec (..),- getTime)+import System.Clock (Clock (..), getTime) import System.IO.Unsafe (unsafeInterleaveIO) import qualified System.Metrics as EKG import System.Metrics.Counter as Counter@@ -203,23 +204,42 @@ gauge = gauge' -- | Record the time taken to perform the named action. The number is--- stored in a 'System.Metrics.Disribution.Distribution' and is converted+-- stored in a 'System.Metrics.Distribution.Distribution' and is converted -- to the specified 'Resolution'. -- -- * /Since v0.1.0.0/-timed' :: (MonadIO m, MonadMetrics m) => Resolution -> Text -> m a -> m a-timed' resolution name action = do- start <- liftIO $ getTime Monotonic- result <- action- end <- liftIO $ getTime Monotonic- distribution name (diffTime resolution end start)- return result+timed' :: (MonadIO m, MonadMetrics m, MonadMask m) => Resolution -> Text -> m a -> m a+timed' resolution name action = timedList resolution [name] action +-- | Record the time taken to perform the action, under several names at once.+-- The number is stored in a 'System.Metrics.Distribution.Distribution' and is+-- converted to the specified 'Resolution'.+--+-- This is useful to store the same durations data sectioned by different criteria, e.g.:+--+-- @+-- timedList Seconds ["request.byUser." <> userName, "request.byType." <> requestType] $ do+-- ...+-- @+--+-- So you will have @"request.byUser.someuser"@ storing duration distribution for requests+-- of user @"someuser"@ of any type; and @"request.byType.sometype"@ storing+-- duration distribution for requests of type @"sometype"@ from any user.+--+timedList :: (MonadIO m, MonadMetrics m, MonadMask m) => Resolution -> [Text] -> m a -> m a+timedList resolution names action = + bracket (liftIO (getTime Monotonic)) finish (const action)+ where+ finish start = do+ end <- liftIO (getTime Monotonic)+ forM_ names $ \name ->+ distribution name (diffTime resolution end start)+ -- | Record the time of executing the given action in seconds. Defers to -- 'timed''. -- -- * /Since v0.1.0.0/-timed :: (MonadIO m, MonadMetrics m) => Text -> m a -> m a+timed :: (MonadIO m, MonadMetrics m, MonadMask m) => Text -> m a -> m a timed = timed' Seconds -- | Set the 'Label' to the given 'Text' value.
src/Control/Monad/Metrics/Internal.hs view
@@ -14,10 +14,10 @@ -} module Control.Monad.Metrics.Internal where -import Data.IORef import Data.HashMap.Strict (HashMap)+import Data.IORef import Data.Text (Text)-import Lens.Micro+import Lens.Micro (Lens') import System.Clock (TimeSpec (..)) import System.Metrics (Store) import System.Metrics.Counter (Counter)@@ -82,9 +82,9 @@ diffTime :: Resolution -> TimeSpec -> TimeSpec -> Double diffTime res (TimeSpec seca nseca) (TimeSpec secb nsecb) =- let secs = seca - secb- nsecs = nseca - nsecb- in convertTimeSpecTo res (TimeSpec secs nsecs)+ let sec' = seca - secb+ nsec' = nseca - nsecb+ in convertTimeSpecTo res (TimeSpec sec' nsec') convertTimeSpecTo :: Resolution -> TimeSpec -> Double convertTimeSpecTo res (TimeSpec secs' nsecs') =