{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE TemplateHaskell #-}

-- |
--  Counters used in telemetry collection. Additional counters can be added here.and
--  serviced in "Hasura.Server.Telemetry".
module Hasura.Server.Telemetry.Counters
  ( -- * Service timing and counts, by various dimensions

    -- ** Local metric recording
    recordTimingMetric,
    RequestDimensions (..),
    RequestTimings (..),

    -- *** Dimensions
    QueryType (..),
    Locality (..),
    Transport (..),

    -- ** Metric upload
    dumpServiceTimingMetrics,
    ServiceTimingMetrics (..),
    ServiceTimingMetric (..),
    RunningTimeBucket (..),
    RequestTimingsCount (..),
  )
where

import Data.Aeson qualified as J
import Data.HashMap.Strict qualified as HashMap
import Data.IORef
import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime)
import GHC.IO.Unsafe (unsafePerformIO)
import Hasura.Prelude

-- | The properties that characterize this request. The dimensions over which
-- we collect metrics for each serviced request.
data RequestDimensions = RequestDimensions
  { RequestDimensions -> QueryType
telemQueryType :: !QueryType,
    RequestDimensions -> Locality
telemLocality :: !Locality,
    RequestDimensions -> Transport
telemTransport :: !Transport
  }
  deriving (Int -> RequestDimensions -> ShowS
[RequestDimensions] -> ShowS
RequestDimensions -> String
(Int -> RequestDimensions -> ShowS)
-> (RequestDimensions -> String)
-> ([RequestDimensions] -> ShowS)
-> Show RequestDimensions
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RequestDimensions -> ShowS
showsPrec :: Int -> RequestDimensions -> ShowS
$cshow :: RequestDimensions -> String
show :: RequestDimensions -> String
$cshowList :: [RequestDimensions] -> ShowS
showList :: [RequestDimensions] -> ShowS
Show, (forall x. RequestDimensions -> Rep RequestDimensions x)
-> (forall x. Rep RequestDimensions x -> RequestDimensions)
-> Generic RequestDimensions
forall x. Rep RequestDimensions x -> RequestDimensions
forall x. RequestDimensions -> Rep RequestDimensions x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. RequestDimensions -> Rep RequestDimensions x
from :: forall x. RequestDimensions -> Rep RequestDimensions x
$cto :: forall x. Rep RequestDimensions x -> RequestDimensions
to :: forall x. Rep RequestDimensions x -> RequestDimensions
Generic, RequestDimensions -> RequestDimensions -> Bool
(RequestDimensions -> RequestDimensions -> Bool)
-> (RequestDimensions -> RequestDimensions -> Bool)
-> Eq RequestDimensions
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RequestDimensions -> RequestDimensions -> Bool
== :: RequestDimensions -> RequestDimensions -> Bool
$c/= :: RequestDimensions -> RequestDimensions -> Bool
/= :: RequestDimensions -> RequestDimensions -> Bool
Eq, Eq RequestDimensions
Eq RequestDimensions
-> (RequestDimensions -> RequestDimensions -> Ordering)
-> (RequestDimensions -> RequestDimensions -> Bool)
-> (RequestDimensions -> RequestDimensions -> Bool)
-> (RequestDimensions -> RequestDimensions -> Bool)
-> (RequestDimensions -> RequestDimensions -> Bool)
-> (RequestDimensions -> RequestDimensions -> RequestDimensions)
-> (RequestDimensions -> RequestDimensions -> RequestDimensions)
-> Ord RequestDimensions
RequestDimensions -> RequestDimensions -> Bool
RequestDimensions -> RequestDimensions -> Ordering
RequestDimensions -> RequestDimensions -> RequestDimensions
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RequestDimensions -> RequestDimensions -> Ordering
compare :: RequestDimensions -> RequestDimensions -> Ordering
$c< :: RequestDimensions -> RequestDimensions -> Bool
< :: RequestDimensions -> RequestDimensions -> Bool
$c<= :: RequestDimensions -> RequestDimensions -> Bool
<= :: RequestDimensions -> RequestDimensions -> Bool
$c> :: RequestDimensions -> RequestDimensions -> Bool
> :: RequestDimensions -> RequestDimensions -> Bool
$c>= :: RequestDimensions -> RequestDimensions -> Bool
>= :: RequestDimensions -> RequestDimensions -> Bool
$cmax :: RequestDimensions -> RequestDimensions -> RequestDimensions
max :: RequestDimensions -> RequestDimensions -> RequestDimensions
$cmin :: RequestDimensions -> RequestDimensions -> RequestDimensions
min :: RequestDimensions -> RequestDimensions -> RequestDimensions
Ord)

instance Hashable RequestDimensions

-- | Accumulated time metrics.
data RequestTimings = RequestTimings
  { -- | Time spent waiting on PG/remote http calls
    RequestTimings -> Seconds
telemTimeIO :: !Seconds,
    -- | Total service time for request (including 'telemTimeIO')
    RequestTimings -> Seconds
telemTimeTot :: !Seconds
  }

-- | Sum
instance Semigroup RequestTimings where
  RequestTimings Seconds
a Seconds
b <> :: RequestTimings -> RequestTimings -> RequestTimings
<> RequestTimings Seconds
x Seconds
y = Seconds -> Seconds -> RequestTimings
RequestTimings (Seconds
a Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Seconds
x) (Seconds
b Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Seconds
y)

-- | 'RequestTimings' along with the count
data RequestTimingsCount = RequestTimingsCount
  { RequestTimingsCount -> Seconds
telemTimeIO :: !Seconds,
    RequestTimingsCount -> Seconds
telemTimeTot :: !Seconds,
    -- | The number of requests that have contributed to the accumulated timings above.
    -- So e.g. @telemTimeTot / count@ would give the mean service time.
    RequestTimingsCount -> Word
telemCount :: !Word
  }
  deriving (Int -> RequestTimingsCount -> ShowS
[RequestTimingsCount] -> ShowS
RequestTimingsCount -> String
(Int -> RequestTimingsCount -> ShowS)
-> (RequestTimingsCount -> String)
-> ([RequestTimingsCount] -> ShowS)
-> Show RequestTimingsCount
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RequestTimingsCount -> ShowS
showsPrec :: Int -> RequestTimingsCount -> ShowS
$cshow :: RequestTimingsCount -> String
show :: RequestTimingsCount -> String
$cshowList :: [RequestTimingsCount] -> ShowS
showList :: [RequestTimingsCount] -> ShowS
Show, (forall x. RequestTimingsCount -> Rep RequestTimingsCount x)
-> (forall x. Rep RequestTimingsCount x -> RequestTimingsCount)
-> Generic RequestTimingsCount
forall x. Rep RequestTimingsCount x -> RequestTimingsCount
forall x. RequestTimingsCount -> Rep RequestTimingsCount x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. RequestTimingsCount -> Rep RequestTimingsCount x
from :: forall x. RequestTimingsCount -> Rep RequestTimingsCount x
$cto :: forall x. Rep RequestTimingsCount x -> RequestTimingsCount
to :: forall x. Rep RequestTimingsCount x -> RequestTimingsCount
Generic, RequestTimingsCount -> RequestTimingsCount -> Bool
(RequestTimingsCount -> RequestTimingsCount -> Bool)
-> (RequestTimingsCount -> RequestTimingsCount -> Bool)
-> Eq RequestTimingsCount
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RequestTimingsCount -> RequestTimingsCount -> Bool
== :: RequestTimingsCount -> RequestTimingsCount -> Bool
$c/= :: RequestTimingsCount -> RequestTimingsCount -> Bool
/= :: RequestTimingsCount -> RequestTimingsCount -> Bool
Eq, Eq RequestTimingsCount
Eq RequestTimingsCount
-> (RequestTimingsCount -> RequestTimingsCount -> Ordering)
-> (RequestTimingsCount -> RequestTimingsCount -> Bool)
-> (RequestTimingsCount -> RequestTimingsCount -> Bool)
-> (RequestTimingsCount -> RequestTimingsCount -> Bool)
-> (RequestTimingsCount -> RequestTimingsCount -> Bool)
-> (RequestTimingsCount
    -> RequestTimingsCount -> RequestTimingsCount)
-> (RequestTimingsCount
    -> RequestTimingsCount -> RequestTimingsCount)
-> Ord RequestTimingsCount
RequestTimingsCount -> RequestTimingsCount -> Bool
RequestTimingsCount -> RequestTimingsCount -> Ordering
RequestTimingsCount -> RequestTimingsCount -> RequestTimingsCount
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RequestTimingsCount -> RequestTimingsCount -> Ordering
compare :: RequestTimingsCount -> RequestTimingsCount -> Ordering
$c< :: RequestTimingsCount -> RequestTimingsCount -> Bool
< :: RequestTimingsCount -> RequestTimingsCount -> Bool
$c<= :: RequestTimingsCount -> RequestTimingsCount -> Bool
<= :: RequestTimingsCount -> RequestTimingsCount -> Bool
$c> :: RequestTimingsCount -> RequestTimingsCount -> Bool
> :: RequestTimingsCount -> RequestTimingsCount -> Bool
$c>= :: RequestTimingsCount -> RequestTimingsCount -> Bool
>= :: RequestTimingsCount -> RequestTimingsCount -> Bool
$cmax :: RequestTimingsCount -> RequestTimingsCount -> RequestTimingsCount
max :: RequestTimingsCount -> RequestTimingsCount -> RequestTimingsCount
$cmin :: RequestTimingsCount -> RequestTimingsCount -> RequestTimingsCount
min :: RequestTimingsCount -> RequestTimingsCount -> RequestTimingsCount
Ord)

-- | Sum
instance Semigroup RequestTimingsCount where
  RequestTimingsCount Seconds
a Seconds
b Word
c <> :: RequestTimingsCount -> RequestTimingsCount -> RequestTimingsCount
<> RequestTimingsCount Seconds
x Seconds
y Word
z =
    Seconds -> Seconds -> Word -> RequestTimingsCount
RequestTimingsCount (Seconds
a Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Seconds
x) (Seconds
b Seconds -> Seconds -> Seconds
forall a. Num a => a -> a -> a
+ Seconds
y) (Word
c Word -> Word -> Word
forall a. Num a => a -> a -> a
+ Word
z)

-- | Internal. Counts and durations across many 'RequestDimensions'.
--
-- NOTE: We use the global mutable variable pattern for metric collection
-- counters for convenience at collection site (don't wear hairshirts that
-- discourage useful reporting).
requestCounters :: IORef (HashMap.HashMap (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
{-# NOINLINE requestCounters #-}
requestCounters :: IORef
  (HashMap
     (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
requestCounters = IO
  (IORef
     (HashMap
        (RequestDimensions, RunningTimeBucket) RequestTimingsCount))
-> IORef
     (HashMap
        (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
forall a. IO a -> a
unsafePerformIO (IO
   (IORef
      (HashMap
         (RequestDimensions, RunningTimeBucket) RequestTimingsCount))
 -> IORef
      (HashMap
         (RequestDimensions, RunningTimeBucket) RequestTimingsCount))
-> IO
     (IORef
        (HashMap
           (RequestDimensions, RunningTimeBucket) RequestTimingsCount))
-> IORef
     (HashMap
        (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
forall a b. (a -> b) -> a -> b
$ HashMap (RequestDimensions, RunningTimeBucket) RequestTimingsCount
-> IO
     (IORef
        (HashMap
           (RequestDimensions, RunningTimeBucket) RequestTimingsCount))
forall a. a -> IO (IORef a)
newIORef HashMap (RequestDimensions, RunningTimeBucket) RequestTimingsCount
forall k v. HashMap k v
HashMap.empty

-- | Internal. Since these metrics are accumulated while graphql-engine is
-- running and sent periodically, we need to include a tag that is unique for
-- each start of hge. This lets us e.g. query for just the latest uploaded
-- sample for each start of hge.
--
-- We use time rather than a UUID since having this be monotonic increasing is
-- convenient.
approxStartTime :: POSIXTime
{-# NOINLINE approxStartTime #-}
approxStartTime :: POSIXTime
approxStartTime = IO POSIXTime -> POSIXTime
forall a. IO a -> a
unsafePerformIO IO POSIXTime
getPOSIXTime

-- | Was this request a mutation (involved DB writes)?
data QueryType = Mutation | Query
  deriving (Int -> QueryType
QueryType -> Int
QueryType -> [QueryType]
QueryType -> QueryType
QueryType -> QueryType -> [QueryType]
QueryType -> QueryType -> QueryType -> [QueryType]
(QueryType -> QueryType)
-> (QueryType -> QueryType)
-> (Int -> QueryType)
-> (QueryType -> Int)
-> (QueryType -> [QueryType])
-> (QueryType -> QueryType -> [QueryType])
-> (QueryType -> QueryType -> [QueryType])
-> (QueryType -> QueryType -> QueryType -> [QueryType])
-> Enum QueryType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: QueryType -> QueryType
succ :: QueryType -> QueryType
$cpred :: QueryType -> QueryType
pred :: QueryType -> QueryType
$ctoEnum :: Int -> QueryType
toEnum :: Int -> QueryType
$cfromEnum :: QueryType -> Int
fromEnum :: QueryType -> Int
$cenumFrom :: QueryType -> [QueryType]
enumFrom :: QueryType -> [QueryType]
$cenumFromThen :: QueryType -> QueryType -> [QueryType]
enumFromThen :: QueryType -> QueryType -> [QueryType]
$cenumFromTo :: QueryType -> QueryType -> [QueryType]
enumFromTo :: QueryType -> QueryType -> [QueryType]
$cenumFromThenTo :: QueryType -> QueryType -> QueryType -> [QueryType]
enumFromThenTo :: QueryType -> QueryType -> QueryType -> [QueryType]
Enum, Int -> QueryType -> ShowS
[QueryType] -> ShowS
QueryType -> String
(Int -> QueryType -> ShowS)
-> (QueryType -> String)
-> ([QueryType] -> ShowS)
-> Show QueryType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> QueryType -> ShowS
showsPrec :: Int -> QueryType -> ShowS
$cshow :: QueryType -> String
show :: QueryType -> String
$cshowList :: [QueryType] -> ShowS
showList :: [QueryType] -> ShowS
Show, QueryType -> QueryType -> Bool
(QueryType -> QueryType -> Bool)
-> (QueryType -> QueryType -> Bool) -> Eq QueryType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: QueryType -> QueryType -> Bool
== :: QueryType -> QueryType -> Bool
$c/= :: QueryType -> QueryType -> Bool
/= :: QueryType -> QueryType -> Bool
Eq, Eq QueryType
Eq QueryType
-> (QueryType -> QueryType -> Ordering)
-> (QueryType -> QueryType -> Bool)
-> (QueryType -> QueryType -> Bool)
-> (QueryType -> QueryType -> Bool)
-> (QueryType -> QueryType -> Bool)
-> (QueryType -> QueryType -> QueryType)
-> (QueryType -> QueryType -> QueryType)
-> Ord QueryType
QueryType -> QueryType -> Bool
QueryType -> QueryType -> Ordering
QueryType -> QueryType -> QueryType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: QueryType -> QueryType -> Ordering
compare :: QueryType -> QueryType -> Ordering
$c< :: QueryType -> QueryType -> Bool
< :: QueryType -> QueryType -> Bool
$c<= :: QueryType -> QueryType -> Bool
<= :: QueryType -> QueryType -> Bool
$c> :: QueryType -> QueryType -> Bool
> :: QueryType -> QueryType -> Bool
$c>= :: QueryType -> QueryType -> Bool
>= :: QueryType -> QueryType -> Bool
$cmax :: QueryType -> QueryType -> QueryType
max :: QueryType -> QueryType -> QueryType
$cmin :: QueryType -> QueryType -> QueryType
min :: QueryType -> QueryType -> QueryType
Ord, (forall x. QueryType -> Rep QueryType x)
-> (forall x. Rep QueryType x -> QueryType) -> Generic QueryType
forall x. Rep QueryType x -> QueryType
forall x. QueryType -> Rep QueryType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. QueryType -> Rep QueryType x
from :: forall x. QueryType -> Rep QueryType x
$cto :: forall x. Rep QueryType x -> QueryType
to :: forall x. Rep QueryType x -> QueryType
Generic)

instance Hashable QueryType

instance J.ToJSON QueryType

instance J.FromJSON QueryType

-- | Was this a PG local query, or did it involve remote execution?
data Locality
  = -- | No data was fetched
    Empty
  | -- | local DB data
    Local
  | -- | remote schema
    Remote
  | -- | mixed
    Heterogeneous
  deriving (Int -> Locality
Locality -> Int
Locality -> [Locality]
Locality -> Locality
Locality -> Locality -> [Locality]
Locality -> Locality -> Locality -> [Locality]
(Locality -> Locality)
-> (Locality -> Locality)
-> (Int -> Locality)
-> (Locality -> Int)
-> (Locality -> [Locality])
-> (Locality -> Locality -> [Locality])
-> (Locality -> Locality -> [Locality])
-> (Locality -> Locality -> Locality -> [Locality])
-> Enum Locality
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Locality -> Locality
succ :: Locality -> Locality
$cpred :: Locality -> Locality
pred :: Locality -> Locality
$ctoEnum :: Int -> Locality
toEnum :: Int -> Locality
$cfromEnum :: Locality -> Int
fromEnum :: Locality -> Int
$cenumFrom :: Locality -> [Locality]
enumFrom :: Locality -> [Locality]
$cenumFromThen :: Locality -> Locality -> [Locality]
enumFromThen :: Locality -> Locality -> [Locality]
$cenumFromTo :: Locality -> Locality -> [Locality]
enumFromTo :: Locality -> Locality -> [Locality]
$cenumFromThenTo :: Locality -> Locality -> Locality -> [Locality]
enumFromThenTo :: Locality -> Locality -> Locality -> [Locality]
Enum, Int -> Locality -> ShowS
[Locality] -> ShowS
Locality -> String
(Int -> Locality -> ShowS)
-> (Locality -> String) -> ([Locality] -> ShowS) -> Show Locality
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Locality -> ShowS
showsPrec :: Int -> Locality -> ShowS
$cshow :: Locality -> String
show :: Locality -> String
$cshowList :: [Locality] -> ShowS
showList :: [Locality] -> ShowS
Show, Locality -> Locality -> Bool
(Locality -> Locality -> Bool)
-> (Locality -> Locality -> Bool) -> Eq Locality
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Locality -> Locality -> Bool
== :: Locality -> Locality -> Bool
$c/= :: Locality -> Locality -> Bool
/= :: Locality -> Locality -> Bool
Eq, Eq Locality
Eq Locality
-> (Locality -> Locality -> Ordering)
-> (Locality -> Locality -> Bool)
-> (Locality -> Locality -> Bool)
-> (Locality -> Locality -> Bool)
-> (Locality -> Locality -> Bool)
-> (Locality -> Locality -> Locality)
-> (Locality -> Locality -> Locality)
-> Ord Locality
Locality -> Locality -> Bool
Locality -> Locality -> Ordering
Locality -> Locality -> Locality
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Locality -> Locality -> Ordering
compare :: Locality -> Locality -> Ordering
$c< :: Locality -> Locality -> Bool
< :: Locality -> Locality -> Bool
$c<= :: Locality -> Locality -> Bool
<= :: Locality -> Locality -> Bool
$c> :: Locality -> Locality -> Bool
> :: Locality -> Locality -> Bool
$c>= :: Locality -> Locality -> Bool
>= :: Locality -> Locality -> Bool
$cmax :: Locality -> Locality -> Locality
max :: Locality -> Locality -> Locality
$cmin :: Locality -> Locality -> Locality
min :: Locality -> Locality -> Locality
Ord, (forall x. Locality -> Rep Locality x)
-> (forall x. Rep Locality x -> Locality) -> Generic Locality
forall x. Rep Locality x -> Locality
forall x. Locality -> Rep Locality x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Locality -> Rep Locality x
from :: forall x. Locality -> Rep Locality x
$cto :: forall x. Rep Locality x -> Locality
to :: forall x. Rep Locality x -> Locality
Generic)

instance Hashable Locality

instance J.ToJSON Locality

instance J.FromJSON Locality

instance Semigroup Locality where
  Locality
Empty <> :: Locality -> Locality -> Locality
<> Locality
x = Locality
x
  Locality
x <> Locality
Empty = Locality
x
  Locality
x <> Locality
y | Locality
x Locality -> Locality -> Bool
forall a. Eq a => a -> a -> Bool
== Locality
y = Locality
x
  Locality
_ <> Locality
_ = Locality
Heterogeneous

instance Monoid Locality where
  mempty :: Locality
mempty = Locality
Empty

-- | Was this a query over http or websockets?
data Transport = HTTP | WebSocket
  deriving (Int -> Transport
Transport -> Int
Transport -> [Transport]
Transport -> Transport
Transport -> Transport -> [Transport]
Transport -> Transport -> Transport -> [Transport]
(Transport -> Transport)
-> (Transport -> Transport)
-> (Int -> Transport)
-> (Transport -> Int)
-> (Transport -> [Transport])
-> (Transport -> Transport -> [Transport])
-> (Transport -> Transport -> [Transport])
-> (Transport -> Transport -> Transport -> [Transport])
-> Enum Transport
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Transport -> Transport
succ :: Transport -> Transport
$cpred :: Transport -> Transport
pred :: Transport -> Transport
$ctoEnum :: Int -> Transport
toEnum :: Int -> Transport
$cfromEnum :: Transport -> Int
fromEnum :: Transport -> Int
$cenumFrom :: Transport -> [Transport]
enumFrom :: Transport -> [Transport]
$cenumFromThen :: Transport -> Transport -> [Transport]
enumFromThen :: Transport -> Transport -> [Transport]
$cenumFromTo :: Transport -> Transport -> [Transport]
enumFromTo :: Transport -> Transport -> [Transport]
$cenumFromThenTo :: Transport -> Transport -> Transport -> [Transport]
enumFromThenTo :: Transport -> Transport -> Transport -> [Transport]
Enum, Int -> Transport -> ShowS
[Transport] -> ShowS
Transport -> String
(Int -> Transport -> ShowS)
-> (Transport -> String)
-> ([Transport] -> ShowS)
-> Show Transport
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Transport -> ShowS
showsPrec :: Int -> Transport -> ShowS
$cshow :: Transport -> String
show :: Transport -> String
$cshowList :: [Transport] -> ShowS
showList :: [Transport] -> ShowS
Show, Transport -> Transport -> Bool
(Transport -> Transport -> Bool)
-> (Transport -> Transport -> Bool) -> Eq Transport
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Transport -> Transport -> Bool
== :: Transport -> Transport -> Bool
$c/= :: Transport -> Transport -> Bool
/= :: Transport -> Transport -> Bool
Eq, Eq Transport
Eq Transport
-> (Transport -> Transport -> Ordering)
-> (Transport -> Transport -> Bool)
-> (Transport -> Transport -> Bool)
-> (Transport -> Transport -> Bool)
-> (Transport -> Transport -> Bool)
-> (Transport -> Transport -> Transport)
-> (Transport -> Transport -> Transport)
-> Ord Transport
Transport -> Transport -> Bool
Transport -> Transport -> Ordering
Transport -> Transport -> Transport
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Transport -> Transport -> Ordering
compare :: Transport -> Transport -> Ordering
$c< :: Transport -> Transport -> Bool
< :: Transport -> Transport -> Bool
$c<= :: Transport -> Transport -> Bool
<= :: Transport -> Transport -> Bool
$c> :: Transport -> Transport -> Bool
> :: Transport -> Transport -> Bool
$c>= :: Transport -> Transport -> Bool
>= :: Transport -> Transport -> Bool
$cmax :: Transport -> Transport -> Transport
max :: Transport -> Transport -> Transport
$cmin :: Transport -> Transport -> Transport
min :: Transport -> Transport -> Transport
Ord, (forall x. Transport -> Rep Transport x)
-> (forall x. Rep Transport x -> Transport) -> Generic Transport
forall x. Rep Transport x -> Transport
forall x. Transport -> Rep Transport x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Transport -> Rep Transport x
from :: forall x. Transport -> Rep Transport x
$cto :: forall x. Rep Transport x -> Transport
to :: forall x. Rep Transport x -> Transport
Generic)

instance Hashable Transport

instance J.ToJSON Transport

instance J.FromJSON Transport

-- | The timings and counts here were from requests with total time longer than
-- 'bucketGreaterThan' (but less than any larger bucket cutoff times).
newtype RunningTimeBucket = RunningTimeBucket {RunningTimeBucket -> Seconds
bucketGreaterThan :: Seconds}
  deriving (Eq RunningTimeBucket
Eq RunningTimeBucket
-> (RunningTimeBucket -> RunningTimeBucket -> Ordering)
-> (RunningTimeBucket -> RunningTimeBucket -> Bool)
-> (RunningTimeBucket -> RunningTimeBucket -> Bool)
-> (RunningTimeBucket -> RunningTimeBucket -> Bool)
-> (RunningTimeBucket -> RunningTimeBucket -> Bool)
-> (RunningTimeBucket -> RunningTimeBucket -> RunningTimeBucket)
-> (RunningTimeBucket -> RunningTimeBucket -> RunningTimeBucket)
-> Ord RunningTimeBucket
RunningTimeBucket -> RunningTimeBucket -> Bool
RunningTimeBucket -> RunningTimeBucket -> Ordering
RunningTimeBucket -> RunningTimeBucket -> RunningTimeBucket
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RunningTimeBucket -> RunningTimeBucket -> Ordering
compare :: RunningTimeBucket -> RunningTimeBucket -> Ordering
$c< :: RunningTimeBucket -> RunningTimeBucket -> Bool
< :: RunningTimeBucket -> RunningTimeBucket -> Bool
$c<= :: RunningTimeBucket -> RunningTimeBucket -> Bool
<= :: RunningTimeBucket -> RunningTimeBucket -> Bool
$c> :: RunningTimeBucket -> RunningTimeBucket -> Bool
> :: RunningTimeBucket -> RunningTimeBucket -> Bool
$c>= :: RunningTimeBucket -> RunningTimeBucket -> Bool
>= :: RunningTimeBucket -> RunningTimeBucket -> Bool
$cmax :: RunningTimeBucket -> RunningTimeBucket -> RunningTimeBucket
max :: RunningTimeBucket -> RunningTimeBucket -> RunningTimeBucket
$cmin :: RunningTimeBucket -> RunningTimeBucket -> RunningTimeBucket
min :: RunningTimeBucket -> RunningTimeBucket -> RunningTimeBucket
Ord, RunningTimeBucket -> RunningTimeBucket -> Bool
(RunningTimeBucket -> RunningTimeBucket -> Bool)
-> (RunningTimeBucket -> RunningTimeBucket -> Bool)
-> Eq RunningTimeBucket
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RunningTimeBucket -> RunningTimeBucket -> Bool
== :: RunningTimeBucket -> RunningTimeBucket -> Bool
$c/= :: RunningTimeBucket -> RunningTimeBucket -> Bool
/= :: RunningTimeBucket -> RunningTimeBucket -> Bool
Eq, Int -> RunningTimeBucket -> ShowS
[RunningTimeBucket] -> ShowS
RunningTimeBucket -> String
(Int -> RunningTimeBucket -> ShowS)
-> (RunningTimeBucket -> String)
-> ([RunningTimeBucket] -> ShowS)
-> Show RunningTimeBucket
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RunningTimeBucket -> ShowS
showsPrec :: Int -> RunningTimeBucket -> ShowS
$cshow :: RunningTimeBucket -> String
show :: RunningTimeBucket -> String
$cshowList :: [RunningTimeBucket] -> ShowS
showList :: [RunningTimeBucket] -> ShowS
Show, (forall x. RunningTimeBucket -> Rep RunningTimeBucket x)
-> (forall x. Rep RunningTimeBucket x -> RunningTimeBucket)
-> Generic RunningTimeBucket
forall x. Rep RunningTimeBucket x -> RunningTimeBucket
forall x. RunningTimeBucket -> Rep RunningTimeBucket x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. RunningTimeBucket -> Rep RunningTimeBucket x
from :: forall x. RunningTimeBucket -> Rep RunningTimeBucket x
$cto :: forall x. Rep RunningTimeBucket x -> RunningTimeBucket
to :: forall x. Rep RunningTimeBucket x -> RunningTimeBucket
Generic, [RunningTimeBucket] -> Value
[RunningTimeBucket] -> Encoding
RunningTimeBucket -> Value
RunningTimeBucket -> Encoding
(RunningTimeBucket -> Value)
-> (RunningTimeBucket -> Encoding)
-> ([RunningTimeBucket] -> Value)
-> ([RunningTimeBucket] -> Encoding)
-> ToJSON RunningTimeBucket
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
$ctoJSON :: RunningTimeBucket -> Value
toJSON :: RunningTimeBucket -> Value
$ctoEncoding :: RunningTimeBucket -> Encoding
toEncoding :: RunningTimeBucket -> Encoding
$ctoJSONList :: [RunningTimeBucket] -> Value
toJSONList :: [RunningTimeBucket] -> Value
$ctoEncodingList :: [RunningTimeBucket] -> Encoding
toEncodingList :: [RunningTimeBucket] -> Encoding
J.ToJSON, Value -> Parser [RunningTimeBucket]
Value -> Parser RunningTimeBucket
(Value -> Parser RunningTimeBucket)
-> (Value -> Parser [RunningTimeBucket])
-> FromJSON RunningTimeBucket
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
$cparseJSON :: Value -> Parser RunningTimeBucket
parseJSON :: Value -> Parser RunningTimeBucket
$cparseJSONList :: Value -> Parser [RunningTimeBucket]
parseJSONList :: Value -> Parser [RunningTimeBucket]
J.FromJSON, Eq RunningTimeBucket
Eq RunningTimeBucket
-> (Int -> RunningTimeBucket -> Int)
-> (RunningTimeBucket -> Int)
-> Hashable RunningTimeBucket
Int -> RunningTimeBucket -> Int
RunningTimeBucket -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> RunningTimeBucket -> Int
hashWithSalt :: Int -> RunningTimeBucket -> Int
$chash :: RunningTimeBucket -> Int
hash :: RunningTimeBucket -> Int
Hashable)

-- NOTE: an HDR histogram is a nice way to collect metrics when you don't know
-- a priori what the most useful binning is. It's not clear how we'd make use
-- of that here though. So these buckets are arbitrary, and can be adjusted as
-- needed, but we shouldn't have more than a handful to keep payload size down.
totalTimeBuckets :: [RunningTimeBucket]
totalTimeBuckets :: [RunningTimeBucket]
totalTimeBuckets = [Seconds] -> [RunningTimeBucket]
forall a b. Coercible a b => a -> b
coerce [Seconds
0.000, Seconds
0.001, Seconds
0.050, Seconds
1.000, Seconds
3600.000 :: Seconds]

-- | Save a timing metric sample in our in-memory store. These will be
-- accumulated and uploaded periodically in "Hasura.Server.Telemetry".
recordTimingMetric :: (MonadIO m) => RequestDimensions -> RequestTimings -> m ()
recordTimingMetric :: forall (m :: * -> *).
MonadIO m =>
RequestDimensions -> RequestTimings -> m ()
recordTimingMetric RequestDimensions
reqDimensions RequestTimings {Seconds
$sel:telemTimeIO:RequestTimings :: RequestTimings -> Seconds
$sel:telemTimeTot:RequestTimings :: RequestTimings -> Seconds
telemTimeIO :: Seconds
telemTimeTot :: Seconds
..} = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
  let ourBucket :: RunningTimeBucket
ourBucket =
        RunningTimeBucket -> Maybe RunningTimeBucket -> RunningTimeBucket
forall a. a -> Maybe a -> a
fromMaybe (Seconds -> RunningTimeBucket
RunningTimeBucket Seconds
0)
          (Maybe RunningTimeBucket -> RunningTimeBucket)
-> Maybe RunningTimeBucket -> RunningTimeBucket
forall a b. (a -> b) -> a -> b
$ [RunningTimeBucket] -> Maybe RunningTimeBucket
forall a. [a] -> Maybe a
listToMaybe -- although we expect 'head' would be safe here
          ([RunningTimeBucket] -> Maybe RunningTimeBucket)
-> [RunningTimeBucket] -> Maybe RunningTimeBucket
forall a b. (a -> b) -> a -> b
$ (RunningTimeBucket -> Bool)
-> [RunningTimeBucket] -> [RunningTimeBucket]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (RunningTimeBucket -> RunningTimeBucket -> Bool
forall a. Ord a => a -> a -> Bool
> Seconds -> RunningTimeBucket
forall a b. Coercible a b => a -> b
coerce Seconds
telemTimeTot)
          ([RunningTimeBucket] -> [RunningTimeBucket])
-> [RunningTimeBucket] -> [RunningTimeBucket]
forall a b. (a -> b) -> a -> b
$ [RunningTimeBucket] -> [RunningTimeBucket]
forall a. [a] -> [a]
reverse
          ([RunningTimeBucket] -> [RunningTimeBucket])
-> [RunningTimeBucket] -> [RunningTimeBucket]
forall a b. (a -> b) -> a -> b
$ [RunningTimeBucket] -> [RunningTimeBucket]
forall a. Ord a => [a] -> [a]
sort [RunningTimeBucket]
totalTimeBuckets
  IORef
  (HashMap
     (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
-> (HashMap
      (RequestDimensions, RunningTimeBucket) RequestTimingsCount
    -> (HashMap
          (RequestDimensions, RunningTimeBucket) RequestTimingsCount,
        ()))
-> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef
  (HashMap
     (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
requestCounters
    ((HashMap
    (RequestDimensions, RunningTimeBucket) RequestTimingsCount
  -> (HashMap
        (RequestDimensions, RunningTimeBucket) RequestTimingsCount,
      ()))
 -> IO ())
-> (HashMap
      (RequestDimensions, RunningTimeBucket) RequestTimingsCount
    -> (HashMap
          (RequestDimensions, RunningTimeBucket) RequestTimingsCount,
        ()))
-> IO ()
forall a b. (a -> b) -> a -> b
$ (,())
    (HashMap (RequestDimensions, RunningTimeBucket) RequestTimingsCount
 -> (HashMap
       (RequestDimensions, RunningTimeBucket) RequestTimingsCount,
     ()))
-> (HashMap
      (RequestDimensions, RunningTimeBucket) RequestTimingsCount
    -> HashMap
         (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
-> HashMap
     (RequestDimensions, RunningTimeBucket) RequestTimingsCount
-> (HashMap
      (RequestDimensions, RunningTimeBucket) RequestTimingsCount,
    ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (RequestTimingsCount -> RequestTimingsCount -> RequestTimingsCount)
-> (RequestDimensions, RunningTimeBucket)
-> RequestTimingsCount
-> HashMap
     (RequestDimensions, RunningTimeBucket) RequestTimingsCount
-> HashMap
     (RequestDimensions, RunningTimeBucket) RequestTimingsCount
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
HashMap.insertWith RequestTimingsCount -> RequestTimingsCount -> RequestTimingsCount
forall a. Semigroup a => a -> a -> a
(<>) (RequestDimensions
reqDimensions, RunningTimeBucket
ourBucket) RequestTimingsCount {$sel:telemCount:RequestTimingsCount :: Word
telemCount = Word
1, Seconds
telemTimeIO :: Seconds
$sel:telemTimeTot:RequestTimingsCount :: Seconds
telemTimeIO :: Seconds
telemTimeTot :: Seconds
..}

-- | The final shape of this part of our metrics data JSON. This should allow
-- reasonably efficient querying using GIN indexes and JSONB containment
-- operations (which treat arrays as sets).
data ServiceTimingMetrics = ServiceTimingMetrics
  { -- | This is set to a new unique value when the counters reset (e.g. because of a restart)
    ServiceTimingMetrics -> Int
collectionTag :: Int,
    ServiceTimingMetrics -> [ServiceTimingMetric]
serviceTimingMetrics :: [ServiceTimingMetric]
  }
  deriving (Int -> ServiceTimingMetrics -> ShowS
[ServiceTimingMetrics] -> ShowS
ServiceTimingMetrics -> String
(Int -> ServiceTimingMetrics -> ShowS)
-> (ServiceTimingMetrics -> String)
-> ([ServiceTimingMetrics] -> ShowS)
-> Show ServiceTimingMetrics
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ServiceTimingMetrics -> ShowS
showsPrec :: Int -> ServiceTimingMetrics -> ShowS
$cshow :: ServiceTimingMetrics -> String
show :: ServiceTimingMetrics -> String
$cshowList :: [ServiceTimingMetrics] -> ShowS
showList :: [ServiceTimingMetrics] -> ShowS
Show, (forall x. ServiceTimingMetrics -> Rep ServiceTimingMetrics x)
-> (forall x. Rep ServiceTimingMetrics x -> ServiceTimingMetrics)
-> Generic ServiceTimingMetrics
forall x. Rep ServiceTimingMetrics x -> ServiceTimingMetrics
forall x. ServiceTimingMetrics -> Rep ServiceTimingMetrics x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ServiceTimingMetrics -> Rep ServiceTimingMetrics x
from :: forall x. ServiceTimingMetrics -> Rep ServiceTimingMetrics x
$cto :: forall x. Rep ServiceTimingMetrics x -> ServiceTimingMetrics
to :: forall x. Rep ServiceTimingMetrics x -> ServiceTimingMetrics
Generic, ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
(ServiceTimingMetrics -> ServiceTimingMetrics -> Bool)
-> (ServiceTimingMetrics -> ServiceTimingMetrics -> Bool)
-> Eq ServiceTimingMetrics
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
== :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
$c/= :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
/= :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
Eq, Eq ServiceTimingMetrics
Eq ServiceTimingMetrics
-> (ServiceTimingMetrics -> ServiceTimingMetrics -> Ordering)
-> (ServiceTimingMetrics -> ServiceTimingMetrics -> Bool)
-> (ServiceTimingMetrics -> ServiceTimingMetrics -> Bool)
-> (ServiceTimingMetrics -> ServiceTimingMetrics -> Bool)
-> (ServiceTimingMetrics -> ServiceTimingMetrics -> Bool)
-> (ServiceTimingMetrics
    -> ServiceTimingMetrics -> ServiceTimingMetrics)
-> (ServiceTimingMetrics
    -> ServiceTimingMetrics -> ServiceTimingMetrics)
-> Ord ServiceTimingMetrics
ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
ServiceTimingMetrics -> ServiceTimingMetrics -> Ordering
ServiceTimingMetrics
-> ServiceTimingMetrics -> ServiceTimingMetrics
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ServiceTimingMetrics -> ServiceTimingMetrics -> Ordering
compare :: ServiceTimingMetrics -> ServiceTimingMetrics -> Ordering
$c< :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
< :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
$c<= :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
<= :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
$c> :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
> :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
$c>= :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
>= :: ServiceTimingMetrics -> ServiceTimingMetrics -> Bool
$cmax :: ServiceTimingMetrics
-> ServiceTimingMetrics -> ServiceTimingMetrics
max :: ServiceTimingMetrics
-> ServiceTimingMetrics -> ServiceTimingMetrics
$cmin :: ServiceTimingMetrics
-> ServiceTimingMetrics -> ServiceTimingMetrics
min :: ServiceTimingMetrics
-> ServiceTimingMetrics -> ServiceTimingMetrics
Ord)

data ServiceTimingMetric = ServiceTimingMetric
  { ServiceTimingMetric -> RequestDimensions
dimensions :: RequestDimensions,
    ServiceTimingMetric -> RunningTimeBucket
bucket :: RunningTimeBucket,
    ServiceTimingMetric -> RequestTimingsCount
metrics :: RequestTimingsCount
  }
  deriving (Int -> ServiceTimingMetric -> ShowS
[ServiceTimingMetric] -> ShowS
ServiceTimingMetric -> String
(Int -> ServiceTimingMetric -> ShowS)
-> (ServiceTimingMetric -> String)
-> ([ServiceTimingMetric] -> ShowS)
-> Show ServiceTimingMetric
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ServiceTimingMetric -> ShowS
showsPrec :: Int -> ServiceTimingMetric -> ShowS
$cshow :: ServiceTimingMetric -> String
show :: ServiceTimingMetric -> String
$cshowList :: [ServiceTimingMetric] -> ShowS
showList :: [ServiceTimingMetric] -> ShowS
Show, (forall x. ServiceTimingMetric -> Rep ServiceTimingMetric x)
-> (forall x. Rep ServiceTimingMetric x -> ServiceTimingMetric)
-> Generic ServiceTimingMetric
forall x. Rep ServiceTimingMetric x -> ServiceTimingMetric
forall x. ServiceTimingMetric -> Rep ServiceTimingMetric x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ServiceTimingMetric -> Rep ServiceTimingMetric x
from :: forall x. ServiceTimingMetric -> Rep ServiceTimingMetric x
$cto :: forall x. Rep ServiceTimingMetric x -> ServiceTimingMetric
to :: forall x. Rep ServiceTimingMetric x -> ServiceTimingMetric
Generic, ServiceTimingMetric -> ServiceTimingMetric -> Bool
(ServiceTimingMetric -> ServiceTimingMetric -> Bool)
-> (ServiceTimingMetric -> ServiceTimingMetric -> Bool)
-> Eq ServiceTimingMetric
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
== :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
$c/= :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
/= :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
Eq, Eq ServiceTimingMetric
Eq ServiceTimingMetric
-> (ServiceTimingMetric -> ServiceTimingMetric -> Ordering)
-> (ServiceTimingMetric -> ServiceTimingMetric -> Bool)
-> (ServiceTimingMetric -> ServiceTimingMetric -> Bool)
-> (ServiceTimingMetric -> ServiceTimingMetric -> Bool)
-> (ServiceTimingMetric -> ServiceTimingMetric -> Bool)
-> (ServiceTimingMetric
    -> ServiceTimingMetric -> ServiceTimingMetric)
-> (ServiceTimingMetric
    -> ServiceTimingMetric -> ServiceTimingMetric)
-> Ord ServiceTimingMetric
ServiceTimingMetric -> ServiceTimingMetric -> Bool
ServiceTimingMetric -> ServiceTimingMetric -> Ordering
ServiceTimingMetric -> ServiceTimingMetric -> ServiceTimingMetric
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ServiceTimingMetric -> ServiceTimingMetric -> Ordering
compare :: ServiceTimingMetric -> ServiceTimingMetric -> Ordering
$c< :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
< :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
$c<= :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
<= :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
$c> :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
> :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
$c>= :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
>= :: ServiceTimingMetric -> ServiceTimingMetric -> Bool
$cmax :: ServiceTimingMetric -> ServiceTimingMetric -> ServiceTimingMetric
max :: ServiceTimingMetric -> ServiceTimingMetric -> ServiceTimingMetric
$cmin :: ServiceTimingMetric -> ServiceTimingMetric -> ServiceTimingMetric
min :: ServiceTimingMetric -> ServiceTimingMetric -> ServiceTimingMetric
Ord)

instance J.FromJSON RequestTimingsCount where
  parseJSON :: Value -> Parser RequestTimingsCount
parseJSON = Options -> Value -> Parser RequestTimingsCount
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
J.genericParseJSON Options
hasuraJSON

instance J.ToJSON RequestTimingsCount where
  toJSON :: RequestTimingsCount -> Value
toJSON = Options -> RequestTimingsCount -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
J.genericToJSON Options
hasuraJSON
  toEncoding :: RequestTimingsCount -> Encoding
toEncoding = Options -> RequestTimingsCount -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
J.genericToEncoding Options
hasuraJSON

instance J.FromJSON RequestDimensions where
  parseJSON :: Value -> Parser RequestDimensions
parseJSON = Options -> Value -> Parser RequestDimensions
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
J.genericParseJSON Options
hasuraJSON

instance J.ToJSON RequestDimensions where
  toJSON :: RequestDimensions -> Value
toJSON = Options -> RequestDimensions -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
J.genericToJSON Options
hasuraJSON
  toEncoding :: RequestDimensions -> Encoding
toEncoding = Options -> RequestDimensions -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
J.genericToEncoding Options
hasuraJSON

instance J.ToJSON ServiceTimingMetric

instance J.FromJSON ServiceTimingMetric

instance J.ToJSON ServiceTimingMetrics

instance J.FromJSON ServiceTimingMetrics

dumpServiceTimingMetrics :: (MonadIO m) => m ServiceTimingMetrics
dumpServiceTimingMetrics :: forall (m :: * -> *). MonadIO m => m ServiceTimingMetrics
dumpServiceTimingMetrics = IO ServiceTimingMetrics -> m ServiceTimingMetrics
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ServiceTimingMetrics -> m ServiceTimingMetrics)
-> IO ServiceTimingMetrics -> m ServiceTimingMetrics
forall a b. (a -> b) -> a -> b
$ do
  HashMap (RequestDimensions, RunningTimeBucket) RequestTimingsCount
cs <- IORef
  (HashMap
     (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
-> IO
     (HashMap
        (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
forall a. IORef a -> IO a
readIORef IORef
  (HashMap
     (RequestDimensions, RunningTimeBucket) RequestTimingsCount)
requestCounters
  let serviceTimingMetrics :: [ServiceTimingMetric]
serviceTimingMetrics = ((((RequestDimensions, RunningTimeBucket), RequestTimingsCount)
  -> ServiceTimingMetric)
 -> [((RequestDimensions, RunningTimeBucket), RequestTimingsCount)]
 -> [ServiceTimingMetric])
-> [((RequestDimensions, RunningTimeBucket), RequestTimingsCount)]
-> (((RequestDimensions, RunningTimeBucket), RequestTimingsCount)
    -> ServiceTimingMetric)
-> [ServiceTimingMetric]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (((RequestDimensions, RunningTimeBucket), RequestTimingsCount)
 -> ServiceTimingMetric)
-> [((RequestDimensions, RunningTimeBucket), RequestTimingsCount)]
-> [ServiceTimingMetric]
forall a b. (a -> b) -> [a] -> [b]
map (HashMap (RequestDimensions, RunningTimeBucket) RequestTimingsCount
-> [((RequestDimensions, RunningTimeBucket), RequestTimingsCount)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList HashMap (RequestDimensions, RunningTimeBucket) RequestTimingsCount
cs)
        ((((RequestDimensions, RunningTimeBucket), RequestTimingsCount)
  -> ServiceTimingMetric)
 -> [ServiceTimingMetric])
-> (((RequestDimensions, RunningTimeBucket), RequestTimingsCount)
    -> ServiceTimingMetric)
-> [ServiceTimingMetric]
forall a b. (a -> b) -> a -> b
$ \((RequestDimensions
dimensions, RunningTimeBucket
bucket), RequestTimingsCount
metrics) -> ServiceTimingMetric {RunningTimeBucket
RequestTimingsCount
RequestDimensions
$sel:dimensions:ServiceTimingMetric :: RequestDimensions
$sel:bucket:ServiceTimingMetric :: RunningTimeBucket
$sel:metrics:ServiceTimingMetric :: RequestTimingsCount
dimensions :: RequestDimensions
bucket :: RunningTimeBucket
metrics :: RequestTimingsCount
..}
      collectionTag :: Int
collectionTag = POSIXTime -> Int
forall b. Integral b => POSIXTime -> b
forall a b. (RealFrac a, Integral b) => a -> b
round POSIXTime
approxStartTime
  ServiceTimingMetrics -> IO ServiceTimingMetrics
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ServiceTimingMetrics {Int
[ServiceTimingMetric]
$sel:collectionTag:ServiceTimingMetrics :: Int
$sel:serviceTimingMetrics:ServiceTimingMetrics :: [ServiceTimingMetric]
serviceTimingMetrics :: [ServiceTimingMetric]
collectionTag :: Int
..}