{-# language OverloadedStrings #-}
{-# language CPP #-}
{-# language NumDecimals #-}
module Prometheus.Metric.GHC (
GHCMetrics
, ghcMetrics
, ghcMetricsWithLabels
) where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>))
#endif
import qualified Data.ByteString.UTF8 as BS
import Data.Text (Text)
import Data.Fixed (Fixed, E9)
#if __GLASGOW_HASKELL__ < 804
import GHC.Conc (numSparks, getNumCapabilities)
import GHC.Stats (GCStats(..), getGCStatsEnabled, getGCStats)
#else
import GHC.Stats (RTSStats(..), GCDetails(..), getRTSStatsEnabled, getRTSStats)
#endif
import qualified GHC.Stats as Stats
import Prometheus
data GHCMetrics = GHCMetrics
ghcMetrics :: Metric GHCMetrics
ghcMetrics = ghcMetricsWithLabels []
ghcMetricsWithLabels :: LabelPairs -> Metric GHCMetrics
ghcMetricsWithLabels labels = Metric (do
statsEnabled <-
#if __GLASGOW_HASKELL__ < 804
getGCStatsEnabled
#else
getRTSStatsEnabled
#endif
if statsEnabled
then return (GHCMetrics, do
stats <-
#if __GLASGOW_HASKELL__ < 804
getGCStats
#else
getRTSStats
#endif
concat <$> mapM (\f -> f labels stats) ghcCollectors
)
else return (GHCMetrics, return [])
)
#if __GLASGOW_HASKELL__ < 804
ghcCollectors :: [LabelPairs -> GCStats -> IO [SampleGroup]]
ghcCollectors = [
\labelpairs gcstats -> do
sparkCount <- numSparks
showCollector
"ghc_sparks"
"The number of sparks in the local spark pool."
GaugeType
sparkCount
labelpairs
, \labelpairs gcstats -> do
numCapabilities <- getNumCapabilities
showCollector
"ghc_capabilities"
"The number of threads that can run truly simultaneously."
GaugeType
numCapabilities
labelpairs
, statsCollector
"ghc_allocated_bytes_total"
"Total number of bytes allocated."
CounterType
bytesAllocated
, statsCollector
"ghc_num_gcs"
"The number of garbage collections performed."
CounterType
numGcs
, statsCollector
"ghc_max_used_bytes"
"The maximum number of live bytes seen so far."
GaugeType
maxBytesUsed
, statsCollector
"ghc_cumulative_used_bytes_total"
"The cumulative total bytes used."
CounterType
cumulativeBytesUsed
, statsCollector
"ghc_copied_bytes_total"
"The number of bytes copied during garbage collection."
CounterType
bytesCopied
, statsCollector
"ghc_current_used_bytes"
"The number of current live bytes."
GaugeType
currentBytesUsed
, statsCollector
"ghc_current_slop_bytes"
"The current number of bytes lost to slop."
GaugeType
currentBytesSlop
, statsCollector
"ghc_max_slop_bytes"
"The maximum number of bytes lost to slop so far."
GaugeType
maxBytesSlop
, statsCollector
"ghc_peak_allocated_megabytes"
"The maximum number of megabytes allocated."
GaugeType
peakMegabytesAllocated
, statsCollector
"ghc_mutator_cpu_seconds_total"
"The CPU time spent running mutator threads."
CounterType
mutatorCpuSeconds
, statsCollector
"ghc_mutator_wall_seconds_total"
"The wall clock time spent running mutator threads."
CounterType
mutatorCpuSeconds
, statsCollector
"ghc_gc_cpu_seconds_total"
"The CPU time spent running GC."
CounterType
gcCpuSeconds
, statsCollector
"ghc_gc_wall_seconds_total"
"The wall clock time spent running GC."
CounterType
gcWallSeconds
, statsCollector
"ghc_cpu_seconds_total"
"Total CPU time elapsed since program start."
CounterType
cpuSeconds
, statsCollector
"ghc_wall_seconds_total"
"Total wall clock time elapsed since start."
CounterType
wallSeconds
, statsCollector
"ghc_parallel_copied_bytes_total"
"Number of bytes copied during GC, minus space held by mutable lists held by the capabilities."
CounterType
parTotBytesCopied
, statsCollector
"ghc_parallel_max_copied_bytes_total"
"Sum of number of bytes copied each GC by the most active GC thread each GC."
CounterType
parMaxBytesCopied
]
#else
ghcCollectors :: [LabelPairs -> RTSStats -> IO [SampleGroup]]
ghcCollectors = [
statsCollector
"ghc_gcs_total"
"Total number of GCs"
CounterType
gcs
, statsCollector
"ghc_major_gcs_total"
"Total number of major (oldest generation) GCs"
CounterType
major_gcs
, statsCollector
"ghc_allocated_bytes_total"
"Total bytes allocated"
CounterType
allocated_bytes
, statsCollector
"ghc_max_live_bytes"
"Maximum live data (including large objects + compact regions)"
GaugeType
max_live_bytes
, statsCollector
"ghc_max_large_objects_bytes"
"Maximum live data in large objects"
GaugeType
max_large_objects_bytes
, statsCollector
"ghc_max_compact_bytes"
"Maximum live data in compact regions"
GaugeType
max_compact_bytes
, statsCollector
"ghc_max_slop_bytes"
"Maximum slop"
GaugeType
max_slop_bytes
, statsCollector
"ghc_max_mem_in_use_bytes"
"Maximum memory in use by the RTS"
GaugeType
max_mem_in_use_bytes
, statsCollector
"ghc_cumulative_live_bytes_total"
"Sum of live bytes across all major GCs. Divided by major_gcs gives the average live data over the lifetime of the program."
CounterType
cumulative_live_bytes
, statsCollector
"ghc_copied_bytes_total"
"Sum of copied_bytes across all GCs"
CounterType
copied_bytes
, statsCollector
"ghc_par_copied_bytes_total"
"Sum of copied_bytes across all parallel GCs"
CounterType
par_copied_bytes
, statsCollector
"ghc_cumulative_par_max_copied_bytes_total"
"Sum of par_max_copied_bytes across all parallel GCs"
CounterType
cumulative_par_max_copied_bytes
, statsCollector
"ghc_mutator_cpu_seconds_total"
"Total CPU time used by the mutator"
CounterType
(rtsTimeToSeconds . mutator_cpu_ns)
, statsCollector
"ghc_mutator_elapsed_seconds_total"
"Total elapsed time used by the mutator"
CounterType
(rtsTimeToSeconds . mutator_elapsed_ns)
, statsCollector
"ghc_gc_cpu_seconds_total"
"Total CPU time used by the GC"
CounterType
(rtsTimeToSeconds . gc_cpu_ns)
, statsCollector
"ghc_gc_elapsed_seconds_total"
"Total elapsed time used by the GC"
CounterType
(rtsTimeToSeconds . gc_elapsed_ns)
, statsCollector
"ghc_cpu_seconds_total"
"Total CPU time (at the previous GC)"
CounterType
(rtsTimeToSeconds . cpu_ns)
, statsCollector
"ghc_elapsed_seconds_total"
"Total elapsed time (at the previous GC)"
CounterType
(rtsTimeToSeconds . elapsed_ns)
, statsCollector
"ghc_gcdetails_gen"
"The generation number of this GC"
HistogramType
(gcdetails_gen . gc)
, statsCollector
"ghc_gcdetails_threads"
"Number of threads used in this GC"
GaugeType
(gcdetails_threads . gc)
, statsCollector
"ghc_gcdetails_allocated_bytes"
"Number of bytes allocated since the previous GC"
GaugeType
(gcdetails_allocated_bytes . gc)
, statsCollector
"ghc_gcdetails_live_bytes"
"Total amount of live data in the heap (including large + compact data)"
GaugeType
(gcdetails_live_bytes . gc)
, statsCollector
"ghc_gcdetails_large_objects_bytes"
"Total amount of live data in large objects"
GaugeType
(gcdetails_large_objects_bytes . gc)
, statsCollector
"ghc_gcdetails_compact_bytes"
"Total amount of live data in compact regions"
GaugeType
(gcdetails_compact_bytes . gc)
, statsCollector
"ghc_gcdetails_slop_bytes"
"Total amount of slop (wasted memory)"
GaugeType
(gcdetails_slop_bytes . gc)
, statsCollector
"ghc_gcdetails_mem_in_use_bytes"
"Total amount of memory in use by the RTS"
CounterType
(gcdetails_mem_in_use_bytes . gc)
, statsCollector
"ghc_gcdetails_copied_bytes"
"Total amount of data copied during this GC"
GaugeType
(gcdetails_copied_bytes . gc)
, statsCollector
"ghc_gcdetails_par_max_copied_bytes"
"In parallel GC, the max amount of data copied by any one thread"
GaugeType
(gcdetails_par_max_copied_bytes . gc)
, statsCollector
"ghc_gcdetails_sync_elapsed_seconds"
"The time elapsed during synchronisation before GC"
GaugeType
(rtsTimeToSeconds . gcdetails_sync_elapsed_ns . gc)
, statsCollector
"ghc_gcdetails_cpu_seconds"
"The CPU time used during GC itself"
GaugeType
(rtsTimeToSeconds . gcdetails_cpu_ns . gc)
, statsCollector
"ghc_gcdetails_elapsed_seconds"
"The time elapsed during GC itself"
GaugeType
(rtsTimeToSeconds . gcdetails_elapsed_ns . gc)
]
rtsTimeToSeconds :: Stats.RtsTime -> Fixed E9
rtsTimeToSeconds = (/ 1e9) . fromIntegral
#endif
#if __GLASGOW_HASKELL__ < 804
statsCollector :: Show a
=> Text -> Text -> SampleType -> (GCStats -> a) -> LabelPairs -> GCStats -> IO [SampleGroup]
statsCollector name help sampleType stat labels gcstats =
showCollector name help sampleType (stat gcstats) labels
#else
statsCollector :: Show a
=> Text -> Text -> SampleType -> (RTSStats -> a) -> LabelPairs -> RTSStats -> IO [SampleGroup]
statsCollector name help sampleType stat labels rtsStats =
showCollector name help sampleType (stat rtsStats) labels
#endif
showCollector :: Show a => Text -> Text -> SampleType -> a -> LabelPairs -> IO [SampleGroup]
showCollector name help sampleType value labels = do
let info = Info name help
let valueBS = BS.fromString $ show value
return [SampleGroup info sampleType [Sample name labels valueBS]]