Safe Haskell | Safe-Infered |
---|
This module provides remote monitoring of a running process over HTTP. It can be used to run an HTTP server that provides both a web-based user interface and a machine-readable API (e.g. JSON). The former can be used by a human to get an overview of what the program is doing and the latter can be used be automated monitoring tools.
Typical usage is to start the monitoring server at program startup
main = do forkServer "localhost" 8000 ...
and then periodically check the stats using a web browser or a command line tool (e.g. curl)
$ curl -H "Accept: application/json" http://localhost:8000/
- data Server
- serverThreadId :: Server -> ThreadId
- forkServer :: ByteString -> Int -> IO Server
- getCounter :: Text -> Server -> IO Counter
Required configuration
To use this module you must first enable GC statistics collection in the run-time system. To enable GC statistics collection, either run your program with
+RTS -T
or compile it with
-with-rtsopts=-T
The runtime overhead of -T
is very small so it's safe to always
leave it enabled.
REST API
To use the machine-readable REST API, send an GET request to the
host and port passed to forkServer
and set the Accept header to
"application/json".
The server returns a JSON object with one attribute per
user-defined counter (created using getCounter
). In addition,
the object includes the following attributes:
bytes_allocated
- Total number of bytes allocated
num_gcs
- Number of garbage collections performed
max_bytes_used
- Maximum number of live bytes seen so far
num_bytes_usage_samples
- Number of byte usage samples taken
cumulative_bytes_used
- Sum of all byte usage samples, can be
used with
numByteUsageSamples
to calculate averages with arbitrary weighting (if you are sampling this record multiple times). bytes_copied
- Number of bytes copied during GC
current_bytes_used
- Current number of live bytes
current_bytes_slop
- Current number of bytes lost to slop
max_bytes_slop
- Maximum number of bytes lost to slop at any one time so far
peak_megabytes_allocated
- Maximum number of megabytes allocated
mutator_cpu_seconds
- CPU time spent running mutator threads. This does not include any profiling overhead or initialization.
mutator_wall_seconds
- Wall clock time spent running mutator threads. This does not include initialization.
gc_cpu_seconds
- CPU time spent running GC
gc_wall_seconds
- Wall clock time spent running GC
cpu_seconds
- Total CPU time elapsed since program start
wall_seconds
- Total wall clock time elapsed since start
par_avg_bytes_copied
- Number of bytes copied during GC, minus
space held by mutable lists held by the capabilities. Can be used
with
parMaxBytesCopied
to determine how well parallel GC utilized all cores. par_max_bytes_copied
- Sum of number of bytes copied each GC by
the most active GC thread each GC. The ratio of
parAvgBytesCopied
divided byparMaxBytesCopied
approaches 1 for a maximally sequential run and approaches the number of threads (set by the RTS flag-N
) for a maximally parallel run.
It's possible to retrieve individual counters by
- appending the counter name to the URL (e.g. "/my_counter"), and
- setting the Accept header to "text/plain".
The reason that single counters cannot be returned as JSON is that JSON doesn't allow for certain values (e.g. integers) to occur at the top-level.
The monitoring server
A handle that can be used to control the monitoring server.
Created by forkServer
.
serverThreadId :: Server -> ThreadIdSource
The thread ID of the server. You can kill the server by killing this thread (i.e. by throwing it an asynchronous exception.)
:: ByteString | Host to listen on (e.g. "localhost") |
-> Int | Port to listen on (e.g. 8000) |
-> IO Server |
Start an HTTP server in a new thread. The server replies to GET requests to the given host and port. The host argument can be either a numeric network address (dotted quad for IPv4, colon-separated hex for IPv6) or a hostname (e.g. "localhost"). The client can control the Content-Type used in responses by setting the Accept header. At the moment two content types are available: "application/json" and "text/html".
User-defined counters
The monitoring server can store and serve user-defined, integer-valued counters. Each counter is associated with a name, which is used when the counter is displayed in the UI or returned in a JSON object.
To create and use a counter, simply call getCounter
to create it
and then call e.g. inc
or add
to modify its
value. Example:
main = do handle <- forkServer "localhost" 8000 counter <- getCounter "iterations" handle let loop n = do inc counter loop loop
Return the counter associated with the given name and server.
Multiple calls to getCounter
with the same arguments will return
the same counter. The first time getCounter
is called for a
given name and server, a new, zero-initialized counter will be
returned.