{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} -- | -- A module for building Bugsnag report payloads. -- Please see the README at . module Network.Bugsnag ( -- * Sending reports sendEvents, queueSingleEvent, Batcher, newBatcher, flushBatcher, -- ** ApiKey ApiKey, apiKey, -- ** Report Report, defaultReport, report_apiKey, report_payloadVersion, report_notifier, report_events, -- ** Event Event, defaultEvent, event_exceptions, event_breadcrumbs, event_request, event_threads, event_context, event_groupingHash, event_unhandled, event_severity, event_severityReason, event_user, event_app, event_device, event_session, event_metaData, -- ** Exception Exception, defaultException, exception_errorClass, exception_message, exception_stacktrace, exception_type, -- ** StackFrame StackFrame, defaultStackFrame, stackFrame_file, stackFrame_lineNumber, stackFrame_columnNumber, stackFrame_method, stackFrame_inProject, stackFrame_code, -- ** Breadcrumb Breadcrumb, defaultBreadcrumb, breadcrumb_timestamp, breadcrumb_name, breadcrumb_type, breadcrumb_metaData, -- ** Request Request, defaultRequest, request_clientIp, request_headers, request_httpMethod, request_url, request_referer, -- ** Thread Thread, defaultThread, thread_id, thread_name, thread_errorReportingThread, thread_stacktrace, thread_type, -- ** SeverityReason SeverityReason, defaultSeverityReason, severityReason_type, severityReason_attributes, -- ** SeverityReasonAttributes SeverityReasonAttributes, defaultSeverityReasonAttributes, severityReasonAttributes_errorType, severityReasonAttributes_level, severityReasonAttributes_signalType, severityReasonAttributes_violationType, severityReasonAttributes_errorClass, -- ** User User, defaultUser, user_id, user_name, user_email, -- ** App App, defaultApp, app_id, app_version, app_versionCode, app_bundleVersion, app_codeBundleId, app_buildUUID, app_releaseStage, app_type, app_dsymUUIDs, app_duration, app_durationInForeground, app_inForeground, app_binaryArch, -- ** Device Device, defaultDevice, device_hostname, device_id, device_manufacturer, device_model, device_modelNumber, device_osName, device_osVersion, device_freeMemory, device_totalMemory, device_freeDisk, device_browserName, device_browserVersion, device_jailBroken, device_orientation, device_time, device_cpuAbi, device_runtimeVersions, -- ** RuntimeVersions RuntimeVersions, defaultRuntimeVersions, runtimeVersions_androidApi, runtimeVersions_bottle, runtimeVersions_celery, runtimeVersions_clangVersion, runtimeVersions_cocos2dx, runtimeVersions_delayedJob, runtimeVersions_django, runtimeVersions_dotnet, runtimeVersions_dotnetApiCompatibility, runtimeVersions_dotnetClr, runtimeVersions_dotnetScriptingRuntime, runtimeVersions_eventMachine, runtimeVersions_expoApp, runtimeVersions_expoSdk, runtimeVersions_flask, runtimeVersions_gin, runtimeVersions_go, runtimeVersions_javaType, runtimeVersions_javaVersion, runtimeVersions_jruby, runtimeVersions_laravel, runtimeVersions_lumen, runtimeVersions_magento, runtimeVersions_mailman, runtimeVersions_martini, runtimeVersions_negroni, runtimeVersions_node, runtimeVersions_osBuild, runtimeVersions_php, runtimeVersions_python, runtimeVersions_que, runtimeVersions_rack, runtimeVersions_rails, runtimeVersions_rake, runtimeVersions_reactNative, runtimeVersions_reactNativeJsEngine, runtimeVersions_resque, runtimeVersions_revel, runtimeVersions_ruby, runtimeVersions_shoryoken, runtimeVersions_sidekiq, runtimeVersions_silex, runtimeVersions_sinatra, runtimeVersions_springBoot, runtimeVersions_springFramework, runtimeVersions_swift, runtimeVersions_symfony, runtimeVersions_tornado, runtimeVersions_unity, runtimeVersions_unityScriptingBackend, runtimeVersions_wordpress, -- ** Session Session, defaultSession, session_id, session_startedAt, session_events, -- ** SessionEvents SessionEvents, defaultSessionEvents, sessionEvents_handled, sessionEvents_unhandled, -- ** PayloadVersion PayloadVersion, payloadVersion5, -- ** Notifier Notifier, thisNotifier, -- ** ExceptionType ExceptionType, cocoaExceptionType, androidExceptionType, browserjsExceptionType, expojsExceptionType, nodejsExceptionType, -- ** BreadcrumbType BreadcrumbType, navigationBreadcrumbType, requestBreadcrumbType, processBreadcrumbType, logBreadcrumbType, userBreadcrumbType, stateBreadcrumbType, errorBreadcrumbType, manualBreadcrumbType, -- ** Thread ThreadType, cocoaThreadType, androidThreadType, browserjsThreadType, -- ** Severity Severity, errorSeverity, warningSeverity, infoSeverity, -- ** SeverityReasonType SeverityReasonType, unhandledExceptionSeverityReasonType, unhandledErrorSeverityReasonType, logSeverityReasonType, signalSeverityReasonType, strictModeSeverityReasonType, unhandledPromiseRejectionSeverityReasonType, callbackErrorInterceptSeverityReasonType, errorClassSeverityReasonType, unhandledPanicSeverityReasonType, userCallbackSetSeveritySeverityReasonType, userSpecifiedSeveritySeverityReasonType, handledExceptionSeverityReasonType, handledErrorSeverityReasonType, handledPanicSeverityReasonType, userContextSetSeveritySeverityReasonType, anrErrorSeverityReasonType, outOfMemorySeverityReasonType, -- ** BinaryArch BinaryArch, x86BinaryArch, x86_64BinaryArch, arm32BinaryArch, arm64BinaryArch, -- ** CpuAbi CpuAbi, x86_64CpuAbi, ) where import Control.Exception (try) import Control.Monad (void) import qualified Data.Aeson import qualified Data.Buffer as Buffer import qualified Data.ByteString.Char8 import Data.Foldable (toList) import Data.HashMap.Strict (HashMap) import Data.Text (Text) import qualified Data.Text.Encoding import qualified Data.Time.Clock import qualified Data.Time.Format import GHC.Generics (Generic) import qualified Network.HTTP.Client as HTTP -- | Send a batch of 'Event's to Rollbar using a single HTTP request. -- -- If you only get your hands on one event at a time then 'queueSingleEvent' is -- probably going to be more efficient. sendEvents :: HTTP.Manager -> ApiKey -> [Event] -> IO (Either HTTP.HttpException ()) sendEvents manager apiKey events = do send manager apiKey Report { report_apiKey = Nothing, report_payloadVersion = payloadVersion5, report_notifier = thisNotifier, report_events = events } -- | Helps you batch Bugsnag 'Event's together so you make fewer HTTP request. newtype Batcher = Batcher (Buffer.Buffer Event) -- | Create a batcher, which you need to use the 'queueSingleEvent' function. newBatcher :: HTTP.Manager -> ApiKey -> (HTTP.HttpException -> IO ()) -> IO Batcher newBatcher manager apiKey onError = do buffer <- Buffer.new Buffer.defaultSettings { Buffer.write = \batch -> either onError pure =<< sendEvents manager apiKey (toList batch), Buffer.size = 100, -- Bugsnag limits requests to 1MB, so this allows for 10KB per event. Buffer.frequencyInMicroSeconds = 5000000 -- 5 seconds } pure (Batcher buffer) -- | Queue a single 'Event' for submission to Bugsnag. If multiple events are -- queued around the same moment they will be batched together and sent in a -- single HTTP request. queueSingleEvent :: Batcher -> Event -> IO () queueSingleEvent (Batcher buffer) = Buffer.push buffer -- | When passing an 'Event' to 'queueSingleEvent' we wait briefly before -- sending it to Bugsnag, to see if other 'Event's get queued we can send to -- Bugsnag in a single HTTP request. This function allows you to immediately -- send any 'Event's that are being held. You might use it when shutting down -- your application. flushBatcher :: Batcher -> IO () flushBatcher (Batcher buffer) = Buffer.flush buffer send :: HTTP.Manager -> ApiKey -> Report -> IO (Either HTTP.HttpException ()) send manager (ApiKey apiKey) report = do now <- Data.Time.Clock.getCurrentTime initReq <- HTTP.parseUrlThrow "https://notify.bugsnag.com" let req = initReq { HTTP.method = "POST", HTTP.requestHeaders = [ ("Bugsnag-Api-Key", Data.Text.Encoding.encodeUtf8 apiKey), ("Content-Type", "application/json"), ("Bugsnag-Payload-Version", "5"), ("Bugsnag-Sent-At", Data.ByteString.Char8.pack (formatISO8601 now)) ], HTTP.requestBody = HTTP.RequestBodyLBS (Data.Aeson.encode report) } try . void $ HTTP.httpNoBody req manager formatISO8601 :: Data.Time.Clock.UTCTime -> String formatISO8601 = Data.Time.Format.formatTime Data.Time.Format.defaultTimeLocale "%FT%T%QZ" -- | The payload of a POST request to https://notify.bugsnag.com/ data Report = Report { -- | The API Key associated with the project. Informs Bugsnag which project has generated this error. -- This is provided for legacy notifiers. It is preferable to use the Bugsnag-Api-Key header instead. report_apiKey :: Maybe ApiKey, -- | The version number of the payload. This is currently 5. -- The Bugsnag-Payload-Version header should be included as well, for compatibility reasons. report_payloadVersion :: PayloadVersion, -- | Describes the notifier itself. These properties are used within Bugsnag to track error rates from a notifier. report_notifier :: Notifier, -- | An array of error events that Bugsnag should be notified of. A notifier can choose to group notices into an array to minimize network traffic, or can notify Bugsnag each time an event occurs. report_events :: [Event] } deriving (Generic, Show) instance Data.Aeson.ToJSON Report where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Report where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default report. defaultReport :: Report defaultReport = Report { report_apiKey = Nothing, report_payloadVersion = payloadVersion5, report_notifier = thisNotifier, report_events = [] } -- | The API Key associated with the project. Informs Bugsnag which project has generated this error. newtype ApiKey = ApiKey Text deriving (Generic, Show) instance Data.Aeson.ToJSON ApiKey where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON ApiKey where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | Construct an 'ApiKey' value. apiKey :: Text -> ApiKey apiKey = ApiKey -- | The version number of the payload. This is currently 5. -- The Bugsnag-Payload-Version header should be included as well, for compatibility reasons. newtype PayloadVersion = PayloadVersion Text deriving (Generic, Show) instance Data.Aeson.ToJSON PayloadVersion where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON PayloadVersion where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | This API only supports payload version 5. payloadVersion5 :: PayloadVersion payloadVersion5 = PayloadVersion "5" -- | Describes the notifier itself. These properties are used within Bugsnag to track error rates from a notifier. data Notifier = Notifier { -- | The notifier name. notifier_name :: Text, -- | The notifier's current version. notifier_version :: Text, -- | The URL associated with the notifier. notifier_url :: Text } deriving (Generic, Show) instance Data.Aeson.ToJSON Notifier where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Notifier where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | Information describing the notifier in this module. thisNotifier :: Notifier thisNotifier = -- The fields below are read directly out of the cabal file for this project. Notifier { notifier_name = "bugsnag-hs", notifier_version = "0.1.0.0", notifier_url = "https://github.com/jwoudenberg/bugsnag-hs#readme" } -- | An array of error events that Bugsnag should be notified of. A notifier can choose to group notices into an array to minimize network traffic, or can notify Bugsnag each time an event occurs. data Event = Event { -- | An array of exceptions that occurred during this event. There must be at least one entry. Most of the time there will only be one exception, but some languages support "nested" or "caused by" exceptions. In this case, exceptions should be unwrapped and added to the array one at a time. The first exception raised should be first in this array. event_exceptions :: [Exception], -- | An array of user- and system-initiated events which led up to an error, providing additional context. This list is sequential and ordered newest to oldest. event_breadcrumbs :: Maybe [Breadcrumb], -- | Details about the web request from the client that experienced the error, if relevant. To display custom request data alongside these standard fields on the Bugsnag website, the custom data should be included in the metaData object in a request object. event_request :: Maybe Request, -- | An array of background threads. This is optional but recommended for apps that rely heavily on threading. Threads should be in an order that makes sense for your application. event_threads :: Maybe [Thread], -- | A string representing what was happening in the application at the time of the error. This string could be used for grouping purposes, depending on the event. Usually this would represent the controller and action in a server based project. It could represent the screen that the user was interacting with in a client side project. For example: -- - On Ruby on Rails the context could be controller#action. -- - In Android, the context could be the top most Activity. -- - In iOS, the context could be the name of the top most UIViewController. event_context :: Maybe Text, -- | Bugsnag's default error grouping can be overridden by specifying a custom grouping hash. event_groupingHash :: Maybe Text, -- | Whether the error was unhandled. If true, the error was detected by the notifier because it was not handled by the application. If false, the errors was handled and reported using Bugsnag.notify. event_unhandled :: Maybe Bool, -- | The severity of the error event_severity :: Maybe Severity, -- | Information about why the severity was picked. event_severityReason :: Maybe SeverityReason, -- | Information about the user affected by the error. These fields are optional but highly recommended. To display custom user data alongside these standard fields on the Bugsnag website, the custom data should be included in the metaData object in a user object. event_user :: Maybe User, -- | Information about the app where the error occurred. These fields are optional but highly recommended. To display custom app data alongside these standard fields on the Bugsnag website, the custom data should be included in the metaData object in an app object. event_app :: Maybe App, -- | Information about the computer/device running the app. These fields are optional but highly recommended. To display custom device data alongside these standard fields on the Bugsnag website, the custom data should be included in the metaData object in a device object. event_device :: Maybe Device, -- | Details of any session information associated with the event. -- This can be used alongside the Bugsnag Session Tracking API to associate the event with a session so that a release's crash rate can be determined. event_session :: Maybe Session, -- | An object containing any further data you wish to attach to this error event. This should contain one or more objects, with each object being displayed in its own tab on the event details on Bugsnag. event_metaData :: Maybe Data.Aeson.Object } deriving (Generic, Show) instance Data.Aeson.ToJSON Event where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Event where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default event. defaultEvent :: Event defaultEvent = Event { event_exceptions = [], event_breadcrumbs = Nothing, event_request = Nothing, event_threads = Nothing, event_context = Nothing, event_groupingHash = Nothing, event_unhandled = Nothing, event_severity = Nothing, event_severityReason = Nothing, event_user = Nothing, event_app = Nothing, event_device = Nothing, event_session = Nothing, event_metaData = Nothing } -- | An exception that occurred during this event. data Exception = Exception { -- | The class of error which occurred. This field is used to group the errors together so should not contain any contextual information that would prevent correct grouping. This would ordinarily be the Exception name when dealing with an exception. exception_errorClass :: Text, -- | The error message associated with the error. Usually this will contain some information about this specific instance of the error and is not used to group the errors. exception_message :: Maybe Text, -- | An array of stackframe objects. Each object represents one line in the exception's stacktrace. Bugsnag uses this information to help with error grouping, as well as displaying it to the user. exception_stacktrace :: [StackFrame], -- | This should be set for the following platforms so that the stacktrace can be parsed correctly: exception_type :: Maybe ExceptionType } deriving (Generic, Show) instance Data.Aeson.ToJSON Exception where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Exception where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default exception. defaultException :: Exception defaultException = Exception { exception_errorClass = "", exception_message = Nothing, exception_stacktrace = [], exception_type = Nothing } -- | Each stackrame represents one line in the exception's stacktrace. Bugsnag uses this information to help with error grouping, as well as displaying it to the user. data StackFrame = StackFrame { -- | The file that this stack frame was executing. It is recommended that you strip any unnecessary or common information from the beginning of the path. stackFrame_file :: Text, -- | The line of the file that this frame of the stack was in. stackFrame_lineNumber :: Int, -- | The column of the file that this frame of the stack was in. stackFrame_columnNumber :: Maybe Int, -- | The method that this particular stack frame is within. stackFrame_method :: Text, -- | If this stacktrace line is in the user's project code, set this to true. It is useful for developers to be able to see which lines of a stacktrace are within their own application, and which are within third party libraries. This boolean field allows Bugsnag to display this information in the stacktrace as well as use the information to help group errors better. stackFrame_inProject :: Maybe Bool, -- | The code in this file surrounding this line. This is an object containing key value pairs where each key is a line number and each value is the code from that line. You can include up to three lines on either side of the line where the error occurred. These will be displayed on the bugsnag dashboard when you expand that line. stackFrame_code :: Maybe (HashMap Int Text) } deriving (Generic, Show) instance Data.Aeson.ToJSON StackFrame where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON StackFrame where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default stackFrame. defaultStackFrame :: StackFrame defaultStackFrame = StackFrame { stackFrame_file = "", stackFrame_lineNumber = 0, stackFrame_columnNumber = Nothing, stackFrame_method = "", stackFrame_inProject = Nothing, stackFrame_code = Nothing } -- | This should be set for the following platforms so that the stacktrace can be parsed correctly: newtype ExceptionType = ExceptionType Text deriving (Generic, Show) instance Data.Aeson.ToJSON ExceptionType where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON ExceptionType where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | For cocoa (iOS/tvOS/macOS) cocoaExceptionType :: ExceptionType cocoaExceptionType = ExceptionType "cocoa" -- | For android androidExceptionType :: ExceptionType androidExceptionType = ExceptionType "android" -- | For browser-based JavaScript browserjsExceptionType :: ExceptionType browserjsExceptionType = ExceptionType "browserjs" -- | For JavaScript in Expo expojsExceptionType :: ExceptionType expojsExceptionType = ExceptionType "expojs" -- | For JavaScript in Node nodejsExceptionType :: ExceptionType nodejsExceptionType = ExceptionType "nodejs" -- | User- and system-initiated event which led up to an error, providing additional context. data Breadcrumb = Breadcrumb { -- | The time at which the event occurred, in [ISO 8601 format](https://tools.ietf.org/html/rfc3339#section-5.8). breadcrumb_timestamp :: Text, -- | A short summary describing the event, such as the user action taken or a new application state. breadcrumb_name :: Text, -- | A category which describes the breadcrumb, from the list of allowed values. breadcrumb_type :: BreadcrumbType, -- | Additional information about the event, as key/value pairs. breadcrumb_metaData :: Maybe (HashMap Text Text) } deriving (Generic, Show) instance Data.Aeson.ToJSON Breadcrumb where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Breadcrumb where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default breadcrumb. defaultBreadcrumb :: Breadcrumb defaultBreadcrumb = Breadcrumb { breadcrumb_timestamp = "", breadcrumb_name = "", breadcrumb_type = navigationBreadcrumbType, breadcrumb_metaData = Nothing } -- | A category which describes the breadcrumb, from the list of allowed values. newtype BreadcrumbType = BreadcrumbType Text deriving (Generic, Show) instance Data.Aeson.ToJSON BreadcrumbType where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON BreadcrumbType where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | Changing screens or content being displayed, with a defined destination and optionally a previous location. navigationBreadcrumbType :: BreadcrumbType navigationBreadcrumbType = BreadcrumbType "navigation" -- | Sending and receiving requests and responses. requestBreadcrumbType :: BreadcrumbType requestBreadcrumbType = BreadcrumbType "request" -- | Performing an intensive task or query. processBreadcrumbType :: BreadcrumbType processBreadcrumbType = BreadcrumbType "process" -- | Messages and severity sent to a logging platform. logBreadcrumbType :: BreadcrumbType logBreadcrumbType = BreadcrumbType "log" -- | Actions performed by the user, like text input, button presses, or confirming/cancelling an alert dialog. userBreadcrumbType :: BreadcrumbType userBreadcrumbType = BreadcrumbType "user" -- | Changing the overall state of an app, such as closing, pausing, or being moved to the background, as well as device state changes like memory or battery warnings and network connectivity changes. stateBreadcrumbType :: BreadcrumbType stateBreadcrumbType = BreadcrumbType "state" -- | An error which was reported to Bugsnag encountered in the same session. errorBreadcrumbType :: BreadcrumbType errorBreadcrumbType = BreadcrumbType "error" -- | User-defined, manually added breadcrumbs. manualBreadcrumbType :: BreadcrumbType manualBreadcrumbType = BreadcrumbType "manual" -- | Details about the web request from the client that experienced the error, if relevant. To display custom request data alongside these standard fields on the Bugsnag website, the custom data should be included in the metaData object in a request object. data Request = Request { -- | The IP address of the client that experienced the error. request_clientIp :: Maybe Text, -- | The headers sent with the request. request_headers :: Maybe (HashMap Text Text), -- | The HTTP method used. request_httpMethod :: Maybe Text, -- | The URL of the request. request_url :: Maybe Text, -- | The [HTTP referer](https://en.wikipedia.org/wiki/HTTP_referer) request_referer :: Maybe Text } deriving (Generic, Show) instance Data.Aeson.ToJSON Request where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Request where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default request. defaultRequest :: Request defaultRequest = Request { request_clientIp = Nothing, request_headers = Nothing, request_httpMethod = Nothing, request_url = Nothing, request_referer = Nothing } -- | An array of background threads. This is optional but recommended for apps that rely heavily on threading. Threads should be in an order that makes sense for your application. data Thread = Thread { -- | The id of the thread in your application. thread_id :: Maybe Text, -- | A human readable name for the thread. thread_name :: Maybe Text, -- | If this is the thread that the error was reported from (either an unhandled error or a call to bugsnag.notify), set this to true. thread_errorReportingThread :: Maybe Bool, -- | An array of stacktrace objects. Each object represents one line in the stacktrace of the thread at the point that the error occurred. thread_stacktrace :: Maybe [StackFrame], -- | Setting this allows the stacktrace to be parsed correctly. thread_type :: Maybe ThreadType } deriving (Generic, Show) instance Data.Aeson.ToJSON Thread where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Thread where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default thread. defaultThread :: Thread defaultThread = Thread { thread_id = Nothing, thread_name = Nothing, thread_errorReportingThread = Nothing, thread_stacktrace = Nothing, thread_type = Nothing } -- | Used for parsing the stack trace correctly. newtype ThreadType = ThreadType Text deriving (Generic, Show) instance Data.Aeson.ToJSON ThreadType where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON ThreadType where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | For cocoa (iOS/tvOS/macOS) cocoaThreadType :: ThreadType cocoaThreadType = ThreadType "cocoa" -- | For android androidThreadType :: ThreadType androidThreadType = ThreadType "android" -- | For browser-based JavaScript browserjsThreadType :: ThreadType browserjsThreadType = ThreadType "browserjs" -- | The severity of the error newtype Severity = Severity Text deriving (Generic, Show) instance Data.Aeson.ToJSON Severity where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Severity where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | The default for unhandled errors. errorSeverity :: Severity errorSeverity = Severity "error" -- | The default when Bugsnag.notify is called. warningSeverity :: Severity warningSeverity = Severity "warning" -- | Can be used in manual Bugsnag.notify calls. infoSeverity :: Severity infoSeverity = Severity "info" -- | Information about why the severity was picked. data SeverityReason = SeverityReason { -- | A type key that represents the reason for the assigned severity. severityReason_type :: SeverityReasonType, -- | Optional attributes to provide extra information about the severity reason. severityReason_attributes :: SeverityReasonAttributes } deriving (Generic, Show) instance Data.Aeson.ToJSON SeverityReason where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON SeverityReason where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default severityReason. defaultSeverityReason :: SeverityReason defaultSeverityReason = SeverityReason { severityReason_type = unhandledExceptionSeverityReasonType, severityReason_attributes = defaultSeverityReasonAttributes } -- | A type key that represents the reason for the assigned severity. newtype SeverityReasonType = SeverityReasonType Text deriving (Generic, Show) instance Data.Aeson.ToJSON SeverityReasonType where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON SeverityReasonType where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | Whenever an uncaught exception is discovered (generic). unhandledExceptionSeverityReasonType :: SeverityReasonType unhandledExceptionSeverityReasonType = SeverityReasonType "unhandledException" -- | When an error is discovered (PHP). unhandledErrorSeverityReasonType :: SeverityReasonType unhandledErrorSeverityReasonType = SeverityReasonType "unhandledError" -- | Whenever a log message is sent (generic). logSeverityReasonType :: SeverityReasonType logSeverityReasonType = SeverityReasonType "log" -- | Whenever a "fatal" signal is discovered (iOS). signalSeverityReasonType :: SeverityReasonType signalSeverityReasonType = SeverityReasonType "signal" -- | Whenever a strictMode issue is discovered (Android). strictModeSeverityReasonType :: SeverityReasonType strictModeSeverityReasonType = SeverityReasonType "strictMode" -- | Whenever an unhandled promise rejection is discovered (JS/Node JS/React Native). unhandledPromiseRejectionSeverityReasonType :: SeverityReasonType unhandledPromiseRejectionSeverityReasonType = SeverityReasonType "unhandledPromiseRejection" -- | callbackErrorIntercept (Node JS). callbackErrorInterceptSeverityReasonType :: SeverityReasonType callbackErrorInterceptSeverityReasonType = SeverityReasonType "callbackErrorIntercept" -- | Whenever an exception with a particular class is automatically sent (Ruby). errorClassSeverityReasonType :: SeverityReasonType errorClassSeverityReasonType = SeverityReasonType "errorClass" -- | When a panic is unhandled and crashes the app (Go). unhandledPanicSeverityReasonType :: SeverityReasonType unhandledPanicSeverityReasonType = SeverityReasonType "unhandledPanic" -- | Whenever a callback changes a report's severity (generic). userCallbackSetSeveritySeverityReasonType :: SeverityReasonType userCallbackSetSeveritySeverityReasonType = SeverityReasonType "userCallbackSetSeverity" -- | Whenever a severity is set through a manual notify call (generic). userSpecifiedSeveritySeverityReasonType :: SeverityReasonType userSpecifiedSeveritySeverityReasonType = SeverityReasonType "userSpecifiedSeverity" -- | Whenever a handled exception is sent through (generic). handledExceptionSeverityReasonType :: SeverityReasonType handledExceptionSeverityReasonType = SeverityReasonType "handledException" -- | Whenever a handled error is sent through (PHP). handledErrorSeverityReasonType :: SeverityReasonType handledErrorSeverityReasonType = SeverityReasonType "handledError" -- | Whenever a panic is handled through AutoNotify or Recover (Go). handledPanicSeverityReasonType :: SeverityReasonType handledPanicSeverityReasonType = SeverityReasonType "handledPanic" -- | Whenever a panic is handled through AutoNotify or Recover (Go). userContextSetSeveritySeverityReasonType :: SeverityReasonType userContextSetSeveritySeverityReasonType = SeverityReasonType "userContextSetSeverity" -- | Whenever an ANR is detected (Android). anrErrorSeverityReasonType :: SeverityReasonType anrErrorSeverityReasonType = SeverityReasonType "anrError" -- | When an app is terminated because it used too much memory (Cocoa). outOfMemorySeverityReasonType :: SeverityReasonType outOfMemorySeverityReasonType = SeverityReasonType "outOfMemory" -- | Optional attributes to provide extra information about the severity reason. data SeverityReasonAttributes = SeverityReasonAttributes { -- | Included for unhandledError severity reason. See [PHP Error Constants](https://www.php.net/manual/en/errorfunc.constants.php). severityReasonAttributes_errorType :: Maybe Text, -- | Included for log severity reason. severityReasonAttributes_level :: Maybe Text, -- | Included for signal severity reason. See [Signal Codes](https://en.wikipedia.org/wiki/C_signal_handling). severityReasonAttributes_signalType :: Maybe Text, -- | Included for strictMode severity reason. See [Strict Mode](https://developer.android.com/reference/android/os/StrictMode.html). severityReasonAttributes_violationType :: Maybe Text, -- | Included for errorClass severity reason. Specifies the error class that is automatically sent. severityReasonAttributes_errorClass :: Maybe Text } deriving (Generic, Show) instance Data.Aeson.ToJSON SeverityReasonAttributes where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON SeverityReasonAttributes where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default severityReasonAttributes. defaultSeverityReasonAttributes :: SeverityReasonAttributes defaultSeverityReasonAttributes = SeverityReasonAttributes { severityReasonAttributes_errorType = Nothing, severityReasonAttributes_level = Nothing, severityReasonAttributes_signalType = Nothing, severityReasonAttributes_violationType = Nothing, severityReasonAttributes_errorClass = Nothing } -- | Information about the user affected by the error. These fields are optional but highly recommended. To display custom user data alongside these standard fields on the Bugsnag website, the custom data should be included in the metaData object in a user object. data User = User { -- | A unique identifier for a user affected by this event. This could be any distinct identifier that makes sense for your application/platform. user_id :: Maybe Text, -- | The user's name, or a string you use to identify them. user_name :: Maybe Text, -- | The user's email address. user_email :: Maybe Text } deriving (Generic, Show) instance Data.Aeson.ToJSON User where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON User where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default user. defaultUser :: User defaultUser = User { user_id = Nothing, user_name = Nothing, user_email = Nothing } -- | Information about the app where the error occurred. These fields are optional but highly recommended. To display custom app data alongside these standard fields on the Bugsnag website, the custom data should be included in the metaData object in an app object. data App = App { -- | A unique ID for the application. app_id :: Maybe Text, -- | The version number of the application which generated the error. app_version :: Maybe Text, -- | The [version code](https://developer.android.com/studio/publish/versioning.html) of the application (Android only) app_versionCode :: Maybe Int, -- | The [bundle version/build number](https://developer.apple.com/library/archive/technotes/tn2420/_index.html) of the application (iOS/macOS/tvOS only) app_bundleVersion :: Maybe Text, -- | A unique identifier to identify a code bundle release when using tools like CodePush (mobile only). app_codeBundleId :: Maybe Text, -- | A build ID that is required to identify a specific build when the version and version code are the same. app_buildUUID :: Maybe Text, -- | The release stage that this error occurred in, for example "development", "staging" or "production". app_releaseStage :: Maybe Text, -- | A specialized type of the application, such as the worker queue or web framework used, like "rails", "mailman", or "celery". app_type :: Maybe Text, -- | The UUIDs of the [debug symbols file](http://lldb.llvm.org/symbols.html) corresponding to this application, if any. app_dsymUUIDs :: Maybe [Text], -- | How long the app has been running for in milliseconds. app_duration :: Maybe Int, -- | How long the app has been in the foreground of the device in milliseconds. app_durationInForeground :: Maybe Int, -- | Whether or not the app was in the foreground when the error occurred. app_inForeground :: Maybe Bool, -- | The architecture of the running binary (Android only). app_binaryArch :: Maybe BinaryArch } deriving (Generic, Show) instance Data.Aeson.ToJSON App where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON App where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default app. defaultApp :: App defaultApp = App { app_id = Nothing, app_version = Nothing, app_versionCode = Nothing, app_bundleVersion = Nothing, app_codeBundleId = Nothing, app_buildUUID = Nothing, app_releaseStage = Nothing, app_type = Nothing, app_dsymUUIDs = Nothing, app_duration = Nothing, app_durationInForeground = Nothing, app_inForeground = Nothing, app_binaryArch = Nothing } -- | The architecture of the running binary (Android only). newtype BinaryArch = BinaryArch Text deriving (Generic, Show) instance Data.Aeson.ToJSON BinaryArch where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON BinaryArch where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | x86/i386 (32-bit). x86BinaryArch :: BinaryArch x86BinaryArch = BinaryArch "x86" -- | x86 (64-bit). x86_64BinaryArch :: BinaryArch x86_64BinaryArch = BinaryArch "x86_64" -- | armeabi/armeabi-v7a (32-bit). arm32BinaryArch :: BinaryArch arm32BinaryArch = BinaryArch "arm32" -- | arm64-v8a (64-bit). arm64BinaryArch :: BinaryArch arm64BinaryArch = BinaryArch "arm64" -- | Information about the computer/device running the app. These fields are optional but highly recommended. To display custom device data alongside these standard fields on the Bugsnag website, the custom data should be included in the metaData object in a device object. data Device = Device { -- | The hostname of the server running your code, if applicable. device_hostname :: Maybe Text, -- | A unique identifier for the device. device_id :: Maybe Text, -- | The manufacturer of the device. device_manufacturer :: Maybe Text, -- | The model of the device. device_model :: Maybe Text, -- | The model number of the device. device_modelNumber :: Maybe Text, -- | The device's operating system name. device_osName :: Maybe Text, -- | The device's operating system version. device_osVersion :: Maybe Text, -- | The number of bytes unused in the device's RAM. device_freeMemory :: Maybe Int, -- | The number of total bytes in the device's RAM. device_totalMemory :: Maybe Int, -- | The number of unused bytes on the drive running the application. device_freeDisk :: Maybe Int, -- | If a web application, the web browser used by the device. device_browserName :: Maybe Text, -- | If a web application, the version of the browser used by the device. device_browserVersion :: Maybe Text, -- | Whether or not the device has been modified to give users root access. device_jailBroken :: Maybe Bool, -- | The orientation of the device at the time of the error. device_orientation :: Maybe Text, -- | The time at which the error occurred, in [ISO 8601 format](https://tools.ietf.org/html/rfc3339#section-5.8). device_time :: Maybe Text, -- | The ABIs supported by the device (Android only). device_cpuAbi :: Maybe [CpuAbi], -- | The versions of the relevant runtimes, languages and/or frameworks for the platform. device_runtimeVersions :: Maybe RuntimeVersions } deriving (Generic, Show) instance Data.Aeson.ToJSON Device where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Device where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default device. defaultDevice :: Device defaultDevice = Device { device_hostname = Nothing, device_id = Nothing, device_manufacturer = Nothing, device_model = Nothing, device_modelNumber = Nothing, device_osName = Nothing, device_osVersion = Nothing, device_freeMemory = Nothing, device_totalMemory = Nothing, device_freeDisk = Nothing, device_browserName = Nothing, device_browserVersion = Nothing, device_jailBroken = Nothing, device_orientation = Nothing, device_time = Nothing, device_cpuAbi = Nothing, device_runtimeVersions = Nothing } -- | The ABIs supported by the device (Android only). newtype CpuAbi = CpuAbi Text deriving (Generic, Show) instance Data.Aeson.ToJSON CpuAbi where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON CpuAbi where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | x86_64CpuAbi :: CpuAbi x86_64CpuAbi = CpuAbi "x86_64" -- | The versions of the relevant runtimes, languages and/or frameworks for the platform. data RuntimeVersions = RuntimeVersions { -- | The Android API level (Android only). runtimeVersions_androidApi :: Maybe Text, -- | Bottle framework version (Python only). runtimeVersions_bottle :: Maybe Text, -- | Celery task queue version (Python only). runtimeVersions_celery :: Maybe Text, -- | Clang compiler version (iOS/tvOS/macOS only). runtimeVersions_clangVersion :: Maybe Text, -- | Cocos2d-x framework version (Cocos2d-x only). runtimeVersions_cocos2dx :: Maybe Text, -- | Delayed Job framework version (Ruby only). runtimeVersions_delayedJob :: Maybe Text, -- | Django framework version (Python only). runtimeVersions_django :: Maybe Text, -- | Description of the framework (.NET only). runtimeVersions_dotnet :: Maybe Text, -- | .NET API compatibility level (Unity only). runtimeVersions_dotnetApiCompatibility :: Maybe Text, -- | Version of .NET Common Language Runtime (.NET only). runtimeVersions_dotnetClr :: Maybe Text, -- | .NET scripting runtime version (Unity only). runtimeVersions_dotnetScriptingRuntime :: Maybe Text, -- | EventMachine library version (Ruby only). runtimeVersions_eventMachine :: Maybe Text, -- | Expo app version (Expo only). runtimeVersions_expoApp :: Maybe Text, -- | Expo SDK version (Expo only). runtimeVersions_expoSdk :: Maybe Text, -- | Flask framework version (Python only). runtimeVersions_flask :: Maybe Text, -- | Gin framework version (Go only). runtimeVersions_gin :: Maybe Text, -- | Go language version (Go only). runtimeVersions_go :: Maybe Text, -- | Java platform implementation type (Java only). runtimeVersions_javaType :: Maybe Text, -- | Java platform implementation type (Java only). runtimeVersions_javaVersion :: Maybe Text, -- | Version of JRuby (Ruby only). runtimeVersions_jruby :: Maybe Text, -- | Laravel framework version (PHP only). runtimeVersions_laravel :: Maybe Text, -- | Lumen framework version (PHP only). runtimeVersions_lumen :: Maybe Text, -- | Magento platform version (PHP only). runtimeVersions_magento :: Maybe Text, -- | Mailman framework version (Ruby only). runtimeVersions_mailman :: Maybe Text, -- | Martini framework version (Go only). runtimeVersions_martini :: Maybe Text, -- | Negroni framework version (Go only). runtimeVersions_negroni :: Maybe Text, -- | Node.js version (Javascript only). runtimeVersions_node :: Maybe Text, -- | Build number of the OS (iOS/tvOS/macOS only). runtimeVersions_osBuild :: Maybe Text, -- | Version of PHP (PHP only). runtimeVersions_php :: Maybe Text, -- | Version of Python (Python only). runtimeVersions_python :: Maybe Text, -- | Que job queue version (Ruby only). runtimeVersions_que :: Maybe Text, -- | Rack webserver version (Ruby only). runtimeVersions_rack :: Maybe Text, -- | Ruby on Rails version (Ruby only). runtimeVersions_rails :: Maybe Text, -- | Rake tool version (Ruby only). runtimeVersions_rake :: Maybe Text, -- | Version of React Native (React Native/Expo only). runtimeVersions_reactNative :: Maybe Text, -- | Javascript engine type (React Native/Expo only). runtimeVersions_reactNativeJsEngine :: Maybe Text, -- | Resque library version (Ruby only). runtimeVersions_resque :: Maybe Text, -- | Revel framework version (Go only). runtimeVersions_revel :: Maybe Text, -- | Version of Ruby (Ruby only). runtimeVersions_ruby :: Maybe Text, -- | Shoryoken framework version (Ruby only). runtimeVersions_shoryoken :: Maybe Text, -- | Sidekiq scheduler version (Ruby only). runtimeVersions_sidekiq :: Maybe Text, -- | Silex framework version (PHP only). runtimeVersions_silex :: Maybe Text, -- | Sinatra DSL version (Ruby only). runtimeVersions_sinatra :: Maybe Text, -- | Spring Boot framework version (Java only). runtimeVersions_springBoot :: Maybe Text, -- | Spring framework version (Java only). runtimeVersions_springFramework :: Maybe Text, -- | Swift language version (iOS/tvOS/macOS only). runtimeVersions_swift :: Maybe Text, -- | Symfony framework version (PHP only). runtimeVersions_symfony :: Maybe Text, -- | Tornado framework version (Python only). runtimeVersions_tornado :: Maybe Text, -- | Version of Unity. runtimeVersions_unity :: Maybe Text, -- | The Unity scripting backend - Mono or IL2CPP (Unity only). runtimeVersions_unityScriptingBackend :: Maybe Text, -- | Wordpress version (PHP only). runtimeVersions_wordpress :: Maybe Text } deriving (Generic, Show) instance Data.Aeson.ToJSON RuntimeVersions where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON RuntimeVersions where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default runtimeVersions. defaultRuntimeVersions :: RuntimeVersions defaultRuntimeVersions = RuntimeVersions { runtimeVersions_androidApi = Nothing, runtimeVersions_bottle = Nothing, runtimeVersions_celery = Nothing, runtimeVersions_clangVersion = Nothing, runtimeVersions_cocos2dx = Nothing, runtimeVersions_delayedJob = Nothing, runtimeVersions_django = Nothing, runtimeVersions_dotnet = Nothing, runtimeVersions_dotnetApiCompatibility = Nothing, runtimeVersions_dotnetClr = Nothing, runtimeVersions_dotnetScriptingRuntime = Nothing, runtimeVersions_eventMachine = Nothing, runtimeVersions_expoApp = Nothing, runtimeVersions_expoSdk = Nothing, runtimeVersions_flask = Nothing, runtimeVersions_gin = Nothing, runtimeVersions_go = Nothing, runtimeVersions_javaType = Nothing, runtimeVersions_javaVersion = Nothing, runtimeVersions_jruby = Nothing, runtimeVersions_laravel = Nothing, runtimeVersions_lumen = Nothing, runtimeVersions_magento = Nothing, runtimeVersions_mailman = Nothing, runtimeVersions_martini = Nothing, runtimeVersions_negroni = Nothing, runtimeVersions_node = Nothing, runtimeVersions_osBuild = Nothing, runtimeVersions_php = Nothing, runtimeVersions_python = Nothing, runtimeVersions_que = Nothing, runtimeVersions_rack = Nothing, runtimeVersions_rails = Nothing, runtimeVersions_rake = Nothing, runtimeVersions_reactNative = Nothing, runtimeVersions_reactNativeJsEngine = Nothing, runtimeVersions_resque = Nothing, runtimeVersions_revel = Nothing, runtimeVersions_ruby = Nothing, runtimeVersions_shoryoken = Nothing, runtimeVersions_sidekiq = Nothing, runtimeVersions_silex = Nothing, runtimeVersions_sinatra = Nothing, runtimeVersions_springBoot = Nothing, runtimeVersions_springFramework = Nothing, runtimeVersions_swift = Nothing, runtimeVersions_symfony = Nothing, runtimeVersions_tornado = Nothing, runtimeVersions_unity = Nothing, runtimeVersions_unityScriptingBackend = Nothing, runtimeVersions_wordpress = Nothing } -- | Details of any session information associated with the event. -- This can be used alongside the Bugsnag Session Tracking API to associate the event with a session so that a release's crash rate can be determined. data Session = Session { -- | The unique identifier of the session. session_id :: Text, -- | The time (in [ISO 8601 format](https://tools.ietf.org/html/rfc3339#section-5.8)) at which the session started. session_startedAt :: Text, -- | Details of the number of handled and unhandled events that have occurred so far in this session. session_events :: SessionEvents } deriving (Generic, Show) instance Data.Aeson.ToJSON Session where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON Session where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default session. defaultSession :: Session defaultSession = Session { session_id = "", session_startedAt = "", session_events = defaultSessionEvents } -- | Details of the number of handled and unhandled events that have occurred so far in this session. data SessionEvents = SessionEvents { -- | Details of the number of handled and unhandled events that have occurred so far in this session. sessionEvents_handled :: Int, -- | The number of unhandled events that have occurred in this session (including this event) sessionEvents_unhandled :: Int } deriving (Generic, Show) instance Data.Aeson.ToJSON SessionEvents where toJSON = Data.Aeson.genericToJSON aesonOptions toEncoding = Data.Aeson.genericToEncoding aesonOptions instance Data.Aeson.FromJSON SessionEvents where parseJSON = Data.Aeson.genericParseJSON aesonOptions -- | A default sessionEvents. defaultSessionEvents :: SessionEvents defaultSessionEvents = SessionEvents { sessionEvents_handled = 0, sessionEvents_unhandled = 0 } aesonOptions :: Data.Aeson.Options aesonOptions = Data.Aeson.defaultOptions { Data.Aeson.fieldLabelModifier = drop 1 . dropWhile (/= '_'), Data.Aeson.omitNothingFields = True }