packages feed

freckle-app 1.6.0.3 → 1.7.0.0

raw patch · 6 files changed

+97/−73 lines, 6 filesdep +aws-xray-client-persistentdep +aws-xray-client-waiPVP ok

version bump matches the API change (PVP)

Dependencies added: aws-xray-client-persistent, aws-xray-client-wai

API changes (from Hackage documentation)

- Freckle.App.Stats.Gauge: add :: (MonadUnliftIO m, MonadReader env m, HasStatsClient env) => Int64 -> Gauge -> m ()
- Freckle.App.Stats.Gauge: data Gauge
- Freckle.App.Stats.Gauge: decrement :: (MonadUnliftIO m, MonadReader env m, HasStatsClient env) => Gauge -> m ()
- Freckle.App.Stats.Gauge: increment :: (MonadUnliftIO m, MonadReader env m, HasStatsClient env) => Gauge -> m ()
- Freckle.App.Stats.Gauge: new :: MonadIO m => Text -> [(Text, Text)] -> m Gauge
- Freckle.App.Stats.Gauge: subtract :: (MonadUnliftIO m, MonadReader env m, HasStatsClient env) => Int64 -> Gauge -> m ()
+ Freckle.App.Stats: data GaugeName
+ Freckle.App.Stats: data Gauges
+ Freckle.App.Stats: dbConnections :: GaugeName
+ Freckle.App.Stats: withGauge :: (MonadReader app m, HasStatsClient app, MonadUnliftIO m) => GaugeName -> m a -> m a
- Freckle.App.Database: runDB :: (HasSqlPool app, MonadUnliftIO m, MonadReader app m) => SqlPersistT m a -> m a
+ Freckle.App.Database: runDB :: (HasSqlPool app, HasStatsClient app, MonadHandler m, MonadUnliftIO m, MonadReader app m) => SqlPersistT m a -> m a
- Freckle.App.Test: runDB :: (HasSqlPool app, MonadUnliftIO m, MonadReader app m) => SqlPersistT m a -> m a
+ Freckle.App.Test: runDB :: (HasSqlPool app, HasStatsClient app, MonadHandler m, MonadUnliftIO m, MonadReader app m) => SqlPersistT m a -> m a

Files

