packages feed

ridley 0.3.2.1 → 0.3.3.0

raw patch · 11 files changed

+201/−65 lines, 11 filesdep +Spockdep +auto-updatedep +safe-exceptionsdep ~basedep ~katipdep ~prometheusnew-component:exe:ridley-examplePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: Spock, auto-update, safe-exceptions

Dependency ranges changed: base, katip, prometheus, text, wai-middleware-metrics

API changes (from Hackage documentation)

- System.Metrics.Prometheus.Ridley.Types: RidleyMetricHandler :: c -> (c -> Bool -> IO ()) -> !Bool -> RidleyMetricHandler
- System.Metrics.Prometheus.Ridley.Types: [flush] :: RidleyMetricHandler -> !Bool
- System.Metrics.Prometheus.Ridley.Types: [metric] :: RidleyMetricHandler -> c
- System.Metrics.Prometheus.Ridley.Types: [updateMetric] :: RidleyMetricHandler -> c -> Bool -> IO ()
+ System.Metrics.Prometheus.Ridley.Types: flush :: RidleyMetricHandler -> Bool
+ System.Metrics.Prometheus.Ridley.Types: label :: RidleyMetricHandler -> Text
+ System.Metrics.Prometheus.Ridley.Types: metric :: RidleyMetricHandler -> c
+ System.Metrics.Prometheus.Ridley.Types: mkRidleyMetricHandler :: forall c. HasCallStack => Text -> c -> (c -> Bool -> IO ()) -> Bool -> RidleyMetricHandler
+ System.Metrics.Prometheus.Ridley.Types: updateMetric :: RidleyMetricHandler -> c -> Bool -> IO ()
- System.Metrics.Prometheus.Ridley.Types: CustomMetric :: Text -> (forall m. MonadIO m => RidleyOptions -> RegistryT m RidleyMetricHandler) -> RidleyMetric
+ System.Metrics.Prometheus.Ridley.Types: CustomMetric :: !Text -> !Maybe Int -> (forall m. MonadIO m => RidleyOptions -> RegistryT m RidleyMetricHandler) -> RidleyMetric

Files

