monad-metrics-extensible

Please see the README on GitHub at https://github.com/0xd34df00d/monad-metrics-extensible#readme


Keywords
library, web, Propose Tags , Data.Dyn, System.Metrics.Extensible, System.Metrics.ExtraTrackers, System.Metrics.Monad, System.Metrics.Monad.Class, System.Metrics.Store, System.Metrics.TrackerInstances, ekg, gadt, haskell, metrics, monad, type-safety
License
BSD-3-Clause
Install
cabal install monad-metrics-extensible-0.1.1.0

Documentation

monad-metrics-extensible

Build Status Hackage Stackage LTS Stackage Nightly

tl;dr

This library simplifies using ekg in three ways:

  • It allows specifying metrics as constructors of a user-defined GADT carrying both the metric name (to avoid typos) and the metric kind (a counter, a distribution and so on — to avoid code duplication). Multiple GADTs in the same appplication are supported (hence "extensible").
  • It encapsulates managing all the necessary EKG objects on-demand via a monadic API.
  • It allows defining new kinds of metrics in the user code (hence "extensible" one more time). You want a combined distribution + counter? No prob!

System.Metrics.Extensible is your entry point of choice!

A quick example

First we enable a few extensions and import some packages:

{-# LANGUAGE DataKinds, GADTs, StandaloneDeriving #-}

import System.Metrics.Extensible
import System.Remote.Monitoring -- for ekg stuff

Then we define a type that represents the possible metrics in our application:

data SomeMetrics ty name where
  SomeCounter     :: SomeMetrics Counter "some_counter"
  AnotherCounter  :: SomeMetrics Counter "other_counter"
  SomeGauge       :: SomeMetrics Gauge   "some_gauge"

The string literals are what will be shown via ekg UI.

There is a couple of requirements:

  • The type shall be of the kind * -> Symbol -> *.
  • The first type argument (Counter and Gauge in the example above) shall be an instance of TrackerLike. All ekg counters are already instances of this class.
  • The type shall be comparable, hence we also do
    deriving instance Eq (SomeMetrics ty name)
    deriving instance Ord (SomeMetrics ty name)

Then we can write our small program!

main :: IO ()
main = do
  ekgServer <- forkServer "localhost" 8000
  withMetricsStore ekgServer $ \store -> flip runMetricsT store $ do
    track SomeCounter
    track SomeGauge 42
  • withMetricsStore creates the metrics store that's managed by this library and runs an IO computation with that store.
  • runMetricsT is what runs the monad transformer giving access to the metrics.
  • track is the function that's responsible for updating the metrics. Its arguments depend on the specific metric that's being tracked: for instance, as can be seen in the example above, Counters have no arguments, while Gauges accept the corresponding new value.