module LaunchDarkly.Server.Events where import Data.Aeson (ToJSON, Value(..), toJSON, object, (.=)) import Data.Text (Text) import GHC.Exts (fromList) import GHC.Natural (Natural, naturalFromInteger) import GHC.Generics (Generic) import Data.Generics.Product (HasField', getField, field, setField) import qualified Data.Text as T import Control.Concurrent.MVar (MVar, putMVar, swapMVar, newEmptyMVar, newMVar, tryTakeMVar, modifyMVar_, modifyMVar, readMVar) import Data.Time.Clock.POSIX (getPOSIXTime) import Control.Lens ((&), (%~)) import Data.Maybe (fromMaybe) import Data.Cache.LRU (LRU, newLRU) import Control.Monad (when, unless) import qualified Data.Cache.LRU as LRU import LaunchDarkly.AesonCompat (KeyMap, keyMapUnion, insertKey, mapValues, objectValues, lookupKey) import LaunchDarkly.Server.Config.Internal (ConfigI, shouldSendEvents) import LaunchDarkly.Server.User.Internal (UserI, userSerializeRedacted) import LaunchDarkly.Server.Details (EvaluationReason(..)) import LaunchDarkly.Server.Features (Flag) data ContextKind = ContextKindUser | ContextKindAnonymousUser deriving (ContextKind -> ContextKind -> Bool forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: ContextKind -> ContextKind -> Bool $c/= :: ContextKind -> ContextKind -> Bool == :: ContextKind -> ContextKind -> Bool $c== :: ContextKind -> ContextKind -> Bool Eq, Int -> ContextKind -> ShowS [ContextKind] -> ShowS ContextKind -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [ContextKind] -> ShowS $cshowList :: [ContextKind] -> ShowS show :: ContextKind -> String $cshow :: ContextKind -> String showsPrec :: Int -> ContextKind -> ShowS $cshowsPrec :: Int -> ContextKind -> ShowS Show) instance ToJSON ContextKind where toJSON :: ContextKind -> Value toJSON ContextKind contextKind = Text -> Value String forall a b. (a -> b) -> a -> b $ case ContextKind contextKind of ContextKind ContextKindUser -> Text "user" ContextKind ContextKindAnonymousUser -> Text "anonymousUser" userGetContextKind :: UserI -> ContextKind userGetContextKind :: UserI -> ContextKind userGetContextKind UserI user = if forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"anonymous" UserI user then ContextKind ContextKindAnonymousUser else ContextKind ContextKindUser data EvalEvent = EvalEvent { EvalEvent -> Text key :: !Text , EvalEvent -> Maybe Integer variation :: !(Maybe Integer) , EvalEvent -> Value value :: !Value , EvalEvent -> Maybe Value defaultValue :: !(Maybe Value) , EvalEvent -> Maybe Natural version :: !(Maybe Natural) , EvalEvent -> Maybe Text prereqOf :: !(Maybe Text) , EvalEvent -> EvaluationReason reason :: !EvaluationReason , EvalEvent -> Bool trackEvents :: !Bool , EvalEvent -> Bool forceIncludeReason :: !Bool , EvalEvent -> Bool debug :: !Bool , EvalEvent -> Maybe Natural debugEventsUntilDate :: !(Maybe Natural) } deriving (forall x. Rep EvalEvent x -> EvalEvent forall x. EvalEvent -> Rep EvalEvent x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep EvalEvent x -> EvalEvent $cfrom :: forall x. EvalEvent -> Rep EvalEvent x Generic, EvalEvent -> EvalEvent -> Bool forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: EvalEvent -> EvalEvent -> Bool $c/= :: EvalEvent -> EvalEvent -> Bool == :: EvalEvent -> EvalEvent -> Bool $c== :: EvalEvent -> EvalEvent -> Bool Eq, Int -> EvalEvent -> ShowS [EvalEvent] -> ShowS EvalEvent -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [EvalEvent] -> ShowS $cshowList :: [EvalEvent] -> ShowS show :: EvalEvent -> String $cshow :: EvalEvent -> String showsPrec :: Int -> EvalEvent -> ShowS $cshowsPrec :: Int -> EvalEvent -> ShowS Show) data EventState = EventState { EventState -> MVar [EventType] events :: !(MVar [EventType]) , EventState -> MVar Integer lastKnownServerTime :: !(MVar Integer) , EventState -> MVar () flush :: !(MVar ()) , EventState -> MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext))) summary :: !(MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext)))) , EventState -> MVar Natural startDate :: !(MVar Natural) , EventState -> MVar (LRU Text ()) userKeyLRU :: !(MVar (LRU Text ())) } deriving (forall x. Rep EventState x -> EventState forall x. EventState -> Rep EventState x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep EventState x -> EventState $cfrom :: forall x. EventState -> Rep EventState x Generic) makeEventState :: ConfigI -> IO EventState makeEventState :: ConfigI -> IO EventState makeEventState ConfigI config = do MVar [EventType] events <- forall a. a -> IO (MVar a) newMVar [] MVar Integer lastKnownServerTime <- forall a. a -> IO (MVar a) newMVar Integer 0 MVar () flush <- forall a. IO (MVar a) newEmptyMVar MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext))) summary <- forall a. a -> IO (MVar a) newMVar forall a. Monoid a => a mempty MVar Natural startDate <- forall a. IO (MVar a) newEmptyMVar MVar (LRU Text ()) userKeyLRU <- forall a. a -> IO (MVar a) newMVar forall a b. (a -> b) -> a -> b $ forall key val. Ord key => Maybe Integer -> LRU key val newLRU forall a b. (a -> b) -> a -> b $ forall (f :: * -> *) a. Applicative f => a -> f a pure forall a b. (a -> b) -> a -> b $ forall a b. (Integral a, Num b) => a -> b fromIntegral forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"userKeyLRUCapacity" ConfigI config forall (f :: * -> *) a. Applicative f => a -> f a pure EventState{MVar Integer MVar Natural MVar [EventType] MVar () MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext))) MVar (LRU Text ()) userKeyLRU :: MVar (LRU Text ()) startDate :: MVar Natural summary :: MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext))) flush :: MVar () lastKnownServerTime :: MVar Integer events :: MVar [EventType] $sel:userKeyLRU:EventState :: MVar (LRU Text ()) $sel:startDate:EventState :: MVar Natural $sel:summary:EventState :: MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext))) $sel:flush:EventState :: MVar () $sel:lastKnownServerTime:EventState :: MVar Integer $sel:events:EventState :: MVar [EventType] ..} convertFeatures :: KeyMap (FlagSummaryContext (KeyMap CounterContext)) -> KeyMap (FlagSummaryContext [CounterContext]) convertFeatures :: KeyMap (FlagSummaryContext (KeyMap CounterContext)) -> KeyMap (FlagSummaryContext [CounterContext]) convertFeatures KeyMap (FlagSummaryContext (KeyMap CounterContext)) summary = forall a b c. (a -> b -> c) -> b -> a -> c flip forall v1 v2. (v1 -> v2) -> KeyMap v1 -> KeyMap v2 mapValues KeyMap (FlagSummaryContext (KeyMap CounterContext)) summary forall a b. (a -> b) -> a -> b $ \FlagSummaryContext (KeyMap CounterContext) context -> FlagSummaryContext (KeyMap CounterContext) context forall a b. a -> (a -> b) -> b & forall (field :: Symbol) s t a b. HasField field s t a b => Lens s t a b field @"counters" forall s t a b. ASetter s t a b -> (a -> b) -> s -> t %~ forall v. KeyMap v -> [v] objectValues queueEvent :: ConfigI -> EventState -> EventType -> IO () queueEvent :: ConfigI -> EventState -> EventType -> IO () queueEvent ConfigI config EventState state EventType event = if Bool -> Bool not (ConfigI -> Bool shouldSendEvents ConfigI config) then forall (f :: * -> *) a. Applicative f => a -> f a pure () else forall a. MVar a -> (a -> IO a) -> IO () modifyMVar_ (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"events" EventState state) forall a b. (a -> b) -> a -> b $ \[EventType] events -> forall (f :: * -> *) a. Applicative f => a -> f a pure forall a b. (a -> b) -> a -> b $ case EventType event of EventTypeSummary SummaryEvent _ -> EventType event forall a. a -> [a] -> [a] : [EventType] events EventType _ | forall (t :: * -> *) a. Foldable t => t a -> Int length [EventType] events forall a. Ord a => a -> a -> Bool < forall a b. (Integral a, Num b) => a -> b fromIntegral (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"eventsCapacity" ConfigI config) -> EventType event forall a. a -> [a] -> [a] : [EventType] events EventType _ -> [EventType] events unixMilliseconds :: IO Natural unixMilliseconds :: IO Natural unixMilliseconds = forall a b. (RealFrac a, Integral b) => a -> b round forall b c a. (b -> c) -> (a -> b) -> a -> c . (forall a. Num a => a -> a -> a * POSIXTime 1000) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> IO POSIXTime getPOSIXTime makeBaseEvent :: a -> IO (BaseEvent a) makeBaseEvent :: forall a. a -> IO (BaseEvent a) makeBaseEvent a child = IO Natural unixMilliseconds forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \Natural now -> forall (f :: * -> *) a. Applicative f => a -> f a pure forall a b. (a -> b) -> a -> b $ BaseEvent { $sel:creationDate:BaseEvent :: Natural creationDate = Natural now, $sel:event:BaseEvent :: a event = a child } processSummary :: ConfigI -> EventState -> IO () processSummary :: ConfigI -> EventState -> IO () processSummary ConfigI config EventState state = forall a. MVar a -> IO (Maybe a) tryTakeMVar (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"startDate" EventState state) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Maybe Natural Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a pure () (Just Natural startDate) -> do Natural endDate <- IO Natural unixMilliseconds KeyMap (FlagSummaryContext [CounterContext]) features <- KeyMap (FlagSummaryContext (KeyMap CounterContext)) -> KeyMap (FlagSummaryContext [CounterContext]) convertFeatures forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> forall a. MVar a -> a -> IO a swapMVar (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"summary" EventState state) forall a. Monoid a => a mempty ConfigI -> EventState -> EventType -> IO () queueEvent ConfigI config EventState state forall a b. (a -> b) -> a -> b $ SummaryEvent -> EventType EventTypeSummary forall a b. (a -> b) -> a -> b $ SummaryEvent {Natural KeyMap (FlagSummaryContext [CounterContext]) $sel:features:SummaryEvent :: KeyMap (FlagSummaryContext [CounterContext]) $sel:endDate:SummaryEvent :: Natural $sel:startDate:SummaryEvent :: Natural features :: KeyMap (FlagSummaryContext [CounterContext]) endDate :: Natural startDate :: Natural ..} class EventKind a where eventKind :: a -> Text data SummaryEvent = SummaryEvent { SummaryEvent -> Natural startDate :: !Natural , SummaryEvent -> Natural endDate :: !Natural , SummaryEvent -> KeyMap (FlagSummaryContext [CounterContext]) features :: !(KeyMap (FlagSummaryContext [CounterContext])) } deriving (forall x. Rep SummaryEvent x -> SummaryEvent forall x. SummaryEvent -> Rep SummaryEvent x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep SummaryEvent x -> SummaryEvent $cfrom :: forall x. SummaryEvent -> Rep SummaryEvent x Generic, Int -> SummaryEvent -> ShowS [SummaryEvent] -> ShowS SummaryEvent -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [SummaryEvent] -> ShowS $cshowList :: [SummaryEvent] -> ShowS show :: SummaryEvent -> String $cshow :: SummaryEvent -> String showsPrec :: Int -> SummaryEvent -> ShowS $cshowsPrec :: Int -> SummaryEvent -> ShowS Show, [SummaryEvent] -> Encoding [SummaryEvent] -> Value SummaryEvent -> Encoding SummaryEvent -> Value forall a. (a -> Value) -> (a -> Encoding) -> ([a] -> Value) -> ([a] -> Encoding) -> ToJSON a toEncodingList :: [SummaryEvent] -> Encoding $ctoEncodingList :: [SummaryEvent] -> Encoding toJSONList :: [SummaryEvent] -> Value $ctoJSONList :: [SummaryEvent] -> Value toEncoding :: SummaryEvent -> Encoding $ctoEncoding :: SummaryEvent -> Encoding toJSON :: SummaryEvent -> Value $ctoJSON :: SummaryEvent -> Value ToJSON) instance EventKind SummaryEvent where eventKind :: SummaryEvent -> Text eventKind SummaryEvent _ = Text "summary" data FlagSummaryContext a = FlagSummaryContext { forall a. FlagSummaryContext a -> Maybe Value defaultValue :: Maybe Value , forall a. FlagSummaryContext a -> a counters :: a } deriving (forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a forall a x. Rep (FlagSummaryContext a) x -> FlagSummaryContext a forall a x. FlagSummaryContext a -> Rep (FlagSummaryContext a) x $cto :: forall a x. Rep (FlagSummaryContext a) x -> FlagSummaryContext a $cfrom :: forall a x. FlagSummaryContext a -> Rep (FlagSummaryContext a) x Generic, Int -> FlagSummaryContext a -> ShowS forall a. Show a => Int -> FlagSummaryContext a -> ShowS forall a. Show a => [FlagSummaryContext a] -> ShowS forall a. Show a => FlagSummaryContext a -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [FlagSummaryContext a] -> ShowS $cshowList :: forall a. Show a => [FlagSummaryContext a] -> ShowS show :: FlagSummaryContext a -> String $cshow :: forall a. Show a => FlagSummaryContext a -> String showsPrec :: Int -> FlagSummaryContext a -> ShowS $cshowsPrec :: forall a. Show a => Int -> FlagSummaryContext a -> ShowS Show) instance ToJSON a => ToJSON (FlagSummaryContext a) where toJSON :: FlagSummaryContext a -> Value toJSON FlagSummaryContext a ctx = [Pair] -> Value object forall a b. (a -> b) -> a -> b $ forall a. (a -> Bool) -> [a] -> [a] filter (forall a. Eq a => a -> a -> Bool (/=) Value Null forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a, b) -> b snd) [ (Key "default", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"defaultValue" FlagSummaryContext a ctx) , (Key "counters", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"counters" FlagSummaryContext a ctx) ] data CounterContext = CounterContext { CounterContext -> Natural count :: !Natural , CounterContext -> Maybe Natural version :: !(Maybe Natural) , CounterContext -> Maybe Integer variation :: !(Maybe Integer) , CounterContext -> Value value :: !Value , CounterContext -> Bool unknown :: !Bool } deriving (forall x. Rep CounterContext x -> CounterContext forall x. CounterContext -> Rep CounterContext x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep CounterContext x -> CounterContext $cfrom :: forall x. CounterContext -> Rep CounterContext x Generic, Int -> CounterContext -> ShowS [CounterContext] -> ShowS CounterContext -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [CounterContext] -> ShowS $cshowList :: [CounterContext] -> ShowS show :: CounterContext -> String $cshow :: CounterContext -> String showsPrec :: Int -> CounterContext -> ShowS $cshowsPrec :: Int -> CounterContext -> ShowS Show) instance ToJSON CounterContext where toJSON :: CounterContext -> Value toJSON CounterContext context = [Pair] -> Value object forall a b. (a -> b) -> a -> b $ [ Key "count" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"count" CounterContext context , Key "value" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"value" CounterContext context ] forall a. Semigroup a => a -> a -> a <> forall a. (a -> Bool) -> [a] -> [a] filter (forall a. Eq a => a -> a -> Bool (/=) Value Null forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a, b) -> b snd) [ Key "version" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"version" CounterContext context , Key "variation" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"variation" CounterContext context , Key "unknown" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv .= if forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"unknown" CounterContext context then forall a. a -> Maybe a Just Bool True else forall a. Maybe a Nothing ] data IdentifyEvent = IdentifyEvent { IdentifyEvent -> Text key :: !Text , IdentifyEvent -> Value user :: !Value } deriving (forall x. Rep IdentifyEvent x -> IdentifyEvent forall x. IdentifyEvent -> Rep IdentifyEvent x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep IdentifyEvent x -> IdentifyEvent $cfrom :: forall x. IdentifyEvent -> Rep IdentifyEvent x Generic, [IdentifyEvent] -> Encoding [IdentifyEvent] -> Value IdentifyEvent -> Encoding IdentifyEvent -> Value forall a. (a -> Value) -> (a -> Encoding) -> ([a] -> Value) -> ([a] -> Encoding) -> ToJSON a toEncodingList :: [IdentifyEvent] -> Encoding $ctoEncodingList :: [IdentifyEvent] -> Encoding toJSONList :: [IdentifyEvent] -> Value $ctoJSONList :: [IdentifyEvent] -> Value toEncoding :: IdentifyEvent -> Encoding $ctoEncoding :: IdentifyEvent -> Encoding toJSON :: IdentifyEvent -> Value $ctoJSON :: IdentifyEvent -> Value ToJSON, Int -> IdentifyEvent -> ShowS [IdentifyEvent] -> ShowS IdentifyEvent -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [IdentifyEvent] -> ShowS $cshowList :: [IdentifyEvent] -> ShowS show :: IdentifyEvent -> String $cshow :: IdentifyEvent -> String showsPrec :: Int -> IdentifyEvent -> ShowS $cshowsPrec :: Int -> IdentifyEvent -> ShowS Show) instance EventKind IdentifyEvent where eventKind :: IdentifyEvent -> Text eventKind IdentifyEvent _ = Text "identify" data IndexEvent = IndexEvent { IndexEvent -> Value user :: Value } deriving (forall x. Rep IndexEvent x -> IndexEvent forall x. IndexEvent -> Rep IndexEvent x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep IndexEvent x -> IndexEvent $cfrom :: forall x. IndexEvent -> Rep IndexEvent x Generic, [IndexEvent] -> Encoding [IndexEvent] -> Value IndexEvent -> Encoding IndexEvent -> Value forall a. (a -> Value) -> (a -> Encoding) -> ([a] -> Value) -> ([a] -> Encoding) -> ToJSON a toEncodingList :: [IndexEvent] -> Encoding $ctoEncodingList :: [IndexEvent] -> Encoding toJSONList :: [IndexEvent] -> Value $ctoJSONList :: [IndexEvent] -> Value toEncoding :: IndexEvent -> Encoding $ctoEncoding :: IndexEvent -> Encoding toJSON :: IndexEvent -> Value $ctoJSON :: IndexEvent -> Value ToJSON, Int -> IndexEvent -> ShowS [IndexEvent] -> ShowS IndexEvent -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [IndexEvent] -> ShowS $cshowList :: [IndexEvent] -> ShowS show :: IndexEvent -> String $cshow :: IndexEvent -> String showsPrec :: Int -> IndexEvent -> ShowS $cshowsPrec :: Int -> IndexEvent -> ShowS Show) instance EventKind IndexEvent where eventKind :: IndexEvent -> Text eventKind IndexEvent _ = Text "index" data FeatureEvent = FeatureEvent { FeatureEvent -> Text key :: !Text , FeatureEvent -> Maybe Value user :: !(Maybe Value) , FeatureEvent -> Maybe Text userKey :: !(Maybe Text) , FeatureEvent -> Value value :: !Value , FeatureEvent -> Maybe Value defaultValue :: !(Maybe Value) , FeatureEvent -> Maybe Natural version :: !(Maybe Natural) , FeatureEvent -> Maybe Integer variation :: !(Maybe Integer) , FeatureEvent -> Maybe EvaluationReason reason :: !(Maybe EvaluationReason) , FeatureEvent -> ContextKind contextKind :: !ContextKind } deriving (forall x. Rep FeatureEvent x -> FeatureEvent forall x. FeatureEvent -> Rep FeatureEvent x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep FeatureEvent x -> FeatureEvent $cfrom :: forall x. FeatureEvent -> Rep FeatureEvent x Generic, Int -> FeatureEvent -> ShowS [FeatureEvent] -> ShowS FeatureEvent -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [FeatureEvent] -> ShowS $cshowList :: [FeatureEvent] -> ShowS show :: FeatureEvent -> String $cshow :: FeatureEvent -> String showsPrec :: Int -> FeatureEvent -> ShowS $cshowsPrec :: Int -> FeatureEvent -> ShowS Show) instance ToJSON FeatureEvent where toJSON :: FeatureEvent -> Value toJSON FeatureEvent event = [Pair] -> Value object forall a b. (a -> b) -> a -> b $ forall a. (a -> Bool) -> [a] -> [a] filter (forall a. Eq a => a -> a -> Bool (/=) Value Null forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a, b) -> b snd) [ (Key "key", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" FeatureEvent event) , (Key "user", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"user" FeatureEvent event) , (Key "userKey", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"userKey" FeatureEvent event) , (Key "value", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"value" FeatureEvent event) , (Key "default", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"defaultValue" FeatureEvent event) , (Key "version", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"version" FeatureEvent event) , (Key "variation", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"variation" FeatureEvent event) , (Key "reason", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"reason" FeatureEvent event) , (Key "contextKind", let c :: ContextKind c = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"contextKind" FeatureEvent event in if ContextKind c forall a. Eq a => a -> a -> Bool == ContextKind ContextKindUser then Value Null else forall a. ToJSON a => a -> Value toJSON ContextKind c) ] instance EventKind FeatureEvent where eventKind :: FeatureEvent -> Text eventKind FeatureEvent _ = Text "feature" newtype DebugEvent = DebugEvent FeatureEvent instance EventKind DebugEvent where eventKind :: DebugEvent -> Text eventKind DebugEvent _ = Text "debug" instance ToJSON DebugEvent where toJSON :: DebugEvent -> Value toJSON (DebugEvent FeatureEvent x) = forall a. ToJSON a => a -> Value toJSON FeatureEvent x addUserToEvent :: (HasField' "user" r (Maybe Value), HasField' "userKey" r (Maybe Text)) => ConfigI -> UserI -> r -> r addUserToEvent :: forall r. (HasField' "user" r (Maybe Value), HasField' "userKey" r (Maybe Text)) => ConfigI -> UserI -> r -> r addUserToEvent ConfigI config UserI user r event = if forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"inlineUsersInEvents" ConfigI config then forall (f :: Symbol) s a. HasField' f s a => a -> s -> s setField @"user" (forall (f :: * -> *) a. Applicative f => a -> f a pure forall a b. (a -> b) -> a -> b $ ConfigI -> UserI -> Value userSerializeRedacted ConfigI config UserI user) r event else forall (f :: Symbol) s a. HasField' f s a => a -> s -> s setField @"userKey" (forall (f :: * -> *) a. Applicative f => a -> f a pure forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" UserI user) r event forceUserInlineInEvent :: ConfigI -> UserI -> FeatureEvent -> FeatureEvent forceUserInlineInEvent :: ConfigI -> UserI -> FeatureEvent -> FeatureEvent forceUserInlineInEvent ConfigI config UserI user FeatureEvent event = forall (f :: Symbol) s a. HasField' f s a => a -> s -> s setField @"userKey" forall a. Maybe a Nothing forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) s a. HasField' f s a => a -> s -> s setField @"user" (forall (f :: * -> *) a. Applicative f => a -> f a pure forall a b. (a -> b) -> a -> b $ ConfigI -> UserI -> Value userSerializeRedacted ConfigI config UserI user) FeatureEvent event makeFeatureEvent :: ConfigI -> UserI -> Bool -> EvalEvent -> FeatureEvent makeFeatureEvent :: ConfigI -> UserI -> Bool -> EvalEvent -> FeatureEvent makeFeatureEvent ConfigI config UserI user Bool includeReason EvalEvent event = forall r. (HasField' "user" r (Maybe Value), HasField' "userKey" r (Maybe Text)) => ConfigI -> UserI -> r -> r addUserToEvent ConfigI config UserI user forall a b. (a -> b) -> a -> b $ FeatureEvent { $sel:key:FeatureEvent :: Text key = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" EvalEvent event , $sel:user:FeatureEvent :: Maybe Value user = forall a. Maybe a Nothing , $sel:userKey:FeatureEvent :: Maybe Text userKey = forall a. Maybe a Nothing , $sel:value:FeatureEvent :: Value value = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"value" EvalEvent event , $sel:defaultValue:FeatureEvent :: Maybe Value defaultValue = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"defaultValue" EvalEvent event , $sel:version:FeatureEvent :: Maybe Natural version = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"version" EvalEvent event , $sel:variation:FeatureEvent :: Maybe Integer variation = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"variation" EvalEvent event , $sel:reason:FeatureEvent :: Maybe EvaluationReason reason = if Bool includeReason Bool -> Bool -> Bool || forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"forceIncludeReason" EvalEvent event then forall (f :: * -> *) a. Applicative f => a -> f a pure forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"reason" EvalEvent event else forall a. Maybe a Nothing , $sel:contextKind:FeatureEvent :: ContextKind contextKind = UserI -> ContextKind userGetContextKind UserI user } data CustomEvent = CustomEvent { CustomEvent -> Text key :: !Text , CustomEvent -> Maybe Value user :: !(Maybe Value) , CustomEvent -> Maybe Text userKey :: !(Maybe Text) , CustomEvent -> Maybe Double metricValue :: !(Maybe Double) , CustomEvent -> Maybe Value value :: !(Maybe Value) , CustomEvent -> ContextKind contextKind :: !ContextKind } deriving (forall x. Rep CustomEvent x -> CustomEvent forall x. CustomEvent -> Rep CustomEvent x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep CustomEvent x -> CustomEvent $cfrom :: forall x. CustomEvent -> Rep CustomEvent x Generic, Int -> CustomEvent -> ShowS [CustomEvent] -> ShowS CustomEvent -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [CustomEvent] -> ShowS $cshowList :: [CustomEvent] -> ShowS show :: CustomEvent -> String $cshow :: CustomEvent -> String showsPrec :: Int -> CustomEvent -> ShowS $cshowsPrec :: Int -> CustomEvent -> ShowS Show) instance ToJSON CustomEvent where toJSON :: CustomEvent -> Value toJSON CustomEvent ctx = [Pair] -> Value object forall a b. (a -> b) -> a -> b $ forall a. (a -> Bool) -> [a] -> [a] filter (forall a. Eq a => a -> a -> Bool (/=) Value Null forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a, b) -> b snd) [ (Key "key", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" CustomEvent ctx) , (Key "user", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"user" CustomEvent ctx) , (Key "userKey", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"userKey" CustomEvent ctx) , (Key "metricValue", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"metricValue" CustomEvent ctx) , (Key "data", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"value" CustomEvent ctx) , (Key "contextKind", let c :: ContextKind c = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"contextKind" CustomEvent ctx in if ContextKind c forall a. Eq a => a -> a -> Bool == ContextKind ContextKindUser then Value Null else forall a. ToJSON a => a -> Value toJSON ContextKind c) ] instance EventKind CustomEvent where eventKind :: CustomEvent -> Text eventKind CustomEvent _ = Text "custom" data AliasEvent = AliasEvent { AliasEvent -> Text key :: !Text , AliasEvent -> ContextKind contextKind :: !ContextKind , AliasEvent -> Text previousKey :: !Text , AliasEvent -> ContextKind previousContextKind :: !ContextKind } deriving (forall x. Rep AliasEvent x -> AliasEvent forall x. AliasEvent -> Rep AliasEvent x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a $cto :: forall x. Rep AliasEvent x -> AliasEvent $cfrom :: forall x. AliasEvent -> Rep AliasEvent x Generic, Int -> AliasEvent -> ShowS [AliasEvent] -> ShowS AliasEvent -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [AliasEvent] -> ShowS $cshowList :: [AliasEvent] -> ShowS show :: AliasEvent -> String $cshow :: AliasEvent -> String showsPrec :: Int -> AliasEvent -> ShowS $cshowsPrec :: Int -> AliasEvent -> ShowS Show) instance ToJSON AliasEvent where toJSON :: AliasEvent -> Value toJSON AliasEvent ctx = [Pair] -> Value object forall a b. (a -> b) -> a -> b $ forall a. (a -> Bool) -> [a] -> [a] filter (forall a. Eq a => a -> a -> Bool (/=) Value Null forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a, b) -> b snd) [ (Key "key", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" AliasEvent ctx) , (Key "contextKind", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"contextKind" AliasEvent ctx) , (Key "previousKey", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"previousKey" AliasEvent ctx) , (Key "previousContextKind", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"previousContextKind" AliasEvent ctx) ] instance EventKind AliasEvent where eventKind :: AliasEvent -> Text eventKind AliasEvent _ = Text "alias" data BaseEvent event = BaseEvent { forall event. BaseEvent event -> Natural creationDate :: Natural , forall event. BaseEvent event -> event event :: event } deriving (forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a forall event x. Rep (BaseEvent event) x -> BaseEvent event forall event x. BaseEvent event -> Rep (BaseEvent event) x $cto :: forall event x. Rep (BaseEvent event) x -> BaseEvent event $cfrom :: forall event x. BaseEvent event -> Rep (BaseEvent event) x Generic, Int -> BaseEvent event -> ShowS forall event. Show event => Int -> BaseEvent event -> ShowS forall event. Show event => [BaseEvent event] -> ShowS forall event. Show event => BaseEvent event -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [BaseEvent event] -> ShowS $cshowList :: forall event. Show event => [BaseEvent event] -> ShowS show :: BaseEvent event -> String $cshow :: forall event. Show event => BaseEvent event -> String showsPrec :: Int -> BaseEvent event -> ShowS $cshowsPrec :: forall event. Show event => Int -> BaseEvent event -> ShowS Show) fromObject :: Value -> KeyMap Value fromObject :: Value -> KeyMap Value fromObject Value x = case Value x of (Object KeyMap Value o) -> KeyMap Value o; Value _ -> forall a. HasCallStack => String -> a error String "expected object" instance (EventKind sub, ToJSON sub) => ToJSON (BaseEvent sub) where toJSON :: BaseEvent sub -> Value toJSON BaseEvent sub event = KeyMap Value -> Value Object forall a b. (a -> b) -> a -> b $ forall v. KeyMap v -> KeyMap v -> KeyMap v keyMapUnion (Value -> KeyMap Value fromObject forall a b. (a -> b) -> a -> b $ forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"event" BaseEvent sub event) forall a b. (a -> b) -> a -> b $ forall l. IsList l => [Item l] -> l fromList [ (Key "creationDate", forall a. ToJSON a => a -> Value toJSON forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"creationDate" BaseEvent sub event) , (Key "kind", Text -> Value String forall a b. (a -> b) -> a -> b $ forall a. EventKind a => a -> Text eventKind forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"event" BaseEvent sub event) ] data EventType = EventTypeIdentify !(BaseEvent IdentifyEvent) | EventTypeFeature !(BaseEvent FeatureEvent) | EventTypeSummary !SummaryEvent | EventTypeCustom !(BaseEvent CustomEvent) | EventTypeIndex !(BaseEvent IndexEvent) | EventTypeDebug !(BaseEvent DebugEvent) | EventTypeAlias !(BaseEvent AliasEvent) instance ToJSON EventType where toJSON :: EventType -> Value toJSON EventType event = case EventType event of EventTypeIdentify BaseEvent IdentifyEvent x -> forall a. ToJSON a => a -> Value toJSON BaseEvent IdentifyEvent x EventTypeFeature BaseEvent FeatureEvent x -> forall a. ToJSON a => a -> Value toJSON BaseEvent FeatureEvent x EventTypeSummary SummaryEvent x -> KeyMap Value -> Value Object forall a b. (a -> b) -> a -> b $ forall v. Text -> v -> KeyMap v -> KeyMap v insertKey Text "kind" (Text -> Value String Text "summary") (Value -> KeyMap Value fromObject forall a b. (a -> b) -> a -> b $ forall a. ToJSON a => a -> Value toJSON SummaryEvent x) EventTypeCustom BaseEvent CustomEvent x -> forall a. ToJSON a => a -> Value toJSON BaseEvent CustomEvent x EventTypeIndex BaseEvent IndexEvent x -> forall a. ToJSON a => a -> Value toJSON BaseEvent IndexEvent x EventTypeDebug BaseEvent DebugEvent x -> forall a. ToJSON a => a -> Value toJSON BaseEvent DebugEvent x EventTypeAlias BaseEvent AliasEvent x -> forall a. ToJSON a => a -> Value toJSON BaseEvent AliasEvent x newUnknownFlagEvent :: Text -> Value -> EvaluationReason -> EvalEvent newUnknownFlagEvent :: Text -> Value -> EvaluationReason -> EvalEvent newUnknownFlagEvent Text key Value defaultValue EvaluationReason reason = EvalEvent { $sel:key:EvalEvent :: Text key = Text key , $sel:variation:EvalEvent :: Maybe Integer variation = forall a. Maybe a Nothing , $sel:value:EvalEvent :: Value value = Value defaultValue , $sel:defaultValue:EvalEvent :: Maybe Value defaultValue = forall (f :: * -> *) a. Applicative f => a -> f a pure Value defaultValue , $sel:version:EvalEvent :: Maybe Natural version = forall a. Maybe a Nothing , $sel:prereqOf:EvalEvent :: Maybe Text prereqOf = forall a. Maybe a Nothing , $sel:reason:EvalEvent :: EvaluationReason reason = EvaluationReason reason , $sel:trackEvents:EvalEvent :: Bool trackEvents = Bool False , $sel:forceIncludeReason:EvalEvent :: Bool forceIncludeReason = Bool False , $sel:debug:EvalEvent :: Bool debug = Bool False , $sel:debugEventsUntilDate:EvalEvent :: Maybe Natural debugEventsUntilDate = forall a. Maybe a Nothing } newSuccessfulEvalEvent :: Flag -> Maybe Integer -> Value -> Maybe Value -> EvaluationReason -> Maybe Text -> EvalEvent newSuccessfulEvalEvent :: Flag -> Maybe Integer -> Value -> Maybe Value -> EvaluationReason -> Maybe Text -> EvalEvent newSuccessfulEvalEvent Flag flag Maybe Integer variation Value value Maybe Value defaultValue EvaluationReason reason Maybe Text prereqOf = EvalEvent { $sel:key:EvalEvent :: Text key = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" Flag flag , $sel:variation:EvalEvent :: Maybe Integer variation = Maybe Integer variation , $sel:value:EvalEvent :: Value value = Value value , $sel:defaultValue:EvalEvent :: Maybe Value defaultValue = Maybe Value defaultValue , $sel:version:EvalEvent :: Maybe Natural version = forall a. a -> Maybe a Just forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"version" Flag flag , $sel:prereqOf:EvalEvent :: Maybe Text prereqOf = Maybe Text prereqOf , $sel:reason:EvalEvent :: EvaluationReason reason = EvaluationReason reason , $sel:trackEvents:EvalEvent :: Bool trackEvents = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"trackEvents" Flag flag Bool -> Bool -> Bool || Bool shouldForceReason , $sel:forceIncludeReason:EvalEvent :: Bool forceIncludeReason = Bool shouldForceReason , $sel:debug:EvalEvent :: Bool debug = Bool False , $sel:debugEventsUntilDate:EvalEvent :: Maybe Natural debugEventsUntilDate = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"debugEventsUntilDate" Flag flag } where shouldForceReason :: Bool shouldForceReason = case EvaluationReason reason of (EvaluationReasonFallthrough Bool inExperiment) -> Bool inExperiment Bool -> Bool -> Bool || forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"trackEventsFallthrough" Flag flag (EvaluationReasonRuleMatch Natural idx Text _ Bool inExperiment) -> Bool inExperiment Bool -> Bool -> Bool || forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"trackEvents" (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"rules" Flag flag forall a. [a] -> Int -> a !! forall a b. (Integral a, Num b) => a -> b fromIntegral Natural idx) EvaluationReason _ -> Bool False makeSummaryKey :: EvalEvent -> Text makeSummaryKey :: EvalEvent -> Text makeSummaryKey EvalEvent event = Text -> [Text] -> Text T.intercalate Text "-" [ forall a. a -> Maybe a -> a fromMaybe Text "" forall a b. (a -> b) -> a -> b $ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap (String -> Text T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Show a => a -> String show) forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"version" EvalEvent event , forall a. a -> Maybe a -> a fromMaybe Text "" forall a b. (a -> b) -> a -> b $ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap (String -> Text T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Show a => a -> String show) forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"variation" EvalEvent event ] summarizeEvent :: KeyMap (FlagSummaryContext (KeyMap CounterContext)) -> EvalEvent -> Bool -> KeyMap (FlagSummaryContext (KeyMap CounterContext)) summarizeEvent :: KeyMap (FlagSummaryContext (KeyMap CounterContext)) -> EvalEvent -> Bool -> KeyMap (FlagSummaryContext (KeyMap CounterContext)) summarizeEvent KeyMap (FlagSummaryContext (KeyMap CounterContext)) context EvalEvent event Bool unknown = KeyMap (FlagSummaryContext (KeyMap CounterContext)) result where key :: Text key = EvalEvent -> Text makeSummaryKey EvalEvent event root :: FlagSummaryContext (KeyMap CounterContext) root = case forall v. Text -> KeyMap v -> Maybe v lookupKey (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" EvalEvent event) KeyMap (FlagSummaryContext (KeyMap CounterContext)) context of (Just FlagSummaryContext (KeyMap CounterContext) x) -> FlagSummaryContext (KeyMap CounterContext) x; Maybe (FlagSummaryContext (KeyMap CounterContext)) Nothing -> forall a. Maybe Value -> a -> FlagSummaryContext a FlagSummaryContext (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"defaultValue" EvalEvent event) forall a. Monoid a => a mempty leaf :: CounterContext leaf = case forall v. Text -> KeyMap v -> Maybe v lookupKey Text key (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"counters" FlagSummaryContext (KeyMap CounterContext) root) of (Just CounterContext x) -> CounterContext x forall a b. a -> (a -> b) -> b & forall (field :: Symbol) s t a b. HasField field s t a b => Lens s t a b field @"count" forall s t a b. ASetter s t a b -> (a -> b) -> s -> t %~ (Natural 1 forall a. Num a => a -> a -> a +) Maybe CounterContext Nothing -> CounterContext { $sel:count:CounterContext :: Natural count = Natural 1 , $sel:version:CounterContext :: Maybe Natural version = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"version" EvalEvent event , $sel:variation:CounterContext :: Maybe Integer variation = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"variation" EvalEvent event , $sel:value:CounterContext :: Value value = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"value" EvalEvent event , $sel:unknown:CounterContext :: Bool unknown = Bool unknown } result :: KeyMap (FlagSummaryContext (KeyMap CounterContext)) result = forall a b c. (a -> b -> c) -> b -> a -> c flip (forall v. Text -> v -> KeyMap v -> KeyMap v insertKey forall a b. (a -> b) -> a -> b $ forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" EvalEvent event) KeyMap (FlagSummaryContext (KeyMap CounterContext)) context forall a b. (a -> b) -> a -> b $ FlagSummaryContext (KeyMap CounterContext) root forall a b. a -> (a -> b) -> b & forall (field :: Symbol) s t a b. HasField field s t a b => Lens s t a b field @"counters" forall s t a b. ASetter s t a b -> (a -> b) -> s -> t %~ forall v. Text -> v -> KeyMap v -> KeyMap v insertKey Text key CounterContext leaf putIfEmptyMVar :: MVar a -> a -> IO () putIfEmptyMVar :: forall a. MVar a -> a -> IO () putIfEmptyMVar MVar a mvar a value = forall a. MVar a -> IO (Maybe a) tryTakeMVar MVar a mvar forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Just a x -> forall a. MVar a -> a -> IO () putMVar MVar a mvar a x; Maybe a Nothing -> forall a. MVar a -> a -> IO () putMVar MVar a mvar a value; runSummary :: Natural -> EventState -> EvalEvent -> Bool -> IO () runSummary :: Natural -> EventState -> EvalEvent -> Bool -> IO () runSummary Natural now EventState state EvalEvent event Bool unknown = forall a. MVar a -> a -> IO () putIfEmptyMVar (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"startDate" EventState state) Natural now forall (m :: * -> *) a b. Monad m => m a -> m b -> m b >> forall a. MVar a -> (a -> IO a) -> IO () modifyMVar_ (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"summary" EventState state) (\KeyMap (FlagSummaryContext (KeyMap CounterContext)) summary -> forall (f :: * -> *) a. Applicative f => a -> f a pure forall a b. (a -> b) -> a -> b $ KeyMap (FlagSummaryContext (KeyMap CounterContext)) -> EvalEvent -> Bool -> KeyMap (FlagSummaryContext (KeyMap CounterContext)) summarizeEvent KeyMap (FlagSummaryContext (KeyMap CounterContext)) summary EvalEvent event Bool unknown) processEvalEvent :: Natural -> ConfigI -> EventState -> UserI -> Bool -> Bool -> EvalEvent -> IO () processEvalEvent :: Natural -> ConfigI -> EventState -> UserI -> Bool -> Bool -> EvalEvent -> IO () processEvalEvent Natural now ConfigI config EventState state UserI user Bool includeReason Bool unknown EvalEvent event = do let featureEvent :: FeatureEvent featureEvent = ConfigI -> UserI -> Bool -> EvalEvent -> FeatureEvent makeFeatureEvent ConfigI config UserI user Bool includeReason EvalEvent event trackEvents :: Bool trackEvents = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"trackEvents" EvalEvent event inlineUsers :: Bool inlineUsers = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"inlineUsersInEvents" ConfigI config debugEventsUntilDate :: Natural debugEventsUntilDate = forall a. a -> Maybe a -> a fromMaybe Natural 0 (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"debugEventsUntilDate" EvalEvent event) Natural lastKnownServerTime <- Integer -> Natural naturalFromInteger forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> (forall a. Num a => a -> a -> a * Integer 1000) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> forall a. MVar a -> IO a readMVar (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"lastKnownServerTime" EventState state) forall (f :: * -> *). Applicative f => Bool -> f () -> f () when Bool trackEvents forall a b. (a -> b) -> a -> b $ ConfigI -> EventState -> EventType -> IO () queueEvent ConfigI config EventState state forall a b. (a -> b) -> a -> b $ BaseEvent FeatureEvent -> EventType EventTypeFeature forall a b. (a -> b) -> a -> b $ forall event. Natural -> event -> BaseEvent event BaseEvent Natural now FeatureEvent featureEvent forall (f :: * -> *). Applicative f => Bool -> f () -> f () when (Natural now forall a. Ord a => a -> a -> Bool < Natural debugEventsUntilDate Bool -> Bool -> Bool && Natural lastKnownServerTime forall a. Ord a => a -> a -> Bool < Natural debugEventsUntilDate) forall a b. (a -> b) -> a -> b $ ConfigI -> EventState -> EventType -> IO () queueEvent ConfigI config EventState state forall a b. (a -> b) -> a -> b $ BaseEvent DebugEvent -> EventType EventTypeDebug forall a b. (a -> b) -> a -> b $ forall event. Natural -> event -> BaseEvent event BaseEvent Natural now forall a b. (a -> b) -> a -> b $ FeatureEvent -> DebugEvent DebugEvent forall a b. (a -> b) -> a -> b $ ConfigI -> UserI -> FeatureEvent -> FeatureEvent forceUserInlineInEvent ConfigI config UserI user FeatureEvent featureEvent Natural -> EventState -> EvalEvent -> Bool -> IO () runSummary Natural now EventState state EvalEvent event Bool unknown forall (f :: * -> *). Applicative f => Bool -> f () -> f () unless (Bool trackEvents Bool -> Bool -> Bool && Bool inlineUsers) forall a b. (a -> b) -> a -> b $ Natural -> ConfigI -> UserI -> EventState -> IO () maybeIndexUser Natural now ConfigI config UserI user EventState state processEvalEvents :: ConfigI -> EventState -> UserI -> Bool -> [EvalEvent] -> Bool -> IO () processEvalEvents :: ConfigI -> EventState -> UserI -> Bool -> [EvalEvent] -> Bool -> IO () processEvalEvents ConfigI config EventState state UserI user Bool includeReason [EvalEvent] events Bool unknown = IO Natural unixMilliseconds forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \Natural now -> forall (t :: * -> *) (m :: * -> *) a b. (Foldable t, Monad m) => (a -> m b) -> t a -> m () mapM_ (Natural -> ConfigI -> EventState -> UserI -> Bool -> Bool -> EvalEvent -> IO () processEvalEvent Natural now ConfigI config EventState state UserI user Bool includeReason Bool unknown) [EvalEvent] events maybeIndexUser :: Natural -> ConfigI -> UserI -> EventState -> IO () maybeIndexUser :: Natural -> ConfigI -> UserI -> EventState -> IO () maybeIndexUser Natural now ConfigI config UserI user EventState state = do Bool noticedUser <- EventState -> UserI -> IO Bool noticeUser EventState state UserI user forall (f :: * -> *). Applicative f => Bool -> f () -> f () when Bool noticedUser forall a b. (a -> b) -> a -> b $ ConfigI -> EventState -> EventType -> IO () queueEvent ConfigI config EventState state (BaseEvent IndexEvent -> EventType EventTypeIndex forall a b. (a -> b) -> a -> b $ forall event. Natural -> event -> BaseEvent event BaseEvent Natural now forall a b. (a -> b) -> a -> b $ IndexEvent { $sel:user:IndexEvent :: Value user = ConfigI -> UserI -> Value userSerializeRedacted ConfigI config UserI user }) noticeUser :: EventState -> UserI -> IO Bool noticeUser :: EventState -> UserI -> IO Bool noticeUser EventState state UserI user = forall a b. MVar a -> (a -> IO (a, b)) -> IO b modifyMVar (forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"userKeyLRU" EventState state) forall a b. (a -> b) -> a -> b $ \LRU Text () cache -> do let key :: Text key = forall (f :: Symbol) a s. HasField' f s a => s -> a getField @"key" UserI user case forall key val. Ord key => key -> LRU key val -> (LRU key val, Maybe val) LRU.lookup Text key LRU Text () cache of (LRU Text () cache', Just () _) -> forall (f :: * -> *) a. Applicative f => a -> f a pure (LRU Text () cache', Bool False) (LRU Text () cache', Maybe () Nothing) -> forall (f :: * -> *) a. Applicative f => a -> f a pure (forall key val. Ord key => key -> val -> LRU key val -> LRU key val LRU.insert Text key () LRU Text () cache', Bool True)