+ example/Main.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE CPP #-}+import           System.Metrics.Prometheus.Ridley+import qualified System.Metrics.Prometheus.Metric.Gauge as P+import qualified System.Metrics.Prometheus.RegistryT as P+import           System.Metrics.Prometheus.Ridley.Types+import           Lens.Micro+import           Web.Spock+import           Web.Spock.Config+import           Network.Wai.Metrics+import           Control.Exception+import           Control.Monad.Trans+import           Data.Time.Clock.POSIX+import           Katip+import           System.IO++spockWeb :: RidleyCtx -> IO ()+spockWeb ctx = do+  spockCfg <- defaultSpockCfg () PCNoDatabase ()+  runSpock 8080 (spock spockCfg (app ctx))++app :: RidleyCtx -> SpockCtxM ctx conn sess st ()+app ctx = do+  case ctx ^. ridleyWaiMetrics of+    Nothing -> return ()+    Just m  -> middleware (metrics m)+  get root $ text "Hello World!"+  get "ping" $ text "pong"++customExpensiveMetric :: RidleyMetric+customExpensiveMetric =+  CustomMetric "my-expensive" (Just $ 60 * 1_000_000) get_metric+  where+    get_metric :: MonadIO m => RidleyOptions -> P.RegistryT m RidleyMetricHandler+    get_metric opts = do+        m <- P.registerGauge "current_time" (opts ^. prometheusOptions . labels)+        return $ mkRidleyMetricHandler "current_time" m update False++    update :: P.Gauge -> Bool -> IO ()+    update gauge _ = do n  <- getPOSIXTime+                        tn <- getCurrentTime+                        putStrLn $ "Updating time, at " <> show tn+                        P.set (realToFrac n) gauge++customCrashfulMetric :: RidleyMetric+customCrashfulMetric =+  CustomMetric "my-crashful" (Just $ 60 * 1_000_000) get_metric+  where+    get_metric :: MonadIO m => RidleyOptions -> P.RegistryT m RidleyMetricHandler+    get_metric opts = do+        m <- P.registerGauge "crashful" (opts ^. prometheusOptions . labels)+        return $ mkRidleyMetricHandler "crashful" m (\_ _ -> throwIO $ userError "CRASH!!") False++main :: IO ()+main = do+#if MIN_VERSION_katip(0,8,0)+    let onlyErrors i = pure $ Katip._itemSeverity i >= Katip.DebugS+    ridleyScribe <-+      Katip.mkHandleScribe Katip.ColorIfTerminal stdout onlyErrors Katip.V2+#else+    ridleyScribe <-+      Katip.mkHandleScribe Katip.ColorIfTerminal stdout Katip.DebugS Katip.V2+#endif+    let opts = newOptions [("service", "ridley-test")] (customExpensiveMetric : customCrashfulMetric : defaultMetrics)+             & prometheusOptions . samplingFrequency .~ 5+             & dataRetentionPeriod .~ Just 60+             & katipScribes .~ ("RidleyTest", [("stdout", ridleyScribe)])+    startRidley opts ["metrics"] 8729 >>= spockWeb
ridley.cabal view
@@ -1,13 +1,13 @@ name:                ridley-version:             0.3.2.1+version:             0.3.3.0 synopsis:            Quick metrics to grow your app strong.-description:         Please see README.md+description:         A collection of Prometheus metrics to monitor your app. Please see README.md homepage:            https://github.com/iconnect/ridley#README license:             BSD3 license-file:        LICENSE author:              Alfredo Di Napoli & the IRIS Connect Engineering Team maintainer:          chrisd@irisconnect.co.uk-copyright:           2017 IRIS Connect Ltd.+copyright:           2022 IRIS Connect Ltd. category:            Web build-type:          Simple data-files:@@ -19,6 +19,11 @@      default: False      description: Enable -Werror +flag library-only+  description: Build without the executable, for downstream packages+  manual: True+  default: True+ library   hs-source-dirs:      src   include-dirs:        include@@ -29,8 +34,10 @@                        System.Metrics.Prometheus.Ridley.Metrics.CPU                        System.Metrics.Prometheus.Ridley.Metrics.Network                        System.Metrics.Prometheus.Ridley.Metrics.Network.Types+  other-modules:       System.Metrics.Prometheus.Ridley.Types.Internal    build-depends:       async < 3.0.0,+                       auto-update >= 0.1,                        base >= 4.7 && < 5,                        containers < 0.7.0.0,                        katip < 0.9.0.0,@@ -38,9 +45,10 @@                        template-haskell,                        ekg-core,                        time,-                       text,+                       text >= 1.2.4.0,                        mtl,                        shelly,+                       safe-exceptions < 1.8,                        transformers,                        prometheus > 0.5.0 && < 2.3.0,                        raw-strings-qq,@@ -85,6 +93,23 @@                      , http-client >= 0.4.30   ghc-options:         -threaded -rtsopts -with-rtsopts=-N   default-language:    Haskell2010++executable ridley-example+    main-is: example/Main.hs+    if !flag(library-only)+      build-depends: base+                   , time+                   , ridley+                   , katip+                   , text+                   , wai-middleware-metrics+                   , Spock+                   , microlens+                   , mtl+                   , prometheus+    if flag(library-only)+      buildable: False+    default-language:    Haskell2010  source-repository head   type:     git
src/System/Metrics/Prometheus/Ridley.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE CPP #-} module System.Metrics.Prometheus.Ridley (     startRidley@@ -22,9 +24,11 @@   , defaultMetrics   ) where +import           Control.AutoUpdate as Auto import           Control.Concurrent (threadDelay, forkIO) import           Control.Concurrent.Async import           Control.Concurrent.MVar+import qualified Control.Exception.Safe as Ex import           Control.Monad (foldM) import           Control.Monad.IO.Class (liftIO, MonadIO) import           Control.Monad.Reader (ask)@@ -32,12 +36,12 @@ import           Data.IORef import qualified Data.List as List import           Data.Map.Strict as M-import           Data.Monoid ((<>)) import qualified Data.Set as Set import           Data.String import qualified Data.Text as T import           Data.Time import           GHC.Conc (getNumCapabilities, getNumProcessors)+import           GHC.Stack import           Katip import           Lens.Micro import           Network.Wai.Metrics (registerWaiMetrics)@@ -55,6 +59,7 @@ import           System.Metrics.Prometheus.Ridley.Metrics.Memory import           System.Metrics.Prometheus.Ridley.Metrics.Network import           System.Metrics.Prometheus.Ridley.Types+import           System.Metrics.Prometheus.Ridley.Types.Internal import           System.Remote.Monitoring.Prometheus  --------------------------------------------------------------------------------@@ -74,9 +79,18 @@   opts <- ask   let popts = opts ^. prometheusOptions   let sev   = opts ^. katipSeverity+  le <- getLogEnv   case x of-    CustomMetric metricName custom -> do-      customMetric <- lift (custom opts)+    CustomMetric metricName mb_timeout custom -> do+      customMetric <- case mb_timeout of+        Nothing   -> lift (custom opts)+        Just microseconds -> do+          RidleyMetricHandler mtr upd flsh lbl cs <- lift (custom opts)+          doUpdate <- liftIO $ Auto.mkAutoUpdate Auto.defaultUpdateSettings+                        { updateAction = upd mtr flsh `Ex.catch` logFailedUpdate le lbl cs+                        , updateFreq   = microseconds+                        }+          pure $ RidleyMetricHandler mtr (\_ _ -> doUpdate) flsh lbl cs       $(logTM) sev $ "Registering CustomMetric '" <> fromString (T.unpack metricName) <> "'..."       (customMetric :) <$> (registerMetrics xs)     ProcessMemory -> do@@ -152,7 +166,7 @@          liftIO $ do           lastUpdate <- newIORef =<< getCurrentTime-          updateLoop <- async $ handlersLoop lastUpdate handlers+          updateLoop <- async $ handlersLoop le' lastUpdate handlers           putMVar x updateLoop          lift $ P.sample >>= serveMetrics port path@@ -165,8 +179,8 @@           $(logTM) ErrorS (fromString $ show e)         Right _ -> return () -    handlersLoop :: IORef UTCTime -> [RidleyMetricHandler] -> IO a-    handlersLoop lastUpdateRef handlers = do+    handlersLoop :: LogEnv -> IORef UTCTime -> [RidleyMetricHandler] -> IO a+    handlersLoop le lastUpdateRef handlers = do       let freq = opts ^. prometheusOptions . samplingFrequency       let flushPeriod = opts ^. dataRetentionPeriod       mustFlush <- case flushPeriod of@@ -180,8 +194,8 @@               return True             False -> return False       threadDelay (freq * 10^6)-      updateHandlers (List.map (\x -> x { flush = mustFlush }) handlers)-      handlersLoop lastUpdateRef handlers+      updateHandlers le (List.map (\x -> x { flush = mustFlush }) handlers)+      handlersLoop le lastUpdateRef handlers  serveMetrics :: MonadIO m => Int -> P.Path -> IO RegistrySample -> m () #if (MIN_VERSION_prometheus(2,2,2))@@ -191,5 +205,16 @@ #endif  ---------------------------------------------------------------------------------updateHandlers :: [RidleyMetricHandler] -> IO ()-updateHandlers = mapM_ runHandler+updateHandlers :: LogEnv -> [RidleyMetricHandler] -> IO ()+updateHandlers le hs = mapM_ (\h@RidleyMetricHandler{..} -> runHandler h `Ex.catchAny` (logFailedUpdate le label _cs)) hs++logFailedUpdate :: LogEnv -> T.Text -> CallStack -> Ex.SomeException -> IO ()+logFailedUpdate le lbl cs ex =+  runKatipContextT le () "errors" $ do+      $(logTM) ErrorS $+        fromString $ "Couldn't update handler for "+                  <> "\"" <> T.unpack lbl <> "\""+                  <> " due to "+                  <> Ex.displayException ex+                  <> " originally defined at "+                  <> prettyCallStack cs
src/System/Metrics/Prometheus/Ridley/Metrics/CPU/Darwin.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} module System.Metrics.Prometheus.Ridley.Metrics.CPU.Darwin@@ -5,7 +6,6 @@   , processCPULoad   ) where -import           Data.Monoid ((<>)) import qualified Data.Vector.Storable as V import qualified Data.Vector.Storable.Mutable as VM import           Foreign.C.Types@@ -37,8 +37,4 @@  -------------------------------------------------------------------------------- processCPULoad :: (P.Gauge, P.Gauge, P.Gauge) -> RidleyMetricHandler-processCPULoad g = RidleyMetricHandler {-    metric = g-  , updateMetric = updateCPULoad-  , flush = False-  }+processCPULoad g = mkRidleyMetricHandler "ridley-process-cpu-load" g updateCPULoad False
src/System/Metrics/Prometheus/Ridley/Metrics/CPU/Unix.hs view
@@ -43,8 +43,4 @@  -------------------------------------------------------------------------------- processCPULoad :: (P.Gauge, P.Gauge, P.Gauge) -> RidleyMetricHandler-processCPULoad g = RidleyMetricHandler {-    metric = g-  , updateMetric = updateCPULoad-  , flush = False-  }+processCPULoad g = mkRidleyMetricHandler "ridley-process-cpu-load" g updateCPULoad False
src/System/Metrics/Prometheus/Ridley/Metrics/DiskUsage.hs view
@@ -84,11 +84,7 @@  -------------------------------------------------------------------------------- diskUsageMetrics :: DiskUsageMetrics -> RidleyMetricHandler-diskUsageMetrics g = RidleyMetricHandler {-    metric = g-  , updateMetric = updateDiskUsageMetrics-  , flush = False-  }+diskUsageMetrics g = mkRidleyMetricHandler "ridley-disk-usage" g updateDiskUsageMetrics False  -------------------------------------------------------------------------------- mkDiskGauge :: MonadIO m => P.Labels -> DiskUsageMetrics -> DiskStats -> P.RegistryT m DiskUsageMetrics
src/System/Metrics/Prometheus/Ridley/Metrics/Memory.hs view
@@ -32,8 +32,4 @@  -------------------------------------------------------------------------------- processMemory :: P.Gauge -> RidleyMetricHandler-processMemory g = RidleyMetricHandler {-    metric = g-  , updateMetric = updateProcessMemory-  , flush = False-  }+processMemory g = mkRidleyMetricHandler "ridley-process-memory" g updateProcessMemory False
src/System/Metrics/Prometheus/Ridley/Metrics/Network/Darwin.hs view
@@ -12,7 +12,6 @@ import           Control.Monad import           Control.Monad.IO.Class import qualified Data.Map.Strict as M-import           Data.Monoid ((<>)) import qualified Data.Text as T import           Foreign.C.String import           Foreign.C.Types@@ -167,11 +166,7 @@  -------------------------------------------------------------------------------- networkMetrics :: NetworkMetrics -> RidleyMetricHandler-networkMetrics g = RidleyMetricHandler {-    metric = g-  , updateMetric = updateNetworkMetrics-  , flush = False-  }+networkMetrics g = mkRidleyMetricHandler "ridley-network-metrics" g updateNetworkMetrics False  -------------------------------------------------------------------------------- mkInterfaceGauge :: MonadIO m => P.Labels -> NetworkMetrics -> IfData -> P.RegistryT m NetworkMetrics
src/System/Metrics/Prometheus/Ridley/Metrics/Network/Unix.hs view
@@ -70,11 +70,7 @@  -------------------------------------------------------------------------------- networkMetrics :: NetworkMetrics -> RidleyMetricHandler-networkMetrics g = RidleyMetricHandler {-    metric = g-  , updateMetric = updateNetworkMetrics-  , flush = False-  }+networkMetrics g = mkRidleyMetricHandler "ridley-network-metrics" g updateNetworkMetrics False  -------------------------------------------------------------------------------- mkInterfaceGauge :: MonadIO m => P.Labels -> NetworkMetrics -> IfData -> P.RegistryT m NetworkMetrics
src/System/Metrics/Prometheus/Ridley/Types.hs view
@@ -1,10 +1,10 @@-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeSynonymInstances #-} module System.Metrics.Prometheus.Ridley.Types (     RidleyT(Ridley)   , Ridley@@ -16,7 +16,12 @@   , PrometheusOptions   , RidleyMetric(..)   , RidleyOptions-  , RidleyMetricHandler(..)+  , RidleyMetricHandler+  , metric+  , updateMetric+  , flush+  , label+  , mkRidleyMetricHandler   , defaultMetrics   , newOptions   , prometheusOptions@@ -32,27 +37,31 @@ import           Control.Monad.Reader (MonadReader) import           Control.Monad.Trans.Class import           Control.Monad.Trans.Reader-import           Data.Monoid import qualified Data.Set as Set import qualified Data.Text as T import           Data.Time+import           GHC.Stack import           Katip import           Lens.Micro.TH import           Network.Wai.Metrics (WaiMetrics) import qualified System.Metrics.Prometheus.MetricId as P import qualified System.Metrics.Prometheus.RegistryT as P import           System.Remote.Monitoring.Prometheus+import           System.Metrics.Prometheus.Ridley.Types.Internal  -------------------------------------------------------------------------------- type Port = Int type PrometheusOptions = AdapterOptions ----------------------------------------------------------------------------------data RidleyMetricHandler = forall c. RidleyMetricHandler {-    metric       :: c-  , updateMetric :: c -> Bool -> IO ()-  , flush        :: !Bool-  -- ^Whether or net to flush this Metric+mkRidleyMetricHandler :: forall c. HasCallStack+                      => T.Text+                      -> c -> (c -> Bool -> IO ()) -> Bool -> RidleyMetricHandler+mkRidleyMetricHandler lbl c runC flsh = withFrozenCallStack $ RidleyMetricHandler {+    metric       = c+  , updateMetric = runC+  , flush        = flsh+  , label        = lbl+  , _cs          = popCallStack callStack   }  --------------------------------------------------------------------------------@@ -64,7 +73,17 @@                   | Wai                   | DiskUsage                   -- ^ Gets stats about Disk usage (free space, etc)-                  | CustomMetric T.Text (forall m. MonadIO m => RidleyOptions -> P.RegistryT m RidleyMetricHandler)+                  | CustomMetric !T.Text+                                 -- ^ The name of the metric+                                 !(Maybe Int)+                                 -- ^ An optional timeout, in microseconds,+                                 -- that regulates how often the metric is+                                 -- actually updated. If Nothing, the metric+                                 -- will be updated using Ridley top-level setting,+                                 -- if 'Just' the underlying 'IO' action will be run+                                 -- only every @n@ seconds, or cached otherwise.+                                 (forall m. MonadIO m => RidleyOptions -> P.RegistryT m RidleyMetricHandler)+                                 -- ^ An action to generate the handler.                   -- ^ A user-defined metric, identified by a name.  instance Show RidleyMetric where@@ -74,7 +93,7 @@   show Network               = "Network"   show Wai                   = "Wai"   show DiskUsage             = "DiskUsage"-  show (CustomMetric name _) = "Custom@" <> T.unpack name+  show (CustomMetric name _ _) = "Custom@" <> T.unpack name  instance Eq RidleyMetric where   (==) ProcessMemory ProcessMemory             = True@@ -83,7 +102,7 @@   (==) Network Network                         = True   (==) Wai     Wai                             = True   (==) DiskUsage DiskUsage                     = True-  (==) (CustomMetric n1 _) (CustomMetric n2 _) = (==) n1 n2+  (==) (CustomMetric n1 _ _) (CustomMetric n2 _ _) = (==) n1 n2   (==) _ _                                     = False  instance Ord RidleyMetric where@@ -120,14 +139,14 @@     Wai                    -> LT     DiskUsage              -> EQ     _                      -> GT-  compare (CustomMetric n1 _) xs = case xs of+  compare (CustomMetric n1 _ _) xs = case xs of     ProcessMemory          -> LT     CPULoad                -> LT     GHCConc                -> LT     Network                -> LT     Wai                    -> LT     DiskUsage              -> LT-    (CustomMetric n2 _)    -> compare n1 n2+    (CustomMetric n2 _ _)    -> compare n1 n2  -------------------------------------------------------------------------------- data RidleyOptions = RidleyOptions {@@ -160,10 +179,10 @@  -------------------------------------------------------------------------------- runHandler :: RidleyMetricHandler -> IO ()-runHandler (RidleyMetricHandler m u f) = u m f+runHandler (RidleyMetricHandler m u f _ _) = u m f  ---------------------------------------------------------------------------------newtype RidleyT t a = Ridley { unRidley :: ReaderT RidleyOptions t a }+newtype RidleyT t a = Ridley { _unRidley :: ReaderT RidleyOptions t a }   deriving (Functor, Applicative, Monad, MonadReader RidleyOptions, MonadIO, MonadTrans)  type Ridley = RidleyT (P.RegistryT (KatipContextT IO))
+ src/System/Metrics/Prometheus/Ridley/Types/Internal.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ExistentialQuantification #-}+module System.Metrics.Prometheus.Ridley.Types.Internal+  ( RidleyMetricHandler(..)+  ) where++import           GHC.Stack+import qualified Data.Text as T++--------------------------------------------------------------------------------+data RidleyMetricHandler = forall c. RidleyMetricHandler {+  -- | An opaque metric+    metric       :: c+  -- | An IO action used to update the metric+  , updateMetric :: c -> Bool -> IO ()+  -- | Whether or not to flush this Metric+  , flush        :: !Bool+  -- | A user-friendly label, used to report errors+  , label        :: !T.Text+  -- | A CallStack, for precise error reporting+  , _cs          :: CallStack+  }+