1
1
{-# LANGUAGE DeriveGeneric #-}
2
+ {-# LANGUAGE LambdaCase #-}
2
3
{-# LANGUAGE NamedFieldPuns #-}
3
4
{-# LANGUAGE OverloadedStrings #-}
4
5
{-# LANGUAGE RecordWildCards #-}
@@ -9,44 +10,24 @@ module Leios.Tracing.Lifecycle (
9
10
lifecycle ,
10
11
) where
11
12
13
+ import Control.Concurrent.Chan (Chan , readChan )
12
14
import Control.Monad ((<=<) )
13
- import Control.Monad.State.Strict (State , execState , gets , modify' )
14
- import Data.Aeson (FromJSON (.. ), Value (Object ), withObject , (.:) )
15
+ import Control.Monad.IO.Class (liftIO )
16
+ import Control.Monad.State.Strict (StateT , execStateT , gets , modify' )
17
+ import Data.Aeson (Value (Object ), withObject , (.:) )
15
18
import Data.Aeson.Types (Parser , parseMaybe )
16
19
import Data.Function (on )
17
20
import Data.List (intercalate )
18
21
import Data.Map.Strict (Map )
19
22
import Data.Monoid (Sum (.. ))
20
23
import Data.Set (Set )
21
24
import Data.Text (Text )
25
+ import Leios.Tracing.Util (Minimum (.. ))
22
26
23
27
import qualified Data.Map.Strict as M (elems , fromList , insertWith , restrictKeys , toList , unionWith )
24
28
import qualified Data.Set as S (map , singleton )
25
29
import qualified Data.Text as T (unpack )
26
30
27
- newtype Earliest a = Earliest { getEarliest :: Maybe a }
28
- deriving (Show )
29
-
30
- instance Eq a => Eq (Earliest a ) where
31
- Earliest (Just x) == Earliest (Just y) = x == y
32
- Earliest Nothing == Earliest Nothing = True
33
- _ == _ = False
34
-
35
- instance Ord a => Ord (Earliest a ) where
36
- Earliest (Just x) `compare` Earliest (Just y) = x `compare` y
37
- Earliest (Just _) `compare` Earliest Nothing = LT
38
- Earliest Nothing `compare` Earliest (Just _) = GT
39
- Earliest Nothing `compare` Earliest Nothing = EQ
40
-
41
- instance Ord a => Semigroup (Earliest a ) where
42
- x <> y = if x < y then x else y
43
-
44
- instance Ord a => Monoid (Earliest a ) where
45
- mempty = Earliest Nothing
46
-
47
- instance FromJSON a => FromJSON (Earliest a ) where
48
- parseJSON = fmap Earliest . parseJSON
49
-
50
31
data ItemKey
51
32
= ItemKey
52
33
{ kind :: Text
@@ -56,13 +37,13 @@ data ItemKey
56
37
57
38
data ItemInfo
58
39
= ItemInfo
59
- { size :: Earliest Int
40
+ { size :: Minimum Int
60
41
, references :: Sum Int
61
- , created :: Earliest Double
62
- , toIB :: Earliest Double
63
- , toEB :: Earliest Double
64
- , toRB :: Earliest Double
65
- , inRB :: Earliest Double
42
+ , created :: Minimum Double
43
+ , toIB :: Minimum Double
44
+ , toEB :: Minimum Double
45
+ , toRB :: Minimum Double
46
+ , inRB :: Minimum Double
66
47
, inIBs :: Set Text
67
48
, inEBs :: Set Text
68
49
}
@@ -102,13 +83,13 @@ toCSV ItemKey{..} ItemInfo{..} =
102
83
sep
103
84
[ T. unpack kind
104
85
, T. unpack item
105
- , maybe " NA " show $ getEarliest size
86
+ , show size
106
87
, show $ getSum references
107
- , maybe " NA " show $ getEarliest created
108
- , maybe " NA " show $ getEarliest toIB
109
- , maybe " NA " show $ getEarliest toEB
110
- , maybe " NA " show $ getEarliest toRB
111
- , maybe " NA " show $ getEarliest inRB
88
+ , show created
89
+ , show toIB
90
+ , show toEB
91
+ , show toRB
92
+ , show inRB
112
93
]
113
94
114
95
itemHeader :: String
@@ -133,13 +114,13 @@ parseEvent :: Value -> Parser (ItemKey, ItemInfo, Index)
133
114
parseEvent =
134
115
withObject " TraceEvent" $ \ event ->
135
116
do
136
- time <- Earliest <$> event .: " time_s"
117
+ time <- Minimum <$> event .: " time_s"
137
118
message <- event .: " message"
138
119
typ <- message .: " type"
139
120
ident <- message .: " id"
140
121
parseMessage typ ident time $ Object message
141
122
142
- parseMessage :: Text -> Text -> Earliest Double -> Value -> Parser (ItemKey , ItemInfo , Index )
123
+ parseMessage :: Text -> Text -> Minimum Double -> Value -> Parser (ItemKey , ItemInfo , Index )
143
124
parseMessage " TXGenerated" item created =
144
125
withObject " TXGenerated" $ \ message ->
145
126
do
@@ -174,7 +155,7 @@ parseMessage _ _ _ =
174
155
175
156
type Index = Map ItemKey ItemInfo
176
157
177
- tally :: Value -> State Index ()
158
+ tally :: Monad m => Value -> StateT Index m ()
178
159
tally event =
179
160
case parseMaybe parseEvent event of
180
161
Just (itemKey, itemInfo, updates) ->
@@ -185,7 +166,7 @@ tally event =
185
166
modify' $ M. unionWith (<>) updates
186
167
Nothing -> pure ()
187
168
188
- updateInclusions :: Text -> ItemKey -> Set Text -> State Index ()
169
+ updateInclusions :: Monad m => Text -> ItemKey -> Set Text -> StateT Index m ()
189
170
updateInclusions kind itemKey includers =
190
171
do
191
172
includers' <- gets $ M. elems . (`M.restrictKeys` S. map (ItemKey kind) includers)
@@ -198,24 +179,30 @@ updateInclusions kind itemKey includers =
198
179
, toRB = mconcat $ toRB <$> includers'
199
180
}
200
181
201
- updateEBs :: ItemKey -> ItemInfo -> State Index ()
182
+ updateEBs :: Monad m => ItemKey -> ItemInfo -> StateT Index m ()
202
183
updateEBs itemKey = updateInclusions " EB" itemKey . inEBs
203
184
204
- updateIBs :: ItemKey -> ItemInfo -> State Index ()
185
+ updateIBs :: Monad m => ItemKey -> ItemInfo -> StateT Index m ()
205
186
updateIBs itemKey = updateInclusions " IB" itemKey . inIBs
206
187
207
- lifecycle :: FilePath -> [ Value ] -> IO ()
188
+ lifecycle :: FilePath -> Chan ( Maybe Value ) -> IO ()
208
189
lifecycle lifecycleFile events =
209
- let
210
- index =
211
- (`execState` mempty ) $
190
+ do
191
+ let
192
+ go =
193
+ do
194
+ liftIO (readChan events)
195
+ >>= \ case
196
+ Nothing -> pure ()
197
+ Just event -> tally event >> go
198
+ index <-
199
+ (`execStateT` mempty ) $
212
200
do
213
201
-- Compute the direct metrics from the traces.
214
- mapM_ tally events
202
+ go
215
203
-- Update arrival in EBs and RBs for IBs.
216
204
mapM_ (uncurry updateEBs) =<< gets M. toList
217
205
-- Update arrival in EBs and RBs for TXs.
218
206
mapM_ (uncurry updateIBs) =<< gets M. toList
219
- in
220
207
writeFile lifecycleFile . unlines . (itemHeader : ) $
221
208
uncurry toCSV <$> M. toList index
0 commit comments