{-# LANGUAGE DataKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} module Arbor.Monad.Metric.Datadog ( logStats , mkEvent ) where import Arbor.Monad.Metric.Type (Counter (..), Gauge (..), MonadMetrics, getMetricMapTVar) import Control.Lens import Control.Monad.IO.Class import Data.Foldable import Data.Generics.Product.Any import Data.Proxy import Data.Semigroup ((<>)) import qualified Arbor.Monad.Metric as C import qualified Arbor.Network.StatsD as S import qualified Arbor.Network.StatsD.Type as Z import qualified Control.Concurrent.STM as STM import qualified Data.Map.Strict as M import qualified Data.Text as T logStats :: (S.MonadStats m, MonadMetrics m) => m () logStats = do tCounterMap <- getMetricMapTVar (counters, _) <- liftIO . STM.atomically $ STM.swapTVar tCounterMap M.empty >>= C.extractValues (Proxy @Counter) traverse_ S.sendMetric $ mkMetricsCounterTagged "counters" counters traverse_ S.sendMetric $ mkMetricsCounterNonTagged counters tGaugeMap <- getMetricMapTVar (gauge, _) <- liftIO . STM.atomically $ STM.swapTVar tGaugeMap M.empty >>= C.extractValues (Proxy @Gauge) traverse_ S.sendMetric $ mkMetricsGaugeTagged "gauge" gauge traverse_ S.sendMetric $ mkMetricsGaugeNonTagged gauge metricName :: String -> T.Text metricName n = T.replace " " "_" (T.pack n) -- create metric m, but tag with stat:[actual stat name] mkMetricsGaugeTagged :: String -> [(Gauge, Double)] -> [Z.Metric] mkMetricsGaugeTagged m = fmap (\(Gauge n, i) -> S.gauge (Z.MetricName (metricName m)) id i & the @"tags" %~ ([S.tag "stat" (T.pack n)] ++)) -- create metrics for each counter mkMetricsGaugeNonTagged :: [(Gauge, Double)] -> [S.Metric] mkMetricsGaugeNonTagged = fmap (\(Gauge n, i) -> S.gauge (Z.MetricName (metricName n)) id i) -- create metric m, but tag with stat:[actual stat name] mkMetricsCounterTagged :: String -> [(Counter, Int)] -> [Z.Metric] mkMetricsCounterTagged m = fmap (\(Counter n, i) -> S.addCounter (Z.MetricName (metricName m)) id i & the @"tags" %~ ([S.tag "stat" (T.pack n)] ++)) -- create metrics for each counter mkMetricsCounterNonTagged :: [(Counter, Int)] -> [S.Metric] mkMetricsCounterNonTagged = fmap (\(Counter n, i) -> S.addCounter (Z.MetricName (metricName n)) id i) mkEvent :: [(String, Int)] -> String -> Z.Tag -> String -> Z.Event mkEvent stats etitle etag fn = S.event (T.pack etitle) desc & the @"tags" %~ ([etag] ++) where desc = T.intercalate "\n" $ T.pack <$> ("File processed: " <> fn) : info info = (\(n, i) -> n <> ": " <> show i) <$> stats