{-# LANGUAGE RecordWildCards, OverloadedStrings #-} module Network.Wai.Application.Monitoring ( monitorGC , monitorGCResponse , encodeGCStats ) where import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Resource (ResourceT) import qualified Data.HashMap.Strict as M import qualified GHC.Stats as Stats import Network.HTTP.Types (status200) import Network.Wai (Application, Response(ResponseBuilder)) import Blaze.ByteString.Builder (fromLazyByteString) import Data.Aeson (toJSON, Value(Object)) import Data.Aeson.Encode (encode) monitorGCResponse :: ResourceT IO Response monitorGCResponse = do stats <- liftIO Stats.getGCStats return $ ResponseBuilder status200 [("Content-Type", "application/json")] $ fromLazyByteString $ encode $ encodeGCStats stats monitorGC :: Application monitorGC = const monitorGCResponse encodeGCStats :: Stats.GCStats -> Value encodeGCStats (Stats.GCStats {..}) = Object $ M.fromList [("counters", counters), ("gauges", gauges)] where counters = Object $ M.fromList [ ("bytes_allocated" , toJSON bytesAllocated) , ("num_gcs" , toJSON numGcs) , ("num_bytes_usage_samples" , toJSON numByteUsageSamples) , ("cumulative_bytes_used" , toJSON cumulativeBytesUsed) , ("bytes_copied" , toJSON bytesCopied) , ("mutator_cpu_seconds" , toJSON mutatorCpuSeconds) , ("mutator_wall_seconds" , toJSON mutatorWallSeconds) , ("gc_cpu_seconds" , toJSON gcCpuSeconds) , ("gc_wall_seconds" , toJSON gcWallSeconds) , ("cpu_seconds" , toJSON cpuSeconds) , ("wall_seconds" , toJSON wallSeconds) ] gauges = Object $ M.fromList [ ("max_bytes_used" , toJSON maxBytesUsed) , ("current_bytes_used" , toJSON currentBytesUsed) , ("current_bytes_slop" , toJSON currentBytesSlop) , ("max_bytes_slop" , toJSON maxBytesSlop) , ("peak_megabytes_allocated" , toJSON $ peakMegabytesAllocated*1024*1024) , ("par_avg_bytes_copied" , toJSON parAvgBytesCopied) , ("par_max_bytes_copied" , toJSON parMaxBytesCopied) ]