CHANGELOG.md view
@@ -1,4 +1,11 @@-## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.6.0.3...main)+## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.7.0.0...main)++## [v1.7.0.0](https://github.com/freckle/freckle-app/compare/v1.6.0.3...v1.7.0.0)++- Add XRay and EKG support to freckle-app's runDB.++  This involves an breaking change in `runDB`'s constraints, thus the major version+  bump.  ## [v1.6.0.3](https://github.com/freckle/freckle-app/compare/v1.6.0.2...v1.6.0.3) 
freckle-app.cabal view
@@ -1,6 +1,6 @@ cabal-version:      1.18 name:               freckle-app-version:            1.6.0.3+version:            1.7.0.0 license:            MIT license-file:       LICENSE maintainer:         Freckle Education@@ -43,7 +43,6 @@         Freckle.App.Prelude         Freckle.App.Scientist         Freckle.App.Stats-        Freckle.App.Stats.Gauge         Freckle.App.Stats.Rts         Freckle.App.Test         Freckle.App.Test.DocTest@@ -74,6 +73,8 @@         Glob >=0.9.3,         MonadRandom >=0.5.1.1,         aeson >=1.5.2.0,+        aws-xray-client-persistent >=0.1.0.5,+        aws-xray-client-wai >=0.1.0.2,         base >=4.11.1.0 && <5,         bugsnag >=1.0.0.1,         bytestring >=0.10.8.2,
library/Freckle/App/Database.hs view
@@ -37,17 +37,23 @@   , createPostgresqlPoolModified   , createSqlPool   , openSimpleConn+  , runSqlConn   , runSqlPool   ) import Database.PostgreSQL.Simple   (Connection, Only(..), connectPostgreSQL, execute) import Database.PostgreSQL.Simple.SqlQQ (sql) import qualified Freckle.App.Env as Env+import Freckle.App.Stats (HasStatsClient)+import qualified Freckle.App.Stats as Stats+import Network.AWS.XRayClient.Persistent+import Network.AWS.XRayClient.WAI import qualified Prelude as Unsafe (read) import System.Process.Typed (proc, readProcessStdout_) import UnliftIO.Concurrent (threadDelay) import UnliftIO.Exception (displayException) import UnliftIO.IORef+import Yesod.Core (MonadHandler, MonadUnliftIO(withRunInIO), waiRequest)  type SqlPool = Pool SqlBackend @@ -65,12 +71,48 @@   makePostgresPoolWith conf  runDB-  :: (HasSqlPool app, MonadUnliftIO m, MonadReader app m)+  :: ( HasSqlPool app+     , HasStatsClient app+     , MonadHandler m+     , MonadUnliftIO m+     , MonadReader app m+     )   => SqlPersistT m a   -> m a runDB action = do   pool <- asks getSqlPool-  runSqlPool action pool+  mVaultData <- vaultDataFromRequest <$> waiRequest+  Stats.withGauge Stats.dbConnections $+    maybe+      runSqlPool+      (runSqlPoolXRay "runDB")+      mVaultData+      action+      pool++-- | @'runSqlPool'@ but with XRay tracing+runSqlPoolXRay+  :: (backend ~ SqlBackend, MonadUnliftIO m)+  => Text+  -- ^ Subsegment name+  --+  -- The top-level subsegment will be named @\"<this> runSqlPool\"@ and the,+  -- with a lower-level subsegment named @\"<this> query\"@.+  --+  -> XRayVaultData -- ^ Vault data to trace with+  -> ReaderT backend m a+  -> Pool backend+  -> m a+runSqlPoolXRay name vaultData action pool =+  traceXRaySubsegment' vaultData (name <> " runSqlPool") id+    $ withRunInIO+    $ \run -> withResource pool $ \backend -> do+        let+          sendTrace = atomicallyAddVaultDataSubsegment vaultData+          stdGenIORef = xrayVaultDataStdGen vaultData+          subsegmentName = name <> " query"+        run . runSqlConn action =<< liftIO+          (xraySqlBackend sendTrace stdGenIORef subsegmentName backend)  data PostgresConnectionConf = PostgresConnectionConf   { pccHost :: String
library/Freckle/App/Stats.hs view
@@ -16,6 +16,12 @@   , withStatsClient   , HasStatsClient(..) +  -- * Gauges+  , Gauges+  , GaugeName+  , dbConnections+  , withGauge+   -- * Reporting   , tagged   , increment@@ -29,7 +35,7 @@ import Freckle.App.Prelude  import Blammo.Logging-import Control.Lens (Lens', lens, view, (&), (.~), (<>~))+import Control.Lens (Lens', lens, to, view, (&), (.~), (<>~)) import Control.Monad.Reader (local) import Data.Aeson (Value(..)) import Data.String@@ -37,6 +43,8 @@ import Freckle.App.Ecs import qualified Freckle.App.Env as Env import qualified Network.StatsD.Datadog as Datadog+import qualified System.Metrics.Gauge as EKG+import UnliftIO.Exception (bracket_) import Yesod.Core.Lens import Yesod.Core.Types (HandlerData) @@ -85,14 +93,32 @@         ]       <> tags +-- should be data but newtype for now because there's only one and only one planned+newtype Gauges = Gauges+  { gdbConnections :: EKG.Gauge+  -- ^ Track open db connections+  }++-- Opaque wrapper to hide EKG.Gauge+newtype GaugeName = GaugeName+  { unGaugeName :: Gauges -> EKG.Gauge+  }++dbConnections :: GaugeName+dbConnections = GaugeName gdbConnections+ data StatsClient = StatsClient   { scClient :: Datadog.StatsClient   , scTags :: [(Text, Text)]+  , scGauges :: Gauges   }  tagsL :: Lens' StatsClient [(Text, Text)] tagsL = lens scTags $ \x y -> x { scTags = y } +gaugesL :: Lens' StatsClient Gauges+gaugesL = lens scGauges $ \x y -> x { scGauges = y }+ class HasStatsClient env where   statsClientL :: Lens' env StatsClient @@ -108,16 +134,25 @@   -> (StatsClient -> m a)   -> m a withStatsClient StatsSettings {..} f = do+  gauges <- liftIO $ fmap Gauges EKG.new   if amsEnabled     then do       tags <- (amsTags <>) <$> getEcsMetadataTags-       Datadog.withDogStatsD amsSettings $ \client ->         -- Add the tags to the thread context so they're present in all logs         withThreadContext (map toPair tags)-          $ f StatsClient { scClient = client, scTags = tags }-    else f $ StatsClient { scClient = Datadog.Dummy, scTags = amsTags }+          $ f StatsClient { scClient = client, scTags = tags, scGauges = gauges }+    else do+      f $ StatsClient { scClient = Datadog.Dummy, scTags = amsTags, scGauges = gauges }   where toPair = bimap (fromString . unpack) String++withGauge :: (MonadReader app m, HasStatsClient app, MonadUnliftIO m) => GaugeName -> m a -> m a+withGauge gaugeName f = do+  gauge' <- view $ statsClientL . gaugesL . to (unGaugeName gaugeName)+  bracket_ (plus1 gauge') (minus1 gauge') f+  where+    plus1 g = liftIO $ EKG.add g 1+    minus1 g = liftIO $ EKG.subtract g 1  -- | Include the given tags on all metrics emitted from a block tagged
− library/Freckle/App/Stats/Gauge.hs
@@ -1,63 +0,0 @@--- | Stateful gauges for "Freckle.App.Stats"-module Freckle.App.Stats.Gauge-  ( Gauge-  , new-  , increment-  , decrement-  , add-  , subtract-  ) where--import Freckle.App.Prelude hiding (subtract)--import Freckle.App.Stats (HasStatsClient)-import qualified Freckle.App.Stats as Stats-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, HasStatsClient env) => Gauge -> m ()-increment = add 1---- | Add to gauge state and report its current value-add-  :: (MonadUnliftIO m, MonadReader env m, HasStatsClient env)-  => Int64-  -> Gauge-  -> m ()-add i = withEKGGauge (`EKG.add` i)---- | Decrement gauge state and report its current value-decrement-  :: (MonadUnliftIO m, MonadReader env m, HasStatsClient env) => Gauge -> m ()-decrement = subtract 1---- | Subtract from gauge state and report its current value-subtract-  :: (MonadUnliftIO m, MonadReader env m, HasStatsClient env)-  => Int64-  -> Gauge-  -> m ()-subtract i = withEKGGauge (`EKG.subtract` i)--withEKGGauge-  :: (MonadUnliftIO m, MonadReader env m, HasStatsClient env)-  => (EKG.Gauge -> IO ())-  -> Gauge-  -> m ()-withEKGGauge f Gauge {..} = do-  current <- liftIO $ do-    f ekgGauge-    EKG.read ekgGauge-  Stats.tagged tags $ Stats.gauge name $ fromIntegral current
package.yaml view
@@ -1,6 +1,6 @@ --- name: freckle-app-version: 1.6.0.3+version: 1.7.0.0 maintainer: Freckle Education category: Utils github: freckle/freckle-app@@ -50,6 +50,8 @@     - Glob     - MonadRandom     - aeson+    - aws-xray-client-persistent+    - aws-xray-client-wai     - bugsnag     - bytestring     - case-insensitive