Skip to content

Commit 2948f29

Browse files
committed
trace-resources: add disk and net stats
1 parent 5eff7ea commit 2948f29

File tree

5 files changed

+161
-37
lines changed

5 files changed

+161
-37
lines changed

trace-resources/src/Cardano/Logging/Resources/Darwin.hsc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ readResourceStatsInternal = getProcessID >>= \pid -> do
100100
, rHeap = GhcStats.gcdetails_mem_in_use_bytes $ GhcStats.gc rts
101101
, rRSS = _resident_size mem
102102
, rCentiBlkIO = 0
103+
, rNetBytesRd = 0
104+
, rNetBytesWr = 0
105+
, rFsBytesRd = 0
106+
, rFsBytesWr = 0
103107
, rThreads = 0
104108
}
105109
where

trace-resources/src/Cardano/Logging/Resources/Dummy.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ readResourceStatsInternal = do
2525
, rRSS = 0
2626
, rHeap = 0
2727
, rCentiBlkIO = 0
28+
, rNetBytesRd = 0
29+
, rNetBytesWr = 0
30+
, rFsBytesRd = 0
31+
, rFsBytesWr = 0
2832
, rThreads = 0
2933
}
3034
where

trace-resources/src/Cardano/Logging/Resources/Linux.hs

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
{-# LANGUAGE CPP #-}
2+
{-# LANGUAGE RecordWildCards #-}
3+
{-# LANGUAGE TypeApplications #-}
24

35
module Cardano.Logging.Resources.Linux
46
(
@@ -14,20 +16,103 @@ import System.Posix.Files (fileMode, getFileStatus,
1416
ownerReadMode)
1517
import Text.Read (readMaybe)
1618

19+
-- * Disk IO stats:
20+
-- /proc/[pid]/io (since kernel 2.6.20)
21+
-- This file contains I/O statistics for the process, for example:
22+
--
23+
-- # cat /proc/3828/io
24+
-- rchar: 323934931
25+
-- wchar: 323929600
26+
-- syscr: 632687
27+
-- syscw: 632675
28+
-- read_bytes: 0
29+
-- write_bytes: 323932160
30+
-- cancelled_write_bytes: 0
31+
--
32+
-- The fields are as follows:
33+
--
34+
-- rchar: characters read
35+
-- The number of bytes which this task has caused to be read from storage. This is simply the sum
36+
-- of bytes which this process passed to read(2) and similar system calls. It includes things such
37+
-- as terminal I/O and is unaffected by whether or not actual physical disk I/O was required (the
38+
-- read might have been satisfied from pagecache).
39+
--
40+
-- wchar: characters written
41+
-- The number of bytes which this task has caused, or shall cause to be written to disk. Similar
42+
-- caveats apply here as with rchar.
43+
--
44+
-- syscr: read syscalls
45+
-- Attempt to count the number of read I/O operations-that is, system calls such as read(2) and
46+
-- pread(2).
47+
--
48+
-- syscw: write syscalls
49+
-- Attempt to count the number of write I/O operations-that is, system calls such as write(2) and
50+
-- pwrite(2).
51+
--
52+
-- read_bytes: bytes read
53+
-- Attempt to count the number of bytes which this process really did cause to be fetched from the
54+
-- storage layer. This is accurate for block-backed filesystems.
55+
--
56+
-- write_bytes: bytes written
57+
-- Attempt to count the number of bytes which this process caused to be sent to the storage layer.
58+
--
59+
-- cancelled_write_bytes:
60+
-- The big inaccuracy here is truncate. If a process writes 1MB to a file and then deletes the
61+
-- file, it will in fact perform no writeout. But it will have been accounted as having caused 1MB
62+
-- of write. In other words: this field represents the number of bytes which this process caused
63+
-- to not happen, by truncating pagecache. A task can cause "negative" I/O too. If this task
64+
-- truncates some dirty pagecache, some I/O which another task has been accounted for (in its
65+
-- write\_bytes) will not be happening.
66+
--
67+
-- Note: In the current implementation, things are a bit racy on 32-bit systems: if process A reads
68+
-- process B's /proc/[pid]/io while process B is updating one of these 64-bit counters, process A could
69+
-- see an intermediate result.
70+
--
71+
-- Permission to access this file is governed by a ptrace access mode PTRACE\_MODE\_READ\_FSCREDS check; see
72+
-- ptrace(2).
73+
--
74+
readProcBlockInOut :: IO (Word64, Word64)
75+
readProcBlockInOut = do
76+
fields <- readProcList "/proc/self/io"
77+
case -- We're only interested in 'read_bytes' & 'write_bytes':
78+
fmap fromInteger . take 3 . drop 9 $ fields of
79+
fsRd: _:fsWr:[] -> pure (fsRd, fsWr)
80+
_ -> pure (0, 0)
81+
82+
-- * Network stats:
83+
-- grep IpExt /proc/<pid>/net/netstat
84+
-- IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts InOctets OutOctets InMcastOctets OutMcastOctets InBcastOctets OutBcastOctets InCsumErrors InNoECTPkts InECT1Pkts InECT0Pkts InCEPkts
85+
-- IpExt: 0 0 20053 8977 2437 23 3163525943 196480057 2426648 1491754 394285 5523 0 3513269 0 217426 0
86+
--
87+
readProcNetInOut :: IO (Word64, Word64)
88+
readProcNetInOut = do
89+
fields <- words . lastline . lines <$> readFile "/proc/self/net/netstat"
90+
case -- We're only interested in 'InOctets' & 'OutOctets':
91+
fmap readMaybe . take 2 . drop 7 $ fields of
92+
Just netIn:Just netOut:[] -> pure (netIn, netOut)
93+
_ -> pure (0, 0)
94+
where
95+
lastline ls | length ls == 4 = last ls -- ensures we read the fourth line
96+
| otherwise = []
97+
1798
-- | TODO we have to expand the |readMemStats| function
1899
-- to read full data from |proc|
19100
readResourceStatsInternal :: IO (Maybe ResourceStats)
20101
readResourceStatsInternal = do
21102
rts <- GhcStats.getRTSStats
22-
mkProcStats rts . fmap fromIntegral <$> readProcList "/proc/self/stat"
103+
net <- readProcNetInOut
104+
fs <- readProcBlockInOut
105+
mkProcStats rts net fs . fmap fromIntegral <$> readProcList "/proc/self/stat"
23106
where
24-
mkProcStats :: GhcStats.RTSStats -> [Word64] -> Maybe ResourceStats
107+
mkProcStats :: GhcStats.RTSStats -> (Word64, Word64) -> (Word64, Word64) -> [Word64] -> Maybe ResourceStats
25108
mkProcStats rts
26-
(_:_:_:_:_:_:_:_:_:_ -- 00-09
27-
:_:_:_:user:sys:_:_:_:_:threads -- 10-19
28-
:_:_:_:rss:_:_:_:_:_:_ -- 20-29
29-
:_:_:_:_:_:_:_:_:_:_ -- 30-39
30-
:_:blkio:_rest) = -- 40-42
109+
(rNetBytesRd, rNetBytesWr)
110+
(rFsBytesRd, rFsBytesWr)
111+
(_:_:_:_:_:_:_:_:_:_ -- 00-09
112+
:_:_:_:user:sys:_:_:_:_:rThreads -- 10-19
113+
:_:_:_:rss:_:_:_:_:_:_ -- 20-29
114+
:_:_:_:_:_:_:_:_:_:_ -- 30-39
115+
:_:rCentiBlkIO:_rest) = -- 40-42
31116
Just $ Resources
32117
{ rCentiCpu = user + sys
33118
, rCentiGC = nsToCenti $ GhcStats.gc_cpu_ns rts
@@ -38,10 +123,9 @@ readResourceStatsInternal = do
38123
, rLive = GhcStats.gcdetails_live_bytes $ GhcStats.gc rts
39124
, rHeap = GhcStats.gcdetails_mem_in_use_bytes $ GhcStats.gc rts
40125
, rRSS = rss * 4096 -- TODO: this is really PAGE_SIZE.
41-
, rCentiBlkIO = blkio
42-
, rThreads = threads
126+
, ..
43127
}
44-
mkProcStats _ _ = Nothing
128+
mkProcStats _ _ _ _ = Nothing
45129
nsToCenti :: GhcStats.RtsTime -> Word64
46130
nsToCenti = floor . (/ (10000000 :: Double)) . fromIntegral
47131

trace-resources/src/Cardano/Logging/Resources/Types.hs

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{-# LANGUAGE DeriveFunctor #-}
33
{-# LANGUAGE DeriveGeneric #-}
44
{-# LANGUAGE FlexibleInstances #-}
5+
{-# LANGUAGE RecordWildCards #-}
56

67
module Cardano.Logging.Resources.Types
78
( Resources(..)
@@ -33,12 +34,16 @@ data Resources a
3334
, rHeap :: !a
3435
, rRSS :: !a
3536
, rCentiBlkIO :: !a
37+
, rNetBytesRd :: !a
38+
, rNetBytesWr :: !a
39+
, rFsBytesRd :: !a
40+
, rFsBytesWr :: !a
3641
, rThreads :: !a
3742
}
3843
deriving (Functor, Generic, Show)
3944

4045
instance Applicative Resources where
41-
pure a = Resources a a a a a a a a a a a
46+
pure a = Resources a a a a a a a a a a a a a a a
4247
f <*> x =
4348
Resources
4449
{ rCentiCpu = rCentiCpu f (rCentiCpu x)
@@ -51,6 +56,10 @@ instance Applicative Resources where
5156
, rHeap = rHeap f (rHeap x)
5257
, rRSS = rRSS f (rRSS x)
5358
, rCentiBlkIO = rCentiBlkIO f (rCentiBlkIO x)
59+
, rNetBytesRd = rNetBytesRd f (rNetBytesRd x)
60+
, rNetBytesWr = rNetBytesWr f (rNetBytesWr x)
61+
, rFsBytesRd = rFsBytesRd f (rFsBytesRd x)
62+
, rFsBytesWr = rFsBytesWr f (rFsBytesWr x)
5463
, rThreads = rThreads f (rThreads x)
5564
}
5665

@@ -76,30 +85,38 @@ docResourceStats :: Documented ResourceStats
7685
docResourceStats = Documented [
7786
DocMsg
7887
[]
79-
[("Resources.Stat.Cputicks", "Reports the CPU ticks, sice the process was started")
80-
,("Resources.Mem.Resident", "")
81-
,("Resources.RTS.GcLiveBytes", "")
82-
,("Resources.RTS.GcMajorNum", "")
83-
,("Resources.RTS.GcMinorNum", "")
84-
,("Resources.RTS.Gcticks", "")
85-
,("Resources.RTS.Mutticks", "")
86-
,("Resources.RTS.Threads","")
88+
[("Resources.Stat.Cputicks", "Kernel-reported CPU ticks (1/100th of a second), since process start")
89+
,("Resources.Mem.Resident", "Kernel-reported RSS (resident set size)")
90+
,("Resources.RTS.GcLiveBytes", "RTS-reported live bytes")
91+
,("Resources.RTS.GcMajorNum", "Major GCs")
92+
,("Resources.RTS.GcMinorNum", "Minor GCs")
93+
,("Resources.RTS.Gcticks", "RTS-reported CPU ticks spent on GC")
94+
,("Resources.RTS.Mutticks", "RTS-reported CPU ticks spent on mutator")
95+
,("Resources.State.NetBytesRd", "IP packet bytes read")
96+
,("Resources.State.NetBytesWr", "IP packet bytes written")
97+
,("Resources.State.FsBytesRd", "FS bytes read")
98+
,("Resources.State.FsBytesWr", "FS bytes written")
99+
,("Resources.RTS.Threads","RTS green thread count")
87100
]
88101
""
89102
]
90103

91104
instance LogFormatting ResourceStats where
92-
forHuman rs = "Resources:"
93-
<> " Cpu Ticks " <> (pack . show) (rCentiCpu rs)
94-
<> ", GC centiseconds " <> (pack . show) (rCentiGC rs)
95-
<> ", Mutator centiseconds " <> (pack . show) (rCentiMut rs)
96-
<> ", GCs major " <> (pack . show) (rGcsMajor rs)
97-
<> ", GCs minor " <> (pack . show) (rGcsMinor rs)
98-
<> ", Allocated bytes " <> (pack . show) (rAlloc rs)
99-
<>" , GC live bytes " <> (pack . show) (rLive rs)
100-
<> ", RTS heap " <> (pack . show) (rHeap rs)
101-
<> ", RSS " <> (pack . show) (rRSS rs)
102-
<> ", Threads " <> (pack . show) (rThreads rs)
105+
forHuman Resources{..} = "Resources:"
106+
<> " Cpu Ticks " <> (pack . show) rCentiCpu
107+
<> ", GC centiseconds " <> (pack . show) rCentiGC
108+
<> ", Mutator centiseconds " <> (pack . show) rCentiMut
109+
<> ", GCs major " <> (pack . show) rGcsMajor
110+
<> ", GCs minor " <> (pack . show) rGcsMinor
111+
<> ", Allocated bytes " <> (pack . show) rAlloc
112+
<>" , GC live bytes " <> (pack . show) rLive
113+
<> ", RTS heap " <> (pack . show) rHeap
114+
<> ", RSS " <> (pack . show) rRSS
115+
<> ", Net bytes read " <> (pack . show) rNetBytesRd
116+
<> " written " <> (pack . show) rNetBytesWr
117+
<> ", FS bytes read " <> (pack . show) rFsBytesRd
118+
<> " written " <> (pack . show) rFsBytesWr
119+
<> ", Threads " <> (pack . show) rThreads
103120
<> "."
104121

105122
forMachine _dtal rs = mconcat
@@ -114,16 +131,27 @@ instance LogFormatting ResourceStats where
114131
, "Heap" .= Number (fromIntegral $ rHeap rs)
115132
, "RSS" .= Number (fromIntegral $ rRSS rs)
116133
, "CentiBlkIO" .= Number (fromIntegral $ rCentiBlkIO rs)
134+
, "NetBytesRd" .= Number (fromIntegral $ rNetBytesRd rs)
135+
, "NetBytesWr" .= Number (fromIntegral $ rNetBytesWr rs)
136+
, "FsBytesRd" .= Number (fromIntegral $ rFsBytesRd rs)
137+
, "FsBytesWr" .= Number (fromIntegral $ rFsBytesWr rs)
117138
, "Threads" .= Number (fromIntegral $ rThreads rs)
118139
]
119140

120141
asMetrics rs =
121-
[ IntM "Resources.Stat.Cputicks" (fromIntegral $ rCentiCpu rs)
122-
, IntM "Resources.Mem.Resident" (fromIntegral $ rRSS rs)
123-
, IntM "Resources.RTS.GcLiveBytes" (fromIntegral $ rLive rs)
124-
, IntM "Resources.RTS.GcMajorNum" (fromIntegral $ rGcsMajor rs)
125-
, IntM "Resources.RTS.GcMinorNum" (fromIntegral $ rGcsMinor rs)
126-
, IntM "Resources.RTS.Gcticks" (fromIntegral $ rCentiGC rs)
127-
, IntM "Resources.RTS.Mutticks" (fromIntegral $ rCentiMut rs)
142+
[ IntM "Resources.Stat.Cputicks" (fromIntegral $ rCentiCpu rs)
143+
, IntM "Resources.RTS.Gcticks" (fromIntegral $ rCentiGC rs)
144+
, IntM "Resources.RTS.Mutticks" (fromIntegral $ rCentiMut rs)
145+
, IntM "Resources.RTS.GcMajorNum" (fromIntegral $ rGcsMajor rs)
146+
, IntM "Resources.RTS.GcMinorNum" (fromIntegral $ rGcsMinor rs)
147+
, IntM "Resources.RTS.Alloc" (fromIntegral $ rAlloc rs)
148+
, IntM "Resources.RTS.GcLiveBytes" (fromIntegral $ rLive rs)
149+
, IntM "Resources.RTS.Heap" (fromIntegral $ rHeap rs)
150+
, IntM "Resources.Mem.Resident" (fromIntegral $ rRSS rs)
151+
, IntM "Resources.Stat.BlkIOticks" (fromIntegral $ rCentiBlkIO rs)
152+
, IntM "Resources.State.NetBytesRd" (fromIntegral $ rNetBytesRd rs)
153+
, IntM "Resources.State.NetBytesWr" (fromIntegral $ rNetBytesWr rs)
154+
, IntM "Resources.State.FsBytesRd" (fromIntegral $ rFsBytesRd rs)
155+
, IntM "Resources.State.FsBytesWr" (fromIntegral $ rFsBytesWr rs)
128156
, IntM "Resources.RTS.Stat.Threads" (fromIntegral $ rThreads rs)
129157
]

trace-resources/src/Cardano/Logging/Resources/Windows.hsc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ readResourceStatsInternal = getCurrentProcessId >>= \pid -> do
154154
, rHeap = GhcStats.gcdetails_mem_in_use_bytes $ GhcStats.gc rts
155155
, rRSS = fromIntegral (_workingSetSize mem)
156156
, rCentiBlkIO = 0
157+
, rNetBytesRd = 0
158+
, rNetBytesWr = 0
159+
, rFsBytesRd = 0
160+
, rFsBytesWr = 0
157161
, rThreads = 0
158162
}
159163
where

0 commit comments

Comments
 (0)