module Patrol.Type.Event where

import qualified Control.Monad.Catch as Catch
import qualified Control.Monad.IO.Class as IO
import qualified Data.Aeson as Aeson
import qualified Data.ByteString.Lazy as LazyByteString
import qualified Data.Map as Map
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import qualified Data.Time as Time
import qualified Network.HTTP.Client as Client
import qualified Network.HTTP.Types as Http
import qualified Patrol.Constant as Constant
import qualified Patrol.Extra.Aeson as Aeson
import qualified Patrol.Extra.List as List
import qualified Patrol.Type.Breadcrumbs as Breadcrumbs
import qualified Patrol.Type.ClientSdkInfo as ClientSdkInfo
import qualified Patrol.Type.Context as Context
import qualified Patrol.Type.DebugMeta as DebugMeta
import qualified Patrol.Type.Dsn as Dsn
import qualified Patrol.Type.EventId as EventId
import qualified Patrol.Type.EventProcessingError as EventProcessingError
import qualified Patrol.Type.EventType as EventType
import qualified Patrol.Type.Exceptions as Exceptions
import qualified Patrol.Type.Level as Level
import qualified Patrol.Type.LogEntry as LogEntry
import qualified Patrol.Type.Platform as Platform
import qualified Patrol.Type.Request as Request
import qualified Patrol.Type.Threads as Threads
import qualified Patrol.Type.TransactionInfo as TransactionInfo
import qualified Patrol.Type.User as User

-- | <https://develop.sentry.dev/sdk/event-payloads/types/#event>
data Event = Event
  { Event -> Maybe Breadcrumbs
breadcrumbs :: Maybe Breadcrumbs.Breadcrumbs,
    Event -> Map Text Context
contexts :: Map.Map Text.Text Context.Context,
    Event -> Maybe DebugMeta
debugMeta :: Maybe DebugMeta.DebugMeta,
    Event -> Text
dist :: Text.Text,
    Event -> Text
environment :: Text.Text,
    Event -> [EventProcessingError]
errors :: [EventProcessingError.EventProcessingError],
    Event -> EventId
eventId :: EventId.EventId,
    Event -> Maybe Exceptions
exception :: Maybe Exceptions.Exceptions,
    Event -> Map Text Value
extra :: Map.Map Text.Text Aeson.Value,
    Event -> [Text]
fingerprint :: [Text.Text],
    Event -> Maybe Level
level :: Maybe Level.Level,
    Event -> Maybe LogEntry
logentry :: Maybe LogEntry.LogEntry,
    Event -> Text
logger :: Text.Text,
    Event -> Map Text Text
modules :: Map.Map Text.Text Text.Text,
    Event -> Maybe Platform
platform :: Maybe Platform.Platform,
    Event -> Text
release :: Text.Text,
    Event -> Maybe Request
request :: Maybe Request.Request,
    Event -> Maybe ClientSdkInfo
sdk :: Maybe ClientSdkInfo.ClientSdkInfo,
    Event -> Text
serverName :: Text.Text,
    Event -> Map Text Text
tags :: Map.Map Text.Text Text.Text,
    Event -> Maybe Threads
threads :: Maybe Threads.Threads,
    Event -> Maybe NominalDiffTime
timeSpent :: Maybe Time.NominalDiffTime,
    Event -> Maybe UTCTime
timestamp :: Maybe Time.UTCTime,
    Event -> Text
transaction :: Text.Text,
    Event -> Maybe TransactionInfo
transactionInfo :: Maybe TransactionInfo.TransactionInfo,
    Event -> Maybe EventType
type_ :: Maybe EventType.EventType,
    Event -> Maybe User
user :: Maybe User.User,
    Event -> Text
version :: Text.Text
  }
  deriving (Event -> Event -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Event -> Event -> Bool
$c/= :: Event -> Event -> Bool
== :: Event -> Event -> Bool
$c== :: Event -> Event -> Bool
Eq, Int -> Event -> ShowS
[Event] -> ShowS
Event -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Event] -> ShowS
$cshowList :: [Event] -> ShowS
show :: Event -> String
$cshow :: Event -> String
showsPrec :: Int -> Event -> ShowS
$cshowsPrec :: Int -> Event -> ShowS
Show)

instance Aeson.ToJSON Event where
  toJSON :: Event -> Value
