monad-metrics alternatives and similar packages
Based on the "monad" category.
Alternatively, view monad-metrics alternatives based on common mentions on social networks and blogs.
-
monad-validate
(NOTE: REPOSITORY MOVED TO NEW OWNER: https://github.com/lexi-lambda/monad-validate) A Haskell monad transformer library for data validation -
monad-control
Lift control operations, like exception catching, through monad transformers -
monad-time
Type class for monads which carry the notion of the current time. -
monad-unlift
Typeclasses for representing monad (transformer) morphisms -
monad-unlift-ref
Typeclasses for representing monad (transformer) morphisms -
monad-logger-prefix
Easily add a prefix to your MonadLogger output. -
monad-batcher
An applicative monad that batches commands for later more efficient execution -
monad-supply
Support for computations which consume values from a (possibly infinite) supply. -
monad-io-adapter
A Haskell package that adapts between MonadIO and MonadBase IO -
monad-task
Task monad transformer that turns event processing into co-routines programming. -
monad-resumption
Resumption and Reactive-Resumption Monads for the Haskell programming language. -
monad-loops-stm
STM-specific control operators (split out of monad-loops as of version 0.4) -
monad-introspect
A reader monad that gives the environment access to the entire transformer stack -
monad-open
Open-ended computation for when you need it (open recursion) -
monad-control-identity
Stronger classes than monad-control -
monad-peel
Lift control operations like exception catching through monad transformers -
monad-interleave
Monads with an unsaveInterleaveIO-like operation -
monad-control-aligned
Lift control operations, like exception catching, through monad transformers -
monad-finally
Guard monadic computations with cleanup actions
Updating dependencies is time-consuming.
Do you think we are missing an alternative of monad-metrics or a related project?
README
monad-metrics
This library defines a convenient wrapper and API for using EKG metrics in your application. It's heavily inspired by the metrics code that Taylor Fausak used in his Haskell application blunt.
Usage
This README is an executable literate Haskell file. If you have stack installed, then you can run the file with:
./README.lhs
We'll need to start with the import/pragma boilerplate:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
import qualified Control.Monad.Metrics as Metrics
import Control.Monad.Metrics (Metrics, Resolution(..), MonadMetrics(..))
import Control.Monad.Reader
import qualified System.Metrics as EKG
The Control.Monad.Metrics
module is designed to be imported qualified.
Initialize!
First, you need to initialize the Metrics
data type. You can do so using
initialize
(to create a new EKG store) or initializeWith
if you want to
pass a preexisting store.
initializing :: Bool -> EKG.Store -> IO Metrics
initializing True store = Metrics.initializeWith store
initializing False _ = Metrics.initialize
Embed!
The next step is to implement an instance of the class MonadMetrics
for your
monad transformer stack. This library has explicitly decided not to provide a
concrete monad transformer to reduce the dependency footprint. Fortunately,
it's pretty easy!
Suppose you've got the following stack:
type App = ReaderT Config IO
data Config = Config { configMetrics :: Metrics }
then you can easily get the required instance with:
instance MonadMetrics (ReaderT Config IO) where
getMetrics = asks configMetrics
Now, you're off to the races! Let's record some metrics.
If you're after a really simple embedding, you can use run
or run'
:
simple :: Int -> IO ()
simple i =
Metrics.run $ do
metrics <- Metrics.getMetrics
Metrics.gauge "Simple" i
forM_ [1..i] $ \_ -> do
Metrics.increment "Count!"
gettingThere :: IO ()
gettingThere =
Metrics.run' (\metrics -> Config metrics) $ do
liftIO $ putStrLn "it accepts a constructor"
Measure!
Once your application has the required instance, you can use EKG's metrics (counters, gauges, labels, distributions).
For detailed descriptions of the various metric types, see the corresponding EKG documentation:
Generally, the library provides "sane default" functions which accept the name of the metric to work with and the value to contribute to that metric.
w = Metrics.label "Foo" "Bar"
x = Metrics.counter "MetricName" 6
y = Metrics.distribution "Distribute" 3.4
z = Metrics.gauge "Gauge" 7
Generalized versions of these functions are available with an apostrophe. Labels accept any Show
able value, while gauges and counters accept any Integral
value.
a = Metrics.label' "List" [1,2,3]
b = Metrics.counter' "Count" (3 :: Integer)
Timers
You can time actions with timed
, which has a resolution of seconds. You can
use timed'
which accepts a Resolution
argument to provide a different
scale.
timedProcess :: App Int
timedProcess =
Metrics.timed "summing1" $ do
pure $! sum [1 .. 100000]
timedInMilliseconds :: App Int
timedInMilliseconds =
Metrics.timed' Microseconds "summing2" $ do
pure $! sum [1..100]
A demonstration
main :: IO ()
main = do
metrics <- Metrics.initialize
flip runReaderT (Config metrics) $ do
Metrics.label "ProgramName" "README"
forM_ [1..10] $ \_ -> do
Metrics.increment "up-to-ten"
Metrics.timed' Nanoseconds "Whatever" $ do
liftIO $ putStrLn "Hello World!"