To set up a Servant/WAI application with monitoring, we will first scaffold a servant application using stack.
> stack new servant-prometheus \https://raw.githubusercontent.com/commercialhaskell/stack-templates/8cb4889fb7c502c18f6f9ecf9cd62aef58589c21/servant.hsfiles \--resolver nightly-2016-05-21
To instrument our servant application, add the following
three dependencies to servant-prometheus.cabal
under the
build-depends
of the library
.
, wai-middleware-prometheus >= 0.1.0.1, prometheus-client >= 0.1.0.1, prometheus-metrics-ghc >= 0.1.0.1
In src/Lib.hs
we need the following 3 imports. They are
fully qualified for clarity.
import Network.Wai.Middleware.Prometheus (prometheus, PrometheusSettings(..))import Prometheus (register)import Prometheus.Metric.GHC (ghcMetrics)
All of our work will be in the startApp
function defined
in the same file. Currently, startApp
is defined as
run 8080 app
. We are going to change that to the
following.
startApp = doregister ghcMetricslet promMiddleware = prometheus $ PrometheusSettings ["metrics"] True Truerun 8080 $ promMiddleware $ app
We also need {-# LANGUAGE OverloadedStrings #-}
for the
["metrics"]
literal.
Finally, to actually enable consumption of GHC metrics, we
need to include the -T
flag in our executable. The
executable
's ghc-options
becomes:
ghc-options: -threaded -rtsopts -with-rtsopts=-TN
After building and running, the servant server should be providing prometheus metrics at /metrics.
stack install --only-dependenciesstack buildstack exec servant-prometheus-exe
All three of the packages we added as dependencies come from fimad/prometheus-haskell.
localhost:8080/metrics should now have the following output, which can be scraped by Prometheus.
http_
prefixed metrics come from the WAI middlewareghc_
prefixed metrics come from ghcMetrics
# HELP http_request_duration_microseconds The HTTP request latencies in microseconds.# TYPE http_request_duration_microseconds summaryhttp_request_duration_microseconds{handler="app",quantile="0.5"} 258.0http_request_duration_microseconds{handler="app",quantile="0.9"} 258.0http_request_duration_microseconds{handler="app",quantile="0.99"} 258.0http_request_duration_microseconds_sum{handler="app"} 258.0http_request_duration_microseconds_count{handler="app"} 1# HELP ghc_sparks The number of sparks in the local spark pool.# TYPE ghc_sparks gaugeghc_sparks 0# HELP ghc_capabilities The number of threads that can run truly simultaneously.# TYPE ghc_capabilities gaugeghc_capabilities 1# HELP ghc_bytes_allocated Total number of bytes allocated.# TYPE ghc_bytes_allocated gaugeghc_bytes_allocated 249136# HELP ghc_num_gcs The number of garbage collections performed.# TYPE ghc_num_gcs gaugeghc_num_gcs 3# HELP ghc_max_bytes_used The maximum number of live bytes seen so far.# TYPE ghc_max_bytes_used gaugeghc_max_bytes_used 65576# HELP ghc_cumulative_bytes_used The cumulative total bytes used.# TYPE ghc_cumulative_bytes_used gaugeghc_cumulative_bytes_used 149136# HELP ghc_bytes_copied The number of bytes copied during garbage collection.# TYPE ghc_bytes_copied gaugeghc_bytes_copied 76344# HELP ghc_current_bytes_used The number of current live bytes.# TYPE ghc_current_bytes_used gaugeghc_current_bytes_used 65504# HELP ghc_current_bytes_slop The current number of bytes lost to slop.# TYPE ghc_current_bytes_slop gaugeghc_current_bytes_slop 0# HELP ghc_max_bytes_slop The maximum number of bytes lost to slop so far.# TYPE ghc_max_bytes_slop gaugeghc_max_bytes_slop 8152# HELP ghc_peak_megabytes_allocated The maximum number of megabytes allocated.# TYPE ghc_peak_megabytes_allocated gaugeghc_peak_megabytes_allocated 1# HELP ghc_mutator_cpu_seconds The CPU time spent running mutator threads.# TYPE ghc_mutator_cpu_seconds gaugeghc_mutator_cpu_seconds 1.471e-3# HELP ghc_mutator_wall_seconds The wall clock time spent running mutator threads.# TYPE ghc_mutator_wall_seconds gaugeghc_mutator_wall_seconds 1.48e-3# HELP ghc_gc_cpu_seconds The CPU time spent running GC.# TYPE ghc_gc_cpu_seconds gaugeghc_gc_cpu_seconds 1.428e-3# HELP ghc_gc_wall_seconds The wall clock time spent running GC.# TYPE ghc_gc_wall_seconds gaugeghc_gc_wall_seconds 1.781416e-3# HELP ghc_cpu_seconds Total CPU time elapsed since program start.# TYPE ghc_cpu_seconds gaugeghc_cpu_seconds 0.352497# HELP ghc_wall_seconds Total wall clock time elapsed since start.# TYPE ghc_wall_seconds gaugeghc_wall_seconds 28.681236189# HELP ghc_parallel_total_bytes_copied Number of bytes copied during GC, minus space held by mutable lists held by the capabilities.# TYPE ghc_parallel_total_bytes_copied gaugeghc_parallel_total_bytes_copied 0# HELP ghc_parallel_max_bytes_copied Sum of number of bytes copiedeach GC by the most active GC thread each GC.# TYPE ghc_parallel_max_bytes_copied gaugeghc_parallel_max_bytes_copied 0