wrecker 0.1.2.0 → 0.1.3.0
raw patch · 7 files changed
+86/−81 lines, 7 files
Files
- examples/Client.lhs +1/−1
- src/Network/Wreq/Wrecker.hs +56/−36
- src/Wrecker.hs +13/−6
- src/Wrecker/Options.hs +4/−2
- src/Wrecker/Recorder.hs +6/−34
- src/Wrecker/Runner.hs +4/−0
- wrecker.cabal +2/−2
examples/Client.lhs view
@@ -340,7 +340,7 @@ ```haskell testScript :: Int -> Environment -> IO ()-testScript port env = WW.withWreq env $ \sess -> do+testScript port = WW.withWreq $ \sess -> do ``` Bootstrap the script and get all the URLs for the endpoints. Unpack `products`, `login` and `checkout` refs for use later down.
src/Network/Wreq/Wrecker.hs view
@@ -1,9 +1,36 @@ {-| This is a copy of the wrecker 'Session' API, 'Network.Wreq.Session' which utilizes 'wrecker''s 'record' function.++ This file was initially copied from Network.Wreq.Session+ (c) 2014 Bryan O'Sullivan. See the source for the full copy right info. -}++-- All of this code below was copied from bos's `Network.Wreq.Session`+-- and modified to include the wrecker recorder {-# LANGUAGE CPP, RecordWildCards #-}-module Network.Wreq.Wrecker where+module Network.Wreq.Wrecker+ ( Session+ , defaultManagerSettings+ -- * Session Creation+ , withWreq+ , withWreqNoCookies+ , withWreqSettings+ -- * HTTP Methods+ , get+ , post+ , head_+ , options+ , put+ , delete+ -- * HTTP Methods with Options+ , getWith+ , postWith+ , headWith+ , optionsWith+ , putWith+ , deleteWith+ ) where import Wrecker import qualified Network.Wreq.Session as Session import Network.Connection (ConnectionContext)@@ -17,6 +44,9 @@ import Data.ByteString (ByteString) import Network.Socket +{-| An opaque type created by 'withWreq', 'withWreqNoCookies',+ or 'withWreqSettings'. All HTTP calls require a 'Session'.+-} data Session = Session { sSession :: Session.Session , sRecorder :: Recorder@@ -26,10 +56,6 @@ -> HTTP.Connection toHTTPConnection HTTP_SHIM.Connection {..} = HTTP.Connection {..} -toSHIMConnection :: HTTP.Connection- -> HTTP_SHIM.Connection-toSHIMConnection HTTP.Connection {..} = HTTP_SHIM.Connection {..}- convertTlsConnection :: IO ( Maybe HostAddress -> String -> Int@@ -85,55 +111,49 @@ , HTTP.managerProxySecure = HTTP.managerProxySecure d } --- |--- Module : Network.Wreq.Internal.Types--- Copyright : (c) 2014 Bryan O'Sullivan------ License : BSD-style--- Maintainer : bos@serpentine.com--- Stability : experimental--- Portability : GHC------ HTTP client types. --- All of this code below was copied from bos's `Network.Wreq.Session`--- and modified to include the wrecker recorder +{- | Create 'ManagerSettings' with no timeout using a shared TLS+ 'ConnectionContext'+-} defaultManagerSettings :: ConnectionContext -> HTTP.ManagerSettings defaultManagerSettings context = convert $ (TLS.mkManagerSettingsContext (Just context) def Nothing) { HTTP_SHIM.managerResponseTimeout = HTTP_SHIM.responseTimeoutNone }--- | Create a 'Session' using the 'wrecker' 'Environment', passing it to the given function. The--- 'Session' will no longer be valid after that function returns.+-- | Create a 'Session' using the 'wrecker' 'Environment', passing it to the+-- given function. The 'Session' will no longer be valid after that+-- function returns. -- -- This session manages cookies and uses default session manager -- configuration.-withWreq :: Environment -> (Session -> IO a) -> IO a-withWreq env- = withSessionControl (recorder env)- (Just (HTTP.createCookieJar []))- (defaultManagerSettings (context env))+withWreq :: (Session -> IO a) -> Environment -> IO a+withWreq f env+ = withWreqSettings (recorder env)+ (Just (HTTP.createCookieJar []))+ (defaultManagerSettings (context env))+ f -- | Create a session. -- -- This uses the default session manager settings, but does not manage -- cookies. It is intended for use with REST-like HTTP-based APIs, -- which typically do not use cookies.-withAPISession :: ConnectionContext -> Recorder -> (Session -> IO a) -> IO a-withAPISession context recorder- = withSessionControl recorder- Nothing- (defaultManagerSettings context)+withWreqNoCookies :: (Session -> IO a) -> Environment -> IO a+withWreqNoCookies f env+ = withWreqSettings (recorder env)+ Nothing+ (defaultManagerSettings (context env))+ f -- | Create a session, using the given cookie jar and manager settings.-withSessionControl :: Recorder- -> Maybe HTTP.CookieJar- -- ^ If 'Nothing' is specified, no cookie management- -- will be performed.- -> HTTP.ManagerSettings- -> (Session -> IO a) -> IO a-withSessionControl recorder cookie settings f+withWreqSettings :: Recorder+ -> Maybe HTTP.CookieJar+ -- ^ If 'Nothing' is specified, no cookie management+ -- will be performed.+ -> HTTP.ManagerSettings+ -> (Session -> IO a) -> IO a+withWreqSettings recorder cookie settings f = Session.withSessionControl cookie settings $ \session -> f (Session session recorder)
src/Wrecker.hs view
@@ -6,22 +6,29 @@ import 'Network.Wreq.Wrecker' to write clients and 'Wrecker' to run the them with either 'defaultMain' ir 'run'.++See https://github.com/skedgeme/wrecker#readme for more information. -}-module Wrecker ( Environment (..)+module Wrecker (-- * Entry Points+ defaultMain+ , run+ , runOne+ -- * Wrecker State+ , Environment (..)+ -- * Recorder , Recorder- , defaultMain , record- , run+ -- * Options , Options (..) , URLDisplay (..) , RunType (..) , DisplayMode (..) , defaultOptions- , runParser+ -- Output Statistics , AllStats (..) , ResultStatistics (..)- , newStandaloneRecorder- , runOne++ ) where import Wrecker.Recorder import Wrecker.Main
src/Wrecker/Options.hs view
@@ -7,8 +7,10 @@ import Data.Monoid {- | There are two typical ways to invoke 'wrecker'. 'RunCount' will execute- each a script 'n' times, where 'n' is the parameter for 'RunCount'.- Alternatively, 'wrecker' can run for specified time with 'RunTimed'.+ each a script 'n' times on each thread. So a run count of 100 and a+ concurrency of 10 will run the script a total of 1000 times.+ Alternatively, 'wrecker' can run for specified number of seconds+ with 'RunTimed'. -} data RunType = RunCount Int | RunTimed Int deriving (Show, Eq)
src/Wrecker/Recorder.hs view
@@ -31,8 +31,8 @@ } deriving (Show) -- | An opaque type for recording actions for profiling.--- No means are provided for creating a 'Recorder' directly.--- To obtain a 'Recorder' use either 'run' or 'defaultMain'.+-- To obtain a 'Recorder' use either 'run', 'defaultMain', 'runOne' or+-- 'newStandaloneRecorder'. data Recorder = Recorder { rRunIndex :: !Int , rQueue :: !(TBMQueue Event)@@ -55,38 +55,10 @@ readEvent :: Recorder -> IO (Maybe Event) readEvent = atomically . readTBMQueue . rQueue -{- | 'record' is how HTTP actions are profiled. Wrap each action of- interest in a call to record.--> import Network.Wreq.Session-> import Data.Aeson->-> loginReshare :: Recorder -> IO ()-> loginReshare recorder = withSession $ \session -> do-> let rc = record recorder->-> Object user <- rc "login"-> $ asJSON-> =<< ( post session "https://somesite.com/login"-> $ object [ "email" .= "example@example.com"-> , "password" .= "12345678"-> ]-> )-> let Just feedUrl = H.lookup "feed" user-> itemRef : _ <- rc "get feed"-> $ asJSON-> =<< ( post session feedUrl-> $ object [ "email" .= "example@example.com"-> , "password" .= "12345678"-> ]-> )-> rc "reshare" $ post session "https://somesite.com/share"-> $ object [ "type" : "reshare"-> , "ref" : itemRef-> ]+{- | 'record' is a low level function for collecting timing information.+ Wrap each action of interest in a call to record. - In this case the 'loginReshare' script would record three actions: "login",- "get feed" and "reshare".+> record recorder $ threadDelay 1000000 'record' measures the elapsed time of the call, and catches 'HttpException' in the case of failure. This means failures@@ -114,7 +86,7 @@ #if MIN_VERSION_http_client(0,5,0) HTTP.HttpExceptionRequest _ (HTTP.StatusCodeException resp _) -> do let code = HTTP.statusCode $ HTTP.responseStatus resp-#else +#else HTTP.StatusCodeException stat _ _ -> do let code = HTTP.statusCode stat #endif
src/Wrecker/Runner.hs view
@@ -32,9 +32,13 @@ -- TODO configure whether errors are used in times or not +-- | The 'Environment' holds state necessary to make and record HTTP calls. data Environment = Environment { recorder :: Recorder+ -- ^ The 'Recorder' can be used with the 'record' function to ... record times. , context :: ConnectionContext+ -- ^ Provided as a convience, this is a shared TLS context to reuse for+ -- better performance. } {- | Typically 'wrecker' will control benchmarking actions. Howeve,r in some situations
wrecker.cabal view
@@ -1,5 +1,5 @@ name: wrecker-version: 0.1.2.0+version: 0.1.3.0 synopsis: An HTTP Performance Benchmarker description: 'wrecker' is a library and executable for creating HTTP benchmarks. It is designed for@@ -8,7 +8,7 @@ 'wrecker' includes a wrapped version of the `wreq` Session API , mainly through 'Network.Wreq.Wrecker'. - See the documentation of 'Wrecker' for more info.+ See https://github.com/skedgeme/wrecker#readme for more information. homepage: https://github.com/skedgeme/wrecker#readme license: BSD3 license-file: LICENSE