HORIZON HASKELLDocslts/ghc-9.14.xd82dee82026-10-12Search names, modules, packages, or :: a typeCtrl K

GHC 9.14.1 · lts/ghc-9.14.x · d82dee8 · 2026-10-12

Moduleekg-core-0.1.2.0Haskell2010

System.Metrics

A module for defining metrics that can be monitored.

Metrics are used to monitor program behavior and performance. All metrics have

  • a name, and

  • a way to get the metric's current value.

This module provides a way to register metrics in a global "metric store". The store can then be used to get a snapshot of all metrics. The store also serves as a central place to keep track of all the program's metrics, both user and library defined.

Here's an example of creating a single counter, used to count the number of request served by a web server:

import System.Metrics
import qualified System.Metrics.Counter as Counter

main = do
    store <- newStore
    requests <- createCounter "myapp.request_count" store
    -- Every time we receive a request:
    Counter.inc requests

This module also provides a way to register a number of predefined metrics that are useful in most applications. See e.g. registerGcMetrics.

  • 3 types
  • 12 values
  • Packageekg-core-0.1.2.0
  • Exports15
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceMetrics.hs

Naming metrics

0 declarations

Compound metric names should be separated using underscores. Example: request_count. Periods in the name imply namespacing. Example: "myapp.users". Some consumers of metrics will use these namespaces to group metrics in e.g. UIs.

Libraries and frameworks that want to register their own metrics should prefix them with a namespace, to avoid collision with user-defined metrics and metrics defined by other libraries. For example, the Snap web framework could prefix all its metrics with "snap.".

It's customary to suffix the metric name with a short string explaining the metric's type e.g. using "_ms" to denote milliseconds.

The metric store

2 declarations

The metric store is a shared store of metrics. It allows several disjoint components (e.g. libraries) to contribute to the set of metrics exposed by an application. Libraries that want to provide a set of metrics should defined a register method, in the style of registerGcMetrics, that registers the metrics in the Store. The register function should document which metrics are registered and their types (i.e. counter, gauge, label, or distribution).

newtypenewtype Store
#

A mutable metric store.

Registering metrics

5 declarations

Before metrics can be sampled they need to be registered with the metric store. The same metric name can only be used once. Passing a metric name that has already been used to one of the register function is an error.

valueregisterCounter
  1. :: Text

    Counter name

  2. -> IO Int64

    Action to read the current metric value

  3. -> Store

    Metric store

  4. -> IO ()
#

Register a non-negative, monotonically increasing, integer-valued metric. The provided action to read the value must be thread-safe. Also see createCounter.

valueregisterGauge
  1. :: Text

    Gauge name

  2. -> IO Int64

    Action to read the current metric value

  3. -> Store

    Metric store

  4. -> IO ()
#

Register an integer-valued metric. The provided action to read the value must be thread-safe. Also see createGauge.

valueregisterLabel
  1. :: Text

    Label name

  2. -> IO Text

    Action to read the current metric value

  3. -> Store

    Metric store

  4. -> IO ()
#

Register a text metric. The provided action to read the value must be thread-safe. Also see createLabel.

valueregisterGroup
  1. :: HashMap Text (a -> Value)

    Metric names and getter functions.

  2. -> IO a

    Action to sample the metric group

  3. -> Store

    Metric store

  4. -> IO ()
#

Register an action that will be executed any time one of the metrics computed from the value it returns needs to be sampled.

When one or more of the metrics listed in the first argument needs to be sampled, the action is executed and the provided getter functions will be used to extract the metric(s) from the action's return value.

The registered action might be called from a different thread and therefore needs to be thread-safe.

This function allows you to sample groups of metrics together. This is useful if

  • you need a consistent view of several metric or

  • sampling the metrics together is more efficient.

For example, sampling GC statistics needs to be done atomically or a GC might strike in the middle of sampling, rendering the values incoherent. Sampling GC statistics is also more efficient if done in "bulk", as the run-time system provides a function to sample all GC statistics at once.

Note that sampling of the metrics is only atomic if the provided action computes a atomically (e.g. if a is a record, the action needs to compute its fields atomically if the sampling is to be atomic.)

Example usage:

{-# LANGUAGE OverloadedStrings #-}
import qualified Data.HashMap.Strict as M
import GHC.Stats
import System.Metrics

main = do
    store <- newStore
    let metrics =
            [ ("num_gcs", Counter . numGcs)
            , ("max_bytes_used", Gauge . maxBytesUsed)
            ]
    registerGroup (M.fromList metrics) getGCStats store

Convenience functions

These functions combined the creation of a mutable reference (e.g. a Counter) with registering that reference in the store in one convenient function.

Predefined metrics

This library provides a number of pre-defined metrics that can easily be added to a metrics store by calling their register function.

valueregisterGcMetrics :: Store -> IO ()
#

Register a number of metrics related to garbage collector behavior.

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.

Registered counters:

rts.gc.bytes_allocated

Total number of bytes allocated

rts.gc.num_gcs

Number of garbage collections performed

rts.gc.num_bytes_usage_samples

Number of byte usage samples taken

rts.gc.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).

rts.gc.bytes_copied

Number of bytes copied during GC

rts.gc.init_cpu_ms

CPU time used by the init phase, in milliseconds. GHC 8.6+ only.

rts.gc.init_wall_ms

Wall clock time spent running the init phase, in milliseconds. GHC 8.6+ only.

rts.gc.mutator_cpu_ms

CPU time spent running mutator threads, in milliseconds. This does not include any profiling overhead or initialization.

rts.gc.mutator_wall_ms

Wall clock time spent running mutator threads, in milliseconds. This does not include initialization.

rts.gc.gc_cpu_ms

CPU time spent running GC, in milliseconds.

rts.gc.gc_wall_ms

Wall clock time spent running GC, in milliseconds.

rts.gc.cpu_ms

Total CPU time elapsed since program start, in milliseconds.

rts.gc.wall_ms

Total wall clock time elapsed since start, in milliseconds.

Registered gauges:

rts.gc.max_bytes_used

Maximum number of live bytes seen so far

rts.gc.max_large_bytes_used

Maximum number of live bytes seen so far just in large ojects

rts.gc.max_compact_bytes_used

Maximum number of live bytes seen so far just in compact regions

rts.gc.current_bytes_used

Current number of live bytes

rts.gc.current_bytes_slop

Current number of bytes lost to slop

rts.gc.max_bytes_slop

Maximum number of bytes lost to slop at any one time so far

rts.gc.peak_megabytes_allocated

Maximum number of megabytes allocated

rts.gc.par_tot_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.

rts.gc.par_avg_bytes_copied

Deprecated alias for

par_tot_bytes_copied

.

rts.gc.par_max_bytes_copied

Sum of number of bytes copied each GC by the most active GC thread each GC. The ratio of

par_tot_bytes_copied

divided by

par_max_bytes_copied

approaches 1 for a maximally sequential run and approaches the number of threads (set by the RTS flag

-N

) for a maximally parallel run. Deprecated by GHC in later versions.

rts.gc.par_balanced_bytes_copied

Sum of balanced data copied by all threads in parallel GC, across all parallel GCs.

rts.gc.nm.sync_cpu_ms

The total CPU time used during the post-mark pause phase of the concurrent nonmoving GC.

rts.gc.nm.sync_elapsed_ms

The total time elapsed during the post-mark pause phase of the concurrent nonmoving GC.

rts.gc.nm.sync_max_elapsed_ms

The maximum elapsed length of any post-mark pause phase of the concurrent nonmoving GC.

rts.gc.nm.cpu_ms

The total CPU time used by the nonmoving GC.

rts.gc.nm.elapsed_ms

The total time elapsed during which there is a nonmoving GC active.

rts.gc.nm.max_elapsed_ms

The maximum time elapsed during any nonmoving GC cycle.

Sampling metrics

3 declarations

The metrics register in the store can be sampled together. Sampling is not atomic. While each metric will be retrieved atomically, the sample is not an atomic snapshot of the system as a whole. See registerGroup for an explanation of how to sample a subset of all metrics atomically.

valuesampleAll :: Store -> IO Sample
#

Sample all metrics. Sampling is not atomic in the sense that some metrics might have been mutated before they're sampled but after some other metrics have already been sampled.