module Network.Metric.Sink.Statsd (
open
, Sink(push, close)
, Group
, Bucket
, MetricSink(..)
) where
import Control.Monad (liftM)
import Network.Socket (SocketType(..))
import System.Random (randomRIO)
import Network.Metric.Internal
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BL
data Sampled = Sampled | Exact | Ignore
data Statsd = Statsd Handle deriving (Show)
instance Sink Statsd where
push (Statsd h) m = enc m >>= hPush h
where
enc (Counter g b v) = put g b v "c" 1.0
enc (Gauge g b v) = put g b v "g" 1.0
enc (Timer g b v) = put g b v "ms" 1.0
close (Statsd h) = hClose h
open :: String -> String -> IO MetricSink
open = fOpen Statsd Datagram
put :: Encodable a
=> Group
-> Bucket
-> a
-> BS.ByteString
-> Double
-> IO BL.ByteString
put group bucket value typ rate = liftM bstr (randomRIO (0.0, 1.0))
where
base = [key group bucket, ":", encode value, "|", typ]
bstr n = BL.fromChunks $ case sample rate n of
Sampled -> base ++ ["@", BS.pack $ show rate]
Exact -> base
Ignore -> []
sample :: Double -> Double -> Sampled
sample rate rand | rate < 1.0 && rand <= rate = Sampled
| rate == 1.0 = Exact
| otherwise = Ignore