Skip to content

Commit 69af29f

Browse files
committed
changed docu generator
1 parent b11617e commit 69af29f

File tree

6 files changed

+190
-134
lines changed

6 files changed

+190
-134
lines changed

cardano-node/src/Cardano/Node/Tracing/Documentation.hs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
{-# LANGUAGE StandaloneDeriving #-}
1010
{-# LANGUAGE TypeOperators #-}
1111
{-# OPTIONS_GHC -Wno-orphans #-}
12+
{-# LANGUAGE TemplateHaskell #-}
1213

1314
module Cardano.Node.Tracing.Documentation
1415
( TraceDocumentationCmd (..)
@@ -117,6 +118,11 @@ import qualified Network.Mux as Mux
117118
import qualified Network.Socket as Socket
118119
import qualified Options.Applicative as Opt
119120
import System.IO
121+
import Data.Time (getZonedTime)
122+
import Data.Text (pack)
123+
import Cardano.Git.Rev (gitRev)
124+
import Paths_cardano_node (version)
125+
import Data.Version (showVersion)
120126

121127

122128
data TraceDocumentationCmd
@@ -832,6 +838,7 @@ docTracersFirstPhase condConfigFileName = do
832838
<> dtAcceptPolicyTrDoc
833839
-- Internal tracer
834840
<> internalTrDoc
841+
835842
pure (bl,trConfig)
836843

837844
docTracersSecondPhase ::
@@ -841,8 +848,15 @@ docTracersSecondPhase ::
841848
-> DocTracer
842849
-> IO ()
843850
docTracersSecondPhase outputFileName mbMetricsHelpFilename trConfig bl = do
844-
docuResultsToText bl trConfig
845-
>>= doWrite outputFileName
851+
text <- docuResultsToText bl trConfig
852+
time <- getZonedTime
853+
let stamp = "Generated at "
854+
<> pack (show time)
855+
<> ", git commit hash "
856+
<> $(gitRev)
857+
<> ", node version "
858+
<> pack (showVersion version) <> "\n"
859+
doWrite outputFileName (text <> stamp)
846860
forM_ mbMetricsHelpFilename $ \f ->
847861
doWrite f (docuResultsToMetricsHelptext bl)
848862
where

trace-dispatcher/src/Cardano/Logging/DocuGenerator.hs

Lines changed: 78 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,34 @@ module Cardano.Logging.DocuGenerator (
2020
, addLimiter
2121
, addSilent
2222
, addDocumentedNamespace
23-
2423
, DocuResult
2524
, DocTracer(..)
2625
) where
2726

2827
import Cardano.Logging.ConfigurationParser ()
28+
import Cardano.Logging.DocuGenerator.RoseTree
29+
import Cardano.Logging.DocuResult (DocuResult (..))
30+
import qualified Cardano.Logging.DocuResult as DocuResult
2931
import Cardano.Logging.Types
32+
import Cardano.Logging.Utils (indent)
3033

3134
import Prelude hiding (lines, unlines)
3235

36+
import Control.Monad (mfilter)
3337
import Control.Monad.IO.Class (MonadIO, liftIO)
3438
import qualified Control.Tracer as TR
3539
import Data.Aeson (ToJSON)
3640
import qualified Data.Aeson.Encode.Pretty as AE
3741
import Data.IORef (modifyIORef, newIORef, readIORef)
38-
import Data.List (groupBy, intersperse, nub, sortBy)
42+
import Data.List (find, groupBy, intersperse, isPrefixOf, nub, sortBy)
3943
import qualified Data.Map.Strict as Map
40-
import Data.Maybe (fromMaybe, mapMaybe)
41-
import Data.Text as T (Text, empty, intercalate, lines, pack, split, stripPrefix, toLower,
44+
import Data.Maybe (fromJust, fromMaybe, mapMaybe)
45+
import Data.Text (split)
46+
import Data.Text as T (Text, empty, intercalate, lines, pack, stripPrefix, toLower,
4247
unlines)
4348
import Data.Text.Internal.Builder (toLazyText)
4449
import Data.Text.Lazy (toStrict)
4550
import Data.Text.Lazy.Builder (Builder, fromString, fromText, singleton)
46-
import Data.Time (getZonedTime)
4751

4852
import Trace.Forward.Utils.DataPoint (DataPoint (..))
4953

@@ -65,12 +69,6 @@ addDocumentedNamespace out (Documented list) =
6569
(\ dm@DocMsg {} -> dm {dmNamespace = nsReplacePrefix out (dmNamespace dm)})
6670
list
6771

68-
data DocuResult =
69-
DocuTracer Builder
70-
| DocuMetric Builder
71-
| DocuDatapoint Builder
72-
deriving (Show)
73-
7472
data DocTracer = DocTracer {
7573
dtTracerNames :: [[Text]]
7674
, dtSilent :: [[Text]]
@@ -87,23 +85,6 @@ instance Semigroup DocTracer where
8785
(dtBuilderList dtl <> dtBuilderList dtr)
8886
(dtWarnings dtl <> dtWarnings dtr)
8987

90-
isTracer :: DocuResult -> Bool
91-
isTracer DocuTracer {} = True
92-
isTracer _ = False
93-
94-
isMetric :: DocuResult -> Bool
95-
isMetric DocuMetric {} = True
96-
isMetric _ = False
97-
98-
isDatapoint :: DocuResult -> Bool
99-
isDatapoint DocuDatapoint {} = True
100-
isDatapoint _ = False
101-
102-
unpackDocu :: DocuResult -> Builder
103-
unpackDocu (DocuTracer b) = b
104-
unpackDocu (DocuMetric b) = b
105-
unpackDocu (DocuDatapoint b) = b
106-
10788
documentTracer' :: forall a a1.
10889
MetaTrace a
10990
=> (Trace IO a1 -> IO (Trace IO a))
@@ -186,7 +167,7 @@ documentTracer tracer = do
186167
documentMetrics' :: [( (Text, Text) , [([Text],[Text])] )] -> Maybe ([Text], DocuResult)
187168
documentMetrics' ncns@(((name, comment), _) : _tail) =
188169
Just ([name], DocuMetric
189-
$ mconcat $ intersperse(fromText "\n\n")
170+
$ mconcat $ intersperse (fromText "\n\n")
190171
[ metricToBuilder (name,comment)
191172
, namespacesMetricsBuilder (nub (concatMap snd ncns))
192173
])
@@ -196,7 +177,7 @@ documentTracer tracer = do
196177
namespacesBuilder [ns] = namespaceBuilder ns
197178
namespacesBuilder [] = fromText "__Warning__: namespace missing"
198179
namespacesBuilder nsl =
199-
mconcat (intersperse (singleton '\n')(map namespaceBuilder nsl))
180+
mconcat (intersperse (singleton '\n') (map namespaceBuilder nsl))
200181

201182
namespaceBuilder :: ([Text], [Text]) -> Builder
202183
namespaceBuilder (nsPr, nsPo) = fromText "### " <>
@@ -206,7 +187,7 @@ documentTracer tracer = do
206187
namespacesMetricsBuilder [ns] = fromText "Dispatched by: \n" <> namespaceMetricsBuilder ns
207188
namespacesMetricsBuilder [] = mempty
208189
namespacesMetricsBuilder nsl = fromText "Dispatched by: \n" <>
209-
mconcat (intersperse (singleton '\n')(map namespaceMetricsBuilder nsl))
190+
mconcat (intersperse (singleton '\n') (map namespaceMetricsBuilder nsl))
210191

211192
namespaceMetricsBuilder :: ([Text], [Text]) -> Builder
212193
namespaceMetricsBuilder (nsPr, nsPo) = mconcat (intersperse (singleton '.')
@@ -453,13 +434,12 @@ docItDatapoint _backend (LoggingContext {}, _) = pure ()
453434
-- Finally generate a text from all the builders
454435
docuResultsToText :: DocTracer -> TraceConfig -> IO Text
455436
docuResultsToText dt@DocTracer {..} configuration = do
456-
time <- getZonedTime
457437
let traceBuilders = sortBy (\ (l,_) (r,_) -> compare l r)
458-
(filter (isTracer . snd) dtBuilderList)
438+
(filter (DocuResult.isTracer . snd) dtBuilderList)
459439
metricsBuilders = sortBy (\ (l,_) (r,_) -> compare l r)
460-
(filter (isMetric .snd) dtBuilderList)
440+
(filter (DocuResult.isMetric .snd) dtBuilderList)
461441
datapointBuilders = sortBy (\ (l,_) (r,_) -> compare l r)
462-
(filter (isDatapoint . snd) dtBuilderList)
442+
(filter (DocuResult.isDatapoint . snd) dtBuilderList)
463443
header = fromText "# Cardano Trace Documentation\n\n"
464444
header1 = fromText "## Table Of Contents\n\n"
465445
toc = generateTOC dt
@@ -469,13 +449,13 @@ docuResultsToText dt@DocTracer {..} configuration = do
469449

470450
header2 = fromText "\n## Trace Messages\n\n"
471451
contentT = mconcat $ intersperse (fromText "\n\n")
472-
(map (unpackDocu . snd) traceBuilders)
452+
(map (DocuResult.unpackDocu . snd) traceBuilders)
473453
header3 = fromText "\n## Metrics\n\n"
474454
contentM = mconcat $ intersperse (fromText "\n\n")
475-
(map (unpackDocu . snd) metricsBuilders)
455+
(map (DocuResult.unpackDocu . snd) metricsBuilders)
476456
header4 = fromText "\n## Datapoints\n\n"
477457
contentD = mconcat $ intersperse (fromText "\n\n")
478-
(map (unpackDocu . snd) datapointBuilders)
458+
(map (DocuResult.unpackDocu . snd) datapointBuilders)
479459
config = fromText "\n## Configuration: \n```\n"
480460
<> AE.encodePrettyToTextBuilder configuration
481461
<> fromText "\n```\n"
@@ -486,7 +466,6 @@ docuResultsToText dt@DocTracer {..} configuration = do
486466
legend = fromText $ utf16CircledT <> "- This is the root of a tracer\n\n" <>
487467
utf16CircledS <> "- This is the root of a tracer that is silent because of the current configuration\n\n" <>
488468
utf16CircledM <> "- This is the root of a tracer, that provides metrics\n\n"
489-
ts = fromString $ "Generated at " <> show time <> ".\n"
490469
pure $ toStrict $ toLazyText (
491470
header
492471
<> header1
@@ -499,114 +478,90 @@ docuResultsToText dt@DocTracer {..} configuration = do
499478
<> contentD
500479
<> config
501480
<> numbers
502-
<> legend
503-
<> ts)
504-
481+
<> legend)
505482

506483
generateTOC :: DocTracer -> [[Text]] -> [[Text]] -> [[Text]] -> Builder
507-
generateTOC dt traces metrics datapoints =
484+
generateTOC DocTracer {..} traces metrics datapoints =
508485
generateTOCTraces
509486
<> generateTOCMetrics
510487
<> generateTOCDatapoints
511488
<> generateTOCRest
512489
where
490+
tracesTree = mapMaybe (trim []) (toTree traces)
491+
metricsTree = toTree (fmap splitToNS metrics)
492+
datapointsTree = toTree datapoints
493+
513494
generateTOCTraces =
514495
fromText "### [Trace Messages](#trace-messages)\n\n"
515-
<> mconcat (reverse (fst (foldl (namespaceToToc (Just dt)) ([], []) traces)))
496+
<> mconcat (map (namespaceToToc traces False []) tracesTree)
516497
<> fromText "\n"
517498
generateTOCMetrics =
518499
fromText "### [Metrics](#metrics)\n\n"
519-
<> mconcat (reverse (fst (foldl (namespaceToToc Nothing) ([], []) (map splitToNS metrics))))
500+
<> mconcat (map (namespaceToToc (fmap splitToNS metrics) True []) metricsTree)
520501
<> fromText "\n"
521502
generateTOCDatapoints =
522503
fromText "### [Datapoints](#datapoints)\n\n"
523-
<> mconcat (reverse (fst (foldl (namespaceToToc Nothing) ([], []) datapoints)))
504+
<> mconcat (map (namespaceToToc datapoints True []) datapointsTree)
524505
<> fromText "\n"
525506
generateTOCRest =
526507
fromText "### [Configuration](#configuration)\n\n"
527508
<> fromText "\n"
528509

529-
530-
namespaceToToc :: Maybe DocTracer -> ([Builder], [Text]) -> [Text]-> ([Builder], [Text])
531-
namespaceToToc condDocTracer (builders, context) ns =
532-
let ref = namespaceRefBuilder ns
533-
in case ns of
534-
(hd:tl) -> if init (hd:tl) == context
535-
then
536-
let symbolsText = case condDocTracer of
537-
Nothing -> ""
538-
Just docTracers -> getSymbolsOf ns docTracers
539-
in ( fromString (concat (replicate (length context) " "))
540-
<> fromText "1. "
541-
<> fromText "["
542-
<> fromText (last ns)
543-
<> fromText symbolsText
544-
<> fromText "](#"
545-
<> ref
546-
<> fromText ")\n" : builders, context)
547-
else
548-
let cpl = commonPrefixLength context ns
549-
ns' = drop cpl ns
550-
context' = take cpl context
551-
in namespaceToTocWithContext condDocTracer (builders, context') ns' ns ref
552-
[] -> ([],[])
553-
namespaceToTocWithContext ::
554-
Maybe DocTracer
555-
-> ([Builder], [Text])
556-
-> [Text]
557-
-> [Text]
558-
-> Builder
559-
-> ([Builder], [Text])
560-
namespaceToTocWithContext condDocTracer (builders, context) ns nsFull ref =
561-
case ns of
562-
[single] -> let symbolsText = case condDocTracer of
563-
Nothing -> ""
564-
Just docTracers -> getSymbolsOf (context ++ [single]) docTracers
565-
in ((fromString (concat (replicate (length context) " "))
566-
<> fromText "1. "
567-
<> fromText "["
568-
<> fromText single
569-
<> fromText symbolsText
570-
<> fromText "](#"
571-
<> ref
572-
<> fromText ")\n") : builders, context)
573-
(hdn : tln) ->
574-
let symbolsText = case condDocTracer of
575-
Nothing -> ""
576-
Just docTracers -> getSymbolsOf (context ++ [hdn]) docTracers
577-
builder = fromString (concat (replicate (length context) " "))
578-
<> fromText "1. __"
579-
<> fromText hdn
580-
<> fromText symbolsText
581-
<> fromText "__\n"
582-
in namespaceToTocWithContext condDocTracer
583-
(builder : builders, context ++ [hdn]) tln nsFull ref
584-
[] -> error "inpossible"
585-
586510
splitToNS :: [Text] -> [Text]
587511
splitToNS [sym] = split (== '.') sym
588512
splitToNS other = other
589513

590-
getSymbolsOf :: [Text] -> DocTracer -> Text
591-
getSymbolsOf ns DocTracer {..} =
592-
let isTracer' = elem ns dtTracerNames
593-
in if isTracer'
594-
then
595-
let isSilent = elem ns dtSilent
596-
noMetrics = elem ns dtNoMetrics
597-
in utf16CircledT <> if isSilent then utf16CircledS else ""
598-
<> if noMetrics then "" else utf16CircledM
599-
else ""
600-
601-
commonPrefixLength :: Eq a => [a] -> [a] -> Int
602-
commonPrefixLength [] _ = 0
603-
commonPrefixLength _ [] = 0
604-
commonPrefixLength (a : ta) (b : tb) =
605-
if a == b
606-
then 1 + commonPrefixLength ta tb
607-
else 0
608-
609-
namespaceRefBuilder ns = mconcat (map (fromText . toLower ) ns)
514+
isTracerSymbol :: [Text] -> Bool
515+
isTracerSymbol tracer = tracer `elem` dtTracerNames
516+
517+
-- Modify the given tracer tree so that the result is a tree where entries which
518+
-- are not tracers are removed. In case the whole tree doesn't contain a tracer, return Nothing.
519+
trim :: [Text] {- accumulated namespace in reverse -} -> RoseTree -> Maybe RoseTree
520+
trim ns (RoseTree x nested) =
521+
let that = reverse (x : ns)
522+
-- List of all nested tracers that we shall render
523+
nestedTrimmed = mapMaybe (trim (x : ns)) nested in
524+
mfilter (\_ -> not (null nestedTrimmed) || isTracerSymbol that) (Just (RoseTree x nestedTrimmed))
525+
526+
namespaceToToc ::
527+
[[Text]]
528+
-> Bool
529+
-> [Text] {- Accumulated namespace in reverse -}
530+
-> RoseTree
531+
-> Builder
532+
namespaceToToc allTracers skipSymbols accns (RoseTree x nested) = text
533+
where
534+
ns = reverse (x : accns)
535+
536+
inner = mconcat (map (namespaceToToc allTracers skipSymbols (x : accns)) nested)
537+
538+
text :: Builder
539+
text =
540+
indent (length accns)
541+
(
542+
"1. "
543+
<> "[" <> fromText x <> fromText symbolsText <> "]"
544+
<> "(#" <> link <> ")\n"
545+
) <> inner
546+
547+
symbolsText :: Text
548+
symbolsText = if skipSymbols then "" else
549+
let isTracer = elem ns dtTracerNames
550+
isSilent = elem ns dtSilent
551+
isMetric = notElem ns dtNoMetrics
552+
in
553+
(if isTracer then utf16CircledT else "")
554+
<> (if isSilent then utf16CircledS else "")
555+
<> (if isMetric then utf16CircledM else "")
556+
557+
-- The link to the description of the first tracer in that namespace
558+
link :: Builder
559+
link = mconcat (map (fromText . toLower) firstTracer)
560+
561+
-- The first tracer in the list of tracers that has that namespace prefix
562+
firstTracer :: [Text]
563+
firstTracer = fromJust $ find (ns `isPrefixOf`) allTracers
564+
610565

611566
asCode :: Builder -> Builder
612567
asCode b = singleton '`' <> b <> singleton '`'

0 commit comments

Comments
 (0)