Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/3-bug-fixes/metrics-handlers
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ensure that all endpoints have a correct handler in prometheus metrics
3 changes: 2 additions & 1 deletion libs/extended/extended.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: 18004f2559de4d4ac804d0a36a2d2780d0bbc10d79ebf78f337c9e6ba7a4ff3f
-- hash: 65015665656bc1ae721971ef3e88ed707aa7a2be02ba04cf4aab39ac6188714a

name: extended
version: 0.1.0
Expand Down Expand Up @@ -42,6 +42,7 @@ library
, extra
, http-types
, imports
, metrics-wai
, optparse-applicative
, servant
, servant-server
Expand Down
1 change: 1 addition & 0 deletions libs/extended/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies:
# for servant's 'ReqBodyCustomError' type defined here.
- errors
- http-types
- metrics-wai
- servant
- servant-server
- servant-swagger
Expand Down
4 changes: 4 additions & 0 deletions libs/extended/src/Servant/API/Extended.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module Servant.API.Extended where

import qualified Data.ByteString.Lazy as BL
import Data.EitherR (fmapL)
import Data.Metrics.Servant
import Data.String.Conversions (cs)
import Data.Typeable
import GHC.TypeLits
Expand Down Expand Up @@ -113,3 +114,6 @@ instance
HasSwagger (ReqBodyCustomError cts tag a :> api)
where
toSwagger Proxy = toSwagger (Proxy @(ReqBody' '[Required, Strict] cts a :> api))

