packages feed

freckle-app 1.0.0.4 → 1.0.1.0

raw patch · 6 files changed

+187/−8 lines, 6 filesdep +ekg-coredep +unordered-containers

Dependencies added: ekg-core, unordered-containers

Files

CHANGELOG.md view
@@ -1,6 +1,11 @@-## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.0.0.4...main)+## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.0.1.0...main) -None.+- None.++## [v1.0.1.0](https://github.com/freckle/freckle-app/compare/v1.0.0.4...v1.0.1.0)++- Added `Freckle.App.Datadog.Gauge` for client side stateful gauges.+- Added `Freckle.App.Datadog.Rts` for sending RTS statistics to DataDog.  ## [v1.0.0.4](https://github.com/freckle/freckle-app/compare/v1.0.0.3...v1.0.0.4) 
freckle-app.cabal view
@@ -1,6 +1,6 @@ cabal-version:      1.12 name:               freckle-app-version:            1.0.0.4+version:            1.0.1.0 license:            MIT license-file:       LICENSE maintainer:         Freckle Education@@ -28,6 +28,8 @@         Freckle.App         Freckle.App.Database         Freckle.App.Datadog+        Freckle.App.Datadog.Gauge+        Freckle.App.Datadog.Rts         Freckle.App.Env         Freckle.App.Env.Internal         Freckle.App.Ghci@@ -69,6 +71,7 @@         data-default >=0.7.1.1,         datadog >=0.2.5.0,         doctest >=0.17,+        ekg-core >=0.1.1.7,         errors >=2.3.0,         exceptions >=0.10.4,         fast-logger >=3.0.5,@@ -104,6 +107,7 @@         transformers-base >=0.4.5.2,         unliftio >=0.2.18,         unliftio-core >=0.2.0.1,+        unordered-containers >=0.2.14.0,         wai >=3.2.3,         wai-extra >=3.1.6,         yaml >=0.11.5.0,
library/Freckle/App/Datadog.hs view
@@ -16,7 +16,7 @@   -- * Higher-level operations   , increment   , counter-  , guage+  , gauge   , histogram   , histogramSince   , histogramSinceMs@@ -27,9 +27,11 @@   , envParseDogStatsSettings   , envParseDogStatsTags   , mkStatsClient-  )-where +  -- * To be removed in next major bump+  , guage+  ) where+ import Prelude  import Control.Lens (set)@@ -78,6 +80,20 @@   -> m () counter name tags = sendAppMetricWithTags name tags Counter +gauge+  :: ( MonadUnliftIO m+     , MonadReader env m+     , HasDogStatsClient env+     , HasDogStatsTags env+     )+  => Text+  -> [(Text, Text)]+  -> Double+  -> m ()+gauge name tags = sendAppMetricWithTags name tags Gauge++{-# DEPRECATED guage "Use gauge instead" #-}+-- | Deprecated typo version of 'gauge' guage   :: ( MonadUnliftIO m      , MonadReader env m@@ -88,7 +104,7 @@   -> [(Text, Text)]   -> Double   -> m ()-guage name tags = sendAppMetricWithTags name tags Gauge+guage = gauge  histogram   :: ( MonadUnliftIO m
+ library/Freckle/App/Datadog/Gauge.hs view
@@ -0,0 +1,90 @@+-- | Stateful gauges for Datadog+module Freckle.App.Datadog.Gauge+  ( Gauge+  , new+  , increment+  , decrement+  , add+  , subtract+  ) where++import Prelude hiding (subtract)++import Control.Monad.IO.Unlift (MonadUnliftIO)+import Control.Monad.Reader+import Data.Int (Int64)+import Data.Text (Text)+import Freckle.App.Datadog (HasDogStatsClient, HasDogStatsTags, gauge)+import qualified System.Metrics.Gauge as EKG++-- | A data type containing all reporting values for a gauge+data Gauge = Gauge+  { name :: Text+  , tags :: [(Text, Text)]+  , ekgGauge :: EKG.Gauge+  }++-- | Create a gauge holding in memory state+new :: MonadIO m => Text -> [(Text, Text)] -> m Gauge+new name tags = Gauge name tags <$> liftIO EKG.new++-- | Increment gauge state and report its current value+increment+  :: ( MonadUnliftIO m+     , MonadReader env m+     , HasDogStatsClient env+     , HasDogStatsTags env+     )+  => Gauge+  -> m ()+increment = add 1++-- | Add to gauge state and report its current value+add+  :: ( MonadUnliftIO m+     , MonadReader env m+     , HasDogStatsClient env+     , HasDogStatsTags env+     )+  => Int64+  -> Gauge+  -> m ()+add i = withEKGGauge (`EKG.add` i)++-- | Decrement gauge state and report its current value+decrement+  :: ( MonadUnliftIO m+     , MonadReader env m+     , HasDogStatsClient env+     , HasDogStatsTags env+     )+  => Gauge+  -> m ()+decrement = subtract 1++-- | Subtract from gauge state and report its current value+subtract+  :: ( MonadUnliftIO m+     , MonadReader env m+     , HasDogStatsClient env+     , HasDogStatsTags env+     )+  => Int64+  -> Gauge+  -> m ()+subtract i = withEKGGauge (`EKG.subtract` i)++withEKGGauge+  :: ( MonadUnliftIO m+     , MonadReader env m+     , HasDogStatsClient env+     , HasDogStatsTags env+     )+  => (EKG.Gauge -> IO ())+  -> Gauge+  -> m ()+withEKGGauge f Gauge {..} = do+  current <- liftIO $ do+    f ekgGauge+    EKG.read ekgGauge+  gauge name tags $ fromIntegral current
+ library/Freckle/App/Datadog/Rts.hs view
@@ -0,0 +1,62 @@+-- | RTS statistics sent to Datadog+module Freckle.App.Datadog.Rts+  ( forkRtsStatPolling+  ) where++import Prelude++import qualified Control.Immortal as Immortal+import Control.Monad (void)+import Control.Monad.IO.Unlift (MonadUnliftIO, liftIO)+import Control.Monad.Reader (MonadReader)+import Data.Foldable (traverse_)+import qualified Data.HashMap.Strict as HashMap+import Data.Text (Text)+import Freckle.App.Datadog (HasDogStatsClient, HasDogStatsTags)+import qualified Freckle.App.Datadog as Datadog+import qualified System.Metrics as Ekg+import qualified System.Metrics.Distribution.Internal as Ekg+import UnliftIO.Concurrent (threadDelay)++-- | Initialize a thread to poll RTS stats+--+-- Stats are collected via `ekg-core` and 'System.Metrics.registerGcMetrics'+--+forkRtsStatPolling+  :: ( MonadUnliftIO m+     , MonadReader env m+     , HasDogStatsClient env+     , HasDogStatsTags env+     )+  => m ()+forkRtsStatPolling = do+  store <- liftIO Ekg.newStore+  liftIO $ Ekg.registerGcMetrics store++  void $ Immortal.create $ \_ -> do+    sample <- liftIO $ Ekg.sampleAll store+    traverse_ (uncurry flushEkgSample) $ HashMap.toList sample++    let seconds n = n * 1000000+    threadDelay $ seconds 1++flushEkgSample+  :: ( MonadUnliftIO m+     , MonadReader env m+     , HasDogStatsClient env+     , HasDogStatsTags env+     )+  => Text+  -> Ekg.Value+  -> m ()+flushEkgSample name = \case+  Ekg.Counter n -> Datadog.counter name [] $ fromIntegral n+  Ekg.Gauge n -> Datadog.gauge name [] $ fromIntegral n+  Ekg.Distribution d -> do+    Datadog.gauge (name <> "." <> "mean") [] $ Ekg.mean d+    Datadog.gauge (name <> "." <> "variance") [] $ Ekg.variance d+    Datadog.gauge (name <> "." <> "sum") [] $ Ekg.sum d+    Datadog.gauge (name <> "." <> "min") [] $ Ekg.min d+    Datadog.gauge (name <> "." <> "max") [] $ Ekg.max d+    Datadog.counter (name <> "." <> "count") [] $ fromIntegral $ Ekg.count d+  Ekg.Label _ -> pure ()
package.yaml view
@@ -1,6 +1,6 @@ --- name: freckle-app-version: 1.0.0.4+version: 1.0.1.0 maintainer: Freckle Education category: Utils github: freckle/freckle-app@@ -60,6 +60,7 @@     - data-default     - datadog     - doctest+    - ekg-core     - errors     - exceptions     - fast-logger@@ -95,6 +96,7 @@     - transformers-base     - unliftio     - unliftio-core+    - unordered-containers     - wai     - wai-extra     - yaml