ekg-core-0.1.0.3: Tracking of system metrics

Safe HaskellNone
LanguageHaskell2010

System.Metrics

Contents

Description

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.

Synopsis

Naming metrics

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

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

data Store Source

A mutable metric store.

newStore :: IO Store Source

Create a new, empty metric store.

Registering metrics

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.

registerCounter Source

Arguments

:: Text

Counter name

-> IO Int64

Action to read the current metric value

-> Store

Metric store

-> IO () 

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

registerGauge Source

Arguments

:: Text

Gauge name

-> IO Int64

Action to read the current metric value

-> Store

Metric store

-> IO () 

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

registerLabel Source

Arguments

:: Text

Label name

-> IO Text

Action to read the current metric value

-> Store

Metric store

-> IO () 

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

registerDistribution Source

Arguments

:: Text

Distribution name

-> IO Stats

Action to read the current metric value

-> Store

Metric store

-> IO () 

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

registerGroup Source

Arguments

:: HashMap Text (a -> Value)

Metric names and getter functions.

-> IO a

Action to sample the metric group

-> Store

Metric store

-> 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.

createCounter Source

Arguments

:: Text

Counter name

-> Store

Metric store

-> IO Counter 

Create and register a zero-initialized counter.

createGauge Source

Arguments

:: Text

Gauge name

-> Store

Metric store

-> IO Gauge 

Create and register a zero-initialized gauge.

createLabel Source

Arguments

:: Text

Label name

-> Store

Metric store

-> IO Label 

Create and register an empty label.

createDistribution Source

Arguments

:: Text

Distribution name

-> Store

Metric store

-> IO Distribution 

Create and register an event tracker.

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.

registerGcMetrics :: Store -> IO () Source

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.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.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.

Sampling metrics

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.

type Sample = HashMap Text Value Source

A sample of some metrics.

sampleAll :: Store -> IO Sample Source

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.

data Value Source

The value of a sampled metric.

Instances