instance RoutesToPaths rest => RoutesToPaths (ReqBodyCustomError' mods list tag a :> rest) where
getRoutes = getRoutes @rest
4 changes: 3 additions & 1 deletion libs/metrics-wai/metrics-wai.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: 1fdffa4b08c579feb0c18fe4c3c12c81ee6c503b5672735f7df5a02e02081c67
-- hash: aefa1a394ca2caa5cad577e67967aace67b79d4c94afeba4dd399b77de826a6c

name: metrics-wai
version: 0.5.7
Expand Down Expand Up @@ -40,6 +40,7 @@ library
, imports
, metrics-core >=0.3
, servant
, servant-multipart
, string-conversions
, text >=0.11
, wai >=3
Expand Down Expand Up @@ -70,6 +71,7 @@ test-suite unit
, metrics-core >=0.3
, metrics-wai
, servant
, servant-multipart
, string-conversions
, text >=0.11
, wai >=3
Expand Down
1 change: 1 addition & 0 deletions libs/metrics-wai/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies:
- metrics-core >=0.3
- containers
- servant
- servant-multipart
- string-conversions
- text >=0.11
- wai >=3
Expand Down
61 changes: 43 additions & 18 deletions libs/metrics-wai/src/Data/Metrics/Servant.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import Network.Wai.Middleware.Prometheus
import qualified Network.Wai.Middleware.Prometheus as Promth
import Network.Wai.Routing (Routes, prepare)
import Servant.API
import Servant.Multipart

-- | This does not catch errors, so it must be called outside of 'WU.catchErrors'.
servantPrometheusMiddleware :: forall proxy api. (RoutesToPaths api) => proxy api -> Wai.Middleware
Expand Down Expand Up @@ -79,41 +80,65 @@ class RoutesToPaths routes where

-- "seg" :> routes
instance
{-# OVERLAPPING #-}
( KnownSymbol seg,
RoutesToPaths segs
) =>
(KnownSymbol seg, RoutesToPaths segs) =>
RoutesToPaths (seg :> segs)
where
getRoutes = [Node (Right . cs $ symbolVal (Proxy @seg)) (getRoutes @segs)]

-- <capture> :> routes
instance
{-# OVERLAPPING #-}
( KnownSymbol capture,
RoutesToPaths segs
) =>
(KnownSymbol capture, RoutesToPaths segs) =>
RoutesToPaths (Capture' mods capture a :> segs)
where
getRoutes = [Node (Left (cs (":" <> symbolVal (Proxy @capture)))) (getRoutes @segs)]

instance
(RoutesToPaths rest) =>
RoutesToPaths (Header' mods name a :> rest)
where
getRoutes = getRoutes @rest

instance
(RoutesToPaths rest) =>
RoutesToPaths (ReqBody' mods cts a :> rest)
where
getRoutes = getRoutes @rest

instance
(RoutesToPaths rest) =>
RoutesToPaths (Summary summary :> rest)
where
getRoutes = getRoutes @rest

instance
RoutesToPaths rest =>
RoutesToPaths (QueryParam' mods name a :> rest)
where
getRoutes = getRoutes @rest

instance RoutesToPaths rest => RoutesToPaths (MultipartForm tag a :> rest) where
getRoutes = getRoutes @rest

instance
RoutesToPaths rest =>
RoutesToPaths (Description desc :> rest)
where
getRoutes = getRoutes @rest

instance RoutesToPaths (Verb method status cts a) where
getRoutes = []

instance RoutesToPaths (NoContentVerb method) where
getRoutes = []

-- route :<|> routes
instance
{-# OVERLAPPING #-}
( RoutesToPaths route,
RoutesToPaths routes
) =>
RoutesToPaths (route :<|> routes)
where
getRoutes = getRoutes @route <> getRoutes @routes

instance
{-# OVERLAPPABLE #-}
( RoutesToPaths segs
) =>
RoutesToPaths (anything :> segs)
where
getRoutes = getRoutes @segs

instance {-# OVERLAPPABLE #-} RoutesToPaths anything where
instance RoutesToPaths Raw where
getRoutes = []
13 changes: 7 additions & 6 deletions libs/wire-api/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ copyright: (c) 2020 Wire Swiss GmbH
license: AGPL-3
dependencies:
- aeson >=0.6
- containers >=0.5
- imports
- types-common >=0.16
- servant-swagger-ui
- case-insensitive
- containers >=0.5
- filepath
- hscim
- imports
- metrics-wai
- saml2-web-sso
- filepath
- servant
- servant-swagger-ui
- types-common >=0.16
library:
source-dirs: src
dependencies:
Expand Down Expand Up @@ -62,7 +64,6 @@ library:
- QuickCheck >=2.14
- quickcheck-instances >=0.3.16
- resourcet
- servant
- servant-client
- servant-client-core
- servant-multipart
Expand Down
4 changes: 4 additions & 0 deletions libs/wire-api/src/Wire/API/ErrorDescription.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Wire.API.ErrorDescription where
import Control.Lens (at, (%~), (.~), (<>~), (?~))
import qualified Data.Aeson as A
import qualified Data.ByteString.Lazy as LBS
import Data.Metrics.Servant
import Data.SOP (I (..), NP (..), NS (..))
import Data.Schema
import Data.Swagger (Swagger)
Expand Down Expand Up @@ -45,6 +46,9 @@ instance
route _ = route (Proxy @api)
hoistServerWithContext _ = hoistServerWithContext (Proxy @api)

instance RoutesToPaths api => RoutesToPaths (CanThrow err :> api) where
getRoutes = getRoutes @api

errorDescriptionAddToSwagger ::
forall (code :: Nat) (label :: Symbol) (desc :: Symbol).
(KnownStatus code, KnownSymbol label, KnownSymbol desc) =>
Expand Down
4 changes: 4 additions & 0 deletions libs/wire-api/src/Wire/API/Routes/MultiVerb.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import qualified Data.ByteString.Lazy as LBS
import Data.Containers.ListUtils
import Data.HashMap.Strict.InsOrd (InsOrdHashMap)
import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
import Data.Metrics.Servant
import Data.Proxy
import Data.SOP
import qualified Data.Sequence as Seq
Expand Down Expand Up @@ -633,3 +634,6 @@ instance
method = reflectMethod (Proxy @method)

hoistClientMonad _ _ f = f

instance RoutesToPaths (MultiVerb method cs as r) where
getRoutes = []
7 changes: 7 additions & 0 deletions libs/wire-api/src/Wire/API/Routes/Public.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module Wire.API.Routes.Public where
import Control.Lens ((<>~))
import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
import Data.Id as Id
import Data.Metrics.Servant
import Data.Swagger
import GHC.Base (Symbol)
import GHC.TypeLits (KnownSymbol)
Expand Down Expand Up @@ -94,6 +95,9 @@ instance
hoistServerWithContext _ pc nt s =
Servant.hoistServerWithContext (Proxy @(InternalAuth ztype opts :> api)) pc nt s

instance RoutesToPaths api => RoutesToPaths (ZAuthServant ztype opts :> api) where
getRoutes = getRoutes @api

-- FUTUREWORK: Make a PR to the servant-swagger package with this instance
instance ToSchema a => ToSchema (Headers ls a) where
declareNamedSchema _ = declareNamedSchema (Proxy @a)
Expand All @@ -116,3 +120,6 @@ instance HasServer api ctx => HasServer (OmitDocs :> api) ctx where
route _ = route (Proxy :: Proxy api)
hoistServerWithContext _ pc nt s =
hoistServerWithContext (Proxy :: Proxy api) pc nt s

instance RoutesToPaths api => RoutesToPaths (OmitDocs :> api) where
getRoutes = getRoutes @api
9 changes: 9 additions & 0 deletions libs/wire-api/src/Wire/API/Routes/QualifiedCapture.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module Wire.API.Routes.QualifiedCapture
where

import Data.Domain
import Data.Metrics.Servant
import Data.Qualified
import Data.Swagger
import GHC.TypeLits
Expand Down Expand Up @@ -96,3 +97,11 @@ instance
clientWithRoute pm _ req (Qualified value domain) =
clientWithRoute pm (Proxy @(WithDomain mods capture a api)) req domain value
hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy @api) f . cl

instance (RoutesToPaths api, KnownSymbol (AppendSymbol capture "_domain"), KnownSymbol capture) => RoutesToPaths (QualifiedCapture' mods capture a :> api) where
getRoutes =
getRoutes
@( Capture' mods (AppendSymbol capture "_domain") Domain
:> Capture' mods capture a
:> api
)
4 changes: 3 additions & 1 deletion libs/wire-api/test/unit/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import qualified Test.Wire.API.Golden.Protobuf as Golden.Protobuf
import qualified Test.Wire.API.Roundtrip.Aeson as Roundtrip.Aeson
import qualified Test.Wire.API.Roundtrip.ByteString as Roundtrip.ByteString
import qualified Test.Wire.API.Roundtrip.CSV as Roundtrip.CSV
import qualified Test.Wire.API.Routes as Routes
import qualified Test.Wire.API.Swagger as Swagger
import qualified Test.Wire.API.Team.Member as Team.Member
import qualified Test.Wire.API.User as User
Expand All @@ -53,5 +54,6 @@ main =
Golden.Generated.tests,
Golden.Manual.tests,
Golden.FromJSON.tests,
Golden.Protobuf.tests
Golden.Protobuf.tests,
Routes.tests
]
23 changes: 23 additions & 0 deletions libs/wire-api/test/unit/Test/Wire/API/Routes.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Test.Wire.API.Routes where

import Data.Metrics.Servant
import Data.Tree
import Imports
import Servant.API
import qualified Test.Tasty as T
import Test.Tasty.HUnit
import Wire.API.Routes.QualifiedCapture

tests :: T.TestTree
tests =
T.testGroup "Routes" $
[T.testGroup "QualifiedCapture" [testCase "must expose the captures in metrics" qualifiedCaptureMetrics]]

type QualifiedCaptureAPI = "users" :> QualifiedCapture' '[] "uid" Int :> Get '[] Int

qualifiedCaptureMetrics :: Assertion
qualifiedCaptureMetrics =
assertEqual
"match metrics path"
[Node (Right "users") [Node (Left ":uid_domain") [Node (Left ":uid") []]]]
(getRoutes @QualifiedCaptureAPI)
6 changes: 5 additions & 1 deletion libs/wire-api/wire-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: 2d17ec32d1990b4f59c918291cd7a1286d20e5c54ad921ecd5eb9d01b4b9f1c8
-- hash: 2e805d6416bf9f547993a1c6fb55d615479783065d19d63e639ffc443301ecee

name: wire-api
version: 0.1.0
Expand Down Expand Up @@ -142,6 +142,7 @@ library
, iso639 >=0.1
, lens >=4.12
, memory
, metrics-wai
, mime >=0.4
, mtl
, pem >=0.2
Expand Down Expand Up @@ -424,6 +425,7 @@ test-suite wire-api-tests
Test.Wire.API.Roundtrip.Aeson
Test.Wire.API.Roundtrip.ByteString
Test.Wire.API.Roundtrip.CSV
Test.Wire.API.Routes
Test.Wire.API.Swagger
Test.Wire.API.Team.Member
Test.Wire.API.User
Expand Down Expand Up @@ -453,11 +455,13 @@ test-suite wire-api-tests
, iso3166-country-codes
, iso639
, lens
, metrics-wai
, mime
, pem
, pretty
, proto-lens
, saml2-web-sso
, servant
, servant-swagger-ui
, string-conversions
, swagger2
Expand Down