Skip to content

Commit 98386c6

Browse files
authored
Merge pull request #49 from ethercrow/rename-threads-for-more-compact-presentation
Rename threads for more compact tracy visualization
2 parents 33cb217 + 05a67bc commit 98386c6

File tree

7 files changed

+66
-41
lines changed

7 files changed

+66
-41
lines changed

.github/workflows/ci.yml

+8-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
ghc: ['8.6', '8.8', '8.10', '9.0']
13+
ghc: ['8.6', '8.8', '8.10']
14+
fail-fast: false
1415
steps:
1516
- uses: actions/[email protected]
1617
- uses: actions/[email protected]
@@ -31,7 +32,7 @@ jobs:
3132
- uses: haskell/actions/setup@v1
3233
with:
3334
ghc-version: ${{ matrix.ghc }}
34-
cabal-version: '3.2'
35+
cabal-version: '3.4'
3536
- name: Update cabal package database
3637
run: cabal update
3738
- name: Build
@@ -48,6 +49,7 @@ jobs:
4849
strategy:
4950
matrix:
5051
stack-yaml: ['stack-8.10.yaml']
52+
fail-fast: false
5153
steps:
5254
- uses: actions/[email protected]
5355
- uses: actions/[email protected]
@@ -75,6 +77,7 @@ jobs:
7577
strategy:
7678
matrix:
7779
stack-yaml: ['stack-8.10.yaml']
80+
fail-fast: false
7881
steps:
7982
- uses: actions/[email protected]
8083
- uses: actions/[email protected]
@@ -101,7 +104,8 @@ jobs:
101104
runs-on: windows-latest
102105
strategy:
103106
matrix:
104-
ghc: ['8.10', '9.0.1']
107+
ghc: ['8.10']
108+
fail-fast: false
105109
steps:
106110
- uses: actions/[email protected]
107111
- uses: actions/[email protected]
@@ -122,7 +126,7 @@ jobs:
122126
- uses: haskell/actions/setup@v1
123127
with:
124128
ghc-version: ${{ matrix.ghc }}
125-
cabal-version: '3.2'
129+
cabal-version: '3.4'
126130
- name: Update cabal package database
127131
run: cabal update
128132
- name: Build

megaexample/Main.hs

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import Control.Concurrent
66
import Control.Concurrent.Async
7+
import Control.Monad
78
import qualified Data.ByteString.Char8 as BS
89
import qualified Data.ByteString.Lazy.Char8 as LBS
910
import Data.Function
@@ -85,8 +86,10 @@ microservice httpRequestCounter = \req respond -> withSpan "handle_http_request"
8586
respond $ Wai.responseLBS status200 [] result
8687
_ -> do
8788
bg_work <- async $ withSpan_ "background_task" do
88-
threadDelay 10000
89-
pure ()
89+
replicateM_ 3 $ do
90+
tasks <- replicateM 5 (async $ withSpan_ "task" $ threadDelay 10000)
91+
mapM_ wait tasks
92+
threadDelay 10000
9093
addEvent sp "message" "started bg work"
9194
rtsStats <- withSpan_ "getRTSStats" getRTSStats
9295
() <- wait bg_work

opentelemetry-extra/exe/eventlog-to-tracy/Main.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ main = do
3939
["-h"] -> help
4040
["--help"] -> help
4141
["help"] -> help
42-
[eventlogFile] -> work eventlogFile CollapseThreads
42+
[eventlogFile] -> work eventlogFile SplitThreads
4343
["--collapse-threads", eventlogFile] -> work eventlogFile CollapseThreads
4444
["--split-threads", eventlogFile] -> work eventlogFile SplitThreads
4545
_ -> help
4646

47-
work :: FilePath -> DoWeCollapseThreads -> IO ()
47+
work :: FilePath -> ThreadPresentation -> IO ()
4848
work inputFile doWeCollapseThreads = do
4949
let chromeFile = inputFile ++ ".trace.json"
5050
tracyFile = inputFile ++ ".tracy"

opentelemetry-extra/src/OpenTelemetry/ChromeExporter.hs

+13-14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ module OpenTelemetry.ChromeExporter where
44

55
import Control.Monad
66
import qualified Data.ByteString as BS
7-
import qualified Data.ByteString.Lazy as LBS
87
import Data.Coerce
98
import Data.Function
109
import Data.HashMap.Strict as HM
@@ -42,7 +41,7 @@ jChromeBeginSpan Span {..} =
4241
[ ("ph", J.textString "B"),
4342
("name", J.textString spanOperation),
4443
("pid", J.intNumber 1),
45-
("tid", J.intNumber $ fromIntegral spanThreadId),
44+
("tid", J.intNumber $ fromIntegral spanDisplayThreadId),
4645
("ts", J.wordNumber . fromIntegral $ div spanStartedAt 1000),
4746
( "args",
4847
J.object
@@ -63,31 +62,31 @@ jChromeEndSpan Span {..} =
6362
[ ("ph", J.textString "E"),
6463
("name", J.textString spanOperation),
6564
("pid", J.intNumber 1),
66-
("tid", J.intNumber $ fromIntegral spanThreadId),
65+
("tid", J.intNumber $ fromIntegral spanDisplayThreadId),
6766
("ts", J.wordNumber . fromIntegral $ div spanFinishedAt 1000)
6867
]
6968

7069
createChromeExporter :: FilePath -> IO (Exporter Span, Exporter Metric)
7170
createChromeExporter path = createChromeExporter' path SplitThreads
7271

73-
createChromeExporter' :: FilePath -> DoWeCollapseThreads -> IO (Exporter Span, Exporter Metric)
74-
createChromeExporter' path doWeCollapseThreads = do
72+
createChromeExporter' :: FilePath -> ThreadPresentation -> IO (Exporter Span, Exporter Metric)
73+
createChromeExporter' path threadPresentation = do
7574
f <- openFile path WriteMode
7675
hPutStrLn f "[ "
77-
let modifyThreadId = case doWeCollapseThreads of
78-
CollapseThreads -> const 1
79-
SplitThreads -> id
76+
let modifyThreadId = case threadPresentation of
77+
CollapseThreads -> pure . const 1
78+
SplitThreads -> pure
8079
span_exporter =
8180
Exporter
8281
( \sps -> do
8382
mapM_
84-
( \sp -> do
85-
let sp' = sp {spanThreadId = modifyThreadId (spanThreadId sp)}
86-
let Span {spanThreadId, spanEvents} = sp'
83+
( \sp@(Span {spanEvents}) -> do
84+
tid' <- modifyThreadId (spanDisplayThreadId sp)
85+
let sp' = sp {spanDisplayThreadId = tid'}
8786
BS.hPutStr f $ J.toByteString $ jChromeBeginSpan sp'
8887
BS.hPutStr f ",\n"
8988
forM_ (sortOn spanEventTimestamp spanEvents) $ \ev -> do
90-
BS.hPutStr f $ J.toByteString $ jChromeEvent $ ChromeEvent (modifyThreadId spanThreadId) ev
89+
BS.hPutStr f $ J.toByteString $ jChromeEvent $ ChromeEvent tid' ev
9190
BS.hPutStr f ",\n"
9291
BS.hPutStr f $ J.toByteString $ jChromeEndSpan sp'
9392
BS.hPutStr f ",\n"
@@ -120,9 +119,9 @@ createChromeExporter' path doWeCollapseThreads = do
120119
(pure ())
121120
pure (span_exporter, metric_exporter)
122121

123-
data DoWeCollapseThreads = CollapseThreads | SplitThreads
122+
data ThreadPresentation = CollapseThreads | SplitThreads
124123

125-
eventlogToChrome :: FilePath -> FilePath -> DoWeCollapseThreads -> IO ()
124+
eventlogToChrome :: FilePath -> FilePath -> ThreadPresentation -> IO ()
126125
eventlogToChrome eventlogFile chromeFile doWeCollapseThreads = do
127126
(span_exporter, metric_exporter) <- createChromeExporter' chromeFile doWeCollapseThreads
128127
exportEventlog span_exporter metric_exporter eventlogFile

opentelemetry-extra/src/OpenTelemetry/Common.hs

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ data Span = Span
6464
{ spanContext :: {-# UNPACK #-} !SpanContext,
6565
spanOperation :: T.Text,
6666
spanThreadId :: Word32,
67+
spanDisplayThreadId :: Word32,
6768
spanStartedAt :: !Timestamp,
6869
spanFinishedAt :: !Timestamp,
6970
spanTags :: !(HM.HashMap TagName TagValue),

opentelemetry-extra/src/OpenTelemetry/EventlogStreaming_Internal.hs

+36-15
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ data WatDoOnEOF = StopOnEOF | SleepAndRetryOnEOF
3535

3636
data State = S
3737
{ originTimestamp :: !Timestamp,
38-
threadMap :: IM.IntMap ThreadId,
38+
cap2thread :: IM.IntMap ThreadId,
3939
spans :: HM.HashMap SpanId Span,
4040
instrumentMap :: HM.HashMap InstrumentId CaptureInstrument,
4141
traceMap :: HM.HashMap ThreadId TraceId,
4242
serial2sid :: HM.HashMap Word64 SpanId,
4343
thread2sid :: HM.HashMap ThreadId SpanId,
44+
thread2displayThread :: HM.HashMap ThreadId ThreadId, -- https://github.com/ethercrow/opentelemetry-haskell/issues/40
45+
nextFreeDisplayThread :: ThreadId,
4446
gcRequestedAt :: !Timestamp,
4547
gcStartedAt :: !Timestamp,
4648
gcGeneration :: !Int,
@@ -52,7 +54,7 @@ data State = S
5254
deriving (Show)
5355

5456
initialState :: Word64 -> R.SMGen -> State
55-
initialState timestamp = S timestamp mempty mempty mempty mempty mempty mempty 0 0 0 0 0 0
57+
initialState timestamp = S timestamp mempty mempty mempty mempty mempty mempty mempty 1 0 0 0 0 0 0
5658

5759
data EventSource
5860
= EventLogHandle Handle WatDoOnEOF
@@ -142,9 +144,9 @@ parseOpenTelemetry UserBinaryMessage {payload} = parseByteString payload
142144
parseOpenTelemetry _ = Nothing
143145

144146
processEvent :: Event -> State -> (State, [Span], [Metric])
145-
processEvent (Event ts ev m_cap) st@(S {..}) =
147+
processEvent (Event ts ev m_cap) st@S {..} =
146148
let now = originTimestamp + ts
147-
m_thread_id = m_cap >>= flip IM.lookup threadMap
149+
m_thread_id = m_cap >>= flip IM.lookup cap2thread
148150
m_trace_id = m_thread_id >>= flip HM.lookup traceMap
149151
in case (ev, m_cap, m_thread_id) of
150152
(WallClockTime {sec, nsec}, _, _) ->
@@ -158,16 +160,21 @@ processEvent (Event ts ev m_cap) st@(S {..}) =
158160
[Metric threadsI [MetricDatapoint now 1]]
159161
)
160162
(RunThread tid, Just cap, _) ->
161-
(st {threadMap = IM.insert cap tid threadMap}, [], [])
163+
(st {cap2thread = IM.insert cap tid cap2thread}, [], [])
162164
(StopThread tid tstatus, Just cap, _)
163165
| isTerminalThreadStatus tstatus ->
164-
( st
165-
{ threadMap = IM.delete cap threadMap,
166-
traceMap = HM.delete tid traceMap
167-
},
168-
[],
169-
[Metric threadsI [MetricDatapoint now (-1)]]
170-
)
166+
let (t2dt, nfdt) = case HM.lookup tid thread2displayThread of
167+
Nothing -> (thread2displayThread, nextFreeDisplayThread)
168+
Just _ -> (HM.delete tid thread2displayThread, nextFreeDisplayThread - 1)
169+
in ( st
170+
{ cap2thread = IM.delete cap cap2thread,
171+
traceMap = HM.delete tid traceMap,
172+
thread2displayThread = t2dt,
173+
nextFreeDisplayThread = nfdt
174+
},
175+
[],
176+
[Metric threadsI [MetricDatapoint now (-1)]]
177+
)
171178
(RequestSeqGC, _, _) ->
172179
(st {gcRequestedAt = now}, [], [])
173180
(RequestParGC, _, _) ->
@@ -187,6 +194,7 @@ processEvent (Event ts ev m_cap) st@(S {..}) =
187194
spanStartedAt = gcStartedAt,
188195
spanFinishedAt = now,
189196
spanThreadId = maxBound,
197+
spanDisplayThreadId = maxBound,
190198
spanTags = mempty,
191199
spanEvents = [],
192200
spanParentId = Nothing,
@@ -200,6 +208,7 @@ processEvent (Event ts ev m_cap) st@(S {..}) =
200208
spanStartedAt = gcRequestedAt,
201209
spanFinishedAt = gcStartedAt,
202210
spanThreadId = maxBound,
211+
spanDisplayThreadId = maxBound,
203212
spanTags = mempty,
204213
spanEvents = [],
205214
spanParentId = Nothing,
@@ -284,12 +293,14 @@ handleOpenTelemetryEventlogEvent m st (tid, now, m_trace_id) =
284293
case HM.lookup serial $ serial2sid st of
285294
Nothing ->
286295
let (st', span_id) = inventSpanId serial st
296+
(st'', display_tid) = inventDisplayTid tid st'
287297
parent = HM.lookup tid (thread2sid st)
288298
sp =
289299
Span
290300
{ spanContext = SpanContext span_id (fromMaybe (TId 42) m_trace_id),
291301
spanOperation = "",
292302
spanThreadId = tid,
303+
spanDisplayThreadId = display_tid,
293304
spanStartedAt = 0,
294305
spanFinishedAt = now,
295306
spanTags = mempty,
@@ -298,7 +309,7 @@ handleOpenTelemetryEventlogEvent m st (tid, now, m_trace_id) =
298309
spanNanosecondsSpentInGC = 0,
299310
spanParentId = parent
300311
}
301-
in (createSpan span_id sp st', [], [])
312+
in (createSpan span_id sp st'', [], [])
302313
Just span_id ->
303314
let (st', sp) = emitSpan serial span_id st
304315
in (st', [sp {spanFinishedAt = now}], [])
@@ -307,11 +318,13 @@ handleOpenTelemetryEventlogEvent m st (tid, now, m_trace_id) =
307318
Nothing ->
308319
let (st', span_id) = inventSpanId serial st
309320
parent = HM.lookup tid (thread2sid st)
321+
(st'', display_tid) = inventDisplayTid tid st'
310322
sp =
311323
Span
312324
{ spanContext = SpanContext span_id (fromMaybe (TId 42) m_trace_id),
313325
spanOperation = operation,
314326
spanThreadId = tid,
327+
spanDisplayThreadId = display_tid,
315328
spanStartedAt = now,
316329
spanFinishedAt = 0,
317330
spanTags = mempty,
@@ -320,10 +333,10 @@ handleOpenTelemetryEventlogEvent m st (tid, now, m_trace_id) =
320333
spanNanosecondsSpentInGC = 0,
321334
spanParentId = parent
322335
}
323-
in (createSpan span_id sp st', [], [])
336+
in (createSpan span_id sp st'', [], [])
324337
Just span_id ->
325338
let (st', sp) = emitSpan serial span_id st
326-
in (st', [sp {spanOperation = operation, spanStartedAt = now, spanThreadId = tid}], [])
339+
in (st', [sp {spanOperation = operation, spanStartedAt = now}], [])
327340
DeclareInstrumentEv iType iId iName ->
328341
(st {instrumentMap = HM.insert iId (CaptureInstrument iType iName) (instrumentMap st)}, [], [])
329342
MetricCaptureEv instrumentId val -> case HM.lookup instrumentId (instrumentMap st) of
@@ -396,6 +409,14 @@ inventSpanId serial st = (st', sid)
396409
(SId -> sid, randomGen') = R.nextWord64 randomGen
397410
st' = st {serial2sid = HM.insert serial sid serial2sid, randomGen = randomGen'}
398411

412+
inventDisplayTid :: ThreadId -> State -> (State, ThreadId)
413+
inventDisplayTid tid st@(S {thread2displayThread, nextFreeDisplayThread}) =
414+
case HM.lookup tid thread2displayThread of
415+
Nothing ->
416+
let new_dtid = nextFreeDisplayThread
417+
in (st {thread2displayThread = HM.insert tid new_dtid thread2displayThread, nextFreeDisplayThread = new_dtid + 1}, new_dtid)
418+
Just dtid -> (st, dtid)
419+
399420
parseText :: [T.Text] -> Maybe OpenTelemetryEventlogEvent
400421
parseText =
401422
\case

stack-8.10.yaml

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
resolver: nightly-2021-01-05
1+
resolver: nightly-2021-04-02
22

33
packages:
44
- megaexample
@@ -10,8 +10,5 @@ packages:
1010
allow-newer: true
1111

1212
extra-deps:
13-
- ghc-events-0.13.0
14-
- ghc-trace-events-0.1.0.1
15-
- hvega-0.9.1.0
1613
- jsonifier-0.1.0.5
1714
- ptr-poker-0.1.1.3

0 commit comments

Comments
 (0)