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
(ContextKind -> ContextKind -> Bool)
-> (ContextKind -> ContextKind -> Bool) -> Eq ContextKind
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
(Int -> ContextKind -> ShowS)
-> (ContextKind -> String)
-> ([ContextKind] -> ShowS)
-> Show ContextKind
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 (Text -> Value) -> Text -> Value
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 UserI -> Bool
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. EvalEvent -> Rep EvalEvent x)
-> (forall x. Rep EvalEvent x -> EvalEvent) -> Generic EvalEvent
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
(EvalEvent -> EvalEvent -> Bool)
-> (EvalEvent -> EvalEvent -> Bool) -> Eq EvalEvent
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
(Int -> EvalEvent -> ShowS)
-> (EvalEvent -> String)
-> ([EvalEvent] -> ShowS)
-> Show EvalEvent
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. EventState -> Rep EventState x)
-> (forall x. Rep EventState x -> EventState) -> Generic EventState
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              <- [EventType] -> IO (MVar [EventType])
forall a. a -> IO (MVar a)
newMVar []
    MVar Integer
lastKnownServerTime <- Integer -> IO (MVar Integer)
forall a. a -> IO (MVar a)
newMVar Integer
0
    MVar ()
flush               <- IO (MVar ())
forall a. IO (MVar a)
newEmptyMVar
    MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
summary             <- KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> IO (MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext))))
forall a. a -> IO (MVar a)
newMVar KeyMap (FlagSummaryContext (KeyMap CounterContext))
forall a. Monoid a => a
mempty
    MVar Natural
startDate           <- IO (MVar Natural)
forall a. IO (MVar a)
newEmptyMVar
    MVar (LRU Text ())
userKeyLRU          <- LRU Text () -> IO (MVar (LRU Text ()))
forall a. a -> IO (MVar a)
newMVar (LRU Text () -> IO (MVar (LRU Text ())))
-> LRU Text () -> IO (MVar (LRU Text ()))
forall a b. (a -> b) -> a -> b
$ Maybe Integer -> LRU Text ()
forall key val. Ord key => Maybe Integer -> LRU key val
newLRU (Maybe Integer -> LRU Text ()) -> Maybe Integer -> LRU Text ()
forall a b. (a -> b) -> a -> b
$ Integer -> Maybe Integer
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer -> Maybe Integer) -> Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Natural -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Natural -> Integer) -> Natural -> Integer
forall a b. (a -> b) -> a -> b
$ ConfigI -> Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"userKeyLRUCapacity" ConfigI
config
    EventState -> IO EventState
forall (f :: * -> *) a. Applicative f => a -> f a
pure EventState :: MVar [EventType]
-> MVar Integer
-> MVar ()
-> MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
-> MVar Natural
-> MVar (LRU Text ())
-> EventState
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 = ((FlagSummaryContext (KeyMap CounterContext)
  -> FlagSummaryContext [CounterContext])
 -> KeyMap (FlagSummaryContext (KeyMap CounterContext))
 -> KeyMap (FlagSummaryContext [CounterContext]))
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> (FlagSummaryContext (KeyMap CounterContext)
    -> FlagSummaryContext [CounterContext])
-> KeyMap (FlagSummaryContext [CounterContext])
forall a b c. (a -> b -> c) -> b -> a -> c
flip (FlagSummaryContext (KeyMap CounterContext)
 -> FlagSummaryContext [CounterContext])
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> KeyMap (FlagSummaryContext [CounterContext])
forall v1 v2. (v1 -> v2) -> KeyMap v1 -> KeyMap v2
mapValues KeyMap (FlagSummaryContext (KeyMap CounterContext))
summary ((FlagSummaryContext (KeyMap CounterContext)
  -> FlagSummaryContext [CounterContext])
 -> KeyMap (FlagSummaryContext [CounterContext]))
-> (FlagSummaryContext (KeyMap CounterContext)
    -> FlagSummaryContext [CounterContext])
-> KeyMap (FlagSummaryContext [CounterContext])
forall a b. (a -> b) -> a -> b
$ \FlagSummaryContext (KeyMap CounterContext)
context -> FlagSummaryContext (KeyMap CounterContext)
context FlagSummaryContext (KeyMap CounterContext)
-> (FlagSummaryContext (KeyMap CounterContext)
    -> FlagSummaryContext [CounterContext])
-> FlagSummaryContext [CounterContext]
forall a b. a -> (a -> b) -> b
& forall s t a b. HasField "counters" s t a b => Lens s t a b
forall (field :: Symbol) s t a b.
HasField field s t a b =>
Lens s t a b
field @"counters" ((KeyMap CounterContext -> Identity [CounterContext])
 -> FlagSummaryContext (KeyMap CounterContext)
 -> Identity (FlagSummaryContext [CounterContext]))
-> (KeyMap CounterContext -> [CounterContext])
-> FlagSummaryContext (KeyMap CounterContext)
-> FlagSummaryContext [CounterContext]
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ KeyMap CounterContext -> [CounterContext]
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 () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure () else
    MVar [EventType] -> ([EventType] -> IO [EventType]) -> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (EventState -> MVar [EventType]
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"events" EventState
state) (([EventType] -> IO [EventType]) -> IO ())
-> ([EventType] -> IO [EventType]) -> IO ()
forall a b. (a -> b) -> a -> b
$ \[EventType]
events ->
        [EventType] -> IO [EventType]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([EventType] -> IO [EventType]) -> [EventType] -> IO [EventType]
forall a b. (a -> b) -> a -> b
$ case EventType
event of
          EventTypeSummary SummaryEvent
_ -> EventType
event EventType -> [EventType] -> [EventType]
forall a. a -> [a] -> [a]
: [EventType]
events
          EventType
_ | [EventType] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [EventType]
events Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Natural -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ConfigI -> Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"eventsCapacity" ConfigI
config) -> EventType
event EventType -> [EventType] -> [EventType]
forall a. a -> [a] -> [a]
: [EventType]
events
          EventType
_ -> [EventType]
events

unixMilliseconds :: IO Natural
unixMilliseconds :: IO Natural
unixMilliseconds = POSIXTime -> Natural
forall a b. (RealFrac a, Integral b) => a -> b
round (POSIXTime -> Natural)
-> (POSIXTime -> POSIXTime) -> POSIXTime -> Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (POSIXTime -> POSIXTime -> POSIXTime
forall a. Num a => a -> a -> a
* POSIXTime
1000) (POSIXTime -> Natural) -> IO POSIXTime -> IO Natural
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO POSIXTime
getPOSIXTime

makeBaseEvent :: a -> IO (BaseEvent a)
makeBaseEvent :: a -> IO (BaseEvent a)
makeBaseEvent a
child = IO Natural
unixMilliseconds IO Natural -> (Natural -> IO (BaseEvent a)) -> IO (BaseEvent a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Natural
now -> BaseEvent a -> IO (BaseEvent a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BaseEvent a -> IO (BaseEvent a))
-> BaseEvent a -> IO (BaseEvent a)
forall a b. (a -> b) -> a -> b
$ BaseEvent :: forall event. Natural -> event -> BaseEvent event
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 = MVar Natural -> IO (Maybe Natural)
forall a. MVar a -> IO (Maybe a)
tryTakeMVar (EventState -> MVar Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"startDate" EventState
state) IO (Maybe Natural) -> (Maybe Natural -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Maybe Natural
Nothing          -> () -> IO ()
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 (KeyMap (FlagSummaryContext (KeyMap CounterContext))
 -> KeyMap (FlagSummaryContext [CounterContext]))
-> IO (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
-> IO (KeyMap (FlagSummaryContext [CounterContext]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> IO (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
forall a. MVar a -> a -> IO a
swapMVar (EventState
-> MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"summary" EventState
state) KeyMap (FlagSummaryContext (KeyMap CounterContext))
forall a. Monoid a => a
mempty
        ConfigI -> EventState -> EventType -> IO ()
queueEvent ConfigI
config EventState
state (EventType -> IO ()) -> EventType -> IO ()
forall a b. (a -> b) -> a -> b
$ SummaryEvent -> EventType
EventTypeSummary (SummaryEvent -> EventType) -> SummaryEvent -> EventType
forall a b. (a -> b) -> a -> b
$ SummaryEvent :: Natural
-> Natural
-> KeyMap (FlagSummaryContext [CounterContext])
-> SummaryEvent
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. SummaryEvent -> Rep SummaryEvent x)
-> (forall x. Rep SummaryEvent x -> SummaryEvent)
-> Generic SummaryEvent
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
(Int -> SummaryEvent -> ShowS)
-> (SummaryEvent -> String)
-> ([SummaryEvent] -> ShowS)
-> Show SummaryEvent
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
(SummaryEvent -> Value)
-> (SummaryEvent -> Encoding)
-> ([SummaryEvent] -> Value)
-> ([SummaryEvent] -> Encoding)
-> ToJSON SummaryEvent
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
    { FlagSummaryContext a -> Maybe Value
defaultValue :: Maybe Value
    , FlagSummaryContext a -> a
counters     :: a
    } deriving ((forall x. FlagSummaryContext a -> Rep (FlagSummaryContext a) x)
-> (forall x. Rep (FlagSummaryContext a) x -> FlagSummaryContext a)
-> Generic (FlagSummaryContext a)
forall x. Rep (FlagSummaryContext a) x -> FlagSummaryContext a
forall x. FlagSummaryContext a -> Rep (FlagSummaryContext a) x
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
[FlagSummaryContext a] -> ShowS
FlagSummaryContext a -> String
(Int -> FlagSummaryContext a -> ShowS)
-> (FlagSummaryContext a -> String)
-> ([FlagSummaryContext a] -> ShowS)
-> Show (FlagSummaryContext a)
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 ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ (Pair -> Bool) -> [Pair] -> [Pair]
forall a. (a -> Bool) -> [a] -> [a]
filter (Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
(/=) Value
Null (Value -> Bool) -> (Pair -> Value) -> Pair -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Value
forall a b. (a, b) -> b
snd)
        [ (Key
"default",  Maybe Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Value -> Value) -> Maybe Value -> Value
forall a b. (a -> b) -> a -> b
$ FlagSummaryContext a -> Maybe Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"defaultValue" FlagSummaryContext a
ctx)
        , (Key
"counters", a -> Value
forall a. ToJSON a => a -> Value
toJSON (a -> Value) -> a -> Value
forall a b. (a -> b) -> a -> b
$ FlagSummaryContext a -> a
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. CounterContext -> Rep CounterContext x)
-> (forall x. Rep CounterContext x -> CounterContext)
-> Generic CounterContext
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
(Int -> CounterContext -> ShowS)
-> (CounterContext -> String)
-> ([CounterContext] -> ShowS)
-> Show CounterContext
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 ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$
        [ Key
"count" Key -> Natural -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= CounterContext -> Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"count" CounterContext
context
        , Key
"value" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= CounterContext -> Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"value" CounterContext
context
        ] [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> (Pair -> Bool) -> [Pair] -> [Pair]
forall a. (a -> Bool) -> [a] -> [a]
filter (Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
(/=) Value
Null (Value -> Bool) -> (Pair -> Value) -> Pair -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Value
forall a b. (a, b) -> b
snd)
        [ Key
"version" Key -> Maybe Natural -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= CounterContext -> Maybe Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"version" CounterContext
context
        , Key
"variation" Key -> Maybe Integer -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= CounterContext -> Maybe Integer
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"variation" CounterContext
context
        , Key
"unknown" Key -> Maybe Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= if CounterContext -> Bool
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"unknown" CounterContext
context then Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True else Maybe Bool
forall a. Maybe a
Nothing
        ]

data IdentifyEvent = IdentifyEvent
    { IdentifyEvent -> Text
key  :: !Text
    , IdentifyEvent -> Value
user :: !Value
    } deriving ((forall x. IdentifyEvent -> Rep IdentifyEvent x)
-> (forall x. Rep IdentifyEvent x -> IdentifyEvent)
-> Generic IdentifyEvent
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
(IdentifyEvent -> Value)
-> (IdentifyEvent -> Encoding)
-> ([IdentifyEvent] -> Value)
-> ([IdentifyEvent] -> Encoding)
-> ToJSON IdentifyEvent
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
(Int -> IdentifyEvent -> ShowS)
-> (IdentifyEvent -> String)
-> ([IdentifyEvent] -> ShowS)
-> Show IdentifyEvent
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. IndexEvent -> Rep IndexEvent x)
-> (forall x. Rep IndexEvent x -> IndexEvent) -> Generic IndexEvent
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
(IndexEvent -> Value)
-> (IndexEvent -> Encoding)
-> ([IndexEvent] -> Value)
-> ([IndexEvent] -> Encoding)
-> ToJSON IndexEvent
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
(Int -> IndexEvent -> ShowS)
-> (IndexEvent -> String)
-> ([IndexEvent] -> ShowS)
-> Show IndexEvent
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. FeatureEvent -> Rep FeatureEvent x)
-> (forall x. Rep FeatureEvent x -> FeatureEvent)
-> Generic FeatureEvent
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
(Int -> FeatureEvent -> ShowS)
-> (FeatureEvent -> String)
-> ([FeatureEvent] -> ShowS)
-> Show FeatureEvent
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 ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ (Pair -> Bool) -> [Pair] -> [Pair]
forall a. (a -> Bool) -> [a] -> [a]
filter (Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
(/=) Value
Null (Value -> Bool) -> (Pair -> Value) -> Pair -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Value
forall a b. (a, b) -> b
snd)
        [ (Key
"key",         Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Text -> Value) -> Text -> Value
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"key"          FeatureEvent
event)
        , (Key
"user",        Maybe Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Value -> Value) -> Maybe Value -> Value
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> Maybe Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"user"         FeatureEvent
event)
        , (Key
"userKey",     Maybe Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Text -> Value) -> Maybe Text -> Value
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> Maybe Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"userKey"      FeatureEvent
event)
        , (Key
"value",       Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Value -> Value) -> Value -> Value
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"value"        FeatureEvent
event)
        , (Key
"default",     Maybe Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Value -> Value) -> Maybe Value -> Value
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> Maybe Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"defaultValue" FeatureEvent
event)
        , (Key
"version",     Maybe Natural -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Natural -> Value) -> Maybe Natural -> Value
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> Maybe Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"version"      FeatureEvent
event)
        , (Key
"variation",   Maybe Integer -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Integer -> Value) -> Maybe Integer -> Value
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> Maybe Integer
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"variation"    FeatureEvent
event)
        , (Key
"reason",      Maybe EvaluationReason -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe EvaluationReason -> Value)
-> Maybe EvaluationReason -> Value
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> Maybe EvaluationReason
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"reason"       FeatureEvent
event)
        , (Key
"contextKind", let c :: ContextKind
c = FeatureEvent -> ContextKind
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"contextKind" FeatureEvent
event in
            if ContextKind
c ContextKind -> ContextKind -> Bool
forall a. Eq a => a -> a -> Bool
== ContextKind
ContextKindUser then Value
Null else ContextKind -> Value
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) = FeatureEvent -> Value
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 :: ConfigI -> UserI -> r -> r
addUserToEvent ConfigI
config UserI
user r
event = if ConfigI -> Bool
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"inlineUsersInEvents" ConfigI
config
    then Maybe Value -> r -> r
forall (f :: Symbol) s a. HasField' f s a => a -> s -> s
setField @"user" (Value -> Maybe Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Value -> Maybe Value) -> Value -> Maybe Value
forall a b. (a -> b) -> a -> b
$ ConfigI -> UserI -> Value
userSerializeRedacted ConfigI
config UserI
user) r
event
    else Maybe Text -> r -> r
forall (f :: Symbol) s a. HasField' f s a => a -> s -> s
setField @"userKey" (Text -> Maybe Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ UserI -> Text
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 = Maybe Text -> FeatureEvent -> FeatureEvent
forall (f :: Symbol) s a. HasField' f s a => a -> s -> s
setField @"userKey" Maybe Text
forall a. Maybe a
Nothing (FeatureEvent -> FeatureEvent) -> FeatureEvent -> FeatureEvent
forall a b. (a -> b) -> a -> b
$ Maybe Value -> FeatureEvent -> FeatureEvent
forall (f :: Symbol) s a. HasField' f s a => a -> s -> s
setField @"user" (Value -> Maybe Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Value -> Maybe Value) -> Value -> Maybe Value
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 = ConfigI -> UserI -> FeatureEvent -> FeatureEvent
forall r.
(HasField' "user" r (Maybe Value),
 HasField' "userKey" r (Maybe Text)) =>
ConfigI -> UserI -> r -> r
addUserToEvent ConfigI
config UserI
user (FeatureEvent -> FeatureEvent) -> FeatureEvent -> FeatureEvent
forall a b. (a -> b) -> a -> b
$ FeatureEvent :: Text
-> Maybe Value
-> Maybe Text
-> Value
-> Maybe Value
-> Maybe Natural
-> Maybe Integer
-> Maybe EvaluationReason
-> ContextKind
-> FeatureEvent
FeatureEvent
    { $sel:key:FeatureEvent :: Text
key          = EvalEvent -> Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"key" EvalEvent
event
    , $sel:user:FeatureEvent :: Maybe Value
user         = Maybe Value
forall a. Maybe a
Nothing
    , $sel:userKey:FeatureEvent :: Maybe Text
userKey      = Maybe Text
forall a. Maybe a
Nothing
    , $sel:value:FeatureEvent :: Value
value        = EvalEvent -> Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"value" EvalEvent
event
    , $sel:defaultValue:FeatureEvent :: Maybe Value
defaultValue = EvalEvent -> Maybe Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"defaultValue" EvalEvent
event
    , $sel:version:FeatureEvent :: Maybe Natural
version      = EvalEvent -> Maybe Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"version" EvalEvent
event
    , $sel:variation:FeatureEvent :: Maybe Integer
variation    = EvalEvent -> Maybe Integer
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
|| EvalEvent -> Bool
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"forceIncludeReason" EvalEvent
event
        then EvaluationReason -> Maybe EvaluationReason
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EvaluationReason -> Maybe EvaluationReason)
-> EvaluationReason -> Maybe EvaluationReason
forall a b. (a -> b) -> a -> b
$ EvalEvent -> EvaluationReason
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"reason" EvalEvent
event else Maybe EvaluationReason
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. CustomEvent -> Rep CustomEvent x)
-> (forall x. Rep CustomEvent x -> CustomEvent)
-> Generic CustomEvent
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
(Int -> CustomEvent -> ShowS)
-> (CustomEvent -> String)
-> ([CustomEvent] -> ShowS)
-> Show CustomEvent
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 ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ (Pair -> Bool) -> [Pair] -> [Pair]
forall a. (a -> Bool) -> [a] -> [a]
filter (Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
(/=) Value
Null (Value -> Bool) -> (Pair -> Value) -> Pair -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Value
forall a b. (a, b) -> b
snd)
        [ (Key
"key",         Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Text -> Value) -> Text -> Value
forall a b. (a -> b) -> a -> b
$ CustomEvent -> Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"key"         CustomEvent
ctx)
        , (Key
"user",        Maybe Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Value -> Value) -> Maybe Value -> Value
forall a b. (a -> b) -> a -> b
$ CustomEvent -> Maybe Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"user"        CustomEvent
ctx)
        , (Key
"userKey",     Maybe Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Text -> Value) -> Maybe Text -> Value
forall a b. (a -> b) -> a -> b
$ CustomEvent -> Maybe Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"userKey"     CustomEvent
ctx)
        , (Key
"metricValue", Maybe Double -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Double -> Value) -> Maybe Double -> Value
forall a b. (a -> b) -> a -> b
$ CustomEvent -> Maybe Double
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"metricValue" CustomEvent
ctx)
        , (Key
"data",        Maybe Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Value -> Value) -> Maybe Value -> Value
forall a b. (a -> b) -> a -> b
$ CustomEvent -> Maybe Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"value"       CustomEvent
ctx)
        , (Key
"contextKind", let c :: ContextKind
c = CustomEvent -> ContextKind
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"contextKind" CustomEvent
ctx in
            if ContextKind
c ContextKind -> ContextKind -> Bool
forall a. Eq a => a -> a -> Bool
== ContextKind
ContextKindUser then Value
Null else ContextKind -> Value
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. AliasEvent -> Rep AliasEvent x)
-> (forall x. Rep AliasEvent x -> AliasEvent) -> Generic AliasEvent
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
(Int -> AliasEvent -> ShowS)
-> (AliasEvent -> String)
-> ([AliasEvent] -> ShowS)
-> Show AliasEvent
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 ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ (Pair -> Bool) -> [Pair] -> [Pair]
forall a. (a -> Bool) -> [a] -> [a]
filter (Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
(/=) Value
Null (Value -> Bool) -> (Pair -> Value) -> Pair -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Value
forall a b. (a, b) -> b
snd)
        [ (Key
"key",                 Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Text -> Value) -> Text -> Value
forall a b. (a -> b) -> a -> b
$ AliasEvent -> Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"key"                 AliasEvent
ctx)
        , (Key
"contextKind",         ContextKind -> Value
forall a. ToJSON a => a -> Value
toJSON (ContextKind -> Value) -> ContextKind -> Value
forall a b. (a -> b) -> a -> b
$ AliasEvent -> ContextKind
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"contextKind"         AliasEvent
ctx)
        , (Key
"previousKey",         Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Text -> Value) -> Text -> Value
forall a b. (a -> b) -> a -> b
$ AliasEvent -> Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"previousKey"         AliasEvent
ctx)
        , (Key
"previousContextKind", ContextKind -> Value
forall a. ToJSON a => a -> Value
toJSON (ContextKind -> Value) -> ContextKind -> Value
forall a b. (a -> b) -> a -> b
$ AliasEvent -> ContextKind
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
    { BaseEvent event -> Natural
creationDate :: Natural
    , BaseEvent event -> event
event        :: event
    } deriving ((forall x. BaseEvent event -> Rep (BaseEvent event) x)
-> (forall x. Rep (BaseEvent event) x -> BaseEvent event)
-> Generic (BaseEvent event)
forall x. Rep (BaseEvent event) x -> BaseEvent event
forall x. BaseEvent event -> Rep (BaseEvent event) x
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
[BaseEvent event] -> ShowS
BaseEvent event -> String
(Int -> BaseEvent event -> ShowS)
-> (BaseEvent event -> String)
-> ([BaseEvent event] -> ShowS)
-> Show (BaseEvent event)
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
_ -> String -> KeyMap 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 (KeyMap Value -> Value) -> KeyMap Value -> Value
forall a b. (a -> b) -> a -> b
$ KeyMap Value -> KeyMap Value -> KeyMap Value
forall v. KeyMap v -> KeyMap v -> KeyMap v
keyMapUnion (Value -> KeyMap Value
fromObject (Value -> KeyMap Value) -> Value -> KeyMap Value
forall a b. (a -> b) -> a -> b
$ sub -> Value
forall a. ToJSON a => a -> Value
toJSON (sub -> Value) -> sub -> Value
forall a b. (a -> b) -> a -> b
$ BaseEvent sub -> sub
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"event" BaseEvent sub
event) (KeyMap Value -> KeyMap Value) -> KeyMap Value -> KeyMap Value
forall a b. (a -> b) -> a -> b
$ [Item (KeyMap Value)] -> KeyMap Value
forall l. IsList l => [Item l] -> l
fromList
        [ (Key
"creationDate", Natural -> Value
forall a. ToJSON a => a -> Value
toJSON (Natural -> Value) -> Natural -> Value
forall a b. (a -> b) -> a -> b
$ BaseEvent sub -> Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"creationDate" BaseEvent sub
event)
        , (Key
"kind",         Text -> Value
String (Text -> Value) -> Text -> Value
forall a b. (a -> b) -> a -> b
$ sub -> Text
forall a. EventKind a => a -> Text
eventKind (sub -> Text) -> sub -> Text
forall a b. (a -> b) -> a -> b
$ BaseEvent sub -> sub
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 -> BaseEvent IdentifyEvent -> Value
forall a. ToJSON a => a -> Value
toJSON BaseEvent IdentifyEvent
x
        EventTypeFeature  BaseEvent FeatureEvent
x -> BaseEvent FeatureEvent -> Value
forall a. ToJSON a => a -> Value
toJSON BaseEvent FeatureEvent
x
        EventTypeSummary  SummaryEvent
x -> KeyMap Value -> Value
Object (KeyMap Value -> Value) -> KeyMap Value -> Value
forall a b. (a -> b) -> a -> b
$ Text -> Value -> KeyMap Value -> KeyMap Value
forall v. Text -> v -> KeyMap v -> KeyMap v
insertKey Text
"kind" (Text -> Value
String Text
"summary") (Value -> KeyMap Value
fromObject (Value -> KeyMap Value) -> Value -> KeyMap Value
forall a b. (a -> b) -> a -> b
$ SummaryEvent -> Value
forall a. ToJSON a => a -> Value
toJSON SummaryEvent
x)
        EventTypeCustom   BaseEvent CustomEvent
x -> BaseEvent CustomEvent -> Value
forall a. ToJSON a => a -> Value
toJSON BaseEvent CustomEvent
x
        EventTypeIndex    BaseEvent IndexEvent
x -> BaseEvent IndexEvent -> Value
forall a. ToJSON a => a -> Value
toJSON BaseEvent IndexEvent
x
        EventTypeDebug    BaseEvent DebugEvent
x -> BaseEvent DebugEvent -> Value
forall a. ToJSON a => a -> Value
toJSON BaseEvent DebugEvent
x
        EventTypeAlias    BaseEvent AliasEvent
x -> BaseEvent AliasEvent -> Value
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 :: Text
-> Maybe Integer
-> Value
-> Maybe Value
-> Maybe Natural
-> Maybe Text
-> EvaluationReason
-> Bool
-> Bool
-> Bool
-> Maybe Natural
-> EvalEvent
EvalEvent
    { $sel:key:EvalEvent :: Text
key                  = Text
key
    , $sel:variation:EvalEvent :: Maybe Integer
variation            = Maybe Integer
forall a. Maybe a
Nothing
    , $sel:value:EvalEvent :: Value
value                = Value
defaultValue
    , $sel:defaultValue:EvalEvent :: Maybe Value
defaultValue         = Value -> Maybe Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure Value
defaultValue
    , $sel:version:EvalEvent :: Maybe Natural
version              = Maybe Natural
forall a. Maybe a
Nothing
    , $sel:prereqOf:EvalEvent :: Maybe Text
prereqOf             = Maybe Text
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 = Maybe Natural
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 :: Text
-> Maybe Integer
-> Value
-> Maybe Value
-> Maybe Natural
-> Maybe Text
-> EvaluationReason
-> Bool
-> Bool
-> Bool
-> Maybe Natural
-> EvalEvent
EvalEvent
    { $sel:key:EvalEvent :: Text
key                  = Flag -> Text
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              = Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Natural -> Maybe Natural) -> Natural -> Maybe Natural
forall a b. (a -> b) -> a -> b
$ Flag -> Natural
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          = Flag -> Bool
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 = Flag -> Maybe Natural
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
|| Flag -> 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
|| Rule -> Bool
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"trackEvents" (Flag -> [Rule]
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"rules" Flag
flag [Rule] -> Int -> Rule
forall a. [a] -> Int -> a
!! Natural -> Int
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
"-"
    [ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"" (Maybe Text -> Text) -> Maybe Text -> Text
forall a b. (a -> b) -> a -> b
$ (Natural -> Text) -> Maybe Natural -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Text
T.pack (String -> Text) -> (Natural -> String) -> Natural -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> String
forall a. Show a => a -> String
show) (Maybe Natural -> Maybe Text) -> Maybe Natural -> Maybe Text
forall a b. (a -> b) -> a -> b
$ EvalEvent -> Maybe Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"version" EvalEvent
event
    , Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"" (Maybe Text -> Text) -> Maybe Text -> Text
forall a b. (a -> b) -> a -> b
$ (Integer -> Text) -> Maybe Integer -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Text
T.pack (String -> Text) -> (Integer -> String) -> Integer -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> String
forall a. Show a => a -> String
show) (Maybe Integer -> Maybe Text) -> Maybe Integer -> Maybe Text
forall a b. (a -> b) -> a -> b
$ EvalEvent -> Maybe Integer
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 Text
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> Maybe (FlagSummaryContext (KeyMap CounterContext))
forall v. Text -> KeyMap v -> Maybe v
lookupKey (EvalEvent -> Text
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  -> Maybe Value
-> KeyMap CounterContext
-> FlagSummaryContext (KeyMap CounterContext)
forall a. Maybe Value -> a -> FlagSummaryContext a
FlagSummaryContext (EvalEvent -> Maybe Value
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"defaultValue" EvalEvent
event) KeyMap CounterContext
forall a. Monoid a => a
mempty
    leaf :: CounterContext
leaf = case Text -> KeyMap CounterContext -> Maybe CounterContext
forall v. Text -> KeyMap v -> Maybe v
lookupKey Text
key (FlagSummaryContext (KeyMap CounterContext) -> KeyMap CounterContext
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"counters" FlagSummaryContext (KeyMap CounterContext)
root) of
        (Just CounterContext
x) -> CounterContext
x CounterContext
-> (CounterContext -> CounterContext) -> CounterContext
forall a b. a -> (a -> b) -> b
& forall s t a b. HasField "count" s t a b => Lens s t a b
forall (field :: Symbol) s t a b.
HasField field s t a b =>
Lens s t a b
field @"count" ((Natural -> Identity Natural)
 -> CounterContext -> Identity CounterContext)
-> (Natural -> Natural) -> CounterContext -> CounterContext
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (Natural
1 Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+)
        Maybe CounterContext
Nothing  -> CounterContext :: Natural
-> Maybe Natural
-> Maybe Integer
-> Value
-> Bool
-> CounterContext
CounterContext
            { $sel:count:CounterContext :: Natural
count     = Natural
1
            , $sel:version:CounterContext :: Maybe Natural
version   = EvalEvent -> Maybe Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"version" EvalEvent
event
            , $sel:variation:CounterContext :: Maybe Integer
variation = EvalEvent -> Maybe Integer
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"variation" EvalEvent
event
            , $sel:value:CounterContext :: Value
value     = EvalEvent -> 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 = (FlagSummaryContext (KeyMap CounterContext)
 -> KeyMap (FlagSummaryContext (KeyMap CounterContext))
 -> KeyMap (FlagSummaryContext (KeyMap CounterContext)))
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> FlagSummaryContext (KeyMap CounterContext)
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Text
-> FlagSummaryContext (KeyMap CounterContext)
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
forall v. Text -> v -> KeyMap v -> KeyMap v
insertKey (Text
 -> FlagSummaryContext (KeyMap CounterContext)
 -> KeyMap (FlagSummaryContext (KeyMap CounterContext))
 -> KeyMap (FlagSummaryContext (KeyMap CounterContext)))
-> Text
-> FlagSummaryContext (KeyMap CounterContext)
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
forall a b. (a -> b) -> a -> b
$ EvalEvent -> Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"key" EvalEvent
event) KeyMap (FlagSummaryContext (KeyMap CounterContext))
context (FlagSummaryContext (KeyMap CounterContext)
 -> KeyMap (FlagSummaryContext (KeyMap CounterContext)))
-> FlagSummaryContext (KeyMap CounterContext)
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
forall a b. (a -> b) -> a -> b
$
        FlagSummaryContext (KeyMap CounterContext)
root FlagSummaryContext (KeyMap CounterContext)
-> (FlagSummaryContext (KeyMap CounterContext)
    -> FlagSummaryContext (KeyMap CounterContext))
-> FlagSummaryContext (KeyMap CounterContext)
forall a b. a -> (a -> b) -> b
& forall s t a b. HasField "counters" s t a b => Lens s t a b
forall (field :: Symbol) s t a b.
HasField field s t a b =>
Lens s t a b
field @"counters" ((KeyMap CounterContext -> Identity (KeyMap CounterContext))
 -> FlagSummaryContext (KeyMap CounterContext)
 -> Identity (FlagSummaryContext (KeyMap CounterContext)))
-> (KeyMap CounterContext -> KeyMap CounterContext)
-> FlagSummaryContext (KeyMap CounterContext)
-> FlagSummaryContext (KeyMap CounterContext)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Text
-> CounterContext -> KeyMap CounterContext -> KeyMap CounterContext
forall v. Text -> v -> KeyMap v -> KeyMap v
insertKey Text
key CounterContext
leaf

putIfEmptyMVar :: MVar a -> a -> IO ()
putIfEmptyMVar :: MVar a -> a -> IO ()
putIfEmptyMVar MVar a
mvar a
value = MVar a -> IO (Maybe a)
forall a. MVar a -> IO (Maybe a)
tryTakeMVar MVar a
mvar IO (Maybe a) -> (Maybe a -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case Just a
x -> MVar a -> a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar a
mvar a
x; Maybe a
Nothing -> MVar a -> a -> IO ()
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 = MVar Natural -> Natural -> IO ()
forall a. MVar a -> a -> IO ()
putIfEmptyMVar (EventState -> MVar Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"startDate" EventState
state) Natural
now IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
    MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
-> (KeyMap (FlagSummaryContext (KeyMap CounterContext))
    -> IO (KeyMap (FlagSummaryContext (KeyMap CounterContext))))
-> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (EventState
-> MVar (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"summary" EventState
state) (\KeyMap (FlagSummaryContext (KeyMap CounterContext))
summary -> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> IO (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (KeyMap (FlagSummaryContext (KeyMap CounterContext))
 -> IO (KeyMap (FlagSummaryContext (KeyMap CounterContext))))
-> KeyMap (FlagSummaryContext (KeyMap CounterContext))
-> IO (KeyMap (FlagSummaryContext (KeyMap CounterContext)))
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 = EvalEvent -> Bool
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"trackEvents" EvalEvent
event
        inlineUsers :: Bool
inlineUsers = ConfigI -> Bool
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"inlineUsersInEvents" ConfigI
config
        debugEventsUntilDate :: Natural
debugEventsUntilDate = Natural -> Maybe Natural -> Natural
forall a. a -> Maybe a -> a
fromMaybe Natural
0 (EvalEvent -> Maybe Natural
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"debugEventsUntilDate" EvalEvent
event)
    Natural
lastKnownServerTime <- Integer -> Natural
naturalFromInteger (Integer -> Natural) -> (Integer -> Integer) -> Integer -> Natural
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
1000) (Integer -> Natural) -> IO Integer -> IO Natural
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MVar Integer -> IO Integer
forall a. MVar a -> IO a
readMVar (EventState -> MVar Integer
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"lastKnownServerTime" EventState
state)
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
trackEvents (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
        ConfigI -> EventState -> EventType -> IO ()
queueEvent ConfigI
config EventState
state (EventType -> IO ()) -> EventType -> IO ()
forall a b. (a -> b) -> a -> b
$ BaseEvent FeatureEvent -> EventType
EventTypeFeature (BaseEvent FeatureEvent -> EventType)
-> BaseEvent FeatureEvent -> EventType
forall a b. (a -> b) -> a -> b
$ Natural -> FeatureEvent -> BaseEvent FeatureEvent
forall event. Natural -> event -> BaseEvent event
BaseEvent Natural
now FeatureEvent
featureEvent
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Natural
now Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
< Natural
debugEventsUntilDate Bool -> Bool -> Bool
&& Natural
lastKnownServerTime Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
< Natural
debugEventsUntilDate) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
        ConfigI -> EventState -> EventType -> IO ()
queueEvent ConfigI
config EventState
state (EventType -> IO ()) -> EventType -> IO ()
forall a b. (a -> b) -> a -> b
$ BaseEvent DebugEvent -> EventType
EventTypeDebug (BaseEvent DebugEvent -> EventType)
-> BaseEvent DebugEvent -> EventType
forall a b. (a -> b) -> a -> b
$ Natural -> DebugEvent -> BaseEvent DebugEvent
forall event. Natural -> event -> BaseEvent event
BaseEvent Natural
now (DebugEvent -> BaseEvent DebugEvent)
-> DebugEvent -> BaseEvent DebugEvent
forall a b. (a -> b) -> a -> b
$ FeatureEvent -> DebugEvent
DebugEvent (FeatureEvent -> DebugEvent) -> FeatureEvent -> 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
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Bool
trackEvents Bool -> Bool -> Bool
&& Bool
inlineUsers) (IO () -> IO ()) -> IO () -> IO ()
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 IO Natural -> (Natural -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Natural
now ->
    (EvalEvent -> IO ()) -> [EvalEvent] -> IO ()
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
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
noticedUser (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
        ConfigI -> EventState -> EventType -> IO ()
queueEvent ConfigI
config EventState
state (BaseEvent IndexEvent -> EventType
EventTypeIndex (BaseEvent IndexEvent -> EventType)
-> BaseEvent IndexEvent -> EventType
forall a b. (a -> b) -> a -> b
$ Natural -> IndexEvent -> BaseEvent IndexEvent
forall event. Natural -> event -> BaseEvent event
BaseEvent Natural
now (IndexEvent -> BaseEvent IndexEvent)
-> IndexEvent -> BaseEvent IndexEvent
forall a b. (a -> b) -> a -> b
$ IndexEvent :: Value -> IndexEvent
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 = MVar (LRU Text ())
-> (LRU Text () -> IO (LRU Text (), Bool)) -> IO Bool
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar (EventState -> MVar (LRU Text ())
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"userKeyLRU" EventState
state) ((LRU Text () -> IO (LRU Text (), Bool)) -> IO Bool)
-> (LRU Text () -> IO (LRU Text (), Bool)) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \LRU Text ()
cache -> do
    let key :: Text
key = UserI -> Text
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"key" UserI
user
    case Text -> LRU Text () -> (LRU Text (), Maybe ())
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 ()
_)  -> (LRU Text (), Bool) -> IO (LRU Text (), Bool)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (LRU Text ()
cache', Bool
False)
        (LRU Text ()
cache', Maybe ()
Nothing) -> (LRU Text (), Bool) -> IO (LRU Text (), Bool)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> () -> LRU Text () -> LRU Text ()
forall key val. Ord key => key -> val -> LRU key val -> LRU key val
LRU.insert Text
key () LRU Text ()
cache', Bool
True)