{-# language ForeignFunctionInterface #-}
{-# language NamedFieldPuns #-}
{-# language OverloadedStrings #-}
{-# language RecordWildCards #-}
{-# language ViewPatterns #-}

{-|

This module exposes a @prometheus-client@ "Metric" for exporting information
about the currently running process.

-}
module Prometheus.Metric.Proc ( ProcMetrics(..), procMetrics ) where

import Data.Char ( isSpace )
import Data.Int ( Int64 )
import Data.List ( isPrefixOf )
import Data.Maybe ( catMaybes, maybeToList )
import Data.String ( fromString )
import Data.Text ( Text, unpack )
import Data.Text.IO ( readFile )
import Foreign.C
import Prelude hiding ( readFile )
import Prometheus
import System.Directory ( listDirectory )
import System.FilePath
import System.IO.Unsafe
import System.Posix.Memory ( sysconfPageSize )
import System.Posix.Process ( getProcessID )
import System.Posix.Types ( ProcessID )
import qualified Text.Regex.Applicative as RE
import qualified Text.Regex.Applicative.Common as RE


-- | The tag for 'procMetrics'.
data ProcMetrics =
  ProcMetrics


{-|

Unregistered metrics for the current process. This is to be used with
'Prometheus.register' to register the metrics.

This exports the following:


* @process_cpu_seconds_total@
* @process_start_time_seconds@
* @process_virtual_memory_bytes@
* @process_resident_memory_bytes@

See the official Prometheus documentation for more information on these standard
metrics: https://prometheus.io/docs/instrumenting/writing_clientlibs/#standard-and-runtime-collectors

-}
procMetrics :: Prometheus.Metric ProcMetrics
procMetrics :: Metric ProcMetrics
procMetrics =
  IO (ProcMetrics, IO [SampleGroup]) -> Metric ProcMetrics
forall s. IO (s, IO [SampleGroup]) -> Metric s
Metric ( (ProcMetrics, IO [SampleGroup])
-> IO (ProcMetrics, IO [SampleGroup])
forall (m :: * -> *) a. Monad m => a -> m a
return ( ProcMetrics
ProcMetrics, IO [SampleGroup]
collect ) )


-- | Returns the number of CPU clock ticks per second.
foreign import ccall unsafe
  clk_tck :: CLong


collect :: IO [ SampleGroup ]
collect :: IO [SampleGroup]
collect = do
  ProcessID
pid <-
    IO ProcessID
getProcessID

  Maybe ProcStat
mprocStat <-
      RE Char ProcStat -> [Char] -> Maybe ProcStat
forall s a. RE s a -> [s] -> Maybe a
RE.match RE Char ProcStat
parseProcStat ([Char] -> Maybe ProcStat)
-> (Text -> [Char]) -> Text -> Maybe ProcStat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
unpack (Text -> Maybe ProcStat) -> IO Text -> IO (Maybe ProcStat)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO Text
readFile ( ProcessID -> [Char]
procPidDir ProcessID
pid [Char] -> [Char] -> [Char]
</> [Char]
"stat" )

  SampleGroup
processOpenFds <-
    ProcessID -> IO SampleGroup
collectProcessOpenFds ProcessID
pid

  Maybe SampleGroup
processMaxFds <-
    ProcessID -> IO (Maybe SampleGroup)
collectProcessMaxFds ProcessID
pid

  [SampleGroup] -> IO [SampleGroup]
forall (m :: * -> *) a. Monad m => a -> m a
return
    ( [ SampleGroup
processOpenFds ]
        [SampleGroup] -> [SampleGroup] -> [SampleGroup]
forall a. Semigroup a => a -> a -> a
<> Maybe SampleGroup -> [SampleGroup]
forall a. Maybe a -> [a]
maybeToList Maybe SampleGroup
processMaxFds
        [SampleGroup] -> [SampleGroup] -> [SampleGroup]
forall a. Semigroup a => a -> a -> a
<> (ProcStat -> [SampleGroup]) -> Maybe ProcStat -> [SampleGroup]
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ( ProcStat -> [SampleGroup]
procStatToMetrics ) Maybe ProcStat
mprocStat
    )


collectProcessOpenFds :: ProcessID -> IO SampleGroup
collectProcessOpenFds :: ProcessID -> IO SampleGroup
collectProcessOpenFds ProcessID
pid = do
  ([[Char]] -> SampleGroup) -> IO [[Char]] -> IO SampleGroup
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
    ( Text -> Text -> SampleType -> Int -> SampleGroup
forall a. Show a => Text -> Text -> SampleType -> a -> SampleGroup
metric Text
"process_open_fds" Text
"Number of open file descriptors." SampleType
GaugeType (Int -> SampleGroup)
-> ([[Char]] -> Int) -> [[Char]] -> SampleGroup
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Char]] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length )
    ( [Char] -> IO [[Char]]
listDirectory ( ProcessID -> [Char]
procPidDir ProcessID
pid [Char] -> [Char] -> [Char]
</> [Char]
"fd" ) )


collectProcessMaxFds :: ProcessID -> IO ( Maybe SampleGroup )
collectProcessMaxFds :: ProcessID -> IO (Maybe SampleGroup)
collectProcessMaxFds ProcessID
pid = do
  [[Char]]
limitLines <-
    [Char] -> [[Char]]
lines ([Char] -> [[Char]]) -> (Text -> [Char]) -> Text -> [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
unpack (Text -> [[Char]]) -> IO Text -> IO [[Char]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO Text
readFile ( ProcessID -> [Char]
procPidDir ProcessID
pid [Char] -> [Char] -> [Char]
</> [Char]
"limits" )

  case ([Char] -> Bool) -> [[Char]] -> [[Char]]
forall a. (a -> Bool) -> [a] -> [a]
filter ( [Char]
"Max open files" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` ) [[Char]]
limitLines of
    ( [Char] -> [[Char]]
words -> [Char]
_max : [Char]
_open : [Char]
_files : [Char]
n : [[Char]]
_ ) : [[Char]]
_ ->
      Maybe SampleGroup -> IO (Maybe SampleGroup)
forall (m :: * -> *) a. Monad m => a -> m a
return
        ( SampleGroup -> Maybe SampleGroup
forall a. a -> Maybe a
Just
            ( Text -> Text -> SampleType -> Int -> SampleGroup
forall a. Show a => Text -> Text -> SampleType -> a -> SampleGroup
metric
                Text
"process_max_fds"
                Text
"Maximum number of open file descriptors."
                SampleType
GaugeType
                ( [Char] -> Int
forall a. Read a => [Char] -> a
read [Char]
n :: Int )
            )
        )

    [[Char]]
_ ->
      Maybe SampleGroup -> IO (Maybe SampleGroup)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SampleGroup
forall a. Maybe a
Nothing


procPidDir :: ProcessID -> FilePath
procPidDir :: ProcessID -> [Char]
procPidDir ProcessID
pid =
  [Char]
"/" [Char] -> [Char] -> [Char]
</> [Char]
"proc" [Char] -> [Char] -> [Char]
</> ProcessID -> [Char]
forall a. Show a => a -> [Char]
show ProcessID
pid


procStatToMetrics :: ProcStat -> [ SampleGroup ]
procStatToMetrics :: ProcStat -> [SampleGroup]
procStatToMetrics ProcStat{ Int64
utime :: ProcStat -> Int64
utime :: Int64
utime, Int64
stime :: ProcStat -> Int64
stime :: Int64
stime, Int64
starttime :: ProcStat -> Int64
starttime :: Int64
starttime, Int64
vsize :: ProcStat -> Int64
vsize :: Int64
vsize, Int64
rss :: ProcStat -> Int64
rss :: Int64
rss } =
  [Maybe SampleGroup] -> [SampleGroup]
forall a. [Maybe a] -> [a]
catMaybes
    [ SampleGroup -> Maybe SampleGroup
forall a. a -> Maybe a
Just SampleGroup
process_cpu_seconds_total
    , Maybe SampleGroup
process_start_time_seconds
    , SampleGroup -> Maybe SampleGroup
forall a. a -> Maybe a
Just SampleGroup
process_virtual_memory_bytes
    , SampleGroup -> Maybe SampleGroup
forall a. a -> Maybe a
Just SampleGroup
process_resident_memory_bytes
    ]

  where

    process_cpu_seconds_total :: SampleGroup
process_cpu_seconds_total =
      Text -> Text -> SampleType -> Double -> SampleGroup
forall a. Show a => Text -> Text -> SampleType -> a -> SampleGroup
metric
        Text
"process_cpu_seconds_total"
        Text
"Total user and system CPU time spent in seconds."
        SampleType
CounterType
        ( Int64 -> Double
fromTicks ( Int64
utime Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int64
stime ) )

    process_start_time_seconds :: Maybe SampleGroup
process_start_time_seconds = do
      Int64
btime <-
        Maybe Int64
mbtime

      SampleGroup -> Maybe SampleGroup
forall (m :: * -> *) a. Monad m => a -> m a
return
        ( Text -> Text -> SampleType -> Double -> SampleGroup
forall a. Show a => Text -> Text -> SampleType -> a -> SampleGroup
metric
            Text
"process_start_time_seconds"
            Text
"Start time of the process since unix epoch in seconds."
            SampleType
GaugeType
            ( Int64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
btime Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Int64 -> Double
fromTicks Int64
starttime )
        )

    process_virtual_memory_bytes :: SampleGroup
process_virtual_memory_bytes =
      Text -> Text -> SampleType -> Int64 -> SampleGroup
forall a. Show a => Text -> Text -> SampleType -> a -> SampleGroup
metric
        Text
"process_virtual_memory_bytes"
        Text
"Virtual memory size in bytes."
        SampleType
GaugeType
        Int64
vsize

    process_resident_memory_bytes :: SampleGroup
process_resident_memory_bytes =
      Text -> Text -> SampleType -> Int64 -> SampleGroup
forall a. Show a => Text -> Text -> SampleType -> a -> SampleGroup
metric
        Text
"process_resident_memory_bytes"
        Text
"Resident memory size in bytes."
        SampleType
GaugeType
        ( Int64
rss Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sysconfPageSize )


metric :: Show a => Text -> Text -> SampleType -> a -> SampleGroup
metric :: Text -> Text -> SampleType -> a -> SampleGroup
metric Text
metricName Text
metricHelp SampleType
metricType a
value =
  Info -> SampleType -> [Sample] -> SampleGroup
SampleGroup
    Info :: Text -> Text -> Info
Info{Text
metricName :: Text
metricHelp :: Text
metricHelp :: Text
metricName :: Text
..}
    SampleType
metricType
    [ Text -> LabelPairs -> ByteString -> Sample
Sample
        Text
metricName
        []
        ( [Char] -> ByteString
forall a. IsString a => [Char] -> a
fromString ( a -> [Char]
forall a. Show a => a -> [Char]
show a
value ) )
    ]


-- | Convert a number of clock ticks into the corresponding duration in seconds.
fromTicks :: Int64 -> Double
fromTicks :: Int64 -> Double
fromTicks Int64
ticks =
  Int64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
ticks Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ CLong -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral CLong
clk_tck


{-|

Returns the current boot time in seconds since Unix epoch. This is a Maybe
as we might not to be able to successfully parse this information out of
@/proc/stat@.

'unsafePerformIO' is used as this value does not change during the
execution of the program, so this gives us a lightweight cache for this
value.

-}
{-# NOINLINE mbtime #-}
mbtime :: Maybe Int64
mbtime :: Maybe Int64
mbtime = IO (Maybe Int64) -> Maybe Int64
forall a. IO a -> a
unsafePerformIO (IO (Maybe Int64) -> Maybe Int64)
-> IO (Maybe Int64) -> Maybe Int64
forall a b. (a -> b) -> a -> b
$ do
  (([Char], Int64, [Char]) -> Int64)
-> Maybe ([Char], Int64, [Char]) -> Maybe Int64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ( \( [Char]
_, Int64
a, [Char]
_ ) -> Int64
a ) (Maybe ([Char], Int64, [Char]) -> Maybe Int64)
-> (Text -> Maybe ([Char], Int64, [Char])) -> Text -> Maybe Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RE Char Int64 -> [Char] -> Maybe ([Char], Int64, [Char])
forall s a. RE s a -> [s] -> Maybe ([s], a, [s])
RE.findFirstInfix ( RE Char [Char]
"btime " RE Char [Char] -> RE Char Int64 -> RE Char Int64
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> RE Char Int64
forall a. Num a => RE Char a
RE.decimal ) ([Char] -> Maybe ([Char], Int64, [Char]))
-> (Text -> [Char]) -> Text -> Maybe ([Char], Int64, [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
unpack
    (Text -> Maybe Int64) -> IO Text -> IO (Maybe Int64)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO Text
readFile [Char]
"/proc/stat"


-- | Specific metrics from @/proc/xyz/stat@ that we are interested in.
data ProcStat = ProcStat
  { ProcStat -> Int64
utime :: Int64
    -- ^ Amount of time that this process has been scheduled in user mode,
    -- measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
  , ProcStat -> Int64
stime :: Int64
    -- ^ Amount of time that this process has been scheduled in kernel mode,
    -- measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
  , ProcStat -> Int64
starttime :: Int64
    -- ^ The time the process started after system boot. In kernels before Linux
    -- 2.6, this value was expressed in jiffies. Since Linux 2.6, the value is
    -- expressed in clock ticks (divide by sysconf(_SC_CLK_TCK)).
  , ProcStat -> Int64
vsize :: Int64
    -- ^ Virtual memory size in bytes.
  , ProcStat -> Int64
rss :: Int64
    -- ^ Resident Set Size: number of pages the process has in real memory. This
    -- is just the pages which count toward text, data, or stack space. This
    -- does not include pages which have not been demand-loaded in, or which are
    -- swapped out.
  }
  deriving
    ( Int -> ProcStat -> [Char] -> [Char]
[ProcStat] -> [Char] -> [Char]
ProcStat -> [Char]
(Int -> ProcStat -> [Char] -> [Char])
-> (ProcStat -> [Char])
-> ([ProcStat] -> [Char] -> [Char])
-> Show ProcStat
forall a.
(Int -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
showList :: [ProcStat] -> [Char] -> [Char]
$cshowList :: [ProcStat] -> [Char] -> [Char]
show :: ProcStat -> [Char]
$cshow :: ProcStat -> [Char]
showsPrec :: Int -> ProcStat -> [Char] -> [Char]
$cshowsPrec :: Int -> ProcStat -> [Char] -> [Char]
Show )


{-|

A regular expression for parsing @/proc/xyz/stat@. See
@man 5 proc@ for more information on the format of this file:
https://linux.die.net/man/5/proc.

-}
parseProcStat :: RE.RE Char ProcStat
parseProcStat :: RE Char ProcStat
parseProcStat =
  Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat
ProcStat
    (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$  RE Char [Char]
any                                                     -- pid %d
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char] -> RE Char [Char]
forall a. RE Char a -> RE Char a
token ( Char -> RE Char Char
forall s. Eq s => s -> RE s s
RE.sym Char
'(' RE Char Char -> RE Char [Char] -> RE Char [Char]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> RE Char Char -> RE Char [Char]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
RE.some RE Char Char
forall s. RE s s
RE.anySym RE Char [Char] -> RE Char Char -> RE Char [Char]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> RE Char Char
forall s. Eq s => s -> RE s s
RE.sym Char
')' ) -- comm %s
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- state %c
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- ppid %d
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- pgrp %d
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- session %d
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- tty_nr %d
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- tpgid %d
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- flags %u (%lu before Linux 2.6.22)
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- minflt %lu
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- cminflt %lu
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- majflt %lu
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char]
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- cmajflt %lu
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char Int64
-> RE Char (Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RE Char Int64 -> RE Char Int64
forall a. RE Char a -> RE Char a
token RE Char Int64
forall a. Num a => RE Char a
RE.decimal                                        -- utime %lu
    RE Char (Int64 -> Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char Int64 -> RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RE Char Int64 -> RE Char Int64
forall a. RE Char a -> RE Char a
token RE Char Int64
forall a. Num a => RE Char a
RE.decimal                                        -- stime %lu
    RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char] -> RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- cutime %ld
    RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char] -> RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- cstime %ld
    RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char] -> RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- priority %ld
    RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char] -> RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- nice %ld
    RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char] -> RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- num_threads %ld
    RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char [Char] -> RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- itrealvalue %ld
    RE Char (Int64 -> Int64 -> Int64 -> ProcStat)
-> RE Char Int64 -> RE Char (Int64 -> Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RE Char Int64 -> RE Char Int64
forall a. RE Char a -> RE Char a
token RE Char Int64
forall a. Num a => RE Char a
RE.decimal                                        -- starttime %llu (was %lu before Linux 2.6)
    RE Char (Int64 -> Int64 -> ProcStat)
-> RE Char Int64 -> RE Char (Int64 -> ProcStat)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RE Char Int64 -> RE Char Int64
forall a. RE Char a -> RE Char a
token RE Char Int64
forall a. Num a => RE Char a
RE.decimal                                        -- vsize %lu
    RE Char (Int64 -> ProcStat) -> RE Char Int64 -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RE Char Int64 -> RE Char Int64
forall a. RE Char a -> RE Char a
token RE Char Int64
forall a. Num a => RE Char a
RE.decimal                                        -- rss %ld
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- rsslim %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- startcode %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- endcode %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- startstack %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- kstkesp %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- kstkeip %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- signal %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- blocked %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- sigignore %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- sigcatch %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- wchan %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- nswap %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- cnswap %lu
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- exit_signal %d (since Linux 2.1.22)
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- processor %d (since Linux 2.2.8)
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- rt_priority %u (since Linux 2.5.19; was %lu before Linux 2.6.22)
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- policy %u (since Linux 2.5.19; was %lu before Linux 2.6.22)
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- delayacct_blkio_ticks %llu (since Linux 2.6.18)
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- guest_time %lu (since Linux 2.6.24)
    RE Char ProcStat -> RE Char [Char] -> RE Char ProcStat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*  RE Char [Char]
any                                                     -- cguest_time %ld (since Linux 2.6.24)

  where

    token :: RE Char a -> RE Char a
token RE Char a
a =
      RE Char a
a RE Char a -> RE Char Char -> RE Char a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (Char -> Bool) -> RE Char Char
forall s. (s -> Bool) -> RE s s
RE.psym Char -> Bool
isSpace RE Char a -> RE Char [Char] -> RE Char a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* RE Char Char -> RE Char [Char]
forall s a. RE s a -> RE s [a]
RE.few ( (Char -> Bool) -> RE Char Char
forall s. (s -> Bool) -> RE s s
RE.psym Char -> Bool
isSpace )

    any :: RE Char [Char]
any =
      RE Char [Char] -> RE Char [Char]
forall a. RE Char a -> RE Char a
token ( RE Char Char -> RE Char [Char]
forall s a. RE s a -> RE s [a]
RE.few RE Char Char
forall s. RE s s
RE.anySym )