Initial commit
commit
a08d3e6867
|
@ -0,0 +1,8 @@
|
||||||
|
/bower_components/
|
||||||
|
/node_modules/
|
||||||
|
/.pulp-cache/
|
||||||
|
/output/
|
||||||
|
/generated-docs/
|
||||||
|
/.psc*
|
||||||
|
/.purs*
|
||||||
|
/.psa*
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "purescript-metrics",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"output"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"purescript-prelude": "^3.1.1",
|
||||||
|
"purescript-console": "^3.0.0",
|
||||||
|
"purescript-aff": "^3.1.0",
|
||||||
|
"purescript-maybe": "^3.0.0",
|
||||||
|
"purescript-foreign-generic": "^5.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"purescript-psci-support": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,213 @@
|
||||||
|
module System.Metrics
|
||||||
|
( Store
|
||||||
|
, MetricSampler(..)
|
||||||
|
, Value(..)
|
||||||
|
, newStore
|
||||||
|
, register
|
||||||
|
, registerOrGet
|
||||||
|
, get
|
||||||
|
, registerCounter
|
||||||
|
, registerGauge
|
||||||
|
, registerHistogram
|
||||||
|
, registerMeter
|
||||||
|
, registerTimer
|
||||||
|
, createOrGetCounter
|
||||||
|
, createOrGetGuage
|
||||||
|
, createOrGetHistogramWithExponentialDecaySampling
|
||||||
|
, createOrGetHistogramWithUniformSampling
|
||||||
|
, createOrGetMeter
|
||||||
|
, createOrGetTimer
|
||||||
|
, sampleOne
|
||||||
|
, sample
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Monad.Aff (Aff)
|
||||||
|
import Control.Monad.Eff (Eff)
|
||||||
|
import Control.Monad.Eff.Class (liftEff)
|
||||||
|
import Control.Monad.Eff.Exception (EXCEPTION, throw)
|
||||||
|
import Control.Monad.Eff.Ref (REF, Ref, modifyRef', newRef, readRef)
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
|
import Data.Generic.Rep.Show (genericShow)
|
||||||
|
import Data.Map as Map
|
||||||
|
import Data.Maybe (Maybe(..))
|
||||||
|
import Data.Traversable (sequence)
|
||||||
|
import System.Metrics.Counter (Counter)
|
||||||
|
import System.Metrics.Counter as Counter
|
||||||
|
import System.Metrics.Gauge (Gauge)
|
||||||
|
import System.Metrics.Gauge as Gauge
|
||||||
|
import System.Metrics.Histogram (Histogram)
|
||||||
|
import System.Metrics.Histogram as Histogram
|
||||||
|
import System.Metrics.Meter (Meter)
|
||||||
|
import System.Metrics.Meter as Meter
|
||||||
|
import System.Metrics.Timer (Timer)
|
||||||
|
import System.Metrics.Timer as Timer
|
||||||
|
|
||||||
|
-- | A mutable metric store.
|
||||||
|
newtype Store = Store (Ref State)
|
||||||
|
|
||||||
|
-- | The 'Store' state.
|
||||||
|
type State = Map.Map String MetricSampler
|
||||||
|
|
||||||
|
data MetricSampler = CounterS Counter
|
||||||
|
| GaugeS Gauge
|
||||||
|
| HistogramS Histogram
|
||||||
|
| MeterS Meter
|
||||||
|
| TimerS Timer
|
||||||
|
|
||||||
|
-- | Create a new, empty metric store.
|
||||||
|
newStore ::forall eff. Eff (ref :: REF | eff) Store
|
||||||
|
newStore = do
|
||||||
|
ref <- newRef Map.empty
|
||||||
|
pure $ Store ref
|
||||||
|
|
||||||
|
register :: forall eff.
|
||||||
|
String -> MetricSampler -> Store -> Eff (ref :: REF | eff) Boolean
|
||||||
|
register name sampler (Store store) = modifyRef' store $ \state ->
|
||||||
|
case Map.lookup name state of
|
||||||
|
Just s -> { state : state, value : false }
|
||||||
|
Nothing -> { state : Map.insert name sampler state, value : true }
|
||||||
|
|
||||||
|
registerOrGet :: forall eff.
|
||||||
|
String -> MetricSampler -> Store -> Eff (ref :: REF | eff) MetricSampler
|
||||||
|
registerOrGet name sampler (Store store) = modifyRef' store $ \state ->
|
||||||
|
case Map.lookup name state of
|
||||||
|
Just s -> { state : state, value : s }
|
||||||
|
Nothing -> { state : Map.insert name sampler state, value : sampler }
|
||||||
|
|
||||||
|
get :: forall eff. String -> Store -> Eff (ref :: REF | eff) (Maybe MetricSampler)
|
||||||
|
get name (Store store) = readRef store >>= pure <<< Map.lookup name
|
||||||
|
|
||||||
|
-- | Register a non-negative, monotonically increasing, integer-valued metric.
|
||||||
|
-- |
|
||||||
|
-- | Also see 'createCounter'.
|
||||||
|
registerCounter :: forall eff.
|
||||||
|
String -> Counter -> Store -> Eff (ref :: REF | eff) Boolean
|
||||||
|
registerCounter name counter = register name (CounterS counter)
|
||||||
|
|
||||||
|
-- | Create and register a zero-initialized counter. Throw exception is the counter is already created.
|
||||||
|
createOrGetCounter :: forall eff.
|
||||||
|
String
|
||||||
|
-> Store
|
||||||
|
-> Eff (ref :: REF, exception :: EXCEPTION | eff) Counter
|
||||||
|
createOrGetCounter name store = do
|
||||||
|
counter <- Counter.new
|
||||||
|
registerOrGet name (CounterS counter) store >>= case _ of
|
||||||
|
CounterS c -> pure c
|
||||||
|
_ -> throw $ "Metric name is already registered: " <> name
|
||||||
|
|
||||||
|
-- | Register an integer-valued metric.
|
||||||
|
-- |
|
||||||
|
-- | Also see 'createGuage'.
|
||||||
|
registerGauge :: forall eff.
|
||||||
|
String -> Gauge -> Store -> Eff (ref :: REF | eff) Boolean
|
||||||
|
registerGauge name gauge = register name (GaugeS gauge)
|
||||||
|
|
||||||
|
-- | Create and register a guage. Throw exception is the guage is already created.
|
||||||
|
createOrGetGuage :: forall eff.
|
||||||
|
String
|
||||||
|
-> (forall e. Aff e Int)
|
||||||
|
-> Store
|
||||||
|
-> Eff (ref :: REF, exception :: EXCEPTION | eff) Gauge
|
||||||
|
createOrGetGuage name f store = do
|
||||||
|
let gauge = Gauge.new f
|
||||||
|
registerOrGet name (GaugeS gauge) store >>= case _ of
|
||||||
|
GaugeS g -> pure g
|
||||||
|
_ -> throw $ "Metric name is already registered: " <> name
|
||||||
|
|
||||||
|
registerHistogram :: forall eff.
|
||||||
|
String -> Histogram -> Store -> Eff (ref :: REF | eff) Boolean
|
||||||
|
registerHistogram name hist = register name (HistogramS hist)
|
||||||
|
|
||||||
|
createOrGetHistogramWithExponentialDecaySampling
|
||||||
|
:: forall eff.
|
||||||
|
String
|
||||||
|
-> Int
|
||||||
|
-> Number
|
||||||
|
-> Store
|
||||||
|
-> Eff (ref :: REF, exception :: EXCEPTION | eff) Histogram
|
||||||
|
createOrGetHistogramWithExponentialDecaySampling name size alpha store = do
|
||||||
|
hist <- Histogram.newWithExponentialDecaySampling size alpha
|
||||||
|
registerOrGet name (HistogramS hist) store >>= case _ of
|
||||||
|
HistogramS c -> pure c
|
||||||
|
_ -> throw $ "Metric name is already registered: " <> name
|
||||||
|
|
||||||
|
createOrGetHistogramWithUniformSampling
|
||||||
|
:: forall eff.
|
||||||
|
String
|
||||||
|
-> Int
|
||||||
|
-> Store
|
||||||
|
-> Eff (ref :: REF, exception :: EXCEPTION | eff) Histogram
|
||||||
|
createOrGetHistogramWithUniformSampling name size store = do
|
||||||
|
hist <- Histogram.newWithUniformSampling size
|
||||||
|
registerOrGet name (HistogramS hist) store >>= case _ of
|
||||||
|
HistogramS c -> pure c
|
||||||
|
_ -> throw $ "Metric name is already registered: " <> name
|
||||||
|
|
||||||
|
registerMeter :: forall eff. String -> Meter -> Store -> Eff (ref :: REF | eff) Boolean
|
||||||
|
registerMeter name meter = register name (MeterS meter)
|
||||||
|
|
||||||
|
createOrGetMeter
|
||||||
|
:: forall eff.
|
||||||
|
String
|
||||||
|
-> Store
|
||||||
|
-> Eff (ref :: REF, exception :: EXCEPTION | eff) Meter
|
||||||
|
createOrGetMeter name store = do
|
||||||
|
meter <- Meter.new
|
||||||
|
registerOrGet name (MeterS meter) store >>= case _ of
|
||||||
|
MeterS c -> pure c
|
||||||
|
_ -> throw $ "Metric name is already registered: " <> name
|
||||||
|
|
||||||
|
registerTimer :: forall eff. String -> Timer -> Store -> Eff (ref :: REF | eff) Boolean
|
||||||
|
registerTimer name timer = register name (TimerS timer)
|
||||||
|
|
||||||
|
createOrGetTimer
|
||||||
|
:: forall eff.
|
||||||
|
String
|
||||||
|
-> Store
|
||||||
|
-> Eff (ref :: REF, exception :: EXCEPTION | eff) Timer
|
||||||
|
createOrGetTimer name store = do
|
||||||
|
timer <- Timer.new
|
||||||
|
registerOrGet name (TimerS timer) store >>= case _ of
|
||||||
|
TimerS c -> pure c
|
||||||
|
_ -> throw $ "Metric name is already registered: " <> name
|
||||||
|
|
||||||
|
type Sample = Map.Map String Value
|
||||||
|
|
||||||
|
data Value = CounterV Int
|
||||||
|
| GaugeV Int
|
||||||
|
| HistogramV Histogram.Summary
|
||||||
|
| MeterV Meter.Summary
|
||||||
|
| TimerV Timer.Summary
|
||||||
|
|
||||||
|
derive instance eqVal :: Eq Value
|
||||||
|
derive instance genVal :: Generic Value _
|
||||||
|
instance showVal :: Show Value where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
sampleOne :: forall eff. MetricSampler -> Aff (ref :: REF | eff) Value
|
||||||
|
sampleOne (CounterS c) = CounterV <$> liftEff (Counter.read c)
|
||||||
|
sampleOne (GaugeS g) = GaugeV <$> Gauge.read g
|
||||||
|
sampleOne (HistogramS h) = HistogramV <$> liftEff (Histogram.read h)
|
||||||
|
sampleOne (MeterS h) = MeterV <$> liftEff (Meter.read h)
|
||||||
|
sampleOne (TimerS h) = TimerV <$> liftEff (Timer.read h)
|
||||||
|
|
||||||
|
sample :: forall eff. Store -> Aff (ref :: REF | eff) Sample
|
||||||
|
sample (Store store) = do
|
||||||
|
state <- liftEff $ readRef store
|
||||||
|
sequence $ map sampleOne state
|
||||||
|
|
||||||
|
-- main = do
|
||||||
|
-- store <- newStore
|
||||||
|
-- counter <- createOrGetCounter "testc" store
|
||||||
|
-- gauge <- createOrGetGuage "testg" (pure 3) store
|
||||||
|
-- hist <- createOrGetHistogramWithExponentialDecaySampling "hizz" 1028 0.015 store
|
||||||
|
-- meter <- createOrGetMeter "mmm" store
|
||||||
|
-- timer <- createOrGetTimer "ttt" store
|
||||||
|
-- Counter.inc counter 2
|
||||||
|
-- Histogram.update hist 1.2
|
||||||
|
-- Histogram.update hist 2.1
|
||||||
|
-- Meter.mark meter
|
||||||
|
-- Timer.update timer (Milliseconds 1000.0)
|
||||||
|
-- launchAff $ sample store >>= logShow
|
|
@ -0,0 +1,28 @@
|
||||||
|
var Counter = require("metrics/metrics/counter");
|
||||||
|
|
||||||
|
var _new = function() {
|
||||||
|
return new Counter();
|
||||||
|
};
|
||||||
|
|
||||||
|
var read = function(c) {
|
||||||
|
return function() {
|
||||||
|
return c.count;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var _inc = function(c, v) {
|
||||||
|
return function() {
|
||||||
|
c.inc(v);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var reset = function(c) {
|
||||||
|
return function() {
|
||||||
|
c.value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports._new = _new;
|
||||||
|
exports.read = read;
|
||||||
|
exports._inc = _inc;
|
||||||
|
exports.reset = reset;
|
|
@ -0,0 +1,18 @@
|
||||||
|
module System.Metrics.Counter (Counter, new, read, inc) where
|
||||||
|
|
||||||
|
import Control.Monad.Eff (Eff)
|
||||||
|
import Control.Monad.Eff.Ref (REF)
|
||||||
|
import Data.Function.Uncurried (Fn2, runFn2)
|
||||||
|
import Prelude (Unit)
|
||||||
|
|
||||||
|
foreign import data Counter :: Type
|
||||||
|
foreign import _new :: forall eff. Eff (ref :: REF | eff) Counter
|
||||||
|
foreign import read :: forall eff. Counter -> Eff (ref :: REF | eff) Int
|
||||||
|
foreign import reset :: forall eff. Counter -> Eff (ref :: REF | eff) Unit
|
||||||
|
foreign import _inc :: forall eff. Fn2 Counter Int (Eff (ref :: REF | eff) Unit)
|
||||||
|
|
||||||
|
new :: forall eff. Eff (ref :: REF | eff) Counter
|
||||||
|
new = _new
|
||||||
|
|
||||||
|
inc :: forall eff. Counter -> Int -> Eff (ref :: REF | eff) Unit
|
||||||
|
inc c = runFn2 _inc c
|
|
@ -0,0 +1,11 @@
|
||||||
|
module System.Metrics.Gauge (Gauge, new, read) where
|
||||||
|
|
||||||
|
import Control.Monad.Aff (Aff)
|
||||||
|
|
||||||
|
newtype Gauge = Gauge (forall eff. Aff eff Int)
|
||||||
|
|
||||||
|
new :: (forall eff. Aff eff Int) -> Gauge
|
||||||
|
new = Gauge
|
||||||
|
|
||||||
|
read :: forall eff. Gauge -> Aff eff Int
|
||||||
|
read (Gauge f) = f
|
|
@ -0,0 +1,60 @@
|
||||||
|
var Histogram = require("metrics/metrics/histogram");
|
||||||
|
|
||||||
|
var clear = function(h) {
|
||||||
|
return function() {
|
||||||
|
h.clear();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var _update = function(h, v) {
|
||||||
|
return function() {
|
||||||
|
h.update(v);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var _percentiles = function(h, ptiles) {
|
||||||
|
return function() {
|
||||||
|
var scoresM = h.percentiles(ptiles);
|
||||||
|
var scores = [];
|
||||||
|
for (var i = 0; i < ptiles.length; i++) {
|
||||||
|
scores.push(scoresM[ptiles[i]]);
|
||||||
|
}
|
||||||
|
if (scores[0]) {
|
||||||
|
return scores;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var _variance = function(h) { return function() { return h.variance(); }; };
|
||||||
|
var _mean = function(h) { return function() { return h.mean(); }; };
|
||||||
|
var _stdDev = function(h) { return function() { return h.stdDev(); }; };
|
||||||
|
var _min = function(h) { return function() { return h.min; }; };
|
||||||
|
var _max = function(h) { return function() { return h.max; }; };
|
||||||
|
var _sum = function(h) { return function() { return h.sum; }; };
|
||||||
|
var count = function(h) { return function() { return h.count; }; };
|
||||||
|
|
||||||
|
var _newWithExponentialDecaySampling = function(size, alpha) {
|
||||||
|
return function() {
|
||||||
|
return Histogram.createExponentialDecayHistogram(size, alpha);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var newWithUniformSampling = function(size) {
|
||||||
|
return function() {
|
||||||
|
return Histogram.createUniformHistogram(size);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.clear = clear;
|
||||||
|
exports._update = _update;
|
||||||
|
exports._percentiles = _percentiles;
|
||||||
|
exports._variance = _variance;
|
||||||
|
exports._mean = _mean;
|
||||||
|
exports._stdDev = _stdDev;
|
||||||
|
exports._min = _min;
|
||||||
|
exports._max = _max;
|
||||||
|
exports._sum = _sum;
|
||||||
|
exports.count = count;
|
||||||
|
exports._newWithExponentialDecaySampling = _newWithExponentialDecaySampling;
|
||||||
|
exports.newWithUniformSampling = newWithUniformSampling;
|
|
@ -0,0 +1,114 @@
|
||||||
|
module System.Metrics.Histogram
|
||||||
|
( Histogram
|
||||||
|
, Summary
|
||||||
|
, newWithExponentialDecaySampling
|
||||||
|
, newWithUniformSampling
|
||||||
|
, clear
|
||||||
|
, update
|
||||||
|
, percentiles
|
||||||
|
, variance
|
||||||
|
, mean
|
||||||
|
, stdDev
|
||||||
|
, min
|
||||||
|
, max
|
||||||
|
, sum
|
||||||
|
, count
|
||||||
|
, read
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad.Eff (Eff)
|
||||||
|
import Control.Monad.Eff.Ref (REF)
|
||||||
|
import Data.Array (index)
|
||||||
|
import Data.Function.Uncurried (Fn2, runFn2)
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
|
import Data.Generic.Rep.Show (genericShow)
|
||||||
|
import Data.Maybe (Maybe)
|
||||||
|
import Data.Nullable (Nullable, toMaybe)
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
foreign import data Histogram :: Type
|
||||||
|
foreign import _newWithExponentialDecaySampling ::
|
||||||
|
forall eff. Fn2 Int Number (Eff (ref :: REF | eff) Histogram)
|
||||||
|
foreign import newWithUniformSampling ::
|
||||||
|
forall eff. Int -> Eff (ref :: REF | eff) Histogram
|
||||||
|
foreign import clear :: forall eff. Histogram -> Eff (ref :: REF | eff) Unit
|
||||||
|
foreign import _update :: forall eff. Fn2 Histogram Number (Eff (ref :: REF | eff) Unit)
|
||||||
|
foreign import _percentiles
|
||||||
|
:: forall eff. Fn2 Histogram (Array Number) (Eff (ref :: REF | eff) (Nullable (Array Number)))
|
||||||
|
foreign import _variance :: forall eff. Histogram -> Eff (ref :: REF | eff) (Nullable Number)
|
||||||
|
foreign import _mean :: forall eff. Histogram -> Eff (ref :: REF | eff) (Nullable Number)
|
||||||
|
foreign import _stdDev :: forall eff. Histogram -> Eff (ref :: REF | eff) (Nullable Number)
|
||||||
|
foreign import _min :: forall eff. Histogram -> Eff (ref :: REF | eff) (Nullable Number)
|
||||||
|
foreign import _max :: forall eff. Histogram -> Eff (ref :: REF | eff) (Nullable Number)
|
||||||
|
foreign import _sum :: forall eff. Histogram -> Eff (ref :: REF | eff) (Nullable Number)
|
||||||
|
foreign import count :: forall eff. Histogram -> Eff (ref :: REF | eff) Int
|
||||||
|
|
||||||
|
newWithExponentialDecaySampling :: forall eff. Int -> Number -> Eff (ref :: REF | eff) Histogram
|
||||||
|
newWithExponentialDecaySampling = runFn2 _newWithExponentialDecaySampling
|
||||||
|
|
||||||
|
update :: forall eff. Histogram -> Number -> Eff (ref :: REF | eff) Unit
|
||||||
|
update = runFn2 _update
|
||||||
|
|
||||||
|
percentiles :: forall eff. Histogram -> Array Number -> Eff (ref :: REF | eff) (Maybe (Array Number))
|
||||||
|
percentiles h ptiles = toMaybe <$> runFn2 _percentiles h ptiles
|
||||||
|
|
||||||
|
variance :: forall eff. Histogram -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
variance h = toMaybe <$> _variance h
|
||||||
|
|
||||||
|
mean :: forall eff. Histogram -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
mean h = toMaybe <$> _mean h
|
||||||
|
|
||||||
|
stdDev :: forall eff. Histogram -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
stdDev h = toMaybe <$> _stdDev h
|
||||||
|
|
||||||
|
min :: forall eff. Histogram -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
min h = toMaybe <$> _min h
|
||||||
|
|
||||||
|
max :: forall eff. Histogram -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
max h = toMaybe <$> _max h
|
||||||
|
|
||||||
|
sum :: forall eff. Histogram -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
sum h = toMaybe <$> _sum h
|
||||||
|
|
||||||
|
newtype Summary = Summary {
|
||||||
|
min :: Maybe Number
|
||||||
|
, max :: Maybe Number
|
||||||
|
, sum :: Maybe Number
|
||||||
|
, variance :: Maybe Number
|
||||||
|
, mean :: Maybe Number
|
||||||
|
, stdDev :: Maybe Number
|
||||||
|
, count :: Int
|
||||||
|
, median :: Maybe Number
|
||||||
|
, p75 :: Maybe Number
|
||||||
|
, p95 :: Maybe Number
|
||||||
|
, p99 :: Maybe Number
|
||||||
|
, p999 :: Maybe Number
|
||||||
|
}
|
||||||
|
|
||||||
|
derive instance eqSummary :: Eq Summary
|
||||||
|
derive instance genericSummary :: Generic Summary _
|
||||||
|
instance showSummary :: Show Summary where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
read :: forall eff. Histogram -> Eff (ref :: REF | eff) Summary
|
||||||
|
read h = do
|
||||||
|
ptiles <- percentiles h [0.5, 0.75, 0.95, 0.99, 0.999]
|
||||||
|
Summary <$> ({ min: _
|
||||||
|
, max: _
|
||||||
|
, sum: _
|
||||||
|
, variance: _
|
||||||
|
, mean: _
|
||||||
|
, stdDev: _
|
||||||
|
, count: _
|
||||||
|
, median: ptiles >>= flip index 0
|
||||||
|
, p75: ptiles >>= flip index 1
|
||||||
|
, p95: ptiles >>= flip index 2
|
||||||
|
, p99: ptiles >>= flip index 3
|
||||||
|
, p999: ptiles >>= flip index 4
|
||||||
|
} <$> min h
|
||||||
|
<*> max h
|
||||||
|
<*> sum h
|
||||||
|
<*> variance h
|
||||||
|
<*> mean h
|
||||||
|
<*> stdDev h
|
||||||
|
<*> count h)
|
|
@ -0,0 +1,49 @@
|
||||||
|
var Meter = require("metrics/metrics/meter");
|
||||||
|
|
||||||
|
var _new = function() {
|
||||||
|
return new Meter();
|
||||||
|
};
|
||||||
|
|
||||||
|
var _markN = function(m, n) {
|
||||||
|
return function() {
|
||||||
|
m.mark(n);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var fifteenMinuteRate = function(m) {
|
||||||
|
return function() {
|
||||||
|
return m.fifteenMinuteRate();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var fiveMinuteRate = function(m) {
|
||||||
|
return function() {
|
||||||
|
return m.fiveMinuteRate();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var oneMinuteRate = function(m) {
|
||||||
|
return function() {
|
||||||
|
return m.oneMinuteRate();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var meanRate = function(m) {
|
||||||
|
return function() {
|
||||||
|
return m.meanRate();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var count = function(m) {
|
||||||
|
return function() {
|
||||||
|
return m.count;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports._new = _new;
|
||||||
|
exports._markN = _markN;
|
||||||
|
exports.fifteenMinuteRate = fifteenMinuteRate;
|
||||||
|
exports.fiveMinuteRate = fiveMinuteRate;
|
||||||
|
exports.oneMinuteRate = oneMinuteRate;
|
||||||
|
exports.meanRate = meanRate;
|
||||||
|
exports.count = count;
|
|
@ -0,0 +1,63 @@
|
||||||
|
module System.Metrics.Meter
|
||||||
|
( Meter
|
||||||
|
, Summary
|
||||||
|
, new
|
||||||
|
, markN
|
||||||
|
, mark
|
||||||
|
, fifteenMinuteRate
|
||||||
|
, fiveMinuteRate
|
||||||
|
, oneMinuteRate
|
||||||
|
, meanRate
|
||||||
|
, count
|
||||||
|
, read
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad.Eff (Eff)
|
||||||
|
import Control.Monad.Eff.Ref (REF)
|
||||||
|
import Data.Function.Uncurried (Fn2, runFn2)
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
|
import Data.Generic.Rep.Show (genericShow)
|
||||||
|
import Prelude (class Eq, class Show, Unit, (<$>), (<*>))
|
||||||
|
|
||||||
|
foreign import data Meter :: Type
|
||||||
|
foreign import _new :: forall eff. Eff (ref :: REF | eff) Meter
|
||||||
|
foreign import _markN :: forall eff. Fn2 Meter Int (Eff (ref :: REF | eff) Unit)
|
||||||
|
foreign import fifteenMinuteRate :: forall eff. Meter -> Eff (ref :: REF | eff) Number
|
||||||
|
foreign import fiveMinuteRate :: forall eff. Meter -> Eff (ref :: REF | eff) Number
|
||||||
|
foreign import oneMinuteRate :: forall eff. Meter -> Eff (ref :: REF | eff) Number
|
||||||
|
foreign import meanRate :: forall eff. Meter -> Eff (ref :: REF | eff) Number
|
||||||
|
foreign import count :: forall eff. Meter -> Eff (ref :: REF | eff) Int
|
||||||
|
|
||||||
|
new :: forall eff. Eff (ref :: REF | eff) Meter
|
||||||
|
new = _new
|
||||||
|
|
||||||
|
markN :: forall eff. Meter -> Int -> Eff (ref :: REF | eff) Unit
|
||||||
|
markN = runFn2 _markN
|
||||||
|
|
||||||
|
mark :: forall eff. Meter -> Eff (ref :: REF | eff) Unit
|
||||||
|
mark m = markN m 1
|
||||||
|
|
||||||
|
newtype Summary = Summary {
|
||||||
|
count :: Int
|
||||||
|
, m1 :: Number
|
||||||
|
, m5 :: Number
|
||||||
|
, m15 :: Number
|
||||||
|
, mean :: Number
|
||||||
|
}
|
||||||
|
|
||||||
|
derive instance eqSummary :: Eq Summary
|
||||||
|
derive instance genericSummary :: Generic Summary _
|
||||||
|
instance showSummary :: Show Summary where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
read :: forall eff. Meter -> Eff (ref :: REF | eff) Summary
|
||||||
|
read m = Summary <$> ({ count: _
|
||||||
|
, m1: _
|
||||||
|
, m5: _
|
||||||
|
, m15: _
|
||||||
|
, mean: _
|
||||||
|
} <$> count m
|
||||||
|
<*> oneMinuteRate m
|
||||||
|
<*> fiveMinuteRate m
|
||||||
|
<*> fifteenMinuteRate m
|
||||||
|
<*> meanRate m)
|
|
@ -0,0 +1,92 @@
|
||||||
|
module System.Metrics.Timer
|
||||||
|
( Timer
|
||||||
|
, Summary
|
||||||
|
, new
|
||||||
|
, update
|
||||||
|
, fifteenMinuteRate
|
||||||
|
, fiveMinuteRate
|
||||||
|
, oneMinuteRate
|
||||||
|
, meanRate
|
||||||
|
, clear
|
||||||
|
, percentiles
|
||||||
|
, mean
|
||||||
|
, stdDev
|
||||||
|
, min
|
||||||
|
, max
|
||||||
|
, sum
|
||||||
|
, count
|
||||||
|
, read
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Monad.Eff (Eff)
|
||||||
|
import Control.Monad.Eff.Ref (REF)
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
|
import Data.Generic.Rep.Show (genericShow)
|
||||||
|
import Data.Maybe (Maybe)
|
||||||
|
import Data.Time.Duration (class Duration, Milliseconds(..), fromDuration)
|
||||||
|
import System.Metrics.Histogram (Histogram)
|
||||||
|
import System.Metrics.Histogram as Histogram
|
||||||
|
import System.Metrics.Meter (Meter)
|
||||||
|
import System.Metrics.Meter as Meter
|
||||||
|
|
||||||
|
newtype Timer = Timer { meter :: Meter, histogram :: Histogram }
|
||||||
|
|
||||||
|
new :: forall eff. Eff (ref :: REF | eff) Timer
|
||||||
|
new = Timer <$> ({ meter: _, histogram: _ }
|
||||||
|
<$> Meter.new
|
||||||
|
<*> Histogram.newWithExponentialDecaySampling 1028 0.015)
|
||||||
|
|
||||||
|
update :: forall a eff. Duration a => Timer -> a -> Eff (ref :: REF | eff) Unit
|
||||||
|
update (Timer { meter, histogram }) d = do
|
||||||
|
let (Milliseconds ms) = fromDuration d
|
||||||
|
Histogram.update histogram ms
|
||||||
|
Meter.mark meter
|
||||||
|
|
||||||
|
fifteenMinuteRate :: forall eff. Timer -> Eff (ref :: REF | eff) Number
|
||||||
|
fifteenMinuteRate (Timer { meter }) = Meter.fifteenMinuteRate meter
|
||||||
|
|
||||||
|
fiveMinuteRate :: forall eff. Timer -> Eff (ref :: REF | eff) Number
|
||||||
|
fiveMinuteRate (Timer { meter }) = Meter.fiveMinuteRate meter
|
||||||
|
|
||||||
|
oneMinuteRate :: forall eff. Timer -> Eff (ref :: REF | eff) Number
|
||||||
|
oneMinuteRate (Timer { meter }) = Meter.oneMinuteRate meter
|
||||||
|
|
||||||
|
meanRate :: forall eff. Timer -> Eff (ref :: REF | eff) Number
|
||||||
|
meanRate (Timer { meter }) = Meter.meanRate meter
|
||||||
|
|
||||||
|
clear :: forall eff. Timer -> Eff (ref :: REF | eff) Unit
|
||||||
|
clear (Timer { histogram }) = Histogram.clear histogram
|
||||||
|
|
||||||
|
percentiles :: forall eff. Timer -> Array Number -> Eff (ref :: REF | eff) (Maybe (Array Number))
|
||||||
|
percentiles (Timer { histogram }) = Histogram.percentiles histogram
|
||||||
|
|
||||||
|
mean :: forall eff. Timer -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
mean (Timer { histogram }) = Histogram.mean histogram
|
||||||
|
|
||||||
|
stdDev :: forall eff. Timer -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
stdDev (Timer { histogram }) = Histogram.stdDev histogram
|
||||||
|
|
||||||
|
min :: forall eff. Timer -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
min (Timer { histogram }) = Histogram.min histogram
|
||||||
|
|
||||||
|
max :: forall eff. Timer -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
max (Timer { histogram }) = Histogram.max histogram
|
||||||
|
|
||||||
|
sum :: forall eff. Timer -> Eff (ref :: REF | eff) (Maybe Number)
|
||||||
|
sum (Timer { histogram }) = Histogram.sum histogram
|
||||||
|
|
||||||
|
count :: forall eff. Timer -> Eff (ref :: REF | eff) Int
|
||||||
|
count (Timer { histogram }) = Histogram.count histogram
|
||||||
|
|
||||||
|
newtype Summary = Summary { duration :: Histogram.Summary, rate :: Meter.Summary }
|
||||||
|
|
||||||
|
derive instance eqSummary :: Eq Summary
|
||||||
|
derive instance genericSummary :: Generic Summary _
|
||||||
|
instance showSummary :: Show Summary where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
read :: forall eff. Timer -> Eff (ref :: REF | eff) Summary
|
||||||
|
read (Timer { meter, histogram }) =
|
||||||
|
Summary <$> ({ duration: _, rate: _} <$> Histogram.read histogram <*> Meter.read meter)
|
Loading…
Reference in New Issue