@@ -10,18 +10,20 @@ module Leios.Tracing.Receipt (
1010 receipt ,
1111) where
1212
13- import Control.Concurrent.Chan (Chan , readChan )
13+ import Control.Concurrent.MVar (MVar , takeMVar )
14+ import Control.Monad (void )
1415import Control.Monad.IO.Class (liftIO )
15- import Control.Monad.State.Strict (StateT , execStateT , modify' )
16+ import Control.Monad.State.Strict (StateT , execStateT , gets , modify' )
1617import Data.Aeson (Value (Object ), withObject , (.:) )
1718import Data.Aeson.Types (Parser , parseMaybe )
1819import Data.Function (on )
1920import Data.List (intercalate )
2021import Data.Map.Strict (Map )
2122import Data.Text (Text )
2223import Leios.Tracing.Util (Maximum (.. ), Minimum (.. ))
24+ import System.IO (IOMode (WriteMode ), hClose , hPutStrLn , openFile )
2325
24- import qualified Data.Map.Strict as M (insertWith , singleton , toAscList , toList )
26+ import qualified Data.Map.Strict as M (insertWith , (!) )
2527import qualified Data.Text as T (unpack )
2628
2729data ItemKey
@@ -36,7 +38,6 @@ data ItemInfo
3638 = ItemInfo
3739 { sent :: Minimum Double
3840 , size :: Maximum Double
39- , receipts :: Map Text Double
4041 }
4142 deriving (Show )
4243
@@ -45,36 +46,26 @@ instance Semigroup ItemInfo where
4546 ItemInfo
4647 { sent = on (<>) sent x y
4748 , size = on (<>) size x y
48- , receipts = on (<>) receipts x y
4949 }
5050
5151instance Monoid ItemInfo where
5252 mempty =
5353 ItemInfo
5454 { sent = mempty
5555 , size = mempty
56- , receipts = mempty
5756 }
5857
59- toCSV :: ItemKey -> ItemInfo -> [String ]
60- toCSV ItemKey {.. } ItemInfo {.. } =
61- let
62- common =
63- [ T. unpack kind
64- , T. unpack item
65- , T. unpack producer
66- , show sent
67- ]
68- receive :: Text -> Double -> String
69- receive recipient received =
70- intercalate sep $
71- common
72- ++ [ T. unpack recipient
73- , show received
74- , show $ (received - ) <$> sent
75- ]
76- in
77- uncurry receive <$> M. toAscList receipts
58+ toCSV :: ItemKey -> ItemInfo -> Text -> Double -> String
59+ toCSV ItemKey {.. } ItemInfo {.. } recipient received =
60+ intercalate sep $
61+ [ T. unpack kind
62+ , T. unpack item
63+ , T. unpack producer
64+ , show sent
65+ , T. unpack recipient
66+ , show received
67+ , show $ (received - ) <$> sent
68+ ]
7869
7970itemHeader :: String
8071itemHeader =
@@ -92,7 +83,7 @@ itemHeader =
9283sep :: String
9384sep = " ,"
9485
95- parseEvent :: Value -> Parser (ItemKey , ItemInfo )
86+ parseEvent :: Value -> Parser (ItemKey , ItemInfo , Maybe ( Text , Double ) )
9687parseEvent =
9788 withObject " TraceEvent" $ \ event ->
9889 do
@@ -102,101 +93,107 @@ parseEvent =
10293 item <- message .: " id"
10394 parseMessage typ item time $ Object message
10495
105- parseMessage :: Text -> Text -> Double -> Value -> Parser (ItemKey , ItemInfo )
96+ parseMessage :: Text -> Text -> Double -> Value -> Parser (ItemKey , ItemInfo , Maybe ( Text , Double ) )
10697parseMessage " TXGenerated" item sent =
10798 withObject " TXGenerated" $ \ message ->
10899 do
109100 let kind = " TX"
110101 producer <- message .: " publisher"
111102 size <- message .: " size_bytes"
112- pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent})
103+ pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent}, Nothing )
113104parseMessage " IBGenerated" item sent =
114105 withObject " IBGenerated" $ \ message ->
115106 do
116107 let kind = " IB"
117108 producer <- message .: " producer"
118109 size <- message .: " size_bytes"
119- pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent})
110+ pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent}, Nothing )
120111parseMessage " EBGenerated" item sent =
121112 withObject " EBGenerated" $ \ message ->
122113 do
123114 let kind = " EB"
124115 producer <- message .: " producer"
125116 size <- message .: " size_bytes"
126- pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent})
117+ pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent}, Nothing )
127118parseMessage " RBGenerated" item sent =
128119 withObject " RBGenerated" $ \ message ->
129120 do
130121 let kind = " RB"
131122 producer <- message .: " producer"
132123 size <- message .: " size_bytes"
133- pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent})
124+ pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent}, Nothing )
134125parseMessage " VTBundleGenerated" item sent =
135126 withObject " VTBundleGenerated" $ \ message ->
136127 do
137128 let kind = " VT"
138129 producer <- message .: " producer"
139130 size <- message .: " size_bytes"
140- pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent})
131+ pure (ItemKey {.. }, mempty {size, sent = Minimum $ Just sent}, Nothing )
141132parseMessage " TXReceived" item received =
142133 withObject " TXReceived" $ \ message ->
143134 do
144135 let kind = " TX"
145136 producer <- message .: " producer"
146137 recipient <- message .: " recipient"
147- pure (ItemKey {.. }, mempty {receipts = M. singleton recipient received} )
138+ pure (ItemKey {.. }, mempty , Just ( recipient, received) )
148139parseMessage " IBReceived" item received =
149140 withObject " IBReceived" $ \ message ->
150141 do
151142 let kind = " IB"
152143 producer <- message .: " producer"
153144 recipient <- message .: " recipient"
154- pure (ItemKey {.. }, mempty {receipts = M. singleton recipient received} )
145+ pure (ItemKey {.. }, mempty , Just ( recipient, received) )
155146parseMessage " EBReceived" item received =
156147 withObject " EBReceived" $ \ message ->
157148 do
158149 let kind = " EB"
159150 producer <- message .: " producer"
160151 recipient <- message .: " recipient"
161- pure (ItemKey {.. }, mempty {receipts = M. singleton recipient received} )
152+ pure (ItemKey {.. }, mempty , Just ( recipient, received) )
162153parseMessage " RBReceived" item received =
163154 withObject " RBReceived" $ \ message ->
164155 do
165156 let kind = " RB"
166157 producer <- message .: " producer"
167158 recipient <- message .: " recipient"
168- pure (ItemKey {.. }, mempty {receipts = M. singleton recipient received} )
159+ pure (ItemKey {.. }, mempty , Just ( recipient, received) )
169160parseMessage " VTBundleReceived" item received =
170161 withObject " VTBundleReceived" $ \ message ->
171162 do
172163 let kind = " VT"
173164 producer <- message .: " producer"
174165 recipient <- message .: " recipient"
175- pure (ItemKey {.. }, mempty {receipts = M. singleton recipient received} )
166+ pure (ItemKey {.. }, mempty , Just ( recipient, received) )
176167parseMessage _ _ _ =
177168 const $ fail " Ignore"
178169
179170type Index = Map ItemKey ItemInfo
180171
181- tally :: Monad m => Value -> StateT Index m ()
172+ tally :: Monad m => Value -> StateT Index m (Maybe String )
182173tally event =
183174 case parseMaybe parseEvent event of
184- Just (itemKey, itemInfo) ->
175+ Just (itemKey, itemInfo, rec ) ->
185176 do
186177 -- Insert the generated items.
187178 modify' $ M. insertWith (<>) itemKey itemInfo
188- Nothing -> pure ()
179+ case rec of
180+ Just (recipient, received) ->
181+ do
182+ itemInfo' <- gets (M. ! itemKey)
183+ pure . Just $ toCSV itemKey itemInfo' recipient received
184+ Nothing -> pure Nothing
185+ Nothing -> pure Nothing
189186
190- receipt :: FilePath -> Chan (Maybe Value ) -> IO ()
191- receipt cpuFile events =
187+ receipt :: FilePath -> MVar (Maybe Value ) -> IO ()
188+ receipt receiptFile events =
192189 do
190+ h <- openFile receiptFile WriteMode
191+ hPutStrLn h itemHeader
193192 let
194193 go =
195- do
196- liftIO (readChan events)
197- >>= \ case
198- Nothing -> pure ()
199- Just event -> tally event >> go
200- index <- go `execStateT` mempty
201- writeFile cpuFile . unlines . (itemHeader : ) . concat $
202- uncurry toCSV <$> M. toList index
194+ liftIO (takeMVar events)
195+ >>= \ case
196+ Nothing -> pure ()
197+ Just event -> tally event >>= maybe (pure () ) (liftIO . hPutStrLn h) >> go
198+ void $ go `execStateT` mempty
199+ hClose h
0 commit comments