ngx-export-tools-extra 0.8.2.0 → 1.0
raw patch · 8 files changed
+319/−117 lines, 8 filesdep ~aeson
Dependency ranges changed: aeson
Files
- Changelog.md +13/−0
- NgxExport/Tools/Aggregate.hs +270/−82
- NgxExport/Tools/EDE.hs +4/−4
- NgxExport/Tools/PCRE.hs +1/−1
- NgxExport/Tools/Prometheus.hs +17/−17
- NgxExport/Tools/ServiceHookAdaptor.hs +2/−1
- NgxExport/Tools/Subrequest.hs +1/−1
- ngx-export-tools-extra.cabal +11/−11
Changelog.md view
@@ -1,3 +1,16 @@+### 1.0++- Module *NgxExport.Tools.Aggregate* can now be built without support from the+ *Snap framework* (flag *SnapAggregateServer* replaces flag *Aggregate*). The+ module now allows building native Nginx-based aggregate services (see updated+ docs).+- In module *NgxExport.Tools.Aggregate*, getting current time with *ngxNow* was+ replaced by *getCurrentTime* because the former is not safe in the async+ context.+- Removed upper bound restriction in the Cabal constraint on the version of+ package *aeson*.+- Package stability tag was promoted to stable.+ ### 0.8.2.0 - In module *NgxExport.Tools.Subrequest*, bridged HTTP subrequests return status
NgxExport/Tools/Aggregate.hs view
@@ -1,13 +1,14 @@-{-# LANGUAGE TemplateHaskell, OverloadedStrings, BangPatterns #-}+{-# LANGUAGE CPP, TemplateHaskell, ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings, BangPatterns #-} ----------------------------------------------------------------------------- -- | -- Module : NgxExport.Tools.Aggregate--- Copyright : (c) Alexey Radkov 2019-2020+-- Copyright : (c) Alexey Radkov 2019-2021 -- License : BSD-style -- -- Maintainer : alexey.radkov@gmail.com--- Stability : experimental+-- Stability : stable -- Portability : non-portable (requires Template Haskell) -- -- An aggregate service from the more extra tools collection for@@ -19,8 +20,13 @@ module NgxExport.Tools.Aggregate ( -- * The typed service exporter -- $aggregateServiceExporter- AggregateServerConf- ,ngxExportAggregateService+#ifdef SNAP_AGGREGATE_SERVER+ AggregateServerConf,+#endif+ ngxExportAggregateService+ -- * Nginx-based aggregate service+ -- $nginxBasedAggregateService+ -- * The worker-side reporter ,reportAggregate -- * Re-exported data constructors from /Foreign.C/@@ -29,6 +35,7 @@ ,Foreign.C.Types.CUInt (..) ) where +import NgxExport import NgxExport.Tools import Language.Haskell.TH@@ -42,22 +49,33 @@ import qualified Data.Map.Strict as M import Data.IORef import Data.Int-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import Data.Time.Clock.POSIX+#if MIN_VERSION_time(1,9,1)+import Data.Fixed+#endif+import Data.Time.Clock+import Data.Time.Calendar import Data.Aeson import Data.Maybe import Control.Monad-import Control.Monad.IO.Class-import Control.Arrow import Control.Exception-import Control.Exception.Enclosed (handleAny) import System.IO.Unsafe+import Safe++#ifdef SNAP_AGGREGATE_SERVER+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import Control.Monad.IO.Class+import Control.Exception.Enclosed (handleAny) import Snap.Http.Server import Snap.Core+#endif -type Aggregate a = IORef (CTime, Map Int32 (CTime, Maybe a)) +type AggregateValue a = (UTCTime, Map Int32 (UTCTime, Maybe a))+type Aggregate a = IORef (AggregateValue a)++type ReportValue a = Maybe (Int32, Maybe a)+ -- $aggregateServiceExporter -- -- An aggregate service collects custom typed data reported by worker processes@@ -214,39 +232,39 @@ -- As far as /reportStats/ is a deferred service, we won't get useful data in 5 -- seconds after Nginx start. ----- > $ curl 'http://127.0.0.1:8020/' | jq+-- > $ curl -s 'http://127.0.0.1:8020/' | jq -- > [--- > "1970-01-01T00:00:00Z",+-- > "1858-11-17T00:00:00Z", -- > {} -- > ] -- -- However, later we should get some useful data. ----- > $ curl 'http://127.0.0.1:8020/' | jq+-- > $ curl -s 'http://127.0.0.1:8020/' | jq -- > [--- > "2019-04-22T14:19:04Z",+-- > "2021-12-08T09:56:18.118132083Z", -- > {--- > "5910": [--- > "2019-04-22T14:19:19Z",+-- > "21651": [+-- > "2021-12-08T09:56:18.12155413Z", -- > {--- > "bytesSent": 0,+-- > "meanBytesSent": 0, -- > "requests": 0,--- > "meanBytesSent": 0+-- > "bytesSent": 0 -- > } -- > ],--- > "5911": [--- > "2019-04-22T14:19:14Z",+-- > "21652": [+-- > "2021-12-08T09:56:18.118132083Z", -- > {--- > "bytesSent": 0,+-- > "meanBytesSent": 0, -- > "requests": 0,--- > "meanBytesSent": 0+-- > "bytesSent": 0 -- > } -- > ] -- > } -- > ] -- -- Here we have collected stats from the two Nginx worker processes with /PIDs/--- /5910/ and /5911/. The timestamps show when the stats was updated the last+-- /21651/ and /21652/. The timestamps show when the stats was updated the last -- time. The topmost timestamp shows the time of the latest /purge/ event. The -- data itself have only zeros as soon we have made no request to the main -- server so far. Let's run 100 simultaneous requests and look at the stats (it@@ -256,29 +274,89 @@ -- -- Wait 5 seconds... ----- > $ curl 'http://127.0.0.1:8020/' | jq+-- > $ curl -s 'http://127.0.0.1:8020/' | jq -- > [--- > "2019-04-22T14:29:04Z",+-- > "2021-12-08T09:56:18.118132083Z", -- > {--- > "5910": [--- > "2019-04-22T14:31:34Z",+-- > "21651": [+-- > "2021-12-08T09:56:48.159263993Z", -- > {--- > "bytesSent": 17751,--- > "requests": 97,--- > "meanBytesSent": 183+-- > "meanBytesSent": 183,+-- > "requests": 84,+-- > "bytesSent": 15372 -- > } -- > ],--- > "5911": [--- > "2019-04-22T14:31:31Z",+-- > "21652": [+-- > "2021-12-08T09:56:48.136934713Z", -- > {--- > "bytesSent": 549,--- > "requests": 3,--- > "meanBytesSent": 183+-- > "meanBytesSent": 183,+-- > "requests": 16,+-- > "bytesSent": 2928 -- > } -- > ] -- > } -- > ] +throwUserError :: String -> IO a+throwUserError = ioError . userError++#if MIN_VERSION_time(1,9,1)+asIntegerPart :: forall a. HasResolution a => Integer -> Fixed a+asIntegerPart = MkFixed . (resolution (undefined :: Fixed a) *)+{-# SPECIALIZE INLINE asIntegerPart :: Integer -> Pico #-}+#endif++toNominalDiffTime :: TimeInterval -> NominalDiffTime+toNominalDiffTime =+#if MIN_VERSION_time(1,9,1)+ secondsToNominalDiffTime . asIntegerPart+#else+ fromRational . toRational . secondsToDiffTime+#endif+ . fromIntegral . toSec++updateAggregate :: Aggregate a -> ReportValue a -> NominalDiffTime -> IO ()+updateAggregate a s int = do+ let (pid, v) = fromJust s+ !t <- getCurrentTime+ atomicModifyIORef' a $+ \(t', v') ->+ (let (!tn, f) =+ if diffUTCTime t t' >= int+ then (t+ ,M.filter $+ \(t'', _) -> diffUTCTime t t'' < int+ )+ else (t', id)+ !vn = f $ M.alter+ (\old ->+ let !new' = if isNothing old || isJust v+ then v+ else snd $ fromJust old+ in Just (t, new')+ ) pid v'+ in (tn, vn)+ ,()+ )++receiveAggregate :: FromJSON a =>+ Aggregate a -> L.ByteString -> ByteString -> IO L.ByteString+receiveAggregate a v sint = do+ let !s = decode' v+ !int = toNominalDiffTime $ readDef (Min 5) $ C8.unpack sint+ when (isNothing s) $ throwUserError "Unreadable aggregate!"+ updateAggregate a (fromJust s) int+ return "done"++sendAggregate :: ToJSON a =>+ Aggregate a -> ByteString -> IO ContentHandlerResult+sendAggregate a = const $ do+ s <- readIORef a+ return (encode s, "text/plain", 200, [])+++#ifdef SNAP_AGGREGATE_SERVER+ -- | Configuration of an aggregate service. -- -- This type is exported because Template Haskell requires that. Though its@@ -292,8 +370,9 @@ -- @ -- -- The value of /asPort/ corresponds to the TCP port of the internal aggregate--- server. The /asPurgeInterval/ is the /purge/ interval. An aggregate service--- should sometimes purge data from worker processes which did not report for a+-- server (the IP address of the internal server is always /127.0.0.1/). The+-- /asPurgeInterval/ is the /purge/ interval. An aggregate service should+-- sometimes purge data from worker processes which have not reported for a -- long time. For example, it makes no sense to keep data from workers that -- have already been terminated. The inactive PIDs get checked every -- /asPurgeInterval/, and data which correspond to PIDs with timestamps older@@ -308,8 +387,10 @@ aggregateServer :: (FromJSON a, ToJSON a) => Aggregate a -> ByteString -> AggregateServerConf -> Bool -> IO L.ByteString-aggregateServer a u = ignitionService $ \conf ->- simpleHttpServe (asConfig $ asPort conf) (asHandler a u conf) >> return ""+aggregateServer a u = ignitionService $ \conf -> do+ let !int = toNominalDiffTime $ asPurgeInterval conf+ simpleHttpServe (asConfig $ asPort conf) $ asHandler a u int+ return "" asConfig :: Int -> Config Snap a asConfig p = setPort p@@ -319,48 +400,30 @@ $ setVerbose False mempty asHandler :: (FromJSON a, ToJSON a) =>- Aggregate a -> ByteString -> AggregateServerConf -> Snap ()-asHandler a u conf =- route [(B.append "put/" u, Snap.Core.method POST $ receiveAggregate a conf)- ,(B.append "get/" u, Snap.Core.method GET $ sendAggregate a)+ Aggregate a -> ByteString -> NominalDiffTime -> Snap ()+asHandler a u int =+ route [(B.append "put/" u+ ,Snap.Core.method POST $ receiveAggregateSnap a int+ )+ ,(B.append "get/" u+ ,Snap.Core.method GET $ sendAggregateSnap a+ ) ] -receiveAggregate :: FromJSON a =>- Aggregate a -> AggregateServerConf -> Snap ()-receiveAggregate a conf =+receiveAggregateSnap :: FromJSON a => Aggregate a -> NominalDiffTime -> Snap ()+receiveAggregateSnap a int = handleAggregateExceptions "Exception while receiving aggregate" $ do !s <- decode' <$> readRequestBody 65536 when (isNothing s) $ liftIO $ throwUserError "Unreadable aggregate!"- liftIO $ do- let (pid, v) = fromJust s- int = fromIntegral . toSec . asPurgeInterval $ conf- !t <- ngxNow- atomicModifyIORef' a $- \(t', v') ->- (let (!tn, f) =- if t - t' >= int- then (t, M.filter $ \(t'', _) -> t - t'' < int)- else (t', id)- !vn = f $ M.alter- (\old ->- let !new' =- if isNothing old || isJust v- then v- else snd $ fromJust old- in Just (t, new')- ) pid v'- in (tn, vn)- ,()- )+ liftIO $ updateAggregate a (fromJust s) int finishWith emptyResponse -sendAggregate :: ToJSON a => Aggregate a -> Snap ()-sendAggregate a =+sendAggregateSnap :: ToJSON a => Aggregate a -> Snap ()+sendAggregateSnap a = handleAggregateExceptions "Exception while sending aggregate" $ do s <- liftIO $ readIORef a modifyResponse $ setContentType "application/json"- writeLBS $ encode $ (toUTCTime *** M.map (first toUTCTime)) s- where toUTCTime (CTime t) = posixSecondsToUTCTime $ fromIntegral t+ writeLBS $ encode s handleAggregateExceptions :: String -> Snap () -> Snap () handleAggregateExceptions cmsg = handleAny $ \e ->@@ -369,9 +432,9 @@ modifyResponse $ setResponseStatus c $ T.encodeUtf8 $ T.pack cmsg writeBS $ T.encodeUtf8 $ T.pack msg -throwUserError :: String -> IO a-throwUserError = ioError . userError+#endif + -- | Exports a simple aggregate service with specified name and the aggregate -- type. --@@ -393,34 +456,159 @@ -> Name -- ^ Name of the aggregate type -> Q [Dec] ngxExportAggregateService f a = do- let nameF = 'aggregateServer+ let sName = mkName $ "aggregate_storage_" ++ f+ storage = varE sName+#ifdef SNAP_AGGREGATE_SERVER+ nameF = 'aggregateServer fName = mkName $ "aggregate_" ++ f- sName = mkName $ "aggregate_storage_" ++ f uName = mkName $ "aggregate_url_" ++ f+#endif+ nameRecv = 'receiveAggregate+ recvName = mkName $ "receiveAggregate_" ++ f+ nameSend = 'sendAggregate+ sendName = mkName $ "sendAggregate_" ++ f concat <$> sequence [sequence- [sigD uName [t|ByteString|]- ,funD uName [clause [] (normalB [|C8.pack f|]) []]- ,sigD sName [t|Aggregate $(conT a)|]+ [sigD sName [t|Aggregate $(conT a)|] ,funD sName [clause []- (normalB [|unsafePerformIO $ newIORef (0, M.empty)|])+ (normalB [|unsafePerformIO $+ newIORef (UTCTime (ModifiedJulianDay 0) 0+ ,M.empty+ )+ |]+ ) [] ] ,pragInlD sName NoInline FunLike AllPhases+#ifdef SNAP_AGGREGATE_SERVER+ ,sigD uName [t|ByteString|]+ ,funD uName [clause [] (normalB [|C8.pack f|]) []] ,sigD fName [t|AggregateServerConf -> Bool -> IO L.ByteString|] ,funD fName [clause []- (normalB [|$(varE nameF) $(varE sName) $(varE uName)|])+ (normalB [|$(varE nameF) $(storage) $(varE uName)|]) [] ]+#endif+ ,sigD recvName [t|L.ByteString -> ByteString -> IO L.ByteString|]+ ,funD recvName+ [clause []+ (normalB [|$(varE nameRecv) $(storage)|])+ []+ ]+ ,sigD sendName [t|ByteString -> IO ContentHandlerResult|]+ ,funD sendName+ [clause []+ (normalB [|$(varE nameSend) $(storage)|])+ []+ ] ]+#ifdef SNAP_AGGREGATE_SERVER -- FIXME: name AggregateServerConf must be imported from the user's -- module unqualified (see details in NgxExport/Tools.hs, function -- ngxExportSimpleService')! ,ngxExportSimpleServiceTyped fName ''AggregateServerConf SingleShotService+#endif+ ,ngxExportAsyncOnReqBody recvName+ ,ngxExportAsyncHandler sendName ]++-- $nginxBasedAggregateService+--+-- Service /simpleService_aggregate_stats/ was implemented using+-- /Snap framework/. Basically, a native Nginx implementation is not easy+-- because the service must listen on a single (not duplicated) file descriptor+-- which is not the case when Nginx spawns more than one worker processes.+-- Running /simpleService_aggregate_stats/ as a shared service is an elegant+-- solution as shared services guarantee that they occupy only one worker at a+-- time. However, /nginx-haskell-module/ provides directive /single_listener/+-- which can be used to apply the required restriction in a custom Nginx virtual+-- server. This directive requires that the virtual server listens with option+-- /reuseport/ and is only available on Linux with socket option+-- /SO_ATTACH_REUSEPORT_CBPF/.+--+-- Exporter 'ngxExportAggregateService' exports additional handlers to build a+-- native Nginx-based aggregate service. Let's replace service+-- /simpleService_aggregate_stats/ from the previous example with such a native+-- Nginx-based aggregate service using /single_listener/ and listening on port+-- /8100/.+--+-- ==== File /nginx.conf/+-- @+-- user nobody;+-- worker_processes 2;+--+-- events {+-- worker_connections 1024;+-- }+--+-- http {+-- default_type application\/octet-stream;+-- sendfile on;+--+-- haskell load \/var\/lib\/nginx\/test_tools_extra_aggregate.so;+--+-- haskell_run_service simpleService_reportStats $hs_reportStats 8100;+--+-- haskell_var_empty_on_error $hs_stats;+--+-- server {+-- listen 8010;+-- server_name main;+-- error_log \/tmp\/nginx-test-haskell-error.log;+-- access_log \/tmp\/nginx-test-haskell-access.log;+--+-- haskell_run updateStats !$hs_updateStats $bytes_sent;+--+-- location \/ {+-- echo Ok;+-- }+-- }+--+-- server {+-- listen 8020;+-- server_name stat;+--+-- location \/ {+-- allow 127.0.0.1;+-- deny all;+-- proxy_pass http:\/\/127.0.0.1:8100\/get\/stats;+-- }+-- }+--+-- server {+-- listen 8100 __/reuseport/__;+-- server_name stats;+--+-- __/single_listener on/__;+--+-- location __/\/put\/stats/__ {+-- haskell_run_async_on_request_body __/receiveAggregate_stats/__+-- $hs_stats \"Min 1\";+--+-- if ($hs_stats = \'\') {+-- return 400;+-- }+--+-- return 200;+-- }+--+-- location __/\/get\/stats/__ {+-- haskell_async_content __/sendAggregate_stats/__ noarg;+-- }+-- }+-- }+-- @+--+-- Handler /receiveAggregate_stats/ accepts a time interval corresponding to the+-- value of /asPurgeInterval/ from service /simpleService_aggregate_stats/. If+-- the value is not readable (say, /noarg/) then it is defaulted to /Min 5/.+--+-- Notice that the stats server must listen on IP address /127.0.0.1/ because+-- 'reportAggregate' (being the base of service /simpleService_reportStats/)+-- reports stats to this address. -- | Reports data to an aggregate service. --
NgxExport/Tools/EDE.hs view
@@ -3,11 +3,11 @@ ----------------------------------------------------------------------------- -- | -- Module : NgxExport.Tools.EDE--- Copyright : (c) Alexey Radkov 2020+-- Copyright : (c) Alexey Radkov 2020-2021 -- License : BSD-style -- -- Maintainer : alexey.radkov@gmail.com--- Stability : experimental+-- Stability : stable -- Portability : non-portable (requires Template Haskell) -- -- EDE templates for parsing JSON objects from the more extra tools collection@@ -29,7 +29,7 @@ import Text.EDE import Text.EDE.Filters-#if EDE_USE_PRETTYPRINTER+#ifdef EDE_USE_PRETTYPRINTER #if MIN_VERSION_prettyprinter(1,7,0) import Prettyprinter (unAnnotate) #else@@ -275,7 +275,7 @@ Failure msg -> throwIO $ EDERenderError $ showPlain msg Success r -> return $ LT.encodeUtf8 r where showPlain = show .-#if EDE_USE_PRETTYPRINTER+#ifdef EDE_USE_PRETTYPRINTER unAnnotate #else plain
NgxExport/Tools/PCRE.hs view
@@ -10,7 +10,7 @@ -- License : BSD-style -- -- Maintainer : alexey.radkov@gmail.com--- Stability : experimental+-- Stability : stable -- Portability : non-portable (requires Template Haskell) -- -- PCRE matching and substitution from the more extra tools collection
NgxExport/Tools/Prometheus.hs view
@@ -4,11 +4,11 @@ ----------------------------------------------------------------------------- -- | -- Module : NgxExport.Tools.Prometheus--- Copyright : (c) Alexey Radkov 2020+-- Copyright : (c) Alexey Radkov 2020-2021 -- License : BSD-style -- -- Maintainer : alexey.radkov@gmail.com--- Stability : experimental+-- Stability : stable -- Portability : non-portable (requires Template Haskell) -- -- Prometheus metrics from the more extra tools collection for@@ -440,8 +440,7 @@ writeIORef conf $ Just a return "" -ngxExportSimpleServiceTyped- 'prometheusConf ''PrometheusConf SingleShotService+ngxExportSimpleServiceTyped 'prometheusConf ''PrometheusConf SingleShotService toPrometheusMetrics' :: PrometheusConf -> AllMetrtics -> PrometheusMetrics toPrometheusMetrics' PrometheusConf {..} (srv, cnts, hs, ocnts) =@@ -934,50 +933,50 @@ -- ,\"__/hst_request_time\@scope=(in_upstreams)_sum/__\" -- ] -- }\';--- +-- -- @ -- @ -- counter $__/cnt_status\@value=(4xx),from=(response)/__ inc $inc_cnt_4xx; -- counter $__/cnt_status\@value=(5xx),from=(response)/__ inc $inc_cnt_5xx;--- +-- -- haskell_run statusLayout $hs_upstream_status $upstream_status; -- counter $__/cnt_status\@value=(4xx),from=(upstream)/__ inc $inc_cnt_u_4xx; -- counter $__/cnt_status\@value=(5xx),from=(upstream)/__ inc $inc_cnt_u_5xx;--- +-- -- # cache $request_time and $bytes_sent -- haskell_run ! $hs_request_time $request_time; -- haskell_run ! $hs_bytes_sent $bytes_sent;--- +-- -- histogram $__/hst_request_time\@scope=(total)/__ 11 $request_time_bucket; -- haskell_run scale1000 $hs_request_time_scaled $hs_request_time; -- counter $hst_request_time\@scope=(total)_sum inc $hs_request_time_scaled;--- +-- -- histogram $hst_bytes_sent 6 $bytes_sent_bucket; -- counter $hst_bytes_sent_sum inc $hs_bytes_sent;--- +-- -- # cache $upstream_response_time -- haskell_run ! $hs_u_response_times $upstream_response_time;--- +-- -- histogram $__/hst_request_time\@scope=(in_upstreams)/__ 11 -- $u_response_time_bucket; -- histogram $__/hst_request_time\@scope=(in_upstreams)/__ undo; -- haskell_run cumulativeFPValue $hs_u_response_time $hs_u_response_times; -- haskell_run scale1000 $hs_u_response_time_scaled $hs_u_response_time;--- +-- -- location \/ { -- echo_sleep 0.5; -- echo Ok; -- }--- +-- -- location \/1 { -- echo_sleep 1.0; -- echo Ok; -- }--- +-- -- location \/404 { -- return 404; -- }--- +-- -- location \/backends { -- histogram $__/hst_request_time\@scope=(in_upstreams)/__ reuse; -- counter $__/hst_request_time\@scope=(in_upstreams)_sum/__ inc@@ -986,7 +985,7 @@ -- proxy_intercept_errors on; -- proxy_pass http:\/\/backends; -- }--- +-- -- location \@status404 { -- histogram $__/hst_request_time\@scope=(in_upstreams)/__ reuse; -- counter $__/hst_request_time\@scope=(in_upstreams)_sum/__ inc@@ -1011,7 +1010,7 @@ -- > $ for i in {1..20} ; do curl -D- 'http://localhost:8010/backends' & done -- > ... ----- > $ curl -s 'http://localhost:8020/' +-- > $ curl -s 'http://localhost:8020/' -- > # HELP cnt_status Number of responses with given status -- > # TYPE cnt_status counter -- > cnt_status{value="4xx",from="response"} 11.0@@ -1072,3 +1071,4 @@ -- > # TYPE hst_request_time_err counter -- > hst_request_time_err{scope="in_upstreams"} 0.0 -- > hst_request_time_err{scope="total"} 0.0+
NgxExport/Tools/ServiceHookAdaptor.hs view
@@ -7,7 +7,7 @@ -- License : BSD-style -- -- Maintainer : alexey.radkov@gmail.com--- Stability : experimental+-- Stability : stable -- Portability : non-portable (requires Template Haskell) -- -- A service hook adaptor from the more extra tools collection for@@ -184,5 +184,6 @@ hookAdaptor :: ByteString -> Bool -> IO L.ByteString hookAdaptor = ignitionService $ const $ forever $ threadDelaySec $ toSec $ Hr 24+ ngxExportSimpleService 'hookAdaptor SingleShotService
NgxExport/Tools/Subrequest.hs view
@@ -8,7 +8,7 @@ -- License : BSD-style -- -- Maintainer : alexey.radkov@gmail.com--- Stability : experimental+-- Stability : stable -- Portability : non-portable (requires Template Haskell) -- -- Easy HTTP subrequests from the more extra tools collection for
ngx-export-tools-extra.cabal view
@@ -1,5 +1,5 @@ name: ngx-export-tools-extra-version: 0.8.2.0+version: 1.0 synopsis: More extra tools for Nginx haskell module description: More extra tools for <https://github.com/lyokha/nginx-haskell-module Nginx haskell module>.@@ -9,7 +9,7 @@ extra-source-files: Changelog.md author: Alexey Radkov <alexey.radkov@gmail.com> maintainer: Alexey Radkov <alexey.radkov@gmail.com>-stability: experimental+stability: stable copyright: 2019-2021 Alexey Radkov category: Network build-type: Simple@@ -19,9 +19,6 @@ type: git location: https://github.com/lyokha/ngx-export-tools-extra -flag Aggregate- description: Build Aggregate module.- flag EDE description: Build EDE module. @@ -33,6 +30,9 @@ flag PCRE description: Build PCRE module. +flag SnapAggregateServer+ description: Build Snap server for Aggregate module.+ library default-language: Haskell2010 build-depends: base >= 4.8 && < 5@@ -41,10 +41,11 @@ , base64 >= 0.3.0.0 , ngx-export , ngx-export-tools >= 0.4.8.0- , aeson >= 1.0.0.0 && < 2.0.0.0 , http-types >= 0.7.0 , http-client >= 0.5.3 , network >= 2.4.0.0+ , aeson >= 1.0.0.0+ , time , binary , case-insensitive , containers@@ -53,11 +54,11 @@ , text , safe - if flag(Aggregate)+ if flag(SnapAggregateServer) build-depends: snap-core , snap-server , enclosed-exceptions- , time+ cpp-options: -DSNAP_AGGREGATE_SERVER if flag(EDE) if flag(EDEUsePrettyprinter)@@ -69,6 +70,7 @@ build-depends: ede , ansi-wl-pprint >= 0.6.3 , trifecta <= 2+ , aeson >= 1.0.0.0 && < 2.0.0.0 if flag(PCRE) build-depends: pcre-light >= 0.4@@ -77,9 +79,7 @@ exposed-modules: NgxExport.Tools.Prometheus , NgxExport.Tools.Subrequest , NgxExport.Tools.ServiceHookAdaptor-- if flag(Aggregate)- exposed-modules: NgxExport.Tools.Aggregate+ , NgxExport.Tools.Aggregate if flag(EDE) exposed-modules: NgxExport.Tools.EDE