module Network.Metric.Sink.Statsd (
Sink(..)
, open
, Group
, Bucket
, AnySink(..)
) 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 Host Handle deriving (Show)
instance Sink Statsd where
push (Statsd host hd) m = mapM enc (measure m) >>= mapM_ (hPush hd)
where
enc (Counter g b v) = put host g b v "c" 1.0
enc (Gauge g b v) = put host g b v "g" 1.0
enc (Timer g b v) = put host g b v "ms" 1.0
close (Statsd _ hd) = hClose hd
open :: Host -> HostName -> PortNumber -> IO AnySink
open host = fOpen (Statsd host) Datagram
put :: Encodable a
=> Host
-> Group
-> Bucket
-> a
-> BS.ByteString
-> Double
-> IO BL.ByteString
put host group bucket value typ rate = liftM (BL.fromChunks . bstr) (sample rate)
where
base = [key host group bucket, ":", encode value, "|", typ]
bstr Sampled = base ++ ["@", BS.pack $ show rate]
bstr Exact = base
bstr Ignore = []
sample :: Double -> IO Sampled
sample rate
| rate < 1.0 = do
r <- randomRIO (0.0, 1.0)
return $ if r <= rate then Sampled else Ignore
| rate == 1.0 = return Exact
| otherwise = return Ignore