diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, Anchor Systems
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Anchor Systems nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import           Distribution.Simple
+main = defaultMain
diff --git a/bench/Main.hs b/bench/Main.hs
new file mode 100644
--- /dev/null
+++ b/bench/Main.hs
@@ -0,0 +1,42 @@
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE DeriveGeneric        #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE PolyKinds            #-}
+{-# LANGUAGE TypeFamilies         #-}
+{-# LANGUAGE TypeOperators        #-}
+module Main (main) where
+
+import           Control.Concurrent
+import           Data.Text                (Text)
+import           Network.Wai              (Application)
+import           Network.Wai.Handler.Warp
+import           Servant
+import           Servant.Ekg
+import           System.Metrics
+import           System.Process
+
+
+type BenchApi = "hello" :> Capture "name" Text :> Get '[JSON] Text
+
+benchApi :: Proxy BenchApi
+benchApi = Proxy
+
+server :: Server BenchApi
+server = return
+
+servantEkgServer :: IO Application
+servantEkgServer = do
+  store <- newStore
+  ms <- newMVar mempty
+  return $ monitorEndpoints benchApi store ms (serve benchApi server)
+
+benchApp :: IO Application -> IO ()
+benchApp app = withApplication app $ \port ->
+  callCommand $ "wrk -c 30 -d 20s --latency -s bench/wrk.lua -t 2 'http://localhost:" ++ show port ++ "'"
+
+main :: IO ()
+main = do
+  putStrLn "Benchmarking servant-ekg"
+  benchApp servantEkgServer
+  putStrLn "Benchmarking without servant-ekg"
+  benchApp . return $ serve benchApi server
diff --git a/lib/Servant/Ekg.hs b/lib/Servant/Ekg.hs
new file mode 100644
--- /dev/null
+++ b/lib/Servant/Ekg.hs
@@ -0,0 +1,168 @@
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE KindSignatures      #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE RecordWildCards     #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators       #-}
+{-# LANGUAGE PolyKinds           #-}
+module Servant.Ekg where
+
+import           Control.Concurrent.MVar
+import           Control.Exception
+import           Control.Monad
+import qualified Data.HashMap.Strict         as H
+import           Data.Monoid
+import           Data.Proxy
+import           Data.Text                   (Text)
+import qualified Data.Text                   as T
+import qualified Data.Text.Encoding          as T
+import           Data.Time.Clock
+import           GHC.TypeLits
+import           Network.HTTP.Types          (Method, Status (..))
+import           Network.Wai
+import           Servant.API
+import           System.Metrics
+import qualified System.Metrics.Counter      as Counter
+import qualified System.Metrics.Distribution as Distribution
+import qualified System.Metrics.Gauge        as Gauge
+
+gaugeInflight :: Gauge.Gauge -> Middleware
+gaugeInflight inflight application request respond =
+    bracket_ (Gauge.inc inflight)
+             (Gauge.dec inflight)
+             (application request respond)
+
+-- | Count responses with 2XX, 4XX, 5XX, and XXX response codes.
+countResponseCodes
+    :: (Counter.Counter, Counter.Counter, Counter.Counter, Counter.Counter)
+    -> Middleware
+countResponseCodes (c2XX, c4XX, c5XX, cXXX) application request respond =
+    application request respond'
+  where
+    respond' res = count (responseStatus res) >> respond res
+    count Status{statusCode = sc }
+        | 200 <= sc && sc < 300 = Counter.inc c2XX
+        | 400 <= sc && sc < 500 = Counter.inc c4XX
+        | 500 <= sc && sc < 600 = Counter.inc c5XX
+        | otherwise             = Counter.inc cXXX
+
+responseTimeDistribution :: Distribution.Distribution -> Middleware
+responseTimeDistribution dist application request respond =
+    bracket getCurrentTime stop $ const $ application request respond
+  where
+    stop t1 = do
+        t2 <- getCurrentTime
+        let dt = diffUTCTime t2 t1
+        Distribution.add dist $ fromRational $ (*1000) $ toRational dt
+
+data Meters = Meters
+    { metersInflight :: Gauge.Gauge
+    , metersC2XX     :: Counter.Counter
+    , metersC4XX     :: Counter.Counter
+    , metersC5XX     :: Counter.Counter
+    , metersCXXX     :: Counter.Counter
+    , metersTime     :: Distribution.Distribution
+    }
+
+monitorEndpoints
+    :: HasEndpoint api
+    => Proxy api
+    -> Store
+    -> MVar (H.HashMap Text Meters)
+    -> Middleware
+monitorEndpoints proxy store meters application request respond = do
+    let path = case getEndpoint proxy request of
+            Nothing -> "unknown"
+            Just (ps,method) -> T.intercalate "." $ ps <> [T.decodeUtf8 method]
+    Meters{..} <- modifyMVar meters $ \ms -> case H.lookup path ms of
+        Nothing -> do
+            let prefix = "servant.path." <> path <> "."
+            metersInflight <- createGauge (prefix <> "in_flight") store
+            metersC2XX <- createCounter (prefix <> "responses.2XX") store
+            metersC4XX <- createCounter (prefix <> "responses.4XX") store
+            metersC5XX <- createCounter (prefix <> "responses.5XX") store
+            metersCXXX <- createCounter (prefix <> "responses.XXX") store
+            metersTime <- createDistribution (prefix <> "time_ms") store
+            let m = Meters{..}
+            return (H.insert path m ms, m)
+        Just m -> return (ms,m)
+    let application' =
+            responseTimeDistribution metersTime .
+            countResponseCodes (metersC2XX, metersC4XX, metersC5XX, metersCXXX) .
+            gaugeInflight metersInflight $
+            application
+    application' request respond
+
+class HasEndpoint a where
+    getEndpoint :: Proxy a -> Request -> Maybe ([Text], Method)
+
+instance (HasEndpoint (a :: *), HasEndpoint (b :: *)) => HasEndpoint (a :<|> b) where
+    getEndpoint _ req =
+        getEndpoint (Proxy :: Proxy a) req `mplus`
+        getEndpoint (Proxy :: Proxy b) req
+
+instance (KnownSymbol (path :: Symbol), HasEndpoint (sub :: *))
+    => HasEndpoint (path :> sub) where
+    getEndpoint _ req =
+        case pathInfo req of
+            p:ps | p == T.pack (symbolVal (Proxy :: Proxy path)) -> do
+                (end, method) <- getEndpoint (Proxy :: Proxy sub) req{ pathInfo = ps }
+                return (p:end, method)
+            _ -> Nothing
+
+instance (KnownSymbol (capture :: Symbol), HasEndpoint (sub :: *))
+    => HasEndpoint (Capture capture a :> sub) where
+    getEndpoint _ req =
+        case pathInfo req of
+            _:ps -> do
+                (end, method) <- getEndpoint (Proxy :: Proxy sub) req{ pathInfo = ps }
+                let p = T.pack $ (':':) $ symbolVal (Proxy :: Proxy capture)
+                return (p:end, method)
+            _ -> Nothing
+
+instance HasEndpoint (sub :: *) => HasEndpoint (Header h a :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (QueryParam (h :: Symbol) a :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (QueryParams (h :: Symbol) a :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (QueryFlag h :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (ReqBody cts a :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (RemoteHost :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (IsSecure :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (HttpVersion :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (Vault :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance HasEndpoint (sub :: *) => HasEndpoint (WithNamedContext x y sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+
+instance ReflectMethod method => HasEndpoint (Verb method status cts a) where
+    getEndpoint _ req = case pathInfo req of
+        [] | requestMethod req == method -> Just ([], method)
+        _ -> Nothing
+      where method = reflectMethod (Proxy :: Proxy method)
+
+instance HasEndpoint (Raw) where
+    getEndpoint _ _ = Just ([],"RAW")
+
+#if MIN_VERSION_servant(0,8,1)
+instance HasEndpoint (sub :: *) => HasEndpoint (CaptureAll (h :: Symbol) a :> sub) where
+    getEndpoint _ = getEndpoint (Proxy :: Proxy sub)
+#endif
diff --git a/servant-ekg.cabal b/servant-ekg.cabal
new file mode 100644
--- /dev/null
+++ b/servant-ekg.cabal
@@ -0,0 +1,66 @@
+name:                servant-ekg
+version:             0.2.0.0
+synopsis:            Helpers for using ekg with servant
+description:         Helpers for using ekg with servant
+license:             BSD3
+license-file:        LICENSE
+author:              Anchor Engineering <engineering@lists.anchor.net.au>, Servant Contributors
+maintainer:          Servant Contributors <haskell-servant-maintainers@googlegroups.com>
+category:            System
+build-type:          Simple
+cabal-version:       >=1.10
+
+source-repository HEAD
+  type: git
+  location: https://github.com/servant/servant-ekg.git
+
+library
+  exposed-modules:     Servant.Ekg
+  hs-source-dirs:      lib
+  build-depends:       base >=4.7 && < 4.10
+                     , ekg-core
+                     , servant > 0.5 && < 0.10
+                     , http-types
+                     , text
+                     , time
+                     , unordered-containers
+                     , wai
+  default-language:    Haskell2010
+
+test-suite spec
+  type: exitcode-stdio-1.0
+  ghc-options: -Wall
+  default-language: Haskell2010
+  hs-source-dirs: test
+  main-is: Spec.hs
+  build-depends:      base == 4.*
+                    , aeson
+                    , ekg
+                    , ekg-core
+                    , servant-ekg
+                    , servant-server
+                    , servant-client
+                    , servant
+                    , http-client
+                    , text
+                    , wai
+                    , warp >= 3.2.4 && < 3.3
+                    , hspec == 2.*
+                    , unordered-containers
+                    , transformers
+
+executable bench
+  hs-source-dirs: bench
+  main-is: Main.hs
+  ghc-options: -Wall -threaded -O2
+  default-language: Haskell2010
+  build-depends:      base == 4.*
+                    , aeson
+                    , ekg
+                    , ekg-core
+                    , servant-ekg
+                    , servant-server
+                    , text
+                    , wai
+                    , warp >= 3.2.4 && < 3.3
+                    , process
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
