git.iko.soy/typeable/rollbar-hs
on master help sign in
14 files changed+174−61
since splitsnapshots
unifiedsplit
.circleci/config.yml+4−2 .gitignore+1−2 Makefile+2−1 package.yaml−46 rollbar-hs.cabal+93 src/Rollbar/Aeson.hs+22 src/Rollbar/Item.hs+8 src/Rollbar/Item/Body.hs+10−4 src/Rollbar/Item/MissingHeaders.hs+8−3 src/Rollbar/Item/Request.hs+12−2 src/Rollbar/Item/Server.hs+5 stack.yaml+6 test/Rollbar/Item/Data/Test.hs+1−1 test/Rollbar/Item/MissingHeaders/Test.hs+2
.circleci/config.yml+4−2
@@ -2,7 +2,7 @@ version: 2
22jobs:
33 ghc-8.2.2:
44 docker:
5− - image: nixorg/nix:circleci
5+ - image: nixorg/nix@sha256:96c3f56563a3b9549ac1da12ff7567c39cb6e648afd6a17d4a1a41f0596ad8f6
66 steps:
77 - checkout
88 - restore_cache:
@@ -12,7 +12,9 @@ jobs:
1212 name: Restoring cache
1313 - run:
1414 name: Compile
15− command: nix-shell --run 'make sdist test -j2'
15+ command: nix-shell --run 'make sdist test --jobs=2'
16+ environment:
17+ CABAL_BUILD_FLAGS: --jobs=2
1618 - save_cache:
1719 key: v2-nix-{{ checksum "package.yaml" }}
1820 name: Caching nix
.gitignore+1−2
@@ -1,6 +1,5 @@
11### Project specific ###
22
3−*.cabal
43.make
54bin
65
@@ -186,4 +185,4 @@ $RECYCLE.BIN/
186185*.lnk
187186
188187
189−# End of https://www.gitignore.io/api/vim,osx,linux,macos,emacs,windows,haskell,visualstudiocode
188+# End of https://www.gitignore.io/api/vim,osx,linux,macos,emacs,windows,haskell,visualstudiocode
Makefile+2−1
@@ -1,5 +1,6 @@
11CABAL ?= cabal
22CABAL_FLAGS ?=
3+CABAL_BUILD_FLAGS ?=
34DIST ?= dist
45GHCID ?= ghcid
56GHCID_FLAGS ?= --ghc-options=-fno-code
@@ -22,7 +23,7 @@ $(CONFIGURE): $(CABAL_FILE)
2223
2324.PHONY: build
2425build $(DOC_TEST): $(CONFIGURE) default.nix
25− $(CABAL) $(CABAL_FLAGS) build
26+ $(CABAL) $(CABAL_FLAGS) build $(CABAL_BUILD_FLAGS)
2627
2728.PHONY: check
2829check: $(CABAL_FILE)
package.yamldeleted−46
@@ -1,46 +0,0 @@
1−author: Hardy Jones
2−category: Web
3−copyright: 2018 Hardy Jones
4−description: |
5− Provides a type-safe encoding of the Rollbar API.
6− Also provides functions to communicate with the Rollbar API.
7−extra-source-files:
8− - CHANGELOG.md
9− - README.md
10−github: joneshf/rollbar-hs
11−library:
12− dependencies:
13− - aeson >= 1.0 && < 1.5
14− - base >= 4.9 && < 5
15− - bytestring >= 0.10 && < 0.11
16− - case-insensitive >= 1.2 && < 1.3
17− - hostname >= 1.0 && < 1.1
18− - http-client >= 0.5 && < 0.6
19− - http-conduit >= 2.2 && < 2.4
20− - http-types >= 0.9 && < 0.13
21− - network >= 2.6 && < 2.8
22− - text >= 1.2 && < 1.3
23− - time >= 1.6 && < 1.9
24− - unordered-containers >= 0.2 && < 0.3
25− - uuid >= 1.3 && < 1.4
26− source-dirs: src
27−license: BSD3
28−maintainer: jones3.hardy@gmail.com
29−name: rollbar-hs
30−synopsis: Core Rollbar data types and APIs.
31−tests:
32− doc-test:
33− dependencies:
34− - QuickCheck >= 2.9
35− - aeson >= 1.0
36− - base >= 4.9
37− - bytestring >= 0.10
38− - case-insensitive >= 1.2
39− - hspec >= 2.4
40− - hspec-golden-aeson >= 0.2
41− - rollbar-hs
42− - text >= 1.2
43− - unordered-containers >= 0.2
44− main: Main.hs
45− source-dirs: test
46−version: '0.3.1.0'
rollbar-hs.cabalnew file+93
@@ -0,0 +1,93 @@
1+cabal-version: 1.12
2+
3+-- This file has been generated from package.yaml by hpack version 0.31.2.
4+--
5+-- see: https://github.com/sol/hpack
6+--
7+-- hash: ac4c551193d60902c95f89512121ee67cb0cafb3a6662796e40323bd0cedff7c
8+
9+name: rollbar-hs
10+version: 0.3.1.0
11+synopsis: Core Rollbar data types and APIs.
12+description: Provides a type-safe encoding of the Rollbar API.
13+ Also provides functions to communicate with the Rollbar API.
14+category: Web
15+homepage: https://github.com/joneshf/rollbar-hs#readme
16+bug-reports: https://github.com/joneshf/rollbar-hs/issues
17+author: Hardy Jones
18+maintainer: jones3.hardy@gmail.com
19+copyright: 2018 Hardy Jones
20+license: BSD3
21+license-file: LICENSE
22+build-type: Simple
23+extra-source-files:
24+ CHANGELOG.md
25+ README.md
26+
27+source-repository head
28+ type: git
29+ location: https://github.com/joneshf/rollbar-hs
30+
31+library
32+ exposed-modules:
33+ Rollbar.AccessToken
34+ Rollbar.API
35+ Rollbar.Item
36+ Rollbar.Item.Body
37+ Rollbar.Item.CodeVersion
38+ Rollbar.Item.Data
39+ Rollbar.Item.Environment
40+ Rollbar.Item.Hardcoded
41+ Rollbar.Item.Internal.Notifier
42+ Rollbar.Item.Internal.Platform
43+ Rollbar.Item.Level
44+ Rollbar.Item.MissingHeaders
45+ Rollbar.Item.Person
46+ Rollbar.Item.Request
47+ Rollbar.Item.Server
48+ Rollbar.Aeson
49+ other-modules:
50+ Paths_rollbar_hs
51+ hs-source-dirs:
52+ src
53+ build-depends:
54+ aeson >=1.1
55+ , base >=4.9
56+ , bytestring >=0.10
57+ , case-insensitive >=1.2
58+ , hostname >=1.0
59+ , http-client >=0.5
60+ , http-conduit >=2.2
61+ , http-types >=0.8.6
62+ , network >=2.6.3
63+ , text >=1.2
64+ , time >=1.6
65+ , unordered-containers >=0.2
66+ , uuid >=1.3
67+ default-language: Haskell2010
68+
69+test-suite doc-test
70+ type: exitcode-stdio-1.0
71+ main-is: Main.hs
72+ other-modules:
73+ Rollbar.Golden
74+ Rollbar.Item.Data.Test
75+ Rollbar.Item.MissingHeaders.Test
76+ Rollbar.Item.Request.Test
77+ Rollbar.QuickCheck
78+ Paths_rollbar_hs
79+ hs-source-dirs:
80+ test
81+ build-depends:
82+ QuickCheck >=2.9
83+ , aeson
84+ , base
85+ , bytestring
86+ , case-insensitive
87+ , hashable
88+ , hspec >=2.4
89+ , hspec-golden-aeson >=0.2
90+ , rollbar-hs
91+ , text
92+ , unordered-containers
93+ default-language: Haskell2010
src/Rollbar/Aeson.hsnew file+22
@@ -0,0 +1,22 @@
1+{-# LANGUAGE CPP #-}
2+
3+module Rollbar.Aeson
4+ ( Key
5+ , textToKey
6+ ) where
7+
8+import Data.Text (Text)
9+#if MIN_VERSION_aeson(2,0,0)
10+import Data.Aeson.Key (Key)
11+import qualified Data.Aeson.Key as Key
12+#else
13+#endif
14+
15+#if MIN_VERSION_aeson(2,0,0)
16+textToKey :: Text -> Key
17+textToKey = Key.fromText
18+#else
19+type Key = Text
20+textToKey :: Text -> Key
21+textToKey = id
22+#endif
src/Rollbar/Item.hs+8
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DataKinds #-}
23{-# LANGUAGE DeriveGeneric #-}
34{-# LANGUAGE NamedFieldPuns #-}
@@ -197,10 +198,17 @@ data Item a headers
197198 }
198199 deriving (Eq, Generic, Show)
199200
201+#if MIN_VERSION_aeson(2, 2, 0)
202+itemKVs
203+ :: (KeyValue e kv, RemoveHeaders headers, ToJSON v)
204+ => Item v headers
205+ -> [kv]
206+#else
200207itemKVs
201208 :: (KeyValue kv, RemoveHeaders headers, ToJSON v)
202209 => Item v headers
203210 -> [kv]
211+#endif
204212itemKVs Item{accessToken, itemData} =
205213 [ "access_token" .= accessToken
206214 , "data" .= itemData
src/Rollbar/Item/Body.hs+10−4
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DeriveGeneric #-}
23{-# LANGUAGE GeneralizedNewtypeDeriving #-}
34{-# LANGUAGE NamedFieldPuns #-}
@@ -33,7 +34,7 @@ import Data.Aeson
3334 , (.=)
3435 )
3536import Data.Aeson.Encoding (pair)
36−import Data.Aeson.Types (typeMismatch)
37+import Data.Aeson.Types (explicitParseField, typeMismatch)
3738import Data.String (IsString)
3839
3940import GHC.Generics (Generic)
@@ -52,16 +53,21 @@ data Body arbitrary
5253 }
5354 deriving (Eq, Generic, Show)
5455
56+#if MIN_VERSION_aeson(2, 2, 0)
57+bodyKVs :: (KeyValue e kv, ToJSON v) => Body v -> [kv]
58+#else
5559bodyKVs :: (KeyValue kv, ToJSON v) => Body v -> [kv]
60+#endif
5661bodyKVs Message{messageBody, messageData} =
5762 [ "body" .= messageBody
5863 , "data" .= messageData
5964 ]
6065
6166instance FromJSON arbitrary => FromJSON (Body arbitrary) where
62− parseJSON (Object o') = do
63− o <- o' .: "message"
64− Message <$> o .: "body" <*> o .: "data"
67+ parseJSON (Object o') = explicitParseField parseMessage o' "message"
68+ where
69+ parseMessage (Object o) = Message <$> o .: "body" <*> o .: "data"
70+ parseMessage v = typeMismatch "Body arbitrary (message)" v
6571 parseJSON v = typeMismatch "Body arbitrary" v
6672
6773instance ToJSON arbitrary => ToJSON (Body arbitrary) where
src/Rollbar/Item/MissingHeaders.hs+8−3
@@ -3,6 +3,7 @@
33{-# LANGUAGE KindSignatures #-}
44{-# LANGUAGE ScopedTypeVariables #-}
55{-# LANGUAGE TypeOperators #-}
6+{-# LANGUAGE CPP #-}
67
78{-|
89 Module : Rollbar.Item.MissingHeaders
@@ -20,6 +21,7 @@ module Rollbar.Item.MissingHeaders
2021
2122import Data.Aeson
2223 (FromJSON, KeyValue, ToJSON, object, parseJSON, toJSON, (.=))
24+import Rollbar.Aeson
2325import Data.Bifunctor (bimap)
2426import Data.CaseInsensitive (mk, original)
2527import Data.Maybe (catMaybes)
@@ -31,7 +33,6 @@ import Network.HTTP.Types (Header, RequestHeaders)
3133
3234import qualified Data.ByteString as BS
3335import qualified Data.ByteString.Char8 as BSC8
34−import qualified Data.Text as T
3536import qualified Data.Text.Encoding as TE
3637
3738-- | The request headers with some missing
@@ -63,7 +64,11 @@ instance FromJSON (MissingHeaders headers) where
6364instance RemoveHeaders headers => ToJSON (MissingHeaders headers) where
6465 toJSON = object . catMaybes . requestHeadersKVs . removeHeaders
6566
67+#if MIN_VERSION_aeson(2, 2, 0)
68+requestHeadersKVs :: forall e kv. KeyValue e kv => RequestHeaders -> [Maybe kv]
69+#else
6670requestHeadersKVs :: forall kv. KeyValue kv => RequestHeaders -> [Maybe kv]
71+#endif
6772requestHeadersKVs = fmap go
6873 where
6974 go :: Header -> Maybe kv
@@ -72,5 +77,5 @@ requestHeadersKVs = fmap go
7277 val <- myDecodeUtf8 val'
7378 pure (key .= val)
7479
75−myDecodeUtf8 :: BS.ByteString -> Maybe T.Text
76−myDecodeUtf8 = either (const Nothing) Just . TE.decodeUtf8'
80+myDecodeUtf8 :: BS.ByteString -> Maybe Key
81+myDecodeUtf8 = either (const Nothing) (Just . textToKey) . TE.decodeUtf8'
src/Rollbar/Item/Request.hs+12−2
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DeriveGeneric #-}
23{-# LANGUAGE GeneralizedNewtypeDeriving #-}
34{-# LANGUAGE NamedFieldPuns #-}
@@ -48,6 +49,7 @@ import GHC.Generics (Generic)
4849import Network.HTTP.Types (Query)
4950import Network.Socket (SockAddr(SockAddrInet), tupleToHostAddress)
5051
52+import Rollbar.Aeson
5153import Rollbar.Item.MissingHeaders
5254
5355import Text.Read (readMaybe)
@@ -96,14 +98,18 @@ instance ToJSON Get where
9698 toJSON (Get q) = object . catMaybes . queryKVs $ q
9799 toEncoding (Get q) = pairs . mconcat . catMaybes . queryKVs $ q
98100
99−queryKVs :: forall kv. (KeyValue kv) => Query -> [Maybe kv]
101+#if MIN_VERSION_aeson(2, 2, 0)
102+queryKVs :: forall e kv. KeyValue e kv => Query -> [Maybe kv]
103+#else
104+queryKVs :: forall kv. KeyValue kv => Query -> [Maybe kv]
105+#endif
100106queryKVs = fmap go
101107 where
102108 go :: (BS.ByteString, Maybe BS.ByteString) -> Maybe kv
103109 go (key', val') = do
104110 key <- myDecodeUtf8 key'
105111 let val = val' >>= myDecodeUtf8
106− pure (key .= val)
112+ pure (textToKey key .= val)
107113
108114-- | The HTTP Verb
109115newtype Method
@@ -149,7 +155,11 @@ instance ToJSON IP where
149155 toJSON (IP ip) = toJSON (show ip)
150156 toEncoding (IP ip) = toEncoding (show ip)
151157
158+#if MIN_VERSION_aeson(2, 2, 0)
159+requestKVs :: (KeyValue e kv, RemoveHeaders headers) => Request headers -> [kv]
160+#else
152161requestKVs :: (KeyValue kv, RemoveHeaders headers) => Request headers -> [kv]
162+#endif
153163requestKVs Request{get, headers, method, queryString, rawBody, url, userIP} =
154164 [ "body" .= rawBody
155165 , "GET" .= get
src/Rollbar/Item/Server.hs+5
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DeriveGeneric #-}
23{-# LANGUAGE GeneralizedNewtypeDeriving #-}
34{-# LANGUAGE NamedFieldPuns #-}
@@ -57,7 +58,11 @@ data Server
5758 }
5859 deriving (Eq, Generic, Show)
5960
61+#if MIN_VERSION_aeson(2, 2, 0)
62+serverKVs :: KeyValue e kv => Server -> [Maybe kv]
63+#else
6064serverKVs :: KeyValue kv => Server -> [Maybe kv]
65+#endif
6166serverKVs Server{branch, host, root, serverCodeVersion} =
6267 [ ("host" .=) <$> host
6368 , ("root" .=) <$> root
stack.yamlnew file+6
@@ -0,0 +1,6 @@
1+resolver: lts-23.7
2+packages:
3+- .
4+
5+nix:
6+ packages: [ zlib ]
test/Rollbar/Item/Data/Test.hs+1−1
@@ -39,6 +39,6 @@ requiredBodyKeys = ["trace", "trace_chain", "message", "crash_report"]
3939key :: Text -> Value -> [(Text, Value)]
4040key k = \case
4141 Object o -> case Data.HashMap.Strict.lookupDefault Null k o of
42− Object o -> Data.HashMap.Strict.toList o
42+ Object o' -> Data.HashMap.Strict.toList o'
4343 _ -> mempty
4444 _ -> mempty
test/Rollbar/Item/MissingHeaders/Test.hs+2
@@ -9,6 +9,7 @@ module Rollbar.Item.MissingHeaders.Test where
99import Data.Aeson (Value (Object), decode', encode,
1010 toJSON)
1111import Data.Functor (void)
12+import Data.Hashable
1213import Data.HashSet (HashSet)
1314import Data.Text (Text)
1415
@@ -91,4 +92,5 @@ keys = \case
9192 Object o -> Data.HashSet.fromMap (void o)
9293 _ -> mempty
9394
95+notMember :: (Eq a, Hashable a) => a -> HashSet a -> Bool
9496notMember x = not . Data.HashSet.member x