packages feed

bugsnag-hs 0.1.0.3 → 0.2.0.0

raw patch · 7 files changed

+8/−235 lines, 7 filesdep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: bytestring

API changes (from Hackage documentation)

- Data.Buffer: data Buffer a
- Data.Buffer: data Settings a
- Data.Buffer: defaultSettings :: Settings a
- Data.Buffer: flush :: Buffer a -> IO ()
- Data.Buffer: frequencyInMicroSeconds :: Settings a -> Int
- Data.Buffer: new :: Settings a -> IO (Buffer a)
- Data.Buffer: push :: Buffer a -> a -> IO ()
- Data.Buffer: size :: Settings a -> Natural
- Data.Buffer: write :: Settings a -> NonEmpty a -> IO ()
- Network.Bugsnag: data Batcher
- Network.Bugsnag: flushBatcher :: Batcher -> IO ()
- Network.Bugsnag: newBatcher :: Manager -> ApiKey -> (HttpException -> IO ()) -> IO Batcher
- Network.Bugsnag: queueSingleEvent :: Batcher -> Event -> IO ()

Files

CHANGELOG.md view
@@ -1,3 +1,8 @@+# 0.2.0.0++- Remove `Data.Buffer` module+- Expand version bounds to include bytestring v0.12.+ # 0.1.0.3  - Expand version bounds to include http-client v0.7.
README.md view
@@ -4,7 +4,5 @@  The library is low-level and provides a faithful representation of version 5 of the [Bugsnag error reporting API][] payload. Almost all documentation comments in this code come from that API's documentation. The intent is for this library to make no assumptions about the structure of the application using it. -The one higher-level functionality this library provides is help batching Bugsnag events together to make fewer HTTP requests, but the use of this functionality is optional.- [bugsnag]: https://www.bugsnag.com/ [bugsnag error reporting api]: https://bugsnagerrorreportingapi.docs.apiary.io/#reference
bugsnag-hs.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 7caac2dd8372f186bc786e2c0c35b6f70284087a246e937655343f3b6105231e+-- hash: 67c246cc1a26f9b2a1ad07fe282ddbf1c55256e19cff590e9e00cd34999909a5  name:           bugsnag-hs-version:        0.1.0.3+version:        0.2.0.0 synopsis:       A Bugsnag client for Haskell. description:    Please see the README at <https://github.com/jwoudenberg/bugsnag-hs>. category:       Web@@ -32,7 +32,6 @@ library   exposed-modules:       Network.Bugsnag-      Data.Buffer   other-modules:       Paths_bugsnag_hs   hs-source-dirs:@@ -41,7 +40,7 @@       aeson >=1.2.4.0 && <1.6     , auto-update >=0.1.4 && <0.2     , base >=4.10.1.0 && <5-    , bytestring >=0.10.8.2 && <0.11+    , bytestring >=0.10.8.2 && <0.12     , http-client >=0.5.10 && <0.8     , stm >=2.4.5.0 && <2.6     , text >=1.2.3.0 && <1.3@@ -53,7 +52,6 @@   type: exitcode-stdio-1.0   main-is: Main.hs   other-modules:-      Spec.Data.Buffer       Spec.Network.Bugsnag       Paths_bugsnag_hs   hs-source-dirs:
− src/Data/Buffer.hs
@@ -1,79 +0,0 @@-{-# LANGUAGE NamedFieldPuns #-}---- |--- A buffer for batched write operations. Push individual items into the buffer--- and provide an operation that writes out batches of them.-module Data.Buffer-  ( -- * Buffer-    Buffer,-    new,-    push,-    flush,--    -- * Settings-    Settings,-    defaultSettings,-    write,-    size,-    frequencyInMicroSeconds,-  )-where--import qualified Control.Concurrent.STM as STM-import qualified Control.Debounce as Debounce-import qualified Data.List.NonEmpty as NonEmpty-import GHC.Natural (Natural)---- | A buffer for write operations.-data Buffer a-  = Buffer-      { -- | Push a new item into the buffer.-        push :: a -> IO (),-        -- | Flush the current contents of the buffer.-        flush :: IO ()-      }---- | Configuration settings for a new 'Buffer'.-data Settings a-  = Settings-      { -- | Function to write a batch of items.-        write :: NonEmpty.NonEmpty a -> IO (),-        -- | The maximum amount of items to write in a single batch.-        size :: Natural,-        -- | The frequency with which the buffer gets flushed automatically.-        frequencyInMicroSeconds :: Int-      }---- | Default 'Buffer' settings. A buffer created by these settings has a size--- of 1 and writes items out as soon as they come in.-defaultSettings :: Settings a-defaultSettings =-  Settings-    { write = \_ -> pure (),-      size = 1,-      frequencyInMicroSeconds = 0-    }---- | Creates a new 'Buffer'.-new :: Settings a -> IO (Buffer a)-new settings = do-  queue <- STM.atomically $ STM.newTBQueue (fromIntegral (size settings))-  let writeList xs = maybe (pure ()) (write settings) (NonEmpty.nonEmpty xs)-  let flush = writeList =<< STM.atomically (STM.flushTBQueue queue)-  scheduleFlush <--    Debounce.mkDebounce-      Debounce.defaultDebounceSettings-        { Debounce.debounceAction = flush,-          Debounce.debounceFreq = frequencyInMicroSeconds settings-        }-  let push x = do-        overflow <- STM.atomically $ do-          full <- STM.isFullTBQueue queue-          toFlush <- if full then STM.flushTBQueue queue else pure []-          STM.writeTBQueue queue x-          pure toFlush-        -- Flush the items that overflow the queue immediately.-        writeList overflow-        -- Schedule a regular flush for the rest.-        scheduleFlush-  pure Buffer {push, flush}
src/Network/Bugsnag.hs view
@@ -8,10 +8,6 @@ module Network.Bugsnag   ( -- * Sending reports     sendEvents,-    queueSingleEvent,-    Batcher,-    newBatcher,-    flushBatcher,      -- ** ApiKey     ApiKey,@@ -290,7 +286,6 @@ 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)@@ -302,9 +297,6 @@ 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@@ -313,35 +305,6 @@       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
test/Main.hs view
@@ -3,10 +3,8 @@   ) where -import qualified Spec.Data.Buffer import qualified Spec.Network.Bugsnag  main :: IO () main = do   Spec.Network.Bugsnag.tests-  Spec.Data.Buffer.tests
− test/Spec/Data/Buffer.hs
@@ -1,110 +0,0 @@-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}--module Spec.Data.Buffer-  ( tests,-  )-where--import qualified Control.Concurrent-import qualified Control.Concurrent.STM as STM-import qualified Data.Buffer as Buffer-import qualified Data.Foldable-import qualified Data.List-import qualified Data.List.NonEmpty as NonEmpty-import qualified Data.Maybe-import GHC.Natural (Natural)-import Hedgehog-import qualified Hedgehog.Gen as Gen-import qualified Hedgehog.Range as Range-import qualified System.Exit--tests :: IO ()-tests = do-  res <- tests'-  if res-    then pure ()-    else System.Exit.die "Spec.Data.Buffer tests failed"--tests' :: IO Bool-tests' =-  checkParallel $-    Group-      "Spec.Data.Buffer"-      [ ("all items get sent", allItemsGetSent)-      ]--allItemsGetSent :: Property-allItemsGetSent = property $ do-  steps <- forAll $ numberItems <$> Gen.list (Range.linear 0 100) step-  size <- forAll $ fromIntegral <$> Gen.int (Range.linear 1 10)-  frequencyInMicroSeconds <- forAll $ waitMicroS-  actualOutput <- evalIO (run size frequencyInMicroSeconds steps)-  let expectedOutput = Data.Maybe.mapMaybe toItem steps-  Data.List.sort actualOutput === Data.List.sort expectedOutput--data Step-  = Push Item-  | WaitMicroS Int-  | Flush-  deriving (Show)--newtype Item = Item Int-  deriving (Eq, Ord, Show)--step :: Gen Step-step =-  Gen.frequency-    [ (5, Gen.constant (Push (Item 0))),-      (5, WaitMicroS <$> waitMicroS),-      (1, Gen.constant Flush)-    ]--numberItems :: [Step] -> [Step]-numberItems = snd . Data.List.mapAccumL numberItem 0--numberItem :: Int -> Step -> (Int, Step)-numberItem counter step =-  case step of-    Push (Item _) -> (counter + 1, Push (Item counter))-    _ -> (counter, step)--waitMicroS :: Gen Int-waitMicroS = Gen.int (Range.linear 0 maxWaitMicroS)--maxWaitMicroS :: Int-maxWaitMicroS = 10000--toItem :: Step -> Maybe Item-toItem step =-  case step of-    Push item -> Just item-    WaitMicroS _ -> Nothing-    Flush -> Nothing--run :: Natural -> Int -> [Step] -> IO [Item]-run size frequencyInMicroSeconds steps = do-  -- Setup the buffer to play the steps through.-  resultQueue <- STM.newTQueueIO-  buffer <--    Buffer.new-      Buffer.defaultSettings-        { Buffer.write = writeToQueue resultQueue,-          Buffer.size,-          Buffer.frequencyInMicroSeconds-        }-  -- Play the steps one by one.-  Data.Foldable.traverse_ (play buffer) steps-  -- Give the queue the opportunity to flush by itself.-  Control.Concurrent.threadDelay (2 * maxWaitMicroS)-  mconcat <$> STM.atomically (STM.flushTQueue resultQueue)--play :: Buffer.Buffer Item -> Step -> IO ()-play buffer step =-  case step of-    Push item -> Buffer.push buffer item-    WaitMicroS delay -> Control.Concurrent.threadDelay delay-    Flush -> Buffer.flush buffer--writeToQueue :: STM.TQueue [a] -> NonEmpty.NonEmpty a -> IO ()-writeToQueue queue list = STM.atomically (STM.writeTQueue queue (NonEmpty.toList list))