toJSON Event
event =
    [Pair] -> Value
Aeson.intoObject
      [ forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"breadcrumbs" forall a b. (a -> b) -> a -> b
$ Event -> Maybe Breadcrumbs
breadcrumbs Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"contexts" forall a b. (a -> b) -> a -> b
$ Event -> Map Text Context
contexts Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"debug_meta" forall a b. (a -> b) -> a -> b
$ Event -> Maybe DebugMeta
debugMeta Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"dist" forall a b. (a -> b) -> a -> b
$ Event -> Text
dist Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"environment" forall a b. (a -> b) -> a -> b
$ Event -> Text
environment Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"errors" forall a b. (a -> b) -> a -> b
$ Event -> [EventProcessingError]
errors Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"exception" forall a b. (a -> b) -> a -> b
$ Event -> Maybe Exceptions
exception Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"extra" forall a b. (a -> b) -> a -> b
$ Event -> Map Text Value
extra Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"event_id" forall a b. (a -> b) -> a -> b
$ Event -> EventId
eventId Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"fingerprint" forall a b. (a -> b) -> a -> b
$ Event -> [Text]
fingerprint Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"level" forall a b. (a -> b) -> a -> b
$ Event -> Maybe Level
level Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"logentry" forall a b. (a -> b) -> a -> b
$ Event -> Maybe LogEntry
logentry Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"logger" forall a b. (a -> b) -> a -> b
$ Event -> Text
logger Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"modules" forall a b. (a -> b) -> a -> b
$ Event -> Map Text Text
modules Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"platform" forall a b. (a -> b) -> a -> b
$ Event -> Maybe Platform
platform Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"release" forall a b. (a -> b) -> a -> b
$ Event -> Text
release Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"request" forall a b. (a -> b) -> a -> b
$ Event -> Maybe Request
request Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"sdk" forall a b. (a -> b) -> a -> b
$ Event -> Maybe ClientSdkInfo
sdk Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"server_name" forall a b. (a -> b) -> a -> b
$ Event -> Text
serverName Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"tags" forall a b. (a -> b) -> a -> b
$ Event -> Map Text Text
tags Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"threads" forall a b. (a -> b) -> a -> b
$ Event -> Maybe Threads
threads Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"time_spent" forall a b. (a -> b) -> a -> b
$ Event -> Maybe NominalDiffTime
timeSpent Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"timestamp" forall a b. (a -> b) -> a -> b
$ Event -> Maybe UTCTime
timestamp Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"transaction" forall a b. (a -> b) -> a -> b
$ Event -> Text
transaction Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"transaction_info" forall a b. (a -> b) -> a -> b
$ Event -> Maybe TransactionInfo
transactionInfo Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"type" forall a b. (a -> b) -> a -> b
$ Event -> Maybe EventType
type_ Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"user" forall a b. (a -> b) -> a -> b
$ Event -> Maybe User
user Event
event,
        forall a. ToJSON a => String -> a -> Pair
Aeson.pair String
"version" forall a b. (a -> b) -> a -> b
$ Event -> Text
version Event
event
      ]

empty :: Event
empty :: Event
empty =
  Event
    { breadcrumbs :: Maybe Breadcrumbs
breadcrumbs = forall a. Maybe a
Nothing,
      contexts :: Map Text Context
contexts = forall k a. Map k a
Map.empty,
      debugMeta :: Maybe DebugMeta
debugMeta = forall a. Maybe a
Nothing,
      dist :: Text
dist = Text
Text.empty,
      environment :: Text
environment = Text
Text.empty,
      errors :: [EventProcessingError]
errors = [],
      eventId :: EventId
eventId = EventId
EventId.empty,
      exception :: Maybe Exceptions
exception = forall a. Maybe a
Nothing,
      extra :: Map Text Value
extra = forall k a. Map k a
Map.empty,
      fingerprint :: [Text]
fingerprint = [],
      level :: Maybe Level
level = forall a. Maybe a
Nothing,
      logentry :: Maybe LogEntry
logentry = forall a. Maybe a
Nothing,
      logger :: Text
logger = Text
Text.empty,
      modules :: Map Text Text
modules = forall k a. Map k a
Map.empty,
      platform :: Maybe Platform
platform = forall a. Maybe a
Nothing,
      release :: Text
release = Text
Text.empty,
      request :: Maybe Request
request = forall a. Maybe a
Nothing,
      sdk :: Maybe ClientSdkInfo
sdk = forall a. Maybe a
Nothing,
      serverName :: Text
serverName = Text
Text.empty,
      tags :: Map Text Text
tags = forall k a. Map k a
Map.empty,
      threads :: Maybe Threads
threads = forall a. Maybe a
Nothing,
      timeSpent :: Maybe NominalDiffTime
timeSpent = forall a. Maybe a
Nothing,
      timestamp :: Maybe UTCTime
timestamp = forall a. Maybe a
Nothing,
      transaction :: Text
transaction = Text
Text.empty,
      transactionInfo :: Maybe TransactionInfo
transactionInfo = forall a. Maybe a
Nothing,
      type_ :: Maybe EventType
type_ = forall a. Maybe a
Nothing,
      user :: Maybe User
user = forall a. Maybe a
Nothing,
      version :: Text
version = Text
Text.empty
    }

new :: (IO.MonadIO io) => io Event
new :: forall (io :: * -> *). MonadIO io => io Event
new = do
  EventId
theEventId <- forall (io :: * -> *). MonadIO io => io EventId
EventId.random
  UTCTime
theTimestamp <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
IO.liftIO IO UTCTime
Time.getCurrentTime
  forall (f :: * -> *) a. Applicative f => a -> f a
pure
    Event
empty
      { environment :: Text
environment = String -> Text
Text.pack String
"production",
        eventId :: EventId
eventId = EventId
theEventId,
        level :: Maybe Level
level = forall a. a -> Maybe a
Just Level
Level.Error,
        platform :: Maybe Platform
platform = forall a. a -> Maybe a
Just Platform
Platform.Haskell,
        timestamp :: Maybe UTCTime
timestamp = forall a. a -> Maybe a
Just UTCTime
theTimestamp,
        type_ :: Maybe EventType
type_ = forall a. a -> Maybe a
Just EventType
EventType.Default,
        version :: Text
version = Text
Constant.sentryVersion
      }

intoRequest :: (Catch.MonadThrow m) => Dsn.Dsn -> Event -> m Client.Request
intoRequest :: forall (m :: * -> *). MonadThrow m => Dsn -> Event -> m Request
intoRequest Dsn
dsn Event
event = do
  Request
theRequest <-
    forall (m :: * -> *). MonadThrow m => String -> m Request
Client.parseUrlThrow
      forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack
      forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => [a] -> a
mconcat
        [ Dsn -> Text
Dsn.protocol Dsn
dsn,
          String -> Text
Text.pack String
"://",
          Dsn -> Text
Dsn.host Dsn
dsn,
          forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
Text.empty (String -> Text
Text.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:) Char
':' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show) forall a b. (a -> b) -> a -> b
$ Dsn -> Maybe Natural
Dsn.port Dsn
dsn,
          Dsn -> Text
Dsn.path Dsn
dsn,
          String -> Text
Text.pack String
"api/",
          Dsn -> Text
Dsn.projectId Dsn
dsn,
          String -> Text
Text.pack String
"/store/"
        ]
  let oldHeaders :: RequestHeaders
oldHeaders = Request -> RequestHeaders
Client.requestHeaders Request
theRequest
      authorization :: ByteString
authorization = Dsn -> ByteString
Dsn.intoAuthorization Dsn
dsn
      newHeaders :: RequestHeaders
newHeaders =
        [ (HeaderName
Http.hContentType, ByteString
Constant.applicationJson),
          (HeaderName
Http.hUserAgent, Text -> ByteString
Text.encodeUtf8 Text
Constant.userAgent),
          (HeaderName
Constant.xSentryAuth, ByteString
authorization)
        ]
  forall (f :: * -> *) a. Applicative f => a -> f a
pure
    Request
theRequest
      { method :: ByteString
Client.method = ByteString
Http.methodPost,
        requestBody :: RequestBody
Client.requestBody = ByteString -> RequestBody
Client.RequestBodyBS forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LazyByteString.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> ByteString
Aeson.encode Event
event,
        requestHeaders :: RequestHeaders
Client.requestHeaders = forall k v. Eq k => [(k, v)] -> [(k, v)] -> [(k, v)]
List.insertAll RequestHeaders
newHeaders RequestHeaders
oldHeaders
      }