{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE OverloadedStrings #-}
module Arbiter.Core.Health
( PgDbHealth (..)
, PgTableHealth (..)
, getPgHealth
, getPgDbHealth
) where
import Data.Aeson (FromJSON, ToJSON)
import Data.Int (Int64)
import Data.Maybe (listToMaybe)
import Data.Text (Text)
import GHC.Generics (Generic)
import Arbiter.Core.Codec (Col (..), RowCodec, col, ncol)
import Arbiter.Core.Job.Schema (SchemaName, TableName)
import Arbiter.Core.MonadArbiter (MonadArbiter (..))
import Arbiter.Core.SchemaTables (allSchemaTables)
import Arbiter.Core.Sql.Health qualified as Sql
import Arbiter.Core.Sql.Query (rows)
data PgDbHealth = PgDbHealth
{ PgDbHealth -> Int64
numBackends :: Int64
, PgDbHealth -> Int64
connActive :: Int64
, PgDbHealth -> Int64
connIdle :: Int64
, PgDbHealth -> Int64
connIdleInTxn :: Int64
, PgDbHealth -> Int64
connIdleInTxnAborted :: Int64
, PgDbHealth -> Int64
connBlocked :: Int64
, PgDbHealth -> Int64
connOther :: Int64
, PgDbHealth -> Double
oldestTxnAge :: Double
, PgDbHealth -> Double
oldestQueryAge :: Double
}
deriving stock (PgDbHealth -> PgDbHealth -> Bool
(PgDbHealth -> PgDbHealth -> Bool)
-> (PgDbHealth -> PgDbHealth -> Bool) -> Eq PgDbHealth
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PgDbHealth -> PgDbHealth -> Bool
== :: PgDbHealth -> PgDbHealth -> Bool
$c/= :: PgDbHealth -> PgDbHealth -> Bool
/= :: PgDbHealth -> PgDbHealth -> Bool
Eq, (forall x. PgDbHealth -> Rep PgDbHealth x)
-> (forall x. Rep PgDbHealth x -> PgDbHealth) -> Generic PgDbHealth
forall x. Rep PgDbHealth x -> PgDbHealth
forall x. PgDbHealth -> Rep PgDbHealth x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PgDbHealth -> Rep PgDbHealth x
from :: forall x. PgDbHealth -> Rep PgDbHealth x
$cto :: forall x. Rep PgDbHealth x -> PgDbHealth
to :: forall x. Rep PgDbHealth x -> PgDbHealth
Generic, Int -> PgDbHealth -> ShowS
[PgDbHealth] -> ShowS
PgDbHealth -> String
(Int -> PgDbHealth -> ShowS)
-> (PgDbHealth -> String)
-> ([PgDbHealth] -> ShowS)
-> Show PgDbHealth
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PgDbHealth -> ShowS
showsPrec :: Int -> PgDbHealth -> ShowS
$cshow :: PgDbHealth -> String
show :: PgDbHealth -> String
$cshowList :: [PgDbHealth] -> ShowS
showList :: [PgDbHealth] -> ShowS
Show)
deriving anyclass (Maybe PgDbHealth
Value -> Parser [PgDbHealth]
Value -> Parser PgDbHealth
(Value -> Parser PgDbHealth)
-> (Value -> Parser [PgDbHealth])
-> Maybe PgDbHealth
-> FromJSON PgDbHealth
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser PgDbHealth
parseJSON :: Value -> Parser PgDbHealth
$cparseJSONList :: Value -> Parser [PgDbHealth]
parseJSONList :: Value -> Parser [PgDbHealth]
$comittedField :: Maybe PgDbHealth
omittedField :: Maybe PgDbHealth
FromJSON, [PgDbHealth] -> Value
[PgDbHealth] -> Encoding
PgDbHealth -> Bool
PgDbHealth -> Value
PgDbHealth -> Encoding
(PgDbHealth -> Value)
-> (PgDbHealth -> Encoding)
-> ([PgDbHealth] -> Value)
-> ([PgDbHealth] -> Encoding)
-> (PgDbHealth -> Bool)
-> ToJSON PgDbHealth
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: PgDbHealth -> Value
toJSON :: PgDbHealth -> Value
$ctoEncoding :: PgDbHealth -> Encoding
toEncoding :: PgDbHealth -> Encoding
$ctoJSONList :: [PgDbHealth] -> Value
toJSONList :: [PgDbHealth] -> Value
$ctoEncodingList :: [PgDbHealth] -> Encoding
toEncodingList :: [PgDbHealth] -> Encoding
$comitField :: PgDbHealth -> Bool
omitField :: PgDbHealth -> Bool
ToJSON)
data PgTableHealth = PgTableHealth
{ PgTableHealth -> Text
table :: Text
, PgTableHealth -> Int64
liveTup :: Int64
, PgTableHealth -> Int64
deadTup :: Int64
, PgTableHealth -> Maybe Double
autovacuumAge :: Maybe Double
, PgTableHealth -> Int64
totalBytes :: Int64
, PgTableHealth -> Double
seqScan :: Double
, PgTableHealth -> Double
idxScan :: Double
, PgTableHealth -> Double
blksHit :: Double
, PgTableHealth -> Double
blksRead :: Double
, PgTableHealth -> Maybe Int64
xidAge :: Maybe Int64
}
deriving stock (PgTableHealth -> PgTableHealth -> Bool
(PgTableHealth -> PgTableHealth -> Bool)
-> (PgTableHealth -> PgTableHealth -> Bool) -> Eq PgTableHealth
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PgTableHealth -> PgTableHealth -> Bool
== :: PgTableHealth -> PgTableHealth -> Bool
$c/= :: PgTableHealth -> PgTableHealth -> Bool
/= :: PgTableHealth -> PgTableHealth -> Bool
Eq, (forall x. PgTableHealth -> Rep PgTableHealth x)
-> (forall x. Rep PgTableHealth x -> PgTableHealth)
-> Generic PgTableHealth
forall x. Rep PgTableHealth x -> PgTableHealth
forall x. PgTableHealth -> Rep PgTableHealth x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PgTableHealth -> Rep PgTableHealth x
from :: forall x. PgTableHealth -> Rep PgTableHealth x
$cto :: forall x. Rep PgTableHealth x -> PgTableHealth
to :: forall x. Rep PgTableHealth x -> PgTableHealth
Generic, Int -> PgTableHealth -> ShowS
[PgTableHealth] -> ShowS
PgTableHealth -> String
(Int -> PgTableHealth -> ShowS)
-> (PgTableHealth -> String)
-> ([PgTableHealth] -> ShowS)
-> Show PgTableHealth
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PgTableHealth -> ShowS
showsPrec :: Int -> PgTableHealth -> ShowS
$cshow :: PgTableHealth -> String
show :: PgTableHealth -> String
$cshowList :: [PgTableHealth] -> ShowS
showList :: [PgTableHealth] -> ShowS
Show)
deriving anyclass (Maybe PgTableHealth
Value -> Parser [PgTableHealth]
Value -> Parser PgTableHealth
(Value -> Parser PgTableHealth)
-> (Value -> Parser [PgTableHealth])
-> Maybe PgTableHealth
-> FromJSON PgTableHealth
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser PgTableHealth
parseJSON :: Value -> Parser PgTableHealth
$cparseJSONList :: Value -> Parser [PgTableHealth]
parseJSONList :: Value -> Parser [PgTableHealth]
$comittedField :: Maybe PgTableHealth
omittedField :: Maybe PgTableHealth
FromJSON, [PgTableHealth] -> Value
[PgTableHealth] -> Encoding
PgTableHealth -> Bool
PgTableHealth -> Value
PgTableHealth -> Encoding
(PgTableHealth -> Value)
-> (PgTableHealth -> Encoding)
-> ([PgTableHealth] -> Value)
-> ([PgTableHealth] -> Encoding)
-> (PgTableHealth -> Bool)
-> ToJSON PgTableHealth
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: PgTableHealth -> Value
toJSON :: PgTableHealth -> Value
$ctoEncoding :: PgTableHealth -> Encoding
toEncoding :: PgTableHealth -> Encoding
$ctoJSONList :: [PgTableHealth] -> Value
toJSONList :: [PgTableHealth] -> Value
$ctoEncodingList :: [PgTableHealth] -> Encoding
toEncodingList :: [PgTableHealth] -> Encoding
$comitField :: PgTableHealth -> Bool
omitField :: PgTableHealth -> Bool
ToJSON)
pgDbHealthCodec :: RowCodec PgDbHealth
pgDbHealthCodec :: RowCodec PgDbHealth
pgDbHealthCodec =
Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Double
-> Double
-> PgDbHealth
PgDbHealth
(Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Double
-> Double
-> PgDbHealth)
-> Ap NullCol Int64
-> Ap
NullCol
(Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Double
-> Double
-> PgDbHealth)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"numbackends" Col Int64
CInt8
Ap
NullCol
(Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Double
-> Double
-> PgDbHealth)
-> Ap NullCol Int64
-> Ap
NullCol
(Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Double
-> Double
-> PgDbHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"active" Col Int64
CInt8
Ap
NullCol
(Int64
-> Int64
-> Int64
-> Int64
-> Int64
-> Double
-> Double
-> PgDbHealth)
-> Ap NullCol Int64
-> Ap
NullCol
(Int64
-> Int64 -> Int64 -> Int64 -> Double -> Double -> PgDbHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"idle" Col Int64
CInt8
Ap
NullCol
(Int64
-> Int64 -> Int64 -> Int64 -> Double -> Double -> PgDbHealth)
-> Ap NullCol Int64
-> Ap
NullCol (Int64 -> Int64 -> Int64 -> Double -> Double -> PgDbHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"idle_in_txn" Col Int64
CInt8
Ap
NullCol (Int64 -> Int64 -> Int64 -> Double -> Double -> PgDbHealth)
-> Ap NullCol Int64
-> Ap NullCol (Int64 -> Int64 -> Double -> Double -> PgDbHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"idle_in_txn_aborted" Col Int64
CInt8
Ap NullCol (Int64 -> Int64 -> Double -> Double -> PgDbHealth)
-> Ap NullCol Int64
-> Ap NullCol (Int64 -> Double -> Double -> PgDbHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"blocked" Col Int64
CInt8
Ap NullCol (Int64 -> Double -> Double -> PgDbHealth)
-> Ap NullCol Int64 -> Ap NullCol (Double -> Double -> PgDbHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"other" Col Int64
CInt8
Ap NullCol (Double -> Double -> PgDbHealth)
-> Ap NullCol Double -> Ap NullCol (Double -> PgDbHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Double -> Ap NullCol Double
forall a. Text -> Col a -> RowCodec a
col Text
"oldest_txn_age" Col Double
CFloat8
Ap NullCol (Double -> PgDbHealth)
-> Ap NullCol Double -> RowCodec PgDbHealth
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Double -> Ap NullCol Double
forall a. Text -> Col a -> RowCodec a
col Text
"oldest_query_age" Col Double
CFloat8
pgTableHealthCodec :: RowCodec PgTableHealth
pgTableHealthCodec :: RowCodec PgTableHealth
pgTableHealthCodec =
Text
-> Int64
-> Int64
-> Maybe Double
-> Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth
PgTableHealth
(Text
-> Int64
-> Int64
-> Maybe Double
-> Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
-> Ap NullCol Text
-> Ap
NullCol
(Int64
-> Int64
-> Maybe Double
-> Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Col Text -> Ap NullCol Text
forall a. Text -> Col a -> RowCodec a
col Text
"relname" Col Text
CText
Ap
NullCol
(Int64
-> Int64
-> Maybe Double
-> Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
-> Ap NullCol Int64
-> Ap
NullCol
(Int64
-> Maybe Double
-> Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"n_live_tup" Col Int64
CInt8
Ap
NullCol
(Int64
-> Maybe Double
-> Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
-> Ap NullCol Int64
-> Ap
NullCol
(Maybe Double
-> Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"n_dead_tup" Col Int64
CInt8
Ap
NullCol
(Maybe Double
-> Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
-> Ap NullCol (Maybe Double)
-> Ap
NullCol
(Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Double -> Ap NullCol (Maybe Double)
forall a. Text -> Col a -> RowCodec (Maybe a)
ncol Text
"autovacuum_age" Col Double
CFloat8
Ap
NullCol
(Int64
-> Double
-> Double
-> Double
-> Double
-> Maybe Int64
-> PgTableHealth)
-> Ap NullCol Int64
-> Ap
NullCol
(Double
-> Double -> Double -> Double -> Maybe Int64 -> PgTableHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol Int64
forall a. Text -> Col a -> RowCodec a
col Text
"total_bytes" Col Int64
CInt8
Ap
NullCol
(Double
-> Double -> Double -> Double -> Maybe Int64 -> PgTableHealth)
-> Ap NullCol Double
-> Ap
NullCol
(Double -> Double -> Double -> Maybe Int64 -> PgTableHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Double -> Ap NullCol Double
forall a. Text -> Col a -> RowCodec a
col Text
"seq_scan" Col Double
CFloat8
Ap
NullCol
(Double -> Double -> Double -> Maybe Int64 -> PgTableHealth)
-> Ap NullCol Double
-> Ap NullCol (Double -> Double -> Maybe Int64 -> PgTableHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Double -> Ap NullCol Double
forall a. Text -> Col a -> RowCodec a
col Text
"idx_scan" Col Double
CFloat8
Ap NullCol (Double -> Double -> Maybe Int64 -> PgTableHealth)
-> Ap NullCol Double
-> Ap NullCol (Double -> Maybe Int64 -> PgTableHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Double -> Ap NullCol Double
forall a. Text -> Col a -> RowCodec a
col Text
"blks_hit" Col Double
CFloat8
Ap NullCol (Double -> Maybe Int64 -> PgTableHealth)
-> Ap NullCol Double -> Ap NullCol (Maybe Int64 -> PgTableHealth)
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Double -> Ap NullCol Double
forall a. Text -> Col a -> RowCodec a
col Text
"blks_read" Col Double
CFloat8
Ap NullCol (Maybe Int64 -> PgTableHealth)
-> Ap NullCol (Maybe Int64) -> RowCodec PgTableHealth
forall a b. Ap NullCol (a -> b) -> Ap NullCol a -> Ap NullCol b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Col Int64 -> Ap NullCol (Maybe Int64)
forall a. Text -> Col a -> RowCodec (Maybe a)
ncol Text
"xid_age" Col Int64
CInt8
getPgHealth :: (MonadArbiter m) => SchemaName -> [TableName] -> m (Maybe PgDbHealth, [PgTableHealth])
getPgHealth :: forall (m :: * -> *).
MonadArbiter m =>
Text -> [Text] -> m (Maybe PgDbHealth, [PgTableHealth])
getPgHealth Text
schemaName [Text]
queueTables = do
dbHealth <- m (Maybe PgDbHealth)
forall (m :: * -> *). MonadArbiter m => m (Maybe PgDbHealth)
getPgDbHealth
tableRows <- executeQuery (rows pgTableHealthCodec (Sql.pgTableHealthSQL schemaName scanned))
pure (dbHealth, tableRows)
where
scanned :: [Text]
scanned = [Text] -> [Text]
allSchemaTables [Text]
queueTables
getPgDbHealth :: (MonadArbiter m) => m (Maybe PgDbHealth)
getPgDbHealth :: forall (m :: * -> *). MonadArbiter m => m (Maybe PgDbHealth)
getPgDbHealth = [PgDbHealth] -> Maybe PgDbHealth
forall a. [a] -> Maybe a
listToMaybe ([PgDbHealth] -> Maybe PgDbHealth)
-> m [PgDbHealth] -> m (Maybe PgDbHealth)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Query PgDbHealth -> m [PgDbHealth]
forall a. Query a -> m [a]
forall (m :: * -> *) a. MonadArbiter m => Query a -> m [a]
executeQuery (RowCodec PgDbHealth -> Query () -> Query PgDbHealth
forall a. RowCodec a -> Query () -> Query a
rows RowCodec PgDbHealth
pgDbHealthCodec Query ()
Sql.pgDbHealthSQL)