Files
graphql-engine/server/src-test/Hasura/Server/TelemetrySpec.hs
Brandon Simmons 58ef316118 Add request timings and count histograms to telemetry. Closes #3552
We upload a set of accumulating timers and counters to track service
time for different types of operations, across several dimensions (e.g.
did we hit the plan cache, was a remote involved, etc.)

Also...

Standardize on DiffTime as a standard duration type, and try to use it
consistently.

See discussion here:
https://github.com/hasura/graphql-engine/pull/3584#pullrequestreview-340679369

It should be possible to overwrite that module so the new threadDelay
sticks per the pattern in #3705 blocked on #3558

Rename the Control.Concurrent.Extended.threadDelay to `sleep` since a
naive use with a literal argument would be very bad!

We catch a bug in 'computeTimeDiff'.

Add convenient 'Read' instances to the time unit utility types. Make
'Second' a newtype to support this.
2020-02-03 18:50:10 -06:00

49 lines
2.3 KiB
Haskell

{-# LANGUAGE DuplicateRecordFields #-}
module Hasura.Server.TelemetrySpec (spec) where
import Hasura.Prelude
import qualified Data.Aeson as A
import Hasura.Server.Telemetry.Counters
import Test.Hspec
spec :: Spec
spec = do
telemetryCountersTests
-- NOTE: this test is effectful/stateful; if we need to we can implement an
-- operation to clear metric store.
telemetryCountersTests :: Spec
telemetryCountersTests = do
describe "request timing counters" $ do
it "is at first empty" $ do
fmap serviceTimingMetrics dumpServiceTimingMetrics `shouldReturn` []
-- excercise accumulating and buckets:
let expected =
-- NOTE: ordering is arbitrary here (and hence fragile)
[ServiceTimingMetric {
dimensions = RequestDimensions Hit Mutation Local HTTP
, bucket = RunningTimeBucket {bucketGreaterThan = 0}
, metrics = RequestTimingsCount {telemTimeIO = 2, telemTimeTot = 200, telemCount = 2}},
ServiceTimingMetric {
dimensions = RequestDimensions Miss Mutation Local HTTP
, bucket = RunningTimeBucket {bucketGreaterThan = 1000}
, metrics = RequestTimingsCount {telemTimeIO = 2, telemTimeTot = 2002, telemCount = 2}},
ServiceTimingMetric {
dimensions = RequestDimensions Hit Query Remote WebSocket
, bucket = RunningTimeBucket {bucketGreaterThan = 100000}
, metrics = RequestTimingsCount {telemTimeIO = 1, telemTimeTot = 100001, telemCount = 1}}]
it "accumulates as expected" $ do
recordTimingMetric (RequestDimensions Hit Mutation Local HTTP) (RequestTimings 1 100)
recordTimingMetric (RequestDimensions Hit Mutation Local HTTP) (RequestTimings 1 100)
recordTimingMetric (RequestDimensions Miss Mutation Local HTTP) (RequestTimings 1 1001)
recordTimingMetric (RequestDimensions Miss Mutation Local HTTP) (RequestTimings 1 1001)
recordTimingMetric (RequestDimensions Hit Query Remote WebSocket) (RequestTimings 1 100001)
fmap serviceTimingMetrics dumpServiceTimingMetrics `shouldReturn` expected
it "serializes and deserializes properly" $ do
fmap (fmap serviceTimingMetrics . A.eitherDecode . A.encode) dumpServiceTimingMetrics
`shouldReturn` Right expected