haxl-2.4.0.0: Haxl/Core/Flags.hs
-- Copyright (c) 2014-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is distributed under the terms of a BSD license,
-- found in the LICENSE file.
{-# LANGUAGE BangPatterns #-}
-- |
-- The 'Flags' type and related functions. This module is provided
-- for access to Haxl internals only; most users should import
-- "Haxl.Core" instead.
--
module Haxl.Core.Flags
(
-- * Report flags
ReportFlag(..)
, ReportFlags
, defaultReportFlags
, profilingReportFlags
, setReportFlag
, clearReportFlag
, testReportFlag
-- * Flags
, Flags(..)
, defaultFlags
, ifTrace
, ifReport
, ifProfiling
) where
import Control.Monad
import Data.Bits
import Data.List (foldl')
import Text.Printf (printf)
-- ---------------------------------------------------------------------------
-- ReportFlags
data ReportFlag
= ReportOutgoneFetches -- ^ outgone fetches, for debugging eg: timeouts
| ReportFetchStats -- ^ data fetch stats & errors
| ReportProfiling -- ^ enabling label stack and profiling
| ReportExceptionLabelStack -- ^ include label stack in HaxlException
| ReportFetchStack -- ^ log cost-center stack traces of dataFetch calls
deriving (Bounded, Enum, Eq, Show)
profilingDependents :: [ReportFlag]
profilingDependents =
[ ReportExceptionLabelStack
, ReportFetchStack
]
newtype ReportFlags = ReportFlags Int
instance Show ReportFlags where
show (ReportFlags fs) = printf "%0*b" (fromEnum maxReportFlag + 1) fs
where
maxReportFlag = maxBound :: ReportFlag
defaultReportFlags :: ReportFlags
defaultReportFlags = ReportFlags 0
profilingReportFlags :: ReportFlags
profilingReportFlags = foldl' (flip setReportFlag) defaultReportFlags
[ ReportOutgoneFetches
, ReportFetchStats
, ReportProfiling
]
setReportFlag :: ReportFlag -> ReportFlags -> ReportFlags
setReportFlag f (ReportFlags fs) =
ReportFlags $ setDependencies $ setBit fs $ fromEnum f
where
setDependencies
| f `elem` profilingDependents = flip setBit $ fromEnum ReportProfiling
| otherwise = id
clearReportFlag :: ReportFlag -> ReportFlags -> ReportFlags
clearReportFlag f (ReportFlags fs) =
ReportFlags $ clearDependents $ clearBit fs $ fromEnum f
where
clearDependents z = case f of
ReportProfiling -> foldl' clearBit z $ map fromEnum profilingDependents
_ -> z
{-# INLINE testReportFlag #-}
testReportFlag :: ReportFlag -> ReportFlags -> Bool
testReportFlag !f (ReportFlags !fs) = testBit fs $ fromEnum f
-- ---------------------------------------------------------------------------
-- Flags
-- | Flags that control the operation of the engine.
data Flags = Flags
{ trace :: {-# UNPACK #-} !Int
-- ^ Tracing level (0 = quiet, 3 = very verbose).
, report :: {-# UNPACK #-} !ReportFlags
-- ^ Report flags
, caching :: {-# UNPACK #-} !Int
-- ^ Non-zero if caching is enabled. If caching is disabled, then
-- we still do batching and de-duplication, but do not cache
-- results.
, recording :: {-# UNPACK #-} !Int
-- ^ Non-zero if recording is enabled. This allows tests to record cache
-- calls for datasources by making uncachedRequest behave like dataFetch
}
defaultFlags :: Flags
defaultFlags = Flags
{ trace = 0
, report = defaultReportFlags
, caching = 1
, recording = 0
}
-- | Runs an action if the tracing level is above the given threshold.
ifTrace :: Monad m => Flags -> Int -> m a -> m ()
ifTrace flags i = when (trace flags >= i) . void
-- | Runs an action if the ReportFlag is set.
ifReport :: Monad m => Flags -> ReportFlag -> m a -> m ()
ifReport flags i = when (testReportFlag i $ report flags) . void
ifProfiling :: Monad m => Flags -> m a -> m ()
ifProfiling flags = ifReport flags ReportProfiling