diff --git a/bench/trace-analyzer/CHANGELOG.md b/bench/trace-analyzer/CHANGELOG.md new file mode 100644 index 00000000000..f5563d862bd --- /dev/null +++ b/bench/trace-analyzer/CHANGELOG.md @@ -0,0 +1,3 @@ +# ChangeLog + +## 0.1.0 diff --git a/bench/trace-analyzer/LICENSE b/bench/trace-analyzer/LICENSE new file mode 100644 index 00000000000..05f60f1016f --- /dev/null +++ b/bench/trace-analyzer/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Input Output (Hong Kong) Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/bench/trace-analyzer/NOTICE b/bench/trace-analyzer/NOTICE new file mode 100644 index 00000000000..309ff5ce006 --- /dev/null +++ b/bench/trace-analyzer/NOTICE @@ -0,0 +1,13 @@ +Copyright 2022 Input Output (Hong Kong) Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/bench/trace-analyzer/README.md b/bench/trace-analyzer/README.md new file mode 100644 index 00000000000..8e0aa557ca6 --- /dev/null +++ b/bench/trace-analyzer/README.md @@ -0,0 +1,11 @@ +# trace-analyzer + +`trace-analyzer` is an application for analyzing traces produced by `cardano-node`. + +For more details please [read the documentation] +TODO + +## Developers + +Benchmarking team is responsible for this library. The primary developer is +[@Jürgen Nicklisch-Franken](https://github.com/jutaro). diff --git a/bench/trace-analyzer/src/Cardano/Tracer/Analyze/CLI.hs b/bench/trace-analyzer/src/Cardano/Tracer/Analyze/CLI.hs new file mode 100644 index 00000000000..6a3424b1866 --- /dev/null +++ b/bench/trace-analyzer/src/Cardano/Tracer/Analyze/CLI.hs @@ -0,0 +1,31 @@ +{-# LANGUAGE ScopedTypeVariables #-} + +module Cardano.Tracer.Analyze.CLI + ( parseAnalyzerParams + ) where + +import Cardano.Tracer.Analyze.Types + +import Options.Applicative + +parseAnalyzerParams :: Parser AnalyzerParams +parseAnalyzerParams = AnalyzerParams <$> + strOption ( + long "trace1" + <> short '1' + <> metavar "FILEPATH" + <> help "First file with trace messages" + <> completer (bashCompleter "file") + ) + <*> strOption ( + long "trace2" + <> short '2' + <> metavar "FILEPATH" + <> help "Second file with trace messages" + <> completer (bashCompleter "file") + ) + <*> switch ( + long "isHuman" + <> short 'u' + <> help "Analyze in human format." + ) diff --git a/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Process.hs b/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Process.hs new file mode 100644 index 00000000000..da17fd5923c --- /dev/null +++ b/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Process.hs @@ -0,0 +1,87 @@ +{-# LANGUAGE ScopedTypeVariables #-} + +module Cardano.Tracer.Analyze.Process + ( parseAndPreprocess + , extractNamespace + ) where + +import Cardano.Tracer.Analyze.Types (FileDBM (..), LineNumber) + +import qualified Data.Aeson as AE +import qualified Data.Aeson.KeyMap as AE +import qualified Data.Attoparsec.ByteString.Char8 as Atto +import qualified Data.ByteString.Char8 as BS +import Data.Either (partitionEithers) +import Data.Foldable (foldl') +import qualified Data.Map as Map +import qualified Data.Text as Txt +import qualified Data.Vector as V + +parseAndPreprocess :: FilePath -> IO FileDBM +parseAndPreprocess fp = do + bs <- BS.readFile fp + let jsonOrErrorLines = + map + (Atto.parseOnly (AE.json <* Atto.endOfInput)) + (BS.lines bs) + jsonOrErrorLineswithLineNumbers = + zipWith + (\e ln -> case e of + Left l -> Left (ln, l) + Right r -> Right (ln, r)) + jsonOrErrorLines + [1 .. ] + (errors, sane) = partitionEithers jsonOrErrorLineswithLineNumbers + kindDict :: Map.Map Txt.Text [(LineNumber, AE.Value)] = + foldl' (\dict (ln, val) -> + Map.insertWith + (++) + (extractKey val) + [(ln, val)] + dict) + Map.empty + sane + valueDict :: Map.Map LineNumber AE.Value = Map.fromList sane + pure $ FileDBM (Txt.pack fp) (length sane) kindDict errors valueDict + +extractKey :: AE.Value -> Txt.Text +extractKey val = + case extractKeyKind val of + Just txt -> txt + Nothing -> + case extractNamespace val of + Just txt -> "NS:" <> txt + Nothing -> "Unclassified" + +extractNamespace :: AE.Value -> Maybe Txt.Text +extractNamespace val = + case val of + AE.Object obj -> + case AE.lookup "ns" obj of + Just arr -> case arr of + AE.Array vec -> + if not (V.null vec) + then case V.head vec of + AE.String txt -> Just txt + _ -> Nothing + else Nothing + AE.String txt -> Just txt + _ -> Nothing + _ -> Nothing + _ -> Nothing + + +extractKeyKind :: AE.Value -> Maybe Txt.Text +extractKeyKind val = + case val of + AE.Object obj -> + case AE.lookup "data" obj of + Just val' -> case val' of + AE.Object obj' -> case AE.lookup "kind" obj' of + Just val'' -> case val'' of + AE.String txt -> Just txt + _ -> Nothing + _ -> Nothing + _ -> Nothing + _ -> Nothing + _ -> Nothing diff --git a/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Report.hs b/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Report.hs new file mode 100644 index 00000000000..5b4e90f91f7 --- /dev/null +++ b/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Report.hs @@ -0,0 +1,158 @@ +{-# LANGUAGE ScopedTypeVariables #-} + +module Cardano.Tracer.Analyze.Report + ( report + ) where + +import Control.Monad (when) +import qualified Data.Aeson as AE +import Data.ByteString.Lazy (toStrict) +import Data.List (nub, (\\)) +import qualified Data.Map as Map +import Data.Text (Text, drop, isPrefixOf, unpack) +import Data.Text.Encoding (decodeUtf8) + +import Cardano.Tracer.Analyze.Process (extractNamespace) +import Cardano.Tracer.Analyze.Types + +report :: FileDBM -> FileDBM -> IO () +report fdbm1 fdbm2 = do + putStrLn "Trace analyzer report:" + putStrLn $ "\nTotal messages db1 " <> + show (fdbLengthTotal fdbm1) + putStrLn $ "Different messages db1 " <> + show (length (Map.toList (fdbKindMap fdbm1))) + putStrLn $ "\nTotal messages db2 " <> + show (fdbLengthTotal fdbm2) + putStrLn $ "Different messages db2 " <> + show (length (Map.toList (fdbKindMap fdbm2))) + putStrLn "" + + reportParseErrors "db1" fdbm1 + reportParseErrors "db2" fdbm2 + + _ <- reportUnclassified "db1" fdbm1 + _ <- reportUnclassified "db2" fdbm2 + + reportClassifiedByNS "db1" fdbm1 + reportClassifiedByNS "db2" fdbm2 + + _ <- reportMissingEntriesOf "db1" fdbm1 "db2" fdbm2 + count1 <- reportMissingEntriesOf "db2" fdbm2 "db1" fdbm1 + + count2 <- reportCommonEntries fdbm1 fdbm2 + putStrLn $ "\n\nTotal number of different new messages db2 " + <> show (count1 + count2) + + + +reportParseErrors :: Text -> FileDBM -> IO () +reportParseErrors txt fdbm = + case fdbErrors fdbm of + [] -> putStrLn $ "No parse errors in " <> unpack txt + l -> do + putStrLn $ "Parse errors in " <> unpack txt + mapM_ printParseError l + where + printParseError :: (LineNumber, String) -> IO () + printParseError (ln,val) = putStrLn $ show ln <> " " <> show val + +reportUnclassified :: Text -> FileDBM -> IO Int +reportUnclassified txt fdbm = + case Map.lookup "Unclassified" (fdbKindMap fdbm) of + Nothing -> do + putStrLn $ "\nNo unclassifieds in " <> unpack txt + pure 0 + Just l -> do + putStrLn $ "\nUnclassifieds in " <> unpack txt + mapM_ printUnclassifiedError l + pure (length l) + where + printUnclassifiedError :: (LineNumber, AE.Value) -> IO () + printUnclassifiedError (ln,val) = + putStrLn $ show ln <> " " <> unpack (decodeUtf8 (toStrict (AE.encode val))) + +reportClassifiedByNS :: Text -> FileDBM -> IO () +reportClassifiedByNS txt fdbm = + case filter (isPrefixOf "NS:") (Map.keys (fdbKindMap fdbm)) of + [] -> putStrLn $ "\nNo classified by Namespace in " <> unpack txt + l -> do + putStrLn $ "\nClassified by Namespace in " <> unpack txt + mapM_ printClassifiedByNSError l + where + printClassifiedByNSError :: Text -> IO () + printClassifiedByNSError txt' = + case Map.lookup txt' (fdbKindMap fdbm) of + Nothing -> putStrLn $ "Can't find entry for " <> show txt' + Just l -> mapM_ (\(ln, val) -> + putStrLn $ show ln <> " " <> + unpack (decodeUtf8 (toStrict (AE.encode val)))) l + +reportMissingEntriesOf :: Text -> FileDBM -> Text -> FileDBM -> IO Int +reportMissingEntriesOf txt1 fdbm1 txt2 fdbm2 = + let keys1 = map canonicalizeKinds (Map.keys (fdbKindMap fdbm1)) + keys2 = map canonicalizeKinds (Map.keys (fdbKindMap fdbm2)) + in case keys1 \\ keys2 of + [] -> do + putStrLn $ "\nNo entries of " <> unpack txt1 <> " are missing in " <> unpack txt2 + pure 0 + l -> do + putStrLn $ "\nThese entries of " <> unpack txt1 <> " are missing in " <> unpack txt2 + mapM_ printMissingError l + pure (length l) + where + printMissingError :: Text -> IO () + printMissingError txt = + case Map.lookup txt (fdbKindMap fdbm1) of + Nothing -> case Map.lookup ("Trace" <> txt) (fdbKindMap fdbm1) of + Just l -> putStrLn $ unpack ("Trace" <> txt) <> " number of entries " + <> show (length l) + Nothing -> putStrLn $ "Can't find entry for " <> unpack txt + Just l -> putStrLn $ unpack txt <> " number of entries " + <> show (length l) + +canonicalizeKinds :: Text -> Text +canonicalizeKinds "ChainSyncClientEvent.TraceDownloadedHeader" = "DownloadedHeader" +canonicalizeKinds "ChainSyncClientEvent.TraceFoundIntersection" = "FoundIntersection" +canonicalizeKinds "ChainSyncClientEvent.TraceRolledBack" = "RolledBack" +canonicalizeKinds "NS:cardano.node.BlockFetchDecision" = "NS:Cardano.Node.BlockFetchDecision" +canonicalizeKinds "TraceImmutableDBEvent.ValidatedLastLocation" = "ImmDbEvent.ValidatedLastLocation" +canonicalizeKinds "TraceImmutableDBEvent.ValidatingChunk" = "ImmDbEvent.ValidatingChunk" +canonicalizeKinds "TraceInitChainSelEvent.ValidCandidate" = "InitChainSelEvent.ValidCandidate" +canonicalizeKinds key = if "Trace" `isPrefixOf` key + then Data.Text.drop 5 key + else key + +reportCommonEntries :: FileDBM -> FileDBM -> IO Int +reportCommonEntries fdbm1 fdbm2 = + let keys = Map.keys (fdbKindMap fdbm1) + keysCanonicalized = zip keys (map canonicalizeKinds keys) + in do + putStrLn "\n\nReporting common entries" + l <- mapM (reportCommonEntry fdbm1 fdbm2) keysCanonicalized + pure (sum l) + +reportCommonEntry :: FileDBM -> FileDBM -> (KindName, KindName) -> IO Int +reportCommonEntry fdbm1 fdbm2 (kindName, kindNameCanonicalized) = + case Map.lookup kindName (fdbKindMap fdbm1) of + Just valuelist1 -> + case Map.lookup kindNameCanonicalized (fdbKindMap fdbm2) of + Just valuelist2 -> do + putStrLn $ "\n\nReporting on " <> unpack kindName + <> " old occurences " <> show (length valuelist1) + <> " new occurences " <> show (length valuelist2) + when (kindName /= kindNameCanonicalized) $ + putStrLn $ "\nCanonicalized as " <> unpack kindNameCanonicalized + let oldNamespaces = nub $ map (extractNamespace . snd) valuelist1 + let newNamespaces = nub $ map (extractNamespace . snd) valuelist2 + case length oldNamespaces of + 0 -> putStrLn "\n\tNo old namespace!" + 1 -> putStrLn $ "\n\tOld namespace " <> show (head oldNamespaces) + _ -> putStrLn $ "\n\tOld namespaces " <> show oldNamespaces + case length newNamespaces of + 0 -> putStrLn "\n\tWARNING No new namespace!" + 1 -> putStrLn $ "\n\tNew namespace " <> show (head newNamespaces) + _ -> putStrLn $ "\n\tWARNING New namespaces " <> show newNamespaces + pure (length newNamespaces) + Nothing -> pure 0 + Nothing -> pure 0 diff --git a/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Types.hs b/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Types.hs new file mode 100644 index 00000000000..f4d94026d8d --- /dev/null +++ b/bench/trace-analyzer/src/Cardano/Tracer/Analyze/Types.hs @@ -0,0 +1,31 @@ +module Cardano.Tracer.Analyze.Types + ( + AnalyzerParams(..) + , LineNumber + , KindName + , FileDBM(..) + ) where + +import Data.Aeson (Value) +import Data.Map +import Data.Text + +-- | Type for CLI parameters required for the service. +data AnalyzerParams = AnalyzerParams + { apTrace1 :: FilePath + , apTrace2 :: FilePath + , apIsHuman :: Bool + } deriving (Show) + +type LineNumber = Int + +type KindName = Text + +data FileDBM = FileDBM { + fdbFileName :: Text + , fdbLengthTotal :: Int + , fdbKindMap :: Map KindName [(LineNumber, Value)] + , fdbErrors :: [(LineNumber, String)] + , fdbValues :: Map LineNumber Value + } + deriving Show diff --git a/bench/trace-analyzer/src/trace-analyzer.hs b/bench/trace-analyzer/src/trace-analyzer.hs new file mode 100644 index 00000000000..ae8033545d9 --- /dev/null +++ b/bench/trace-analyzer/src/trace-analyzer.hs @@ -0,0 +1,26 @@ +import Data.Version (showVersion) +import Options.Applicative + +import Cardano.Tracer.Analyze.CLI +import Cardano.Tracer.Analyze.Process +import Cardano.Tracer.Analyze.Report +import Cardano.Tracer.Analyze.Types +import Paths_trace_analyzer (version) + +main :: IO () +main = do + tracerParams <- customExecParser (prefs showHelpOnEmpty) analyzerInfo + db1 <- parseAndPreprocess (apTrace1 tracerParams) + db2 <- parseAndPreprocess (apTrace2 tracerParams) + report db1 db2 + pure () + where + analyzerInfo :: ParserInfo AnalyzerParams + analyzerInfo = info + (parseAnalyzerParams <**> helper <**> versionOption) + (fullDesc <> header "cardano-analyzer - the tracer analyzer service for Cardano node.") + versionOption = infoOption + (showVersion version) + (long "version" <> + short 'v' <> + help "Show version") diff --git a/bench/trace-analyzer/trace-analyzer.cabal b/bench/trace-analyzer/trace-analyzer.cabal new file mode 100644 index 00000000000..b62a8958d5a --- /dev/null +++ b/bench/trace-analyzer/trace-analyzer.cabal @@ -0,0 +1,55 @@ +cabal-version: 2.4 +name: trace-analyzer +version: 0.1.0 +synopsis: See README for more info +description: See README for more info +license: Apache-2.0 +license-file: LICENSE +copyright: 2022 Input Output (Hong Kong) Ltd. +author: IOHK +maintainer: operations@iohk.io +build-type: Simple +extra-doc-files: README.md + CHANGELOG.md + +common base { build-depends: base >= 4.14 && < 4.15 } + +common project-config + default-language: Haskell2010 + + ghc-options: -Wall + -Wcompat + -Wincomplete-record-updates + -Wincomplete-uni-patterns + -Wno-unticked-promoted-constructors + -Wno-orphans + -Wpartial-fields + -Wredundant-constraints + -Wunused-packages + + default-extensions: OverloadedStrings + +executable trace-analyzer + import: base, project-config + + hs-source-dirs: src + + main-is: trace-analyzer.hs + + build-depends: aeson + , optparse-applicative + , text + , containers + , attoparsec + , bytestring + , vector + + ghc-options: -threaded + -rtsopts + -with-rtsopts=-T + + other-modules: Paths_trace_analyzer + , Cardano.Tracer.Analyze.CLI + , Cardano.Tracer.Analyze.Process + , Cardano.Tracer.Analyze.Types + , Cardano.Tracer.Analyze.Report diff --git a/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx.hs b/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx.hs index 0c5a1c000fa..e8262003061 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx.hs @@ -32,7 +32,7 @@ import Network.Socket (AddrInfo (..), AddrInfoFlag (..), Family (..), addrFamily, addrFlags, addrSocketType, defaultHints, getAddrInfo) import Cardano.CLI.Types (SigningKeyFile (..)) -import Cardano.Node.Types +import Cardano.Node.Configuration.NodeAddress import Ouroboros.Consensus.Shelley.Eras (StandardShelley) diff --git a/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx/LocalProtocolDefinition.hs b/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx/LocalProtocolDefinition.hs index eb60327b619..4b03a1b4976 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx/LocalProtocolDefinition.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx/LocalProtocolDefinition.hs @@ -1,6 +1,7 @@ {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} module Cardano.Benchmarking.GeneratorTx.LocalProtocolDefinition @@ -16,12 +17,14 @@ import Data.Version (showVersion) import Cardano.Prelude hiding (TypeError, show) import Control.Monad.Trans.Except.Extra (firstExceptT) -import Ouroboros.Network.Block (MaxSlotNo(..)) + +import Cardano.Tracing.Config (TraceOptions(..)) import qualified Cardano.Chain.Genesis as Genesis import Cardano.Node.Configuration.Logging import Cardano.Node.Configuration.POM +import Cardano.Node.Handlers.Shutdown import Cardano.Node.Protocol.Cardano import Cardano.Node.Protocol.Types (SomeConsensusProtocol) import Cardano.Node.Types @@ -44,8 +47,13 @@ startProtocol logConfigFile = do where mkLoggingLayer :: NodeConfiguration -> SomeConsensusProtocol -> ExceptT CliError IO LoggingLayer mkLoggingLayer nc ptcl = - firstExceptT (\(ConfigErrorFileNotFound fp) -> ConfigNotFoundError fp) $ - createLoggingLayer (pack $ showVersion version) nc ptcl + firstExceptT (\ case + (ConfigErrorFileNotFound fp) -> ConfigNotFoundError fp + ConfigErrorNoEKG -> EKGNotFoundError) $ + createLoggingLayer + (pack $ showVersion version) + nc {ncTraceConfig=TracingOff} + ptcl mkNodeConfig :: FilePath -> IO NodeConfiguration mkNodeConfig logConfig = do @@ -61,8 +69,7 @@ startProtocol logConfigFile = do , shelleyBulkCredsFile = Just "" } , pncValidateDB = Last $ Just False - , pncShutdownIPC = Last Nothing - , pncShutdownOnSlotSynced = Last $ Just NoMaxSlotNo + , pncShutdownConfig = Last $ Just $ ShutdownConfig Nothing Nothing , pncConfigFile = Last $ Just configFp } configYamlPc <- parseNodeConfigurationFP . Just $ configFp @@ -74,6 +81,7 @@ data CliError = GenesisReadError !FilePath !Genesis.GenesisDataError | FileNotFoundError !FilePath | ConfigNotFoundError !FilePath + | EKGNotFoundError | ProtocolInstantiationError !Text | BenchmarkRunnerError !GeneratorTx.TxGenError deriving stock Show diff --git a/bench/tx-generator/src/Cardano/Benchmarking/Script/Example.hs b/bench/tx-generator/src/Cardano/Benchmarking/Script/Example.hs index 73f6ce52ed9..f2326d2b774 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/Script/Example.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/Script/Example.hs @@ -10,7 +10,7 @@ import Data.Dependent.Sum ((==>) ) import Cardano.Api (AnyCardanoEra(..), CardanoEra(..), Quantity(..), ScriptData(..), SlotNo(..), quantityToLovelace ) import Cardano.Api.Shelley (ExecutionUnits(..)) -import Cardano.Node.Types +import Cardano.Node.Configuration.NodeAddress import Ouroboros.Network.NodeToClient (withIOManager) import Cardano.Benchmarking.Types @@ -56,7 +56,7 @@ testScript = , ImportGenesisFund DiscardTX passPartout passPartout , CreateChange LocalSocket (PayToAddr passPartout) (quantityToLovelace 10000) 1000 , RunBenchmark (DumpToFile "/tmp/tx-list.txt") SpendOutput (ThreadName "walletThread") (NumberOfTxs 1000) (TPSRate 10) - , RunBenchmark (DumpToFile "/tmp/tx-list.txt") scriptDef (ThreadName "walletThread") (NumberOfTxs 1000) (TPSRate 10) + , RunBenchmark (DumpToFile "/tmp/tx-list.txt") scriptDef (ThreadName "walletThread") (NumberOfTxs 1000) (TPSRate 10) , Reserved [] ] where diff --git a/bench/tx-generator/src/Cardano/Benchmarking/Types.hs b/bench/tx-generator/src/Cardano/Benchmarking/Types.hs index a3aa889017e..435fa2459dc 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/Types.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/Types.hs @@ -7,8 +7,7 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Cardano.Benchmarking.Types - ( - Ack(..) + ( Ack(..) , NodeIPv4Address , NumberOfInputsPerTx(..) , NumberOfOutputsPerTx(..) @@ -29,7 +28,7 @@ import Data.Word import GHC.Generics import Data.Aeson -import Cardano.Node.Types (NodeIPv4Address) +import Cardano.Node.Configuration.NodeAddress myJsonOptions :: Options myJsonOptions = defaultOptions { diff --git a/cabal.project b/cabal.project index 093c5a94d1d..9ea0e66ede9 100644 --- a/cabal.project +++ b/cabal.project @@ -84,6 +84,9 @@ package trace-dispatcher package trace-forward tests: True +package trace-resources + tests: True + -- The following is needed because Nix is doing something crazy. package byron-spec-ledger tests: False diff --git a/cardano-node-chairman/app/Cardano/Chairman.hs b/cardano-node-chairman/app/Cardano/Chairman.hs index 39ef49ace99..f1b5929a335 100644 --- a/cardano-node-chairman/app/Cardano/Chairman.hs +++ b/cardano-node-chairman/app/Cardano/Chairman.hs @@ -13,7 +13,7 @@ module Cardano.Chairman (chairmanTest) where import Cardano.Api.Protocol.Types -import Cardano.Node.Types (SocketPath (..)) +import Cardano.Node.Configuration.NodeAddress (SocketPath (..)) import Cardano.Prelude hiding (ByteString, STM, atomically, catch, option, show, throwIO) import Control.Monad.Class.MonadAsync import Control.Monad.Class.MonadST diff --git a/cardano-node-chairman/app/Cardano/Chairman/Commands/Run.hs b/cardano-node-chairman/app/Cardano/Chairman/Commands/Run.hs index 41d691013d3..e209b5a9bd3 100644 --- a/cardano-node-chairman/app/Cardano/Chairman/Commands/Run.hs +++ b/cardano-node-chairman/app/Cardano/Chairman/Commands/Run.hs @@ -14,6 +14,7 @@ import Cardano.Api.Protocol.Shelley import Cardano.Chairman (chairmanTest) import Cardano.Node.Configuration.POM (parseNodeConfigurationFP, pncProtocol) import Cardano.Node.Protocol.Types (Protocol (..)) +import Cardano.Node.Configuration.NodeAddress import Cardano.Node.Types import Cardano.Prelude hiding (option) import Control.Monad.Class.MonadTime (DiffTime) diff --git a/cardano-node/cardano-node.cabal b/cardano-node/cardano-node.cabal index 05d9eeeee6a..cd268f40c8b 100644 --- a/cardano-node/cardano-node.cabal +++ b/cardano-node/cardano-node.cabal @@ -60,7 +60,9 @@ library hs-source-dirs: src exposed-modules: Cardano.Node.Configuration.Logging + Cardano.Node.Configuration.NodeAddress Cardano.Node.Configuration.POM + Cardano.Node.Configuration.Socket Cardano.Node.Configuration.Topology Cardano.Node.Configuration.TopologyP2P Cardano.Node.Handlers.Shutdown @@ -76,14 +78,40 @@ library Cardano.Node.Queries Cardano.Node.Run Cardano.Node.STM + Cardano.Node.Startup + Cardano.Node.TraceConstraints + Cardano.Node.Tracing Cardano.Node.Types + Cardano.Node.Tracing.API + Cardano.Node.Tracing.Compat + Cardano.Node.Tracing.Documentation + Cardano.Node.Tracing.Era.Byron + Cardano.Node.Tracing.Era.HardFork + Cardano.Node.Tracing.Era.Shelley + Cardano.Node.Tracing.Tracers + Cardano.Node.Tracing.Tracers.BlockReplayProgress + Cardano.Node.Tracing.Tracers.ChainDB + Cardano.Node.Tracing.Tracers.Consensus + Cardano.Node.Tracing.Tracers.Diffusion + Cardano.Node.Tracing.Tracers.KESInfo + Cardano.Node.Tracing.Tracers.StartLeadershipCheck + Cardano.Node.Tracing.Tracers.ForgingThreadStats + Cardano.Node.Tracing.Tracers.Resources + Cardano.Node.Tracing.Tracers.Peer + Cardano.Node.Tracing.Tracers.Startup + Cardano.Node.Tracing.Tracers.Shutdown + Cardano.Node.Tracing.Tracers.P2P + Cardano.Node.Tracing.Tracers.NonP2P + Cardano.Node.Tracing.Tracers.NodeToClient + Cardano.Node.Tracing.Tracers.NodeToNode + Cardano.Node.Tracing.Formatting + Cardano.Node.Tracing.Render Cardano.Tracing.Config - Cardano.Tracing.Constraints - Cardano.Tracing.Kernel Cardano.Tracing.Metrics Cardano.Tracing.Peer Cardano.Tracing.Render Cardano.Tracing.Startup + Cardano.Tracing.Shutdown Cardano.Tracing.Tracers Cardano.Tracing.OrphanInstances.Byron Cardano.Tracing.OrphanInstances.Common @@ -93,7 +121,6 @@ library Cardano.Tracing.OrphanInstances.Shelley other-modules: Paths_cardano_node - Cardano.Node.Configuration.Socket build-depends: aeson >= 1.5.6.0 , async @@ -149,6 +176,9 @@ library , text , time , tracer-transformers + , trace-dispatcher + , trace-forward + , trace-resources , transformers , transformers-except , typed-protocols diff --git a/cardano-node/src/Cardano/Node/Configuration/Logging.hs b/cardano-node/src/Cardano/Node/Configuration/Logging.hs index 6e001d45584..56360b63688 100644 --- a/cardano-node/src/Cardano/Node/Configuration/Logging.hs +++ b/cardano-node/src/Cardano/Node/Configuration/Logging.hs @@ -1,15 +1,15 @@ -{-# LANGUAGE CPP #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE Rank2Types #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PackageImports #-} +{-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} module Cardano.Node.Configuration.Logging ( LoggingLayer (..) , EKGDirect(..) , createLoggingLayer - , nodeBasicInfo , shutdownLoggingLayer , traceCounter -- re-exports @@ -24,10 +24,11 @@ module Cardano.Node.Configuration.Logging import Cardano.Prelude hiding (trace) +import qualified Control.Concurrent as Conc import qualified Control.Concurrent.Async as Async import Control.Exception.Safe (MonadCatch) import Control.Monad.Trans.Except.Extra (catchIOExceptT) -import Control.Tracer +import "contra-tracer" Control.Tracer import Data.List (nub) import qualified Data.Map as Map import Data.Text (pack) @@ -49,7 +50,8 @@ import qualified Cardano.BM.Configuration as Config import qualified Cardano.BM.Configuration.Model as Config import Cardano.BM.Data.Aggregated (Measurable (..)) import Cardano.BM.Data.Backend (Backend, BackendKind (..)) -import Cardano.BM.Data.LogItem (LOContent (..), LOMeta (..), LoggerName) +import Cardano.BM.Data.LogItem (LOContent (..), LOMeta (..), + LoggerName) import qualified Cardano.BM.Observer.Monadic as Monadic import qualified Cardano.BM.Observer.STM as Stm import Cardano.BM.Plugin (loadPlugin) @@ -63,23 +65,26 @@ import qualified Cardano.BM.Trace as Trace import Cardano.BM.Tracing import qualified Cardano.Chain.Genesis as Gen -import Cardano.Slotting.Slot (EpochSize (..)) +import qualified Cardano.Ledger.Shelley.API as SL import qualified Ouroboros.Consensus.BlockchainTime.WallClock.Types as WCT import Ouroboros.Consensus.Byron.Ledger.Conversions import Ouroboros.Consensus.Cardano.Block import Ouroboros.Consensus.Cardano.CanHardFork import qualified Ouroboros.Consensus.Config as Consensus -import Ouroboros.Consensus.Config.SupportsNode (ConfigSupportsNode (..)) +import Ouroboros.Consensus.Config.SupportsNode + (ConfigSupportsNode (..)) import Ouroboros.Consensus.HardFork.Combinator.Degenerate import Ouroboros.Consensus.Node.ProtocolInfo import Ouroboros.Consensus.Shelley.Ledger.Ledger -import qualified Cardano.Ledger.Shelley.API as SL import Cardano.Api.Protocol.Types (BlockType (..), protocolInfo) import Cardano.Config.Git.Rev (gitRev) -import Cardano.Node.Configuration.POM (NodeConfiguration (..), ncProtocol) +import Cardano.Node.Configuration.POM (NodeConfiguration (..), + ncProtocol) import Cardano.Node.Protocol.Types (SomeConsensusProtocol (..)) import Cardano.Node.Types +import Cardano.Slotting.Slot (EpochSize (..)) +import Cardano.Tracing.Config (TraceOptions (..)) import Cardano.Tracing.OrphanInstances.Common () import Paths_cardano_node (version) @@ -153,7 +158,6 @@ createLoggingLayer -> SomeConsensusProtocol -> ExceptT ConfigError IO LoggingLayer createLoggingLayer ver nodeConfig' p = do - logConfig <- loggingCLIConfiguration $ if ncLoggingSwitch nodeConfig' -- Re-interpret node config again, as logging 'Configuration': @@ -165,21 +169,21 @@ createLoggingLayer ver nodeConfig' p = do Config.setTextOption logConfig "appversion" ver Config.setTextOption logConfig "appcommit" gitRev - (baseTrace, switchBoard) <- liftIO $ setupTrace_ logConfig "cardano" + (baseTrace', switchBoard) <- liftIO $ setupTrace_ logConfig "cardano" let loggingEnabled :: Bool loggingEnabled = ncLoggingSwitch nodeConfig' trace :: Trace IO Text trace = if loggingEnabled - then baseTrace + then baseTrace' else Trace.nullTracer when loggingEnabled $ liftIO $ loggingPreInit nodeConfig' logConfig switchBoard trace - mEKGServer <- liftIO $ Switchboard.getSbEKGServer switchBoard + mbEKGServer <- liftIO $ Switchboard.getSbEKGServer switchBoard - mbEkgDirect <- case mEKGServer of + mbEkgDirect <- case mbEKGServer of Nothing -> pure Nothing Just sv -> do refGauge <- liftIO $ newMVar Map.empty @@ -244,7 +248,7 @@ createLoggingLayer ver nodeConfig' p = do when (ncLogMetrics nodeConfig) $ -- Record node metrics, if configured - startCapturingMetrics trace + startCapturingMetrics (ncTraceConfig nodeConfig) trace mkLogLayer :: Configuration -> Switchboard Text -> Maybe EKGDirect -> Trace IO Text -> LoggingLayer mkLogLayer logConfig switchBoard mbEkgDirect trace = @@ -267,14 +271,20 @@ createLoggingLayer ver nodeConfig' p = do , llEKGDirect = mbEkgDirect } - startCapturingMetrics :: Trace IO Text -> IO () - startCapturingMetrics tr = do + startCapturingMetrics :: TraceOptions + -> Trace IO Text + -> IO () + startCapturingMetrics (TraceDispatcher _) _tr = do + pure () + + startCapturingMetrics _ tr = do void . Async.async . forever $ do readResourceStats >>= maybe (pure ()) (traceResourceStats (appendName "node" tr)) - threadDelay 1000000 -- TODO: make configurable + Conc.threadDelay 1000000 -- TODO: make configurable + traceResourceStats :: Trace IO Text -> ResourceStats -> IO () traceResourceStats tr rs = do traceWith (toLogObject' NormalVerbosity $ appendName "resources" tr) rs @@ -331,7 +341,7 @@ nodeBasicInfo nc (SomeConsensusProtocol whichP pForInfo) nodeStartTime' = do ++ getGenesisValues "Mary" cfgMary ++ getGenesisValues "Alonzo" cfgAlonzo items = nub $ - [ ("protocol", pack . protocolName $ ncProtocol nc) + [ ("protocol", pack . show $ ncProtocol nc) , ("version", pack . showVersion $ version) , ("commit", gitRev) , ("nodeStartTime", show nodeStartTime') diff --git a/cardano-node/src/Cardano/Node/Configuration/NodeAddress.hs b/cardano-node/src/Cardano/Node/Configuration/NodeAddress.hs new file mode 100644 index 00000000000..1d2fa95f645 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Configuration/NodeAddress.hs @@ -0,0 +1,168 @@ +{-# LANGUAGE DeriveFunctor #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralisedNewtypeDeriving #-} +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE MonoLocalBinds #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} + +module Cardano.Node.Configuration.NodeAddress + ( -- * Node addresses + NodeAddress'(..) + , NodeIPAddress + , nodeAddressToSockAddr + , NodeIPv4Address + , NodeIPv6Address + , NodeDnsAddress + , nodeIPv4ToIPAddress + , nodeIPv6ToIPAddress + , nodeDnsAddressToDomainAddress + , NodeHostIPAddress (..) + , nodeHostIPAddressToSockAddr + , NodeHostIPv4Address (..) + , NodeHostIPv6Address (..) + , nodeHostIPv4AddressToIPAddress + , nodeHostIPv6AddressToIPAddress + , NodeHostDnsAddress (..) + , nodeHostDnsAddressToDomain + , PortNumber + , SocketPath(..) + ) where + +import Cardano.Prelude +import Prelude (fail) + +import Data.Aeson (FromJSON (..), ToJSON (..), Value (..), + (.:), (.=), withObject, object) +import Data.IP (IP (..), IPv4, IPv6) +import Data.IP qualified as IP +import Data.Text qualified as Text +import Data.Text.Encoding qualified as Text +import Network.DNS qualified as DNS (Domain) +import Network.Socket (PortNumber, SockAddr (..)) + +import Ouroboros.Network.PeerSelection.RootPeersDNS (DomainAccessPoint (..)) + + +-- | IPv4 or IPv6 address with a port number. +data NodeAddress' addr = NodeAddress + { naHostAddress :: !addr + , naPort :: !PortNumber + } deriving (Eq, Ord, Show, Functor) + +type NodeIPAddress = NodeAddress' NodeHostIPAddress +type NodeIPv4Address = NodeAddress' NodeHostIPv4Address +type NodeIPv6Address = NodeAddress' NodeHostIPv6Address +type NodeDnsAddress = NodeAddress' NodeHostDnsAddress + +instance FromJSON addr => FromJSON (NodeAddress' addr) where + parseJSON = withObject "NodeAddress" $ \v -> do + NodeAddress + <$> v .: "addr" + <*> ((fromIntegral :: Int -> PortNumber) <$> v .: "port") + +instance ToJSON addr => ToJSON (NodeAddress' addr) where + toJSON na = + object + [ "addr" .= toJSON (naHostAddress na) + , "port" .= (fromIntegral (naPort na) :: Int) + ] + + +nodeIPv4ToIPAddress :: NodeIPv4Address -> NodeIPAddress +nodeIPv4ToIPAddress = fmap nodeHostIPv4AddressToIPAddress + +nodeIPv6ToIPAddress :: NodeIPv6Address -> NodeIPAddress +nodeIPv6ToIPAddress = fmap nodeHostIPv6AddressToIPAddress + +nodeDnsAddressToDomainAddress :: NodeDnsAddress -> DomainAccessPoint +nodeDnsAddressToDomainAddress NodeAddress { naHostAddress = NodeHostDnsAddress dns, naPort } + = DomainAccessPoint (Text.encodeUtf8 dns) naPort + +nodeAddressToSockAddr :: NodeIPAddress -> SockAddr +nodeAddressToSockAddr (NodeAddress addr port) = + case unNodeHostIPAddress addr of + IP.IPv4 ipv4 -> SockAddrInet port (IP.toHostAddress ipv4) + IP.IPv6 ipv6 -> SockAddrInet6 port 0 (IP.toHostAddress6 ipv6) 0 + +nodeHostIPAddressToSockAddr :: NodeIPAddress -> SockAddr +nodeHostIPAddressToSockAddr NodeAddress { naHostAddress = NodeHostIPAddress ip, naPort } = + case ip of + IPv4 ipv4 -> SockAddrInet (fromIntegral naPort) (IP.toHostAddress ipv4) + IPv6 ipv6 -> SockAddrInet6 (fromIntegral naPort) 0 (IP.toHostAddress6 ipv6) 0 + + +newtype NodeHostIPv4Address + = NodeHostIPv4Address { unNodeHostIPv4Address :: IPv4 } + deriving newtype Show + deriving (Eq, Ord) + +instance FromJSON NodeHostIPv4Address where + parseJSON (String ipStr) = + case readMaybe $ Text.unpack ipStr of + Just ip -> pure $ NodeHostIPv4Address ip + Nothing -> fail $ "Parsing of IPv4 failed: " <> Text.unpack ipStr + parseJSON invalid = fail $ "Parsing of IPv4 failed due to type mismatch. " + <> "Encountered: " <> show invalid <> "\n" + +instance ToJSON NodeHostIPv4Address where + toJSON (NodeHostIPv4Address ip) = String (Text.pack $ show ip) + + +newtype NodeHostIPv6Address + = NodeHostIPv6Address { unNodeHostIPv6Address :: IPv6 } + deriving newtype Show + deriving (Eq, Ord) + +instance FromJSON NodeHostIPv6Address where + parseJSON (String ipStr) = + case readMaybe $ Text.unpack ipStr of + Just ip -> pure $ NodeHostIPv6Address ip + Nothing -> fail $ "Parsing of IPv6 failed: " <> Text.unpack ipStr + parseJSON invalid = fail $ "Parsing of IPv6 failed due to type mismatch. " + <> "Encountered: " <> show invalid <> "\n" +instance ToJSON NodeHostIPv6Address where + toJSON (NodeHostIPv6Address ip) = String (Text.pack $ show ip) + + +newtype NodeHostIPAddress + = NodeHostIPAddress { unNodeHostIPAddress :: IP } + deriving newtype Show + deriving (Eq, Ord) + +instance FromJSON NodeHostIPAddress where + parseJSON (String ipStr) = + case readMaybe $ Text.unpack ipStr of + Just ip -> pure $ NodeHostIPAddress ip + Nothing -> fail $ "Parsing of IP failed: " <> Text.unpack ipStr + parseJSON invalid = fail $ "Parsing of IP failed due to type mismatch. " + <> "Encountered: " <> show invalid <> "\n" + +instance ToJSON NodeHostIPAddress where + toJSON (NodeHostIPAddress ip) = String (Text.pack $ show ip) + +nodeHostIPv6AddressToIPAddress :: NodeHostIPv6Address -> NodeHostIPAddress +nodeHostIPv6AddressToIPAddress (NodeHostIPv6Address ip) = NodeHostIPAddress (IPv6 ip) + +nodeHostIPv4AddressToIPAddress :: NodeHostIPv4Address -> NodeHostIPAddress +nodeHostIPv4AddressToIPAddress (NodeHostIPv4Address ip) = NodeHostIPAddress (IPv4 ip) + + +-- | Domain name. +-- +newtype NodeHostDnsAddress + = NodeHostDnsAddress { unNodeHostDnsAddress :: Text } + deriving newtype Show + deriving (Eq, Ord) + +nodeHostDnsAddressToDomain :: NodeHostDnsAddress -> DNS.Domain +nodeHostDnsAddressToDomain = Text.encodeUtf8 . unNodeHostDnsAddress + + +-- | Socket path +-- +newtype SocketPath = SocketPath + { unSocketPath :: FilePath } + deriving stock (Eq, Ord) + deriving newtype (FromJSON, IsString, Show) diff --git a/cardano-node/src/Cardano/Node/Configuration/POM.hs b/cardano-node/src/Cardano/Node/Configuration/POM.hs index a60e22f9166..050c58cba6e 100644 --- a/cardano-node/src/Cardano/Node/Configuration/POM.hs +++ b/cardano-node/src/Cardano/Node/Configuration/POM.hs @@ -1,8 +1,8 @@ -{-# LANGUAGE GADTs #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wno-noncanonical-monoid-instances #-} @@ -22,8 +22,8 @@ module Cardano.Node.Configuration.POM where import Cardano.Prelude -import Prelude (String) import qualified GHC.Show as Show +import Prelude (String) import Control.Monad (fail) import Data.Aeson @@ -34,19 +34,19 @@ import Generic.Data (gmappend) import Generic.Data.Orphans () import Options.Applicative import System.FilePath (takeDirectory, ()) -import System.Posix.Types (Fd (..)) import qualified Cardano.Chain.Update as Byron import Cardano.Crypto (RequiresNetworkMagic (..)) +import Cardano.Node.Configuration.Socket (SocketConfig (..)) +import Cardano.Node.Handlers.Shutdown import Cardano.Node.Protocol.Types (Protocol (..)) import Cardano.Node.Types import Cardano.Tracing.Config import Ouroboros.Consensus.Mempool.API (MempoolCapacityBytes (..), MempoolCapacityBytesOverride (..)) +import qualified Ouroboros.Consensus.Node as Consensus (NetworkP2PMode (..)) import Ouroboros.Consensus.Storage.LedgerDB.DiskPolicy (SnapshotInterval (..)) -import Ouroboros.Network.Block (MaxSlotNo (..)) -import Ouroboros.Network.NodeToNode (DiffusionMode (..), AcceptedConnectionsLimit (..)) -import qualified Ouroboros.Consensus.Node as Consensus ( NetworkP2PMode (..) ) +import Ouroboros.Network.NodeToNode (AcceptedConnectionsLimit (..), DiffusionMode (..)) data NetworkP2PMode = EnabledP2PMode | DisabledP2PMode deriving (Eq, Show, Generic) @@ -72,10 +72,8 @@ instance Show SomeNetworkP2PMode where data NodeConfiguration = NodeConfiguration - { ncNodeIPv4Addr :: !(Maybe NodeHostIPv4Address) - , ncNodeIPv6Addr :: !(Maybe NodeHostIPv6Address) - , ncNodePortNumber :: !(Maybe PortNumber) - -- | Filepath of the configuration yaml file. This file determines + { ncSocketConfig :: !SocketConfig + -- | Filepath of the configuration yaml file. This file determines -- all the configuration settings required for the cardano node -- (logging, tracing, protocol, slot length etc) , ncConfigFile :: !ConfigYamlFilePath @@ -83,14 +81,12 @@ data NodeConfiguration , ncDatabaseFile :: !DbFile , ncProtocolFiles :: !ProtocolFilepaths , ncValidateDB :: !Bool - , ncShutdownIPC :: !(Maybe Fd) - , ncShutdownOnSlotSynced :: !MaxSlotNo + , ncShutdownConfig :: !ShutdownConfig -- Protocol-specific parameters: , ncProtocolConfig :: !NodeProtocolConfiguration -- Node parameters, not protocol-specific: - , ncSocketPath :: !(Maybe SocketPath) , ncDiffusionMode :: !DiffusionMode , ncSnapshotInterval :: !SnapshotInterval @@ -144,9 +140,7 @@ data NodeConfiguration data PartialNodeConfiguration = PartialNodeConfiguration - { pncNodeIPv4Addr :: !(Last NodeHostIPv4Address) - , pncNodeIPv6Addr :: !(Last NodeHostIPv6Address) - , pncNodePortNumber :: !(Last PortNumber) + { pncSocketConfig :: !(Last SocketConfig) -- | Filepath of the configuration yaml file. This file determines -- all the configuration settings required for the cardano node -- (logging, tracing, protocol, slot length etc) @@ -155,14 +149,12 @@ data PartialNodeConfiguration , pncDatabaseFile :: !(Last DbFile) , pncProtocolFiles :: !(Last ProtocolFilepaths) , pncValidateDB :: !(Last Bool) - , pncShutdownIPC :: !(Last Fd) - , pncShutdownOnSlotSynced :: !(Last MaxSlotNo) + , pncShutdownConfig :: !(Last ShutdownConfig) -- Protocol-specific parameters: , pncProtocolConfig :: !(Last NodeProtocolConfiguration) -- Node parameters, not protocol-specific: - , pncSocketPath :: !(Last SocketPath) , pncDiffusionMode :: !(Last DiffusionMode) , pncSnapshotInterval :: !(Last SnapshotInterval) , pncTestEnableDevelopmentNetworkProtocols :: !(Last Bool) @@ -199,7 +191,7 @@ data PartialNodeConfiguration instance AdjustFilePaths PartialNodeConfiguration where adjustFilePaths f x = x { pncProtocolConfig = adjustFilePaths f (pncProtocolConfig x) - , pncSocketPath = adjustFilePaths f (pncSocketPath x) + , pncSocketConfig = adjustFilePaths f (pncSocketConfig x) } instance Semigroup PartialNodeConfiguration where @@ -223,9 +215,16 @@ instance FromJSON PartialNodeConfiguration where pncMaxConcurrencyDeadline <- Last <$> v .:? "MaxConcurrencyDeadline" -- Logging parameters - pncLoggingSwitch <- Last . Just <$> v .:? "TurnOnLogging" .!= True - pncLogMetrics <- Last <$> v .:? "TurnOnLogMetrics" - pncTraceConfig <- Last . Just <$> traceConfigParser v + pncLoggingSwitch' <- v .:? "TurnOnLogging" .!= True + pncLogMetrics <- Last <$> v .:? "TurnOnLogMetrics" + useTraceDispatcher <- v .:? "UseTraceDispatcher" .!= False + pncTraceConfig <- Last . Just <$> if pncLoggingSwitch' + then + traceConfigParser v + (if useTraceDispatcher + then TraceDispatcher + else TracingOnLegacy) + else pure TracingOff -- Protocol parameters protocol <- v .:? "Protocol" .!= ByronProtocol @@ -269,25 +268,21 @@ instance FromJSON PartialNodeConfiguration where pure PartialNodeConfiguration { pncProtocolConfig - , pncSocketPath + , pncSocketConfig = Last . Just $ SocketConfig mempty mempty mempty pncSocketPath , pncDiffusionMode , pncSnapshotInterval , pncTestEnableDevelopmentNetworkProtocols , pncMaxConcurrencyBulkSync , pncMaxConcurrencyDeadline - , pncLoggingSwitch + , pncLoggingSwitch = Last $ Just pncLoggingSwitch' , pncLogMetrics , pncTraceConfig - , pncNodeIPv4Addr = mempty - , pncNodeIPv6Addr = mempty - , pncNodePortNumber = mempty , pncConfigFile = mempty , pncTopologyFile = mempty , pncDatabaseFile = mempty , pncProtocolFiles = mempty , pncValidateDB = mempty - , pncShutdownIPC = mempty - , pncShutdownOnSlotSynced = mempty + , pncShutdownConfig = mempty , pncMaybeMempoolCapacityOverride , pncProtocolIdleTimeout , pncTimeWaitTimeout @@ -413,18 +408,14 @@ defaultPartialNodeConfiguration = { pncConfigFile = Last . Just $ ConfigYamlFilePath "configuration/cardano/mainnet-config.json" , pncDatabaseFile = Last . Just $ DbFile "mainnet/db/" , pncLoggingSwitch = Last $ Just True - , pncSocketPath = mempty + , pncSocketConfig = Last . Just $ SocketConfig mempty mempty mempty mempty , pncDiffusionMode = Last $ Just InitiatorAndResponderDiffusionMode , pncSnapshotInterval = Last $ Just DefaultSnapshotInterval , pncTestEnableDevelopmentNetworkProtocols = Last $ Just False , pncTopologyFile = Last . Just $ TopologyFile "configuration/cardano/mainnet-topology.json" - , pncNodeIPv4Addr = mempty - , pncNodeIPv6Addr = mempty - , pncNodePortNumber = mempty , pncProtocolFiles = mempty , pncValidateDB = mempty - , pncShutdownIPC = mempty - , pncShutdownOnSlotSynced = mempty + , pncShutdownConfig = mempty , pncProtocolConfig = mempty , pncMaxConcurrencyBulkSync = mempty , pncMaxConcurrencyDeadline = mempty @@ -461,13 +452,14 @@ makeNodeConfiguration pnc = do databaseFile <- lastToEither "Missing DatabaseFile" $ pncDatabaseFile pnc protocolFiles <- lastToEither "Missing ProtocolFiles" $ pncProtocolFiles pnc validateDB <- lastToEither "Missing ValidateDB" $ pncValidateDB pnc - shutdownOnSlotSynced <- lastToEither "Missing ShutdownOnSlotSynced" $ pncShutdownOnSlotSynced pnc protocolConfig <- lastToEither "Missing ProtocolConfig" $ pncProtocolConfig pnc loggingSwitch <- lastToEither "Missing LoggingSwitch" $ pncLoggingSwitch pnc logMetrics <- lastToEither "Missing LogMetrics" $ pncLogMetrics pnc traceConfig <- lastToEither "Missing TraceConfig" $ pncTraceConfig pnc diffusionMode <- lastToEither "Missing DiffusionMode" $ pncDiffusionMode pnc snapshotInterval <- lastToEither "Missing SnapshotInterval" $ pncSnapshotInterval pnc + shutdownConfig <- lastToEither "Missing ShutdownConfig" $ pncShutdownConfig pnc + socketConfig <- lastToEither "Missing SocketConfig" $ pncSocketConfig pnc ncTargetNumberOfRootPeers <- lastToEither "Missing TargetNumberOfRootPeers" @@ -498,18 +490,14 @@ makeNodeConfiguration pnc = do lastToEither "Missing TestEnableDevelopmentNetworkProtocols" $ pncTestEnableDevelopmentNetworkProtocols pnc return $ NodeConfiguration - { ncNodeIPv4Addr = getLast $ pncNodeIPv4Addr pnc - , ncNodeIPv6Addr = getLast $ pncNodeIPv6Addr pnc - , ncNodePortNumber = getLast $ pncNodePortNumber pnc - , ncConfigFile = configFile + { ncConfigFile = configFile , ncTopologyFile = topologyFile , ncDatabaseFile = databaseFile , ncProtocolFiles = protocolFiles , ncValidateDB = validateDB - , ncShutdownIPC = getLast $ pncShutdownIPC pnc - , ncShutdownOnSlotSynced = shutdownOnSlotSynced + , ncShutdownConfig = shutdownConfig , ncProtocolConfig = protocolConfig - , ncSocketPath = getLast $ pncSocketPath pnc + , ncSocketConfig = socketConfig , ncDiffusionMode = diffusionMode , ncSnapshotInterval = snapshotInterval , ncTestEnableDevelopmentNetworkProtocols = testEnableDevelopmentNetworkProtocols diff --git a/cardano-node/src/Cardano/Node/Configuration/Socket.hs b/cardano-node/src/Cardano/Node/Configuration/Socket.hs index 8152ec053c9..863aeb8773a 100644 --- a/cardano-node/src/Cardano/Node/Configuration/Socket.hs +++ b/cardano-node/src/Cardano/Node/Configuration/Socket.hs @@ -3,7 +3,8 @@ {-# LANGUAGE ScopedTypeVariables #-} module Cardano.Node.Configuration.Socket - ( gatherConfiguredSockets + ( SocketConfig (..) + , gatherConfiguredSockets , SocketOrSocketInfo(..) , getSocketOrSocketInfoAddr , SocketConfigError(..) @@ -16,12 +17,12 @@ import Prelude (String) import qualified Prelude import Control.Monad.Trans.Except.Extra (handleIOExceptT) +import Generic.Data.Orphans () import Network.Socket (AddrInfo (..), AddrInfoFlag (..), Family (AF_INET, AF_INET6), SockAddr, Socket, SocketType (..)) import qualified Network.Socket as Socket -import Cardano.Node.Configuration.POM (NodeConfiguration (..)) -import Cardano.Node.Types +import Cardano.Node.Configuration.NodeAddress import Ouroboros.Network.NodeToClient (LocalAddress (..), LocalSocket (..)) @@ -100,6 +101,14 @@ renderSocketConfigError (GetAddrInfoError addr port ex) = "Failure while getting address information for the public listening " <> "address: " <> show addr <> " " <> show port <> " : " <> displayException ex +data SocketConfig + = SocketConfig + { ncNodeIPv4Addr :: !(Last NodeHostIPv4Address) + , ncNodeIPv6Addr :: !(Last NodeHostIPv6Address) + , ncNodePortNumber :: !(Last PortNumber) + , ncSocketPath :: !(Last SocketPath) + } + deriving (Eq, Show) -- | Gather from the various sources of configuration which sockets we will use -- for the public node-to-node and the local node-to-client IPC. It returns @@ -111,15 +120,15 @@ renderSocketConfigError (GetAddrInfoError addr port ex) = -- * node cli -- * systemd socket activation -- -gatherConfiguredSockets :: NodeConfiguration +gatherConfiguredSockets :: SocketConfig -> ExceptT SocketConfigError IO (Maybe (SocketOrSocketInfo Socket SockAddr), Maybe (SocketOrSocketInfo Socket SockAddr), Maybe (SocketOrSocketInfo LocalSocket LocalAddress)) -gatherConfiguredSockets NodeConfiguration { ncNodeIPv4Addr, - ncNodeIPv6Addr, - ncNodePortNumber, - ncSocketPath } = do +gatherConfiguredSockets SocketConfig { ncNodeIPv4Addr, + ncNodeIPv6Addr, + ncNodePortNumber, + ncSocketPath } = do systemDSockets <- liftIO getSystemdSockets @@ -135,7 +144,7 @@ gatherConfiguredSockets NodeConfiguration { ncNodeIPv4Addr, -- only when 'ncNodeIPv4Addr' is specified or an ipv4 socket is passed -- through socket activation - ipv4 <- case (ncNodeIPv4Addr, firstIpv4Socket) of + ipv4 <- case (getLast ncNodeIPv4Addr, firstIpv4Socket) of (Nothing, Nothing) -> pure Nothing (Nothing, Just sock) -> return (Just (ActualSocket sock)) (Just _, Just _) -> throwError ClashingPublicIpv4SocketGiven @@ -143,11 +152,11 @@ gatherConfiguredSockets NodeConfiguration { ncNodeIPv4Addr, fmap (SocketInfo . addrAddress) . head <$> nodeAddressInfo (Just $ nodeHostIPv4AddressToIPAddress addr) - ncNodePortNumber + (getLast ncNodePortNumber) -- only when 'ncNodeIPv6Addr' is specified or an ipv6 socket is passed -- through socket activation - ipv6 <- case (ncNodeIPv6Addr, firstIpv6Socket) of + ipv6 <- case (getLast ncNodeIPv6Addr, firstIpv6Socket) of (Nothing, Nothing) -> pure Nothing (Nothing, Just sock) -> return (Just (ActualSocket sock)) (Just _, Just _) -> throwError ClashingPublicIpv6SocketGiven @@ -155,7 +164,7 @@ gatherConfiguredSockets NodeConfiguration { ncNodeIPv4Addr, fmap (SocketInfo . addrAddress) . head <$> nodeAddressInfo (Just $ nodeHostIPv6AddressToIPAddress addr) - ncNodePortNumber + (getLast ncNodePortNumber) -- When none of the addresses was given. We try resolve address passing -- only 'ncNodePortNumber'. @@ -163,7 +172,7 @@ gatherConfiguredSockets NodeConfiguration { ncNodeIPv4Addr, <- case (ipv4, ipv6) of (Nothing, Nothing) -> do - info <- nodeAddressInfo Nothing ncNodePortNumber + info <- nodeAddressInfo Nothing $ getLast ncNodePortNumber let ipv4' = SocketInfo . addrAddress <$> find ((== AF_INET) . addrFamily) info ipv6' = SocketInfo . addrAddress @@ -183,7 +192,7 @@ gatherConfiguredSockets NodeConfiguration { ncNodeIPv4Addr, -- only when 'ncSocketpath' is specified or a unix socket is passed through -- socket activation - local <- case (ncSocketPath, firstUnixSocket) of + local <- case (getLast ncSocketPath, firstUnixSocket) of (Nothing, Nothing) -> return Nothing (Just _, Just _) -> throwError ClashingLocalSocketGiven (Nothing, Just sock) -> return . Just $ ActualSocket sock diff --git a/cardano-node/src/Cardano/Node/Configuration/Topology.hs b/cardano-node/src/Cardano/Node/Configuration/Topology.hs index 4ddae107742..70f57dfea08 100644 --- a/cardano-node/src/Cardano/Node/Configuration/Topology.hs +++ b/cardano-node/src/Cardano/Node/Configuration/Topology.hs @@ -25,6 +25,7 @@ import qualified Data.Text as Text import Cardano.Node.Configuration.POM (NodeConfiguration (..)) import Cardano.Node.Types +import Cardano.Node.Configuration.NodeAddress import Ouroboros.Consensus.Util.Condense (Condense (..)) diff --git a/cardano-node/src/Cardano/Node/Configuration/TopologyP2P.hs b/cardano-node/src/Cardano/Node/Configuration/TopologyP2P.hs index eb81bd75ef2..917c574e981 100644 --- a/cardano-node/src/Cardano/Node/Configuration/TopologyP2P.hs +++ b/cardano-node/src/Cardano/Node/Configuration/TopologyP2P.hs @@ -33,6 +33,7 @@ import qualified Data.Text as Text import Cardano.Node.Configuration.POM (NodeConfiguration (..)) import Cardano.Slotting.Slot (SlotNo (..)) +import Cardano.Node.Configuration.NodeAddress import Cardano.Node.Types import Cardano.Node.Configuration.Topology (TopologyError (..)) diff --git a/cardano-node/src/Cardano/Node/Handlers/Shutdown.hs b/cardano-node/src/Cardano/Node/Handlers/Shutdown.hs index 641228c3c99..16306279a35 100644 --- a/cardano-node/src/Cardano/Node/Handlers/Shutdown.hs +++ b/cardano-node/src/Cardano/Node/Handlers/Shutdown.hs @@ -1,11 +1,17 @@ +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PackageImports #-} {-# LANGUAGE ScopedTypeVariables #-} module Cardano.Node.Handlers.Shutdown ( -- * Generalised shutdown handling - withShutdownHandling + ShutdownConfig (..) + , withShutdownHandling + + , ShutdownTrace (..) -- * Watch ChainDB for passing a configured slot sync limit threshold, -- translating it to a graceful shutdown. @@ -13,6 +19,9 @@ module Cardano.Node.Handlers.Shutdown ) where +import Data.Aeson (FromJSON, ToJSON) +import Generic.Data (Generic) +import Generic.Data.Orphans () import Prelude import Control.Concurrent.Async (race_) @@ -25,63 +34,75 @@ import qualified System.IO as IO import qualified System.IO.Error as IO import System.Posix.Types (Fd (Fd)) -import Cardano.BM.Data.Tracer (TracingVerbosity (..), severityNotice, trTransformer) -import Cardano.BM.Trace import Cardano.Slotting.Slot (WithOrigin (..)) -import Control.Tracer +import "contra-tracer" Control.Tracer import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB import Ouroboros.Consensus.Util.ResourceRegistry (ResourceRegistry) import Ouroboros.Consensus.Util.STM (Watcher (..), forkLinkedWatcher) import Ouroboros.Network.Block (MaxSlotNo (..), SlotNo, pointSlot) -import Cardano.Node.Configuration.POM (NodeConfiguration (..)) + +data ShutdownTrace + = ShutdownRequested + -- ^ Received shutdown request + | AbnormalShutdown + -- ^ Non-isEOFError shutdown request + | ShutdownUnexpectedInput Text + -- ^ Received shutdown request but found unexpected input in --shutdown-ipc FD: + | RequestingShutdown Text + -- ^ Ringing the node shutdown doorbell for reason + | ShutdownArmedAtSlot SlotNo + -- ^ Will terminate upon reaching maxSlot + deriving (Generic, FromJSON, ToJSON) + +data ShutdownConfig + = ShutdownConfig + { scIPC :: !(Maybe Fd) + , scOnSlotSynced :: !(Maybe MaxSlotNo) + } + deriving (Eq, Show) -- | We provide an optional cross-platform method to politely request shut down. -- The parent process passes us the file descriptor number of the read end of a pipe, -- via the CLI with @--shutdown-ipc FD@ withShutdownHandling - :: Maybe Fd - -> Trace IO Text + :: ShutdownConfig + -> Tracer IO ShutdownTrace -> IO () -- ^ Action to potentially shutdown via file descriptor -> IO () -withShutdownHandling Nothing _ action = action -withShutdownHandling (Just fileDescriptor) trace action = do - race_ (waitForEOF fileDescriptor) action +withShutdownHandling ShutdownConfig{scIPC = Nothing} _ action = action +withShutdownHandling ShutdownConfig{scIPC = Just fd} tr action = do + race_ (waitForEOF fd) action where - tracer :: Tracer IO Text - tracer = trTransformer MaximalVerbosity (severityNotice trace) - waitForEOF :: Fd -> IO () - waitForEOF (Fd fd) = do - hnd <- IO.fdToHandle fd + waitForEOF (Fd fileDesc) = do + hnd <- IO.fdToHandle fileDesc r <- try $ IO.hGetChar hnd case r of Left e - | IO.isEOFError e -> do - traceWith tracer "Received shutdown request and shutting node down..." + | IO.isEOFError e -> + traceWith tr ShutdownRequested | otherwise -> do - traceWith tracer "Received shutdown request but did not encounter EOL in --shutdown-ipc FD" + traceWith tr AbnormalShutdown throwIO e - Right inp -> do - traceWith tracer - $ "Received shutdown request but found unexpected input in --shutdown-ipc FD: " <> pack (show inp) + Right inp -> + traceWith tr (ShutdownUnexpectedInput . pack $ show inp) -- | Spawn a thread that would cause node to shutdown upon ChainDB reaching the -- configuration-defined slot. maybeSpawnOnSlotSyncedShutdownHandler - :: NodeConfiguration - -> Trace IO Text + :: ShutdownConfig + -> Tracer IO ShutdownTrace -> ResourceRegistry IO -> ChainDB.ChainDB IO blk -> IO () -maybeSpawnOnSlotSyncedShutdownHandler nc trace registry chaindb = - case ncShutdownOnSlotSynced nc of - NoMaxSlotNo -> return () - MaxSlotNo maxSlot -> do - traceWith (trTransformer MaximalVerbosity $ severityNotice trace) - ("will terminate upon reaching " <> pack (show maxSlot)) +maybeSpawnOnSlotSyncedShutdownHandler sc tr registry chaindb = + case scOnSlotSynced sc of + Just (MaxSlotNo maxSlot) -> do + traceWith tr (ShutdownArmedAtSlot maxSlot) spawnSlotLimitTerminator maxSlot + _ -> pure () where spawnSlotLimitTerminator :: SlotNo -> IO () spawnSlotLimitTerminator maxSlot = @@ -91,8 +112,8 @@ maybeSpawnOnSlotSyncedShutdownHandler nc trace registry chaindb = , wNotify = \case Origin -> pure () At cur -> when (cur >= maxSlot) $ do - traceWith (trTransformer MaximalVerbosity $ severityNotice trace) - (("spawnSlotLimitTerminator: reached target " :: String) <> show cur) + traceWith tr (RequestingShutdown $ "spawnSlotLimitTerminator: reached target " + <> (pack . show) cur) throwIO ExitSuccess , wReader = pointSlot <$> ChainDB.getTipPoint chaindb } diff --git a/cardano-node/src/Cardano/Node/Parsers.hs b/cardano-node/src/Cardano/Node/Parsers.hs index 3b3fc622299..713e3ef5bb1 100644 --- a/cardano-node/src/Cardano/Node/Parsers.hs +++ b/cardano-node/src/Cardano/Node/Parsers.hs @@ -24,7 +24,10 @@ import Ouroboros.Consensus.Mempool.API (MempoolCapacityBytes (..), MempoolCapacityBytesOverride (..)) import Ouroboros.Consensus.Storage.LedgerDB.DiskPolicy (SnapshotInterval (..)) +import Cardano.Node.Configuration.NodeAddress import Cardano.Node.Configuration.POM (PartialNodeConfiguration (..), lastOption) +import Cardano.Node.Configuration.Socket +import Cardano.Node.Handlers.Shutdown import Cardano.Node.Types nodeCLIParser :: Parser PartialNodeConfiguration @@ -62,19 +65,20 @@ nodeRunParser = do validate <- lastOption parseValidateDB shutdownIPC <- lastOption parseShutdownIPC - - shutdownOnSlotSynced <- lastOption parseShutdownOnSlotSynced + shutdownOnSlot <- lastOption parseShutdownOnSlotSynced maybeMempoolCapacityOverride <- lastOption parseMempoolCapacityOverride pure $ PartialNodeConfiguration - { pncNodeIPv4Addr = nIPv4Address - , pncNodeIPv6Addr = nIPv6Address - , pncNodePortNumber = nPortNumber + { pncSocketConfig = + Last . Just $ SocketConfig + nIPv4Address + nIPv6Address + nPortNumber + socketFp , pncConfigFile = ConfigYamlFilePath <$> nodeConfigFp , pncTopologyFile = TopologyFile <$> topFp , pncDatabaseFile = DbFile <$> dbFp - , pncSocketPath = socketFp , pncDiffusionMode = mempty , pncSnapshotInterval = snapshotInterval , pncTestEnableDevelopmentNetworkProtocols = mempty @@ -87,8 +91,8 @@ nodeRunParser = do , shelleyBulkCredsFile } , pncValidateDB = validate - , pncShutdownIPC = shutdownIPC - , pncShutdownOnSlotSynced = shutdownOnSlotSynced + , pncShutdownConfig = + Last . Just $ ShutdownConfig (getLast shutdownIPC) (getLast shutdownOnSlot) , pncProtocolConfig = mempty , pncMaxConcurrencyBulkSync = mempty , pncMaxConcurrencyDeadline = mempty diff --git a/cardano-node/src/Cardano/Node/Protocol/Byron.hs b/cardano-node/src/Cardano/Node/Protocol/Byron.hs index 2e51e4dd16c..b5178fc3578 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Byron.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Byron.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-} module Cardano.Node.Protocol.Byron @@ -29,17 +31,21 @@ import qualified Cardano.Chain.UTxO as UTxO import qualified Cardano.Chain.Update as Update import Cardano.Crypto.ProtocolMagic (RequiresNetworkMagic) +import Cardano.Node.Types import Ouroboros.Consensus.Cardano import qualified Ouroboros.Consensus.Cardano as Consensus import qualified Ouroboros.Consensus.Mempool.TxLimits as TxLimits -import Cardano.Node.Types - import Cardano.Node.Protocol.Types import Cardano.Tracing.OrphanInstances.Byron () import Cardano.Tracing.OrphanInstances.HardFork () import Cardano.Tracing.OrphanInstances.Shelley () +import Cardano.Node.Tracing.Era.Byron () +import Cardano.Node.Tracing.Era.HardFork () +import Cardano.Node.Tracing.Tracers.ChainDB () + + ------------------------------------------------------------------------------ -- Byron protocol diff --git a/cardano-node/src/Cardano/Node/Protocol/Cardano.hs b/cardano-node/src/Cardano/Node/Protocol/Cardano.hs index 142dbb945cf..0fbea400433 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Cardano.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Cardano.hs @@ -1,7 +1,7 @@ -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wno-orphans #-} @@ -39,7 +39,6 @@ import Cardano.Tracing.OrphanInstances.Shelley () import qualified Cardano.Node.Protocol.Alonzo as Alonzo import qualified Cardano.Node.Protocol.Byron as Byron import qualified Cardano.Node.Protocol.Shelley as Shelley - import Cardano.Node.Protocol.Types ------------------------------------------------------------------------------ diff --git a/cardano-node/src/Cardano/Node/Protocol/Shelley.hs b/cardano-node/src/Cardano/Node/Protocol/Shelley.hs index 39ff109e560..97b9f43c725 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Shelley.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Shelley.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -54,6 +55,10 @@ import Cardano.Node.Types import Cardano.Tracing.OrphanInstances.HardFork () import Cardano.Tracing.OrphanInstances.Shelley () +import Cardano.Node.Tracing.Era.HardFork () +import Cardano.Node.Tracing.Era.Shelley () +import Cardano.Node.Tracing.Formatting () + import Cardano.Node.Protocol.Types ------------------------------------------------------------------------------ diff --git a/cardano-node/src/Cardano/Node/Protocol/Types.hs b/cardano-node/src/Cardano/Node/Protocol/Types.hs index 250a0bf03ff..d1434be2cdc 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Types.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Types.hs @@ -11,9 +11,9 @@ module Cardano.Node.Protocol.Types , SomeConsensusProtocol(..) ) where -import Cardano.Prelude +import Prelude +import Cardano.Prelude (Generic, NFData) -import Control.Monad.Fail (fail) import Data.Aeson import NoThunks.Class (NoThunks) @@ -21,12 +21,18 @@ import qualified Cardano.Api.Protocol.Types as Cardano import Cardano.Node.Orphans () import Cardano.Node.Queries (HasKESInfo, HasKESMetricsData) -import Cardano.Tracing.Constraints (TraceConstraints) +import Cardano.Node.TraceConstraints (TraceConstraints) + data Protocol = ByronProtocol | ShelleyProtocol | CardanoProtocol - deriving (Eq, Show, Generic) + deriving (Eq, Generic) + +instance Show Protocol where + show ByronProtocol = "Byron" + show ShelleyProtocol = "Shelley" + show CardanoProtocol = "Byron; Shelley" deriving instance NFData Protocol deriving instance NoThunks Protocol @@ -47,8 +53,6 @@ instance FromJSON Protocol where _ -> fail $ "Parsing of Protocol failed. " <> show str <> " is not a valid protocol" - - data SomeConsensusProtocol where SomeConsensusProtocol :: forall blk. ( Cardano.Protocol IO blk diff --git a/cardano-node/src/Cardano/Node/Queries.hs b/cardano-node/src/Cardano/Node/Queries.hs index bb96c85ccb1..7464fdf6595 100644 --- a/cardano-node/src/Cardano/Node/Queries.hs +++ b/cardano-node/src/Cardano/Node/Queries.hs @@ -6,6 +6,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE UndecidableInstances #-} @@ -15,45 +16,71 @@ module Cardano.Node.Queries -- * KES , MaxKESEvolutions (..) , OperationalCertStartKESPeriod (..) + , GetKESInfo(..) , HasKESInfo(..) , KESMetricsData (..) , HasKESMetricsData (..) -- * General ledger , LedgerQueries(..) + -- * Node kernel + , NodeKernelData(..) + , nkQueryChain + , nkQueryLedger + , mapNodeKernelDataIO + , setNodeKernel + , mkNodeKernelData + -- * Re-exports + , NodeKernel (..) + , LocalConnectionId + , RemoteConnectionId + , StrictMaybe(..) + , fromSMaybe ) where import Cardano.Prelude hiding (All, (:.:)) +import Data.IORef (IORef, newIORef, readIORef, writeIORef) import Data.Map.Strict qualified as Map import Data.SOP.Strict -import Cardano.Crypto.KES.Class (Period) -import Cardano.Protocol.TPraos.OCert (KESPeriod (..)) import Cardano.Chain.Block qualified as Byron import Cardano.Chain.UTxO qualified as Byron import Cardano.Crypto.Hash qualified as Crypto import Cardano.Crypto.Hashing qualified as Byron.Crypto +import Cardano.Crypto.KES.Class (Period) +import Cardano.Protocol.TPraos.OCert (KESPeriod (..)) + +import Cardano.Ledger.BaseTypes (StrictMaybe (..), fromSMaybe) import Cardano.Ledger.SafeHash qualified as Ledger import Cardano.Ledger.Shelley.LedgerState qualified as Shelley import Cardano.Ledger.Shelley.UTxO qualified as Shelley import Cardano.Ledger.TxIn qualified as Ledger -import Ouroboros.Consensus.HardFork.Combinator.Embed.Unary +import Ouroboros.Consensus.Block (ForgeStateInfo, ForgeStateUpdateError) +import Ouroboros.Consensus.Byron.Ledger.Block (ByronBlock) import Ouroboros.Consensus.Byron.Ledger.Block qualified as Byron import Ouroboros.Consensus.Byron.Ledger.Ledger qualified as Byron -import Ouroboros.Consensus.Shelley.Ledger qualified as Shelley +import Ouroboros.Consensus.Byron.Ledger.Mempool (TxId (..)) import Ouroboros.Consensus.Cardano qualified as Cardano import Ouroboros.Consensus.Cardano.Block qualified as Cardano -import Ouroboros.Consensus.Block (ForgeStateInfo, ForgeStateUpdateError) -import Ouroboros.Consensus.Byron.Ledger.Block (ByronBlock) -import Ouroboros.Consensus.Byron.Ledger.Mempool (TxId (..)) import Ouroboros.Consensus.HardFork.Combinator import Ouroboros.Consensus.HardFork.Combinator.AcrossEras (OneEraForgeStateInfo (..), OneEraForgeStateUpdateError (..)) -import Ouroboros.Consensus.Protocol.Ledger.HotKey qualified as HotKey +import Ouroboros.Consensus.HardFork.Combinator.Embed.Unary +import Ouroboros.Consensus.Ledger.Abstract (IsLedger) +import Ouroboros.Consensus.Ledger.Extended (ExtLedgerState) +import Ouroboros.Consensus.Node (NodeKernel (..)) +import Ouroboros.Consensus.Shelley.Ledger qualified as Shelley import Ouroboros.Consensus.Shelley.Ledger.Block (ShelleyBlock) import Ouroboros.Consensus.Shelley.Ledger.Mempool (TxId (..)) import Ouroboros.Consensus.Shelley.Node () +import Ouroboros.Consensus.Protocol.Ledger.HotKey qualified as HotKey +import Ouroboros.Consensus.Storage.ChainDB qualified as ChainDB import Ouroboros.Consensus.TypeFamilyWrappers +import Ouroboros.Consensus.Util.Orphans () + +import Ouroboros.Network.AnchoredFragment qualified as AF +import Ouroboros.Network.NodeToClient (LocalConnectionId) +import Ouroboros.Network.NodeToNode (RemoteConnectionId) -- @@ -173,6 +200,33 @@ instance All HasKESMetricsData xs => HasKESMetricsData (HardForkBlock xs) where -> K KESMetricsData blk getOne = K . getKESMetricsData (Proxy @blk) . unwrapForgeStateInfo +-- +-- * GetKESInfo +-- +class GetKESInfo blk where + getKESInfoFromStateInfo :: Proxy blk -> ForgeStateInfo blk -> Maybe HotKey.KESInfo + getKESInfoFromStateInfo _ _ = Nothing + +instance GetKESInfo (ShelleyBlock era) where + getKESInfoFromStateInfo _ = Just + +instance GetKESInfo ByronBlock + +instance All GetKESInfo xs => GetKESInfo (HardForkBlock xs) where + getKESInfoFromStateInfo _ forgeStateInfo = + case forgeStateInfo of + CurrentEraLacksBlockForging _ -> Nothing + CurrentEraForgeStateUpdated currentEraForgeStateInfo -> + hcollapse + . hcmap (Proxy @GetKESInfo) getOne + . getOneEraForgeStateInfo + $ currentEraForgeStateInfo + where + getOne :: forall blk. GetKESInfo blk + => WrapForgeStateInfo blk + -> K (Maybe HotKey.KESInfo) blk + getOne = K . getKESInfoFromStateInfo (Proxy @blk) . unwrapForgeStateInfo + -- -- * General ledger -- @@ -219,3 +273,42 @@ instance LedgerQueries (Cardano.CardanoBlock c) where Cardano.LedgerStateAllegra ledgerAllegra -> ledgerDelegMapSize ledgerAllegra Cardano.LedgerStateMary ledgerMary -> ledgerDelegMapSize ledgerMary Cardano.LedgerStateAlonzo ledgerAlonzo -> ledgerDelegMapSize ledgerAlonzo + +-- +-- * Node kernel +-- +newtype NodeKernelData blk = + NodeKernelData + { unNodeKernelData :: IORef (StrictMaybe (NodeKernel IO RemoteConnectionId LocalConnectionId blk)) + } + +mkNodeKernelData :: IO (NodeKernelData blk) +mkNodeKernelData = NodeKernelData <$> newIORef SNothing + +setNodeKernel :: NodeKernelData blk + -> NodeKernel IO RemoteConnectionId LocalConnectionId blk + -> IO () +setNodeKernel (NodeKernelData ref) nodeKern = + writeIORef ref $ SJust nodeKern + +mapNodeKernelDataIO :: + (NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO a) + -> NodeKernelData blk + -> IO (StrictMaybe a) +mapNodeKernelDataIO f (NodeKernelData ref) = + readIORef ref >>= traverse f + +nkQueryLedger :: + IsLedger (LedgerState blk) + => (ExtLedgerState blk -> a) + -> NodeKernel IO RemoteConnectionId LocalConnectionId blk + -> IO a +nkQueryLedger f NodeKernel{getChainDB} = + f <$> atomically (ChainDB.getCurrentLedger getChainDB) + +nkQueryChain :: + (AF.AnchoredFragment (Header blk) -> a) + -> NodeKernel IO RemoteConnectionId LocalConnectionId blk + -> IO a +nkQueryChain f NodeKernel{getChainDB} = + f <$> atomically (ChainDB.getCurrentChain getChainDB) diff --git a/cardano-node/src/Cardano/Node/Run.hs b/cardano-node/src/Cardano/Node/Run.hs index 2e6d702fa47..e93c0cc0997 100644 --- a/cardano-node/src/Cardano/Node/Run.hs +++ b/cardano-node/src/Cardano/Node/Run.hs @@ -1,11 +1,13 @@ -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE CPP #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE PackageImports #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TupleSections #-} +{-# LANGUAGE TypeApplications #-} #if !defined(mingw32_HOST_OS) #define UNIX @@ -17,24 +19,25 @@ module Cardano.Node.Run ) where import Cardano.Prelude hiding (ByteString, STM, atomically, take, trace) +import Prelude (String, error, id) import Data.IP (toSockAddr) -import Prelude (String, id) import qualified Control.Concurrent.Async as Async import Control.Monad.Class.MonadSTM.Strict import Control.Monad.Trans.Except.Extra (left) -import Control.Tracer +import "contra-tracer" Control.Tracer import qualified Data.Map.Strict as Map import Data.Text (breakOn, pack, take) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import Data.Time.Clock (getCurrentTime) -import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds) import Data.Version (showVersion) import Network.HostName (getHostName) import Network.Socket (Socket) -import System.Directory (canonicalizePath, createDirectoryIfMissing, makeAbsolute) +import System.Directory (canonicalizePath, createDirectoryIfMissing, + makeAbsolute) import System.Environment (lookupEnv) + #ifdef UNIX import System.Posix.Files import qualified System.Posix.Signals as Signals @@ -43,7 +46,6 @@ import System.Posix.Types (FileMode) import System.Win32.File #endif -import Cardano.BM.Data.LogItem (LogObject (..)) import Cardano.BM.Data.Tracer (ToLogObject (..), TracingVerbosity (..)) import Cardano.BM.Data.Transformers (setHostname) import Cardano.BM.Trace @@ -52,17 +54,20 @@ import Paths_cardano_node (version) import qualified Cardano.Crypto.Libsodium as Crypto import Cardano.Node.Configuration.Logging (LoggingLayer (..), createLoggingLayer, - nodeBasicInfo, shutdownLoggingLayer) + shutdownLoggingLayer) import Cardano.Node.Configuration.POM (NodeConfiguration (..), PartialNodeConfiguration (..), SomeNetworkP2PMode (..), defaultPartialNodeConfiguration, makeNodeConfiguration, parseNodeConfigurationFP) -import Cardano.Node.Queries (HasKESInfo (..), HasKESMetricsData (..)) +import Cardano.Node.Configuration.NodeAddress +import Cardano.Node.Startup import Cardano.Node.Types +import Cardano.Node.Tracing.API +import Cardano.Node.Tracing.Tracers.Startup (getStartupInfo) import Cardano.Tracing.Config (TraceOptions (..), TraceSelection (..)) -import Cardano.Tracing.Constraints (TraceConstraints) -import Cardano.Tracing.Startup import qualified Ouroboros.Consensus.Config as Consensus +import Ouroboros.Consensus.Config.SupportsNode + (ConfigSupportsNode (..)) import Ouroboros.Consensus.Node (NetworkP2PMode (..), RunNode, RunNodeArgs (..), StdRunNodeArgs (..)) import qualified Ouroboros.Consensus.Node as Node (getChainDB, run) @@ -91,7 +96,8 @@ import qualified Cardano.Node.Configuration.TopologyP2P as TopologyP2P import Cardano.Node.Handlers.Shutdown import Cardano.Node.Protocol (mkConsensusProtocol) import Cardano.Node.Protocol.Types -import Cardano.Tracing.Kernel +import Cardano.Node.TraceConstraints (TraceConstraints) +import Cardano.Node.Queries import Cardano.Tracing.Peer import Cardano.Tracing.Tracers @@ -126,66 +132,95 @@ runNode cmdPc = do p :: SomeConsensusProtocol <- case eitherSomeProtocol of Left err -> putStrLn (displayError err) >> exitFailure - Right p -> pure p - - eLoggingLayer <- runExceptT $ createLoggingLayer - (Text.pack (showVersion version)) - nc - p - - loggingLayer <- case eLoggingLayer of - Left err -> putTextLn (show err) >> exitFailure - Right res -> return res - - !trace <- setupTrace loggingLayer - let tracer = contramap pack $ toLogObject trace - - logTracingVerbosity nc tracer - - let handleNodeWithTracers - :: ( HasKESMetricsData blk - , HasKESInfo blk - , TraceConstraints blk - , Protocol.Protocol IO blk - ) - => Protocol.ProtocolInfoArgs IO blk - -> IO () - handleNodeWithTracers runP = do - -- This IORef contains node kernel structure which holds node kernel. - -- Used for ledger queries and peer connection status. - nodeKernelData <- mkNodeKernelData - let ProtocolInfo { pInfoConfig = cfg } = Protocol.protocolInfo runP - case ncEnableP2P nc of - SomeNetworkP2PMode p2pMode -> do - tracers <- mkTracers - (Consensus.configBlock cfg) - (ncTraceConfig nc) - trace - nodeKernelData - (llEKGDirect loggingLayer) - p2pMode - Async.withAsync (handlePeersListSimple trace nodeKernelData) - $ \_peerLogingThread -> - -- We ignore peer loging thread if it dies, but it will be killed - -- when 'handleSimpleNode' terminates. - handleSimpleNode p runP p2pMode trace tracers nc - (setNodeKernel nodeKernelData) - `finally` - shutdownLoggingLayer loggingLayer + Right p -> pure p + + let networkMagic :: NetworkMagic = + case p of + SomeConsensusProtocol _ runP -> + let ProtocolInfo { pInfoConfig } = Protocol.protocolInfo runP + in getNetworkMagic $ Consensus.configBlock pInfoConfig case p of - SomeConsensusProtocol _ runP -> handleNodeWithTracers runP + SomeConsensusProtocol _ runP -> + handleNodeWithTracers cmdPc nc p networkMagic runP + +handleNodeWithTracers + :: ( TraceConstraints blk + , Protocol.Protocol IO blk + ) + => PartialNodeConfiguration + -> NodeConfiguration + -> SomeConsensusProtocol + -> NetworkMagic + -> Protocol.ProtocolInfoArgs IO blk + -> IO () +handleNodeWithTracers cmdPc nc p networkMagic runP = do + -- This IORef contains node kernel structure which holds node kernel. + -- Used for ledger queries and peer connection status. + nodeKernelData <- mkNodeKernelData + let ProtocolInfo { pInfoConfig = cfg } = Protocol.protocolInfo runP + case ncEnableP2P nc of + SomeNetworkP2PMode p2pMode -> do + let fp = maybe "No file path found!" + unConfigPath + (getLast (pncConfigFile cmdPc)) + (tracers, mLoggingLayer) <- + case ncTraceConfig nc of + TraceDispatcher{} -> do + (, Nothing) <$> + initTraceDispatcher + nc + p + networkMagic + nodeKernelData + p2pMode + _ -> do + eLoggingLayer <- runExceptT $ createLoggingLayer + (Text.pack (showVersion version)) + nc + p + + loggingLayer <- case eLoggingLayer of + Left err -> putTextLn (show err) >> exitFailure + Right res -> return res + !trace <- setupTrace loggingLayer + let tracer = contramap pack $ toLogObject trace + logTracingVerbosity nc tracer + + (,Just loggingLayer) <$> + mkTracers + (Consensus.configBlock cfg) + (ncTraceConfig nc) + trace + nodeKernelData + (llEKGDirect loggingLayer) + p2pMode + + getStartupInfo nc p fp + >>= mapM_ (traceWith $ startupTracer tracers) + + Async.withAsync (handlePeersListSimple (error "Implement Tracer IO [Peer blk]") nodeKernelData) + $ \_peerLogingThread -> + -- We ignore peer loging thread if it dies, but it will be killed + -- when 'handleSimpleNode' terminates. + handleSimpleNode runP p2pMode tracers nc + (setNodeKernel nodeKernelData) + `finally` + forM_ mLoggingLayer + shutdownLoggingLayer + logTracingVerbosity :: NodeConfiguration -> Tracer IO String -> IO () logTracingVerbosity nc tracer = case ncTraceConfig nc of TracingOff -> return () - TracingOn traceConf -> + TracingOnLegacy traceConf -> case traceVerbosity traceConf of NormalVerbosity -> traceWith tracer "tracing verbosity = normal verbosity " MinimalVerbosity -> traceWith tracer "tracing verbosity = minimal verbosity " MaximalVerbosity -> traceWith tracer "tracing verbosity = maximal verbosity " - + TraceDispatcher _traceConf -> + pure () -- | Add the application name and unqualified hostname to the logging -- layer basic trace. -- @@ -213,7 +248,6 @@ handlePeersListSimple tr nodeKern = forever $ do getCurrentPeers nodeKern >>= tracePeers tr threadDelay 2000000 -- 2 seconds. - -- | Sets up a simple node, which will run the chain sync protocol and block -- fetch protocol, and, if core, will also look at the mempool when trying to -- create a new block. @@ -223,10 +257,8 @@ handleSimpleNode . ( RunNode blk , Protocol.Protocol IO blk ) - => SomeConsensusProtocol - -> Protocol.ProtocolInfoArgs IO blk + => Protocol.ProtocolInfoArgs IO blk -> NetworkP2PMode p2p - -> Trace IO Text -> Tracers RemoteConnectionId LocalConnectionId blk p2p -> NodeConfiguration -> (NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO ()) @@ -234,21 +266,26 @@ handleSimpleNode -- layer is initialised. This implies this function must not block, -- otherwise the node won't actually start. -> IO () -handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do +handleSimpleNode runP p2pMode tracers nc onKernel = do logStartupWarnings - let pInfo = Protocol.protocolInfo runP + traceWith (startupTracer tracers) + =<< StartupTime <$> getCurrentTime - createTracers nc trace + when (ncValidateDB nc) $ + traceWith (startupTracer tracers) + StartupDBValidation + + let pInfo = Protocol.protocolInfo runP (publicIPv4SocketOrAddr, publicIPv6SocketOrAddr, localSocketOrPath) <- do - result <- runExceptT (gatherConfiguredSockets nc) + result <- runExceptT (gatherConfiguredSockets $ ncSocketConfig nc) case result of Right triplet -> return triplet - Left error -> do - traceWith (startupTracer nodeTracers) - $ StartupSocketConfigError error - throwIO error + Left err -> do + traceWith (startupTracer tracers) + $ StartupSocketConfigError err + throwIO err dbPath <- canonDbPath nc @@ -268,9 +305,9 @@ handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do Nothing -> Nothing , Diffusion.daLocalAddress = case localSocketOrPath of -- TODO allow expressing the Nothing case in the config - Just (ActualSocket localSocket) -> Just (Left localSocket) - Just (SocketInfo localAddr) -> Just (Right localAddr) - Nothing -> Nothing + Just (ActualSocket localSocket) -> Just (Left localSocket) + Just (SocketInfo localAddr) -> Just (Right localAddr) + Nothing -> Nothing , Diffusion.daAcceptedConnectionsLimit = AcceptedConnectionsLimit { acceptedConnectionsHardLimit = 512 @@ -283,7 +320,7 @@ handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do ipv4 <- traverse getSocketOrSocketInfoAddr publicIPv4SocketOrAddr ipv6 <- traverse getSocketOrSocketInfoAddr publicIPv6SocketOrAddr - traceWith (startupTracer nodeTracers) + traceWith (startupTracer tracers) (StartupInfo (catMaybes [ipv4, ipv6]) localSocketOrPath ( limitToLatestReleasedVersion fst @@ -295,25 +332,28 @@ handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do $ Proxy @blk )) - withShutdownHandling (ncShutdownIPC nc) trace $ + withShutdownHandling (ncShutdownConfig nc) (shutdownTracer tracers) $ let nodeArgs = RunNodeArgs - { rnTraceConsensus = consensusTracers nodeTracers - , rnTraceNTN = nodeToNodeTracers nodeTracers - , rnTraceNTC = nodeToClientTracers nodeTracers + { rnTraceConsensus = consensusTracers tracers + , rnTraceNTN = nodeToNodeTracers tracers + , rnTraceNTC = nodeToClientTracers tracers , rnProtocolInfo = pInfo , rnNodeKernelHook = \registry nodeKernel -> do - maybeSpawnOnSlotSyncedShutdownHandler nc trace registry + maybeSpawnOnSlotSyncedShutdownHandler + (ncShutdownConfig nc) + (shutdownTracer tracers) + registry (Node.getChainDB nodeKernel) onKernel nodeKernel , rnEnableP2P = p2pMode } in case p2pMode of EnabledP2PMode -> do - traceWith (startupTracer nodeTracers) + traceWith (startupTracer tracers) (StartupP2PInfo (ncDiffusionMode nc)) nt <- TopologyP2P.readTopologyFileOrError nc let (localRoots, publicRoots) = producerAddresses nt - traceWith (startupTracer nodeTracers) + traceWith (startupTracer tracers) $ NetworkConfig localRoots publicRoots (useLedgerAfterSlot nt) @@ -339,10 +379,10 @@ handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do , srnDiffusionArgumentsExtra = mkP2PArguments nc (readTVar localRootsVar) (readTVar publicRootsVar) (readTVar useLedgerVar) - , srnDiffusionTracers = diffusionTracers nodeTracers - , srnDiffusionTracersExtra = diffusionTracersExtra nodeTracers + , srnDiffusionTracers = diffusionTracers tracers + , srnDiffusionTracersExtra = diffusionTracersExtra tracers , srnEnableInDevelopmentVersions = ncTestEnableDevelopmentNetworkProtocols nc - , srnTraceChainDB = chainDBTracer nodeTracers + , srnTraceChainDB = chainDBTracer tracers , srnMaybeMempoolCapacityOverride = ncMaybeMempoolCapacityOverride nc } DisabledP2PMode -> do @@ -372,10 +412,10 @@ handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do , srnDatabasePath = dbPath , srnDiffusionArguments = diffusionArguments , srnDiffusionArgumentsExtra = mkNonP2PArguments ipProducers dnsProducers - , srnDiffusionTracers = diffusionTracers nodeTracers - , srnDiffusionTracersExtra = diffusionTracersExtra nodeTracers + , srnDiffusionTracers = diffusionTracers tracers + , srnDiffusionTracersExtra = diffusionTracersExtra tracers , srnEnableInDevelopmentVersions = ncTestEnableDevelopmentNetworkProtocols nc - , srnTraceChainDB = chainDBTracer nodeTracers + , srnTraceChainDB = chainDBTracer tracers , srnMaybeMempoolCapacityOverride = ncMaybeMempoolCapacityOverride nc } where @@ -384,9 +424,9 @@ handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do (case p2pMode of DisabledP2PMode -> return () EnabledP2PMode -> do - traceWith (startupTracer nodeTracers) P2PWarning + traceWith (startupTracer tracers) P2PWarning when (not $ ncTestEnableDevelopmentNetworkProtocols nc) - $ traceWith (startupTracer nodeTracers) + $ traceWith (startupTracer tracers) P2PWarningDevelopementNetworkProtocols ) :: IO () -- annoying, but unavoidable for GADT type inference @@ -406,29 +446,11 @@ handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do $ supportedNodeToClientVersions (Proxy @blk) when ( ncTestEnableDevelopmentNetworkProtocols nc && (not (null developmentNtnVersions) || not (null developmentNtcVersions)) ) - $ traceWith (startupTracer nodeTracers) + $ traceWith (startupTracer tracers) (WarningDevelopmentNetworkProtocols developmentNtnVersions developmentNtcVersions) - createTracers - :: NodeConfiguration - -> Trace IO Text - -> IO () - createTracers NodeConfiguration { ncValidateDB } - tr = do - startTime <- getCurrentTime - traceNodeBasicInfo tr =<< nodeBasicInfo nc scp startTime - traceCounter "nodeStartTime" tr (ceiling $ utcTimeToPOSIXSeconds startTime) - traceWith (startupTracer nodeTracers) - $ StartupTime startTime - when ncValidateDB $ traceWith (startupTracer nodeTracers) StartupDBValidation - - traceNodeBasicInfo :: Trace IO Text -> [LogObject Text] -> IO () - traceNodeBasicInfo tr basicInfoItems = - forM_ basicInfoItems $ \(LogObject nm mt content) -> - traceNamedObject (appendName nm tr) (mt, content) - #ifdef UNIX updateTopologyConfiguration :: StrictTVar IO [(Int, Map RelayAccessPoint PeerAdvertise)] -> StrictTVar IO [RelayAccessPoint] @@ -436,16 +458,16 @@ handleSimpleNode scp runP p2pMode trace nodeTracers nc onKernel = do -> Signals.Handler updateTopologyConfiguration localRootsVar publicRootsVar useLedgerVar = Signals.Catch $ do - traceWith (startupTracer nodeTracers) NetworkConfigUpdate + traceWith (startupTracer tracers) NetworkConfigUpdate result <- try $ readTopologyFileOrError nc case result of Left (FatalError err) -> - traceWith (startupTracer nodeTracers) + traceWith (startupTracer tracers) $ NetworkConfigUpdateError $ pack "Error reading topology configuration file:" <> err Right nt -> do let (localRoots, publicRoots) = producerAddresses nt - traceWith (startupTracer nodeTracers) + traceWith (startupTracer tracers) $ NetworkConfig localRoots publicRoots (useLedgerAfterSlot nt) atomically $ do writeTVar localRootsVar localRoots diff --git a/cardano-node/src/Cardano/Node/Startup.hs b/cardano-node/src/Cardano/Node/Startup.hs new file mode 100644 index 00000000000..9bac6f94722 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Startup.hs @@ -0,0 +1,207 @@ +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE UndecidableInstances #-} + +module Cardano.Node.Startup where + +import Prelude + +import Data.Aeson (FromJSON, ToJSON) +import Data.Map (Map) +import Data.Text (Text, pack) +import Data.Time.Clock (NominalDiffTime, UTCTime) +import Data.Version (showVersion) +import Data.Word (Word64) +import GHC.Generics (Generic) + +import Network.HostName (getHostName) +import qualified Network.Socket as Socket + +import Cardano.Ledger.Shelley.Genesis (sgSystemStart) + +import qualified Ouroboros.Consensus.BlockchainTime.WallClock.Types as WCT +import Ouroboros.Consensus.Cardano.Block +import Ouroboros.Consensus.Config +import Ouroboros.Consensus.HardFork.Combinator.Degenerate +import Ouroboros.Consensus.Ledger.Query (getSystemStart) +import Ouroboros.Consensus.Node (pInfoConfig) +import Ouroboros.Consensus.Node.NetworkProtocolVersion + (BlockNodeToClientVersion, BlockNodeToNodeVersion) +import Ouroboros.Consensus.Cardano.CanHardFork (shelleyLedgerConfig) +import Ouroboros.Consensus.Shelley.Ledger.Ledger (shelleyLedgerGenesis) + +import Ouroboros.Network.Magic (NetworkMagic (..)) +import Ouroboros.Network.NodeToClient (LocalAddress (..), + LocalSocket, NodeToClientVersion) +import Ouroboros.Network.NodeToNode (DiffusionMode (..), + NodeToNodeVersion) +import Ouroboros.Network.PeerSelection.LedgerPeers (UseLedgerAfter (..)) +import Ouroboros.Network.PeerSelection.Types (PeerAdvertise) +import Ouroboros.Network.PeerSelection.RelayAccessPoint (RelayAccessPoint) +import Ouroboros.Network.Subscription.Dns (DnsSubscriptionTarget (..)) +import Ouroboros.Network.Subscription.Ip (IPSubscriptionTarget (..)) + +import Cardano.Api.Protocol.Types (BlockType (..), protocolInfo) +import Cardano.Node.Configuration.Socket +import Cardano.Node.Protocol.Types (Protocol (..), SomeConsensusProtocol (..)) +import Cardano.Logging + +import Paths_cardano_node (version) +import Cardano.Config.Git.Rev (gitRev) + +data StartupTrace blk = + -- | Log startup information. + -- + StartupInfo + [SocketOrSocketInfo Socket.SockAddr Socket.SockAddr] + -- ^ node-to-node addresses + (Maybe (SocketOrSocketInfo LocalSocket LocalAddress)) + -- ^ node-to-client socket path + (Map NodeToNodeVersion (BlockNodeToNodeVersion blk)) + -- ^ supported node-to-node versions + (Map NodeToClientVersion (BlockNodeToClientVersion blk)) + -- ^ supported node-to-client versions + + -- | Log peer-to-peer diffusion mode + | StartupP2PInfo DiffusionMode + + | StartupTime UTCTime + + | StartupNetworkMagic NetworkMagic + + | StartupSocketConfigError SocketConfigError + + | StartupDBValidation + + -- | Log that the network configuration is being updated. + -- + | NetworkConfigUpdate + + -- | Log network configuration update error. + -- + | NetworkConfigUpdateError Text + + -- | Log peer-to-peer network configuration, either on startup or when its + -- updated. + -- + | NetworkConfig [(Int, Map RelayAccessPoint PeerAdvertise)] + [RelayAccessPoint] + UseLedgerAfter + + -- | Warn when 'EnableP2P' is set. + | P2PWarning + + -- | Warn that peer-to-peer requires + -- 'TestEnableDevelopmentNetworkProtocols' to be set. + -- + | P2PWarningDevelopementNetworkProtocols + + -- | Warn when 'TestEnableDevelopmentNetworkProtocols' is set. + -- + | WarningDevelopmentNetworkProtocols [NodeToNodeVersion] [NodeToClientVersion] + + | BICommon BasicInfoCommon + | BIShelley BasicInfoShelleyBased + | BIByron BasicInfoByron + | BINetwork BasicInfoNetwork + +data BasicInfoCommon = BasicInfoCommon { + biConfigPath :: FilePath + , biNetworkMagic :: NetworkMagic + , biProtocol :: Text + , biVersion :: Text + , biCommit :: Text + , biNodeStartTime :: UTCTime + } + +data BasicInfoShelleyBased = BasicInfoShelleyBased { + bisEra :: Text + , bisSystemStartTime :: UTCTime + , bisSlotLength :: NominalDiffTime + , bisEpochLength :: Word64 + , bisSlotsPerKESPeriod :: Word64 +} + +data BasicInfoByron = BasicInfoByron { + bibSystemStartTime :: UTCTime + , bibSlotLength :: NominalDiffTime + , bibEpochLength :: Word64 +} + +data BasicInfoNetwork = BasicInfoNetwork { + niAddresses :: [SocketOrSocketInfo Socket.SockAddr Socket.SockAddr] + , niDiffusionMode :: DiffusionMode + , niDnsProducers :: [DnsSubscriptionTarget] + , niIpProducers :: IPSubscriptionTarget + } + +data NodeInfo = NodeInfo + { niName :: Text + , niProtocol :: Text + , niVersion :: Text + , niCommit :: Text + , niStartTime :: UTCTime + , niSystemStartTime :: UTCTime + } deriving (Eq, Generic, ToJSON, FromJSON, Show) + +docNodeInfoTraceEvent :: Documented NodeInfo +docNodeInfoTraceEvent = Documented [ + DocMsg + (NodeInfo "" "" "" "" anyProto anyProto) + [] + "Basic information about this node collected at startup\ + \\n\ + \\n _niName_: Name of the node. \ + \\n _niProtocol_: Protocol which this nodes uses. \ + \\n _niVersion_: Software version which this node is using. \ + \\n _niStartTime_: Start time of this node. \ + \\n _niSystemStartTime_: How long did the start of the node took." + ] + +-- | Prepare basic info about the node. This info will be sent to 'cardano-tracer'. +prepareNodeInfo + :: Protocol + -> SomeConsensusProtocol + -> TraceConfig + -> UTCTime + -> IO NodeInfo +prepareNodeInfo ptcl (SomeConsensusProtocol whichP pForInfo) tc nodeStartTime = do + nodeName <- prepareNodeName + return $ NodeInfo + { niName = nodeName + , niProtocol = pack . show $ ptcl + , niVersion = pack . showVersion $ version + , niCommit = gitRev + , niStartTime = nodeStartTime + , niSystemStartTime = systemStartTime + } + where + cfg = pInfoConfig $ protocolInfo pForInfo + + systemStartTime :: UTCTime + systemStartTime = + case whichP of + ByronBlockType -> + getSystemStartByron + ShelleyBlockType -> + let DegenLedgerConfig cfgShelley = configLedger cfg + in getSystemStartShelley cfgShelley + CardanoBlockType -> + let CardanoLedgerConfig _ cfgShelley cfgAllegra cfgMary cfgAlonzo = configLedger cfg + in minimum [ getSystemStartByron + , getSystemStartShelley cfgShelley + , getSystemStartShelley cfgAllegra + , getSystemStartShelley cfgMary + , getSystemStartShelley cfgAlonzo + ] + + getSystemStartByron = WCT.getSystemStart . getSystemStart . configBlock $ cfg + getSystemStartShelley = sgSystemStart . shelleyLedgerGenesis . shelleyLedgerConfig + + prepareNodeName = + case tcNodeName tc of + Just aName -> return aName + Nothing -> pack <$> getHostName diff --git a/cardano-node/src/Cardano/Tracing/Constraints.hs b/cardano-node/src/Cardano/Node/TraceConstraints.hs similarity index 61% rename from cardano-node/src/Cardano/Tracing/Constraints.hs rename to cardano-node/src/Cardano/Node/TraceConstraints.hs index f35938603cf..10499d26f5a 100644 --- a/cardano-node/src/Cardano/Tracing/Constraints.hs +++ b/cardano-node/src/Cardano/Node/TraceConstraints.hs @@ -1,16 +1,16 @@ -{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} - -module Cardano.Tracing.Constraints - ( TraceConstraints - ) where +module Cardano.Node.TraceConstraints (TraceConstraints) where import Prelude (Show) import Data.Aeson import Cardano.BM.Tracing (ToObject) -import Cardano.Node.Queries (ConvertTxId, LedgerQueries) +import Cardano.Logging (LogFormatting) +import Cardano.Node.Queries (ConvertTxId, GetKESInfo (..), + HasKESInfo (..), HasKESMetricsData (..), LedgerQueries) import Cardano.Ledger.Alonzo (AlonzoEra) import Cardano.Ledger.Alonzo.PParams (PParamsUpdate) @@ -19,15 +19,19 @@ import Cardano.Ledger.Alonzo.Rules.Utxo (UtxoPredicateFailure) import Cardano.Ledger.Alonzo.Rules.Utxow (AlonzoPredFail) import Cardano.Ledger.Alonzo.TxBody (TxOut) import Cardano.Ledger.Crypto (StandardCrypto) -import Ouroboros.Consensus.Block (BlockProtocol, CannotForge, ForgeStateUpdateError, - Header) + +import Ouroboros.Consensus.Block (BlockProtocol, CannotForge, + ConvertRawHash, ForgeStateUpdateError, Header) import Ouroboros.Consensus.HeaderValidation (OtherHeaderEnvelopeError) import Ouroboros.Consensus.Ledger.Abstract (LedgerError) -import Ouroboros.Consensus.Ledger.Inspect (LedgerEvent) -import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr, HasTxId, HasTxs (..)) +import Ouroboros.Consensus.Ledger.Inspect (LedgerEvent, LedgerUpdate, + LedgerWarning) +import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr, + HasTxId, HasTxs (..)) import Ouroboros.Consensus.Protocol.Abstract (ValidationErr) import Ouroboros.Consensus.Shelley.Ledger.Mempool (GenTx, TxId) + -- | Tracing-related constraints for monitoring purposes. type TraceConstraints blk = ( ConvertTxId blk @@ -37,6 +41,13 @@ type TraceConstraints blk = , ToJSON (TxId (GenTx blk)) , ToJSON (TxOut (AlonzoEra StandardCrypto)) , ToJSON (PParamsUpdate (AlonzoEra StandardCrypto)) + , HasKESMetricsData blk + , HasKESInfo blk + , ConvertRawHash blk + , GetKESInfo blk + , Show blk + , Show (Header blk) + , ToObject (ApplyTxErr blk) , ToObject (GenTx blk) , ToObject (Header blk) @@ -49,6 +60,18 @@ type TraceConstraints blk = , ToObject (UtxoPredicateFailure (AlonzoEra StandardCrypto)) , ToObject (AlonzoBbodyPredFail (AlonzoEra StandardCrypto)) , ToObject (AlonzoPredFail (AlonzoEra StandardCrypto)) - , Show blk - , Show (Header blk) + + , LogFormatting (LedgerUpdate blk) + , LogFormatting (LedgerWarning blk) + , LogFormatting (ApplyTxErr blk) + , LogFormatting (GenTx blk) + , LogFormatting (Header blk) + , LogFormatting (LedgerError blk) + , LogFormatting (OtherHeaderEnvelopeError blk) + , LogFormatting (ValidationErr (BlockProtocol blk)) + , LogFormatting (CannotForge blk) + , LogFormatting (ForgeStateUpdateError blk) + , LogFormatting (UtxoPredicateFailure (AlonzoEra StandardCrypto)) + , LogFormatting (AlonzoBbodyPredFail (AlonzoEra StandardCrypto)) + , LogFormatting (AlonzoPredFail (AlonzoEra StandardCrypto)) ) diff --git a/cardano-node/src/Cardano/Node/Tracing.hs b/cardano-node/src/Cardano/Node/Tracing.hs new file mode 100644 index 00000000000..a6d432b96d7 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing.hs @@ -0,0 +1,51 @@ +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE PackageImports #-} +{-# LANGUAGE ImportQualifiedPost #-} +module Cardano.Node.Tracing + ( Tracers (..) + ) where + +import Prelude (IO) + +import Codec.CBOR.Read (DeserialiseFailure) +import "contra-tracer" Control.Tracer (Tracer) + +import Ouroboros.Consensus.Network.NodeToClient qualified as NodeToClient +import Ouroboros.Consensus.Network.NodeToNode qualified as NodeToNode +import Ouroboros.Consensus.Node.Tracers qualified as Consensus +import Ouroboros.Consensus.Storage.ChainDB qualified as ChainDB +import Ouroboros.Network.Diffusion qualified as Diffusion + +import Ouroboros.Network.NodeToNode (NodeToNodeVersion, RemoteAddress) +import Ouroboros.Network.NodeToClient (LocalAddress, NodeToClientVersion) + +import Cardano.Node.Handlers.Shutdown (ShutdownTrace) +import Cardano.Node.Startup (NodeInfo, StartupTrace) + +import Cardano.Logging.Resources +import Cardano.Node.Tracing.Tracers.Peer (PeerT) + + +data Tracers peer localPeer blk p2p = Tracers + { -- | Trace the ChainDB + chainDBTracer :: Tracer IO (ChainDB.TraceEvent blk) + -- | Consensus-specific tracers. + , consensusTracers :: Consensus.Tracers IO peer localPeer blk + -- | Tracers for the node-to-node protocols. + , nodeToNodeTracers :: NodeToNode.Tracers IO peer blk DeserialiseFailure + --, serialisedBlockTracer :: NodeToNode.SerialisedTracer IO peer blk (SerialisedBlockTrace) + -- | Tracers for the node-to-client protocols + , nodeToClientTracers :: NodeToClient.Tracers IO localPeer blk DeserialiseFailure + -- | Diffusion tracers + , diffusionTracers :: Diffusion.Tracers RemoteAddress NodeToNodeVersion + LocalAddress NodeToClientVersion + IO + , diffusionTracersExtra :: Diffusion.ExtraTracers p2p + + , startupTracer :: Tracer IO (StartupTrace blk) + , shutdownTracer :: Tracer IO ShutdownTrace + , nodeInfoTracer :: Tracer IO NodeInfo + , resourcesTracer :: Tracer IO ResourceStats + , peersTracer :: Tracer IO [PeerT blk] + } diff --git a/cardano-node/src/Cardano/Node/Tracing/API.hs b/cardano-node/src/Cardano/Node/Tracing/API.hs new file mode 100644 index 00000000000..0d056da5225 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/API.hs @@ -0,0 +1,93 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MonoLocalBinds #-} +{-# LANGUAGE PackageImports #-} +{-# LANGUAGE RankNTypes #-} + +module Cardano.Node.Tracing.API + ( initTraceDispatcher + ) where + +import Prelude + +import "contra-tracer" Control.Tracer (traceWith) +import Data.Maybe (fromMaybe) +import Data.Time.Clock (getCurrentTime) + +import System.Metrics as EKG + +import Network.Mux.Trace (TraceLabelPeer (..)) + +import Ouroboros.Consensus.Ledger.Inspect (LedgerEvent) +import Ouroboros.Consensus.MiniProtocol.ChainSync.Client (TraceChainSyncClientEvent) +import Ouroboros.Consensus.Node (NetworkP2PMode, RunNode) +import Ouroboros.Network.ConnectionId (ConnectionId) +import Ouroboros.Network.Magic (NetworkMagic) +import Ouroboros.Network.NodeToClient (withIOManager) +import Ouroboros.Network.NodeToNode (RemoteAddress) + +import Cardano.Node.Configuration.POM (NodeConfiguration (..), ncProtocol) +import Cardano.Node.Protocol.Types +import Cardano.Node.Queries +import Cardano.Node.Startup +import Cardano.Node.TraceConstraints +import Cardano.Node.Tracing +import Cardano.Node.Types + +import Cardano.Logging hiding (traceWith) +import Cardano.Node.Tracing.Tracers +import Cardano.Node.Tracing.Tracers.Peer (startPeerTracer) +import Cardano.Node.Tracing.Tracers.Resources (startResourceTracer) + +initTraceDispatcher :: + forall blk p2p. + ( RunNode blk + , TraceConstraints blk + + , LogFormatting (LedgerEvent blk) + , LogFormatting + (TraceLabelPeer (ConnectionId RemoteAddress) (TraceChainSyncClientEvent blk)) + ) + => NodeConfiguration + -> SomeConsensusProtocol + -> NetworkMagic + -> NodeKernelData blk + -> NetworkP2PMode p2p + -> IO (Tracers RemoteConnectionId LocalConnectionId blk p2p) +initTraceDispatcher nc p networkMagic nodeKernel p2pMode = do + trConfig <- readConfiguration (unConfigPath $ ncConfigFile nc) +-- trace ("TraceConfig " <> show trConfig) $ pure () + + ekgStore <- EKG.newStore + ekgTrace <- ekgTracer (Left ekgStore) + + -- TODO: check if this is the correct way to use withIOManager + (forwardSink, dpStore) <- + withIOManager $ \iomgr -> + initForwarding iomgr trConfig networkMagic ekgStore + + stdoutTrace <- standardTracer + + tracers <- + mkDispatchTracers + nodeKernel + stdoutTrace + (forwardTracer forwardSink) + (Just ekgTrace) + (dataPointTracer dpStore) + trConfig + p2pMode + + startResourceTracer + (resourcesTracer tracers) + (fromMaybe 1000 (tcResourceFreqency trConfig)) + + startPeerTracer + (peersTracer tracers) + nodeKernel + (fromMaybe 2000 (tcPeerFreqency trConfig)) + + now <- getCurrentTime + prepareNodeInfo (ncProtocol nc) p trConfig now + >>= traceWith (nodeInfoTracer tracers) + + pure tracers diff --git a/cardano-node/src/Cardano/Node/Tracing/Compat.hs b/cardano-node/src/Cardano/Node/Tracing/Compat.hs new file mode 100644 index 00000000000..692f6857792 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Compat.hs @@ -0,0 +1,22 @@ +{-# LANGUAGE LambdaCase #-} + +module Cardano.Node.Tracing.Compat + ( toDetailLevel + , fromDetailLevel + ) where + +import qualified Cardano.BM.Data.Tracer as IOMF +import qualified Cardano.Logging.Types as TD + +toDetailLevel :: IOMF.TracingVerbosity -> TD.DetailLevel +toDetailLevel = \case + IOMF.MinimalVerbosity -> TD.DMinimal + IOMF.NormalVerbosity -> TD.DNormal + IOMF.MaximalVerbosity -> TD.DMaximum + +fromDetailLevel :: TD.DetailLevel -> IOMF.TracingVerbosity +fromDetailLevel = \case + TD.DMinimal -> IOMF.MinimalVerbosity + TD.DNormal -> IOMF.NormalVerbosity + TD.DDetailed -> IOMF.NormalVerbosity + TD.DMaximum -> IOMF.MaximalVerbosity diff --git a/cardano-node/src/Cardano/Node/Tracing/Documentation.hs b/cardano-node/src/Cardano/Node/Tracing/Documentation.hs new file mode 100644 index 00000000000..679950dd474 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Documentation.hs @@ -0,0 +1,813 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module Cardano.Node.Tracing.Documentation + ( docTracers + ) where + +import Data.Aeson.Types (ToJSON) +import qualified Data.Text.IO as T +import Network.Mux (MuxTrace (..), WithMuxBearer (..)) +import qualified Network.Socket as Socket + +import Cardano.Logging +import Cardano.Logging.Resources +import Cardano.Logging.Resources.Types +import Cardano.Prelude hiding (trace) + +import Cardano.Node.Tracing.Formatting () +import Cardano.Node.Tracing.Tracers.BlockReplayProgress +import Cardano.Node.Tracing.Tracers.ChainDB +import Cardano.Node.Tracing.Tracers.Consensus +import Cardano.Node.Tracing.Tracers.Diffusion +import Cardano.Node.Tracing.Tracers.ForgingThreadStats (forgeThreadStats) +import Cardano.Node.Tracing.Tracers.KESInfo +import Cardano.Node.Tracing.Tracers.NodeToClient +import Cardano.Node.Tracing.Tracers.NodeToNode +import Cardano.Node.Tracing.Tracers.NonP2P +import Cardano.Node.Tracing.Tracers.P2P +import Cardano.Node.Tracing.Tracers.Peer +import Cardano.Node.Tracing.Tracers.Shutdown +import Cardano.Node.Tracing.Tracers.Startup + +import Cardano.Node.Handlers.Shutdown (ShutdownTrace) +import Cardano.Node.Startup +import Cardano.Node.TraceConstraints + +import Ouroboros.Consensus.BlockchainTime.WallClock.Util (TraceBlockchainTimeEvent (..)) +import Ouroboros.Consensus.Ledger.Query (Query) +import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr, GenTx, GenTxId, TxId) +import Ouroboros.Consensus.Ledger.SupportsProtocol (LedgerSupportsProtocol) +import Ouroboros.Consensus.Mempool.API (TraceEventMempool (..)) +import Ouroboros.Consensus.MiniProtocol.BlockFetch.Server + (TraceBlockFetchServerEvent (..)) +import Ouroboros.Consensus.MiniProtocol.ChainSync.Client (TraceChainSyncClientEvent) +import Ouroboros.Consensus.MiniProtocol.ChainSync.Server (TraceChainSyncServerEvent) +import Ouroboros.Consensus.MiniProtocol.LocalTxSubmission.Server + (TraceLocalTxSubmissionServerEvent (..)) +import qualified Ouroboros.Consensus.Node.Run as Consensus +import qualified Ouroboros.Consensus.Node.Tracers as Consensus +import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey +import Ouroboros.Consensus.Shelley.Ledger.Block +import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB + +import Ouroboros.Network.Block (Point (..), Tip) +import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch +import Ouroboros.Network.BlockFetch.Decision +import Ouroboros.Network.ConnectionHandler (ConnectionHandlerTrace (..)) +import Ouroboros.Network.ConnectionId (ConnectionId) +import Ouroboros.Network.ConnectionManager.Types (ConnectionManagerTrace (..)) +import qualified Ouroboros.Network.Diffusion as Diffusion +import Ouroboros.Network.Driver.Simple (TraceSendRecv) +import Ouroboros.Network.InboundGovernor (InboundGovernorTrace) +import Ouroboros.Network.KeepAlive (TraceKeepAliveClient (..)) +import qualified Ouroboros.Network.NodeToClient as NtC +import Ouroboros.Network.NodeToNode (ErrorPolicyTrace (..), RemoteAddress, WithAddr (..)) +import qualified Ouroboros.Network.NodeToNode as NtN +import Ouroboros.Network.PeerSelection.Governor (DebugPeerSelection (..), + PeerSelectionCounters (..), TracePeerSelection (..)) +import Ouroboros.Network.PeerSelection.LedgerPeers (TraceLedgerPeers) +import Ouroboros.Network.PeerSelection.PeerStateActions (PeerSelectionActionsTrace (..)) +import Ouroboros.Network.PeerSelection.RootPeersDNS (TraceLocalRootPeers (..), + TracePublicRootPeers (..)) +import Ouroboros.Network.Protocol.BlockFetch.Type (BlockFetch) +import Ouroboros.Network.Protocol.ChainSync.Type (ChainSync) +import Ouroboros.Network.Protocol.LocalStateQuery.Type (LocalStateQuery) +import qualified Ouroboros.Network.Protocol.LocalTxSubmission.Type as LTS +import Ouroboros.Network.Protocol.TxSubmission.Type (TxSubmission) +import Ouroboros.Network.Protocol.TxSubmission2.Type (TxSubmission2) +import Ouroboros.Network.Server2 (ServerTrace (..)) +import Ouroboros.Network.Snocket (LocalAddress (..)) +import Ouroboros.Network.Subscription.Dns (DnsTrace (..), WithDomainName (..)) +import Ouroboros.Network.Subscription.Ip (WithIPList (..)) +import Ouroboros.Network.Subscription.Worker (SubscriptionTrace (..)) +import Ouroboros.Network.TxSubmission.Inbound (TraceTxSubmissionInbound) +import Ouroboros.Network.TxSubmission.Outbound (TraceTxSubmissionOutbound) + + + +-- Have to repeat the construction of the tracers here, +-- as the tracers are behind old tracer interface after construction in mkDispatchTracers. +-- Can be changed, when old tracers have gone +docTracers :: forall blk t peer peerConn remotePeer resolverError ntnVersion ntnVersionData. + ( Show t + , forall result. Show (Query blk result) + , TraceConstraints blk + , LogFormatting (ChainDB.InvalidBlockReason blk) + , LedgerSupportsProtocol blk + , Consensus.RunNode blk + , LogFormatting peer + , LogFormatting remotePeer + , Show remotePeer + , Show peer + , Show resolverError + , Show peerConn + , Show ntnVersion + , ToJSON ntnVersion + , Show ntnVersionData + , ToJSON ntnVersionData + ) + => FilePath + -> FilePath + -> Proxy blk + -> IO () +docTracers configFileName outputFileName _ = do + trConfig <- readConfiguration configFileName + let trBase :: Trace IO FormattedMessage = docTracer (Stdout MachineFormat) + trForward :: Trace IO FormattedMessage = docTracer Forwarder + trDataPoint = docTracerDatapoint DatapointBackend + mbTrEKG :: Maybe (Trace IO FormattedMessage) = Just (docTracer EKGBackend) + -- NodeInfo tracer + nodeInfoTr <- mkDataPointTracer + trDataPoint + (const ["NodeInfo"]) + configureTracers trConfig docNodeInfoTraceEvent [nodeInfoTr] + nodeInfoTrDoc <- documentTracer trConfig nodeInfoTr + (docNodeInfoTraceEvent :: Documented NodeInfo) + + -- Resource tracer + resourcesTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Resources" + (const []) + (const Info) + allPublic + configureTracers trConfig docResourceStats [resourcesTr] + resourcesTrDoc <- documentTracer trConfig resourcesTr + (docResourceStats :: Documented ResourceStats) + + -- Startup tracer + startupTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Startup" + namesStartupInfo + (const Notice) + allPublic + configureTracers trConfig docStartupInfo [startupTr] + startupTrDoc <- documentTracer trConfig startupTr + (docStartupInfo :: Documented (StartupTrace blk)) + + shutdownTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Shutdown" + namesForShutdown + severityShutdown + allPublic + configureTracers trConfig docShutdown [shutdownTr] + shutdownTrDoc <- documentTracer trConfig shutdownTr + (docShutdown :: Documented ShutdownTrace) + + -- Peers tracer + peersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Peers" + namesForPeers + severityPeers + allPublic + configureTracers trConfig docPeers [peersTr] + peersTrDoc <- documentTracer trConfig peersTr + (docPeers :: Documented [PeerT blk]) + + + chainDBTr <- mkCardanoTracer' + trBase trForward mbTrEKG + "ChainDB" + namesForChainDBTraceEvents + severityChainDB + allPublic + withAddedToCurrentChainEmptyLimited + configureTracers trConfig docChainDBTraceEvent [chainDBTr] + chainDBTrDoc <- documentTracer trConfig chainDBTr + (docChainDBTraceEvent :: Documented (ChainDB.TraceEvent blk)) + + replayBlockTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ReplayBlock" + namesForReplayBlockStats + severityReplayBlockStats + allPublic + configureTracers trConfig docReplayedBlock [replayBlockTr] + replayBlockTrDoc <- documentTracer trConfig replayBlockTr + (docReplayedBlock :: Documented ReplayBlockStats) + +---- Consensus tracers + + chainSyncClientTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncClient" + namesForChainSyncClientEvent + severityChainSyncClientEvent + allPublic + configureTracers trConfig docChainSyncClientEvent [chainSyncClientTr] + chainSyncClientTrDoc <- documentTracer trConfig chainSyncClientTr + (docChainSyncClientEvent :: Documented (BlockFetch.TraceLabelPeer + (ConnectionId RemoteAddress) + (TraceChainSyncClientEvent blk))) + + chainSyncServerHeaderTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncServerHeader" + namesForChainSyncServerEvent + severityChainSyncServerEvent + allPublic + configureTracers trConfig docChainSyncServerEvent [chainSyncServerHeaderTr] + chainSyncServerHeaderTrDoc <- documentTracer trConfig chainSyncServerHeaderTr + (docChainSyncServerEvent :: Documented (TraceChainSyncServerEvent blk)) + + chainSyncServerBlockTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncServerBlock" + namesForChainSyncServerEvent + severityChainSyncServerEvent + allPublic + configureTracers trConfig docChainSyncServerEvent [chainSyncServerBlockTr] + chainSyncServerBlockTrDoc <- documentTracer trConfig chainSyncServerBlockTr + (docChainSyncServerEvent :: Documented (TraceChainSyncServerEvent blk)) + + blockFetchDecisionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetchDecision" + namesForBlockFetchDecision + severityBlockFetchDecision + allConfidential + configureTracers trConfig docBlockFetchDecision [blockFetchDecisionTr] + blockFetchDecisionTrDoc <- documentTracer trConfig blockFetchDecisionTr + (docBlockFetchDecision :: Documented [BlockFetch.TraceLabelPeer + remotePeer + (FetchDecision [Point (Header blk)])]) + + blockFetchClientTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetchClient" + namesForBlockFetchClient + severityBlockFetchClient + allPublic + configureTracers trConfig docBlockFetchClient [blockFetchClientTr] + blockFetchClientTrDoc <- documentTracer trConfig blockFetchClientTr + (docBlockFetchClient :: Documented (BlockFetch.TraceLabelPeer + remotePeer + (BlockFetch.TraceFetchClientState (Header blk)))) + + blockFetchServerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetchServer" + namesForBlockFetchServer + severityBlockFetchServer + allPublic + configureTracers trConfig docBlockFetchServer [blockFetchServerTr] + blockFetchServerTrDoc <- documentTracer trConfig blockFetchServerTr + (docBlockFetchServer :: Documented (TraceBlockFetchServerEvent blk)) + + forgeKESInfoTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ForgeStateInfo" + namesForKESInfo + severityKESInfo + allPublic + configureTracers trConfig docForgeKESInfo [forgeKESInfoTr] + forgeKESInfoTrDoc <- documentTracer trConfig forgeKESInfoTr + (docForgeKESInfo :: Documented (Consensus.TraceLabelCreds HotKey.KESInfo)) + + txInboundTr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxInbound" + namesForTxInbound + severityTxInbound + allPublic + configureTracers trConfig docTxInbound [txInboundTr] + txInboundTrDoc <- documentTracer trConfig txInboundTr + (docTxInbound :: Documented (BlockFetch.TraceLabelPeer + remotePeer + (TraceTxSubmissionInbound txid tx))) + + txOutboundTr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxOutbound" + namesForTxOutbound + severityTxOutbound + allPublic + configureTracers trConfig docTxOutbound [txOutboundTr] + txOutboundTrDoc <- documentTracer trConfig txOutboundTr + (docTxOutbound :: Documented (BlockFetch.TraceLabelPeer + remotePeer + (TraceTxSubmissionOutbound (TxId (GenTx blk)) tx))) + + localTxSubmissionServerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalTxSubmissionServer" + namesForLocalTxSubmissionServer + severityLocalTxSubmissionServer + allPublic + configureTracers trConfig docLocalTxSubmissionServer [localTxSubmissionServerTr] + localTxSubmissionServerTrDoc <- documentTracer trConfig localTxSubmissionServerTr + (docLocalTxSubmissionServer :: Documented (TraceLocalTxSubmissionServerEvent blk)) + + + mempoolTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Mempool" + namesForMempool + severityMempool + allPublic + configureTracers trConfig docMempool [mempoolTr] + mempoolTrDoc <- documentTracer trConfig mempoolTr + (docMempool :: Documented (TraceEventMempool blk)) + + forgeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Forge" + namesForForge + severityForge + allPublic + + -- TODO Tracers docforgeThreadStatsTr? + forgeThreadStatsTr <- mkCardanoTracer' + trBase trForward mbTrEKG + "ForgeStats" + namesForForge + severityForge + allPublic + forgeThreadStats + configureTracers trConfig docForge [forgeTr, forgeThreadStatsTr] + forgeTrDoc <- documentTracer trConfig forgeTr + (docForge :: Documented + (Either (Consensus.TraceLabelCreds (Consensus.TraceForgeEvent blk)) + (Consensus.TraceLabelCreds TraceStartLeadershipCheckPlus))) + + blockchainTimeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockchainTime" + namesForBlockchainTime + severityBlockchainTime + allPublic + configureTracers trConfig docBlockchainTime [blockchainTimeTr] + blockchainTimeTrDoc <- documentTracer trConfig blockchainTimeTr + (docBlockchainTime :: Documented (TraceBlockchainTimeEvent t)) + +-- Node to client + + keepAliveClientTr <- mkCardanoTracer + trBase trForward mbTrEKG + "KeepAliveClient" + namesForKeepAliveClient + severityKeepAliveClient + allPublic + configureTracers trConfig docKeepAliveClient [keepAliveClientTr] + keepAliveClientTrDoc <- documentTracer trConfig keepAliveClientTr + (docKeepAliveClient :: Documented (TraceKeepAliveClient peer)) + + chainSyncTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncClient" + namesForTChainSync + severityTChainSync + allPublic + configureTracers trConfig docTChainSync [chainSyncTr] + chainSyncTrDoc <- documentTracer trConfig chainSyncTr + (docTChainSync :: Documented + (BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync x (Point blk) (Tip blk))))) + + txSubmissionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxSubmissionClient" + namesForTTxSubmission + severityTTxSubmission + allPublic + configureTracers trConfig docTTxSubmission [txSubmissionTr] + txSubmissionTrDoc <- documentTracer trConfig txSubmissionTr + (docTTxSubmission :: Documented + (BlockFetch.TraceLabelPeer + peer + (TraceSendRecv + (LTS.LocalTxSubmission + (GenTx blk) (ApplyTxErr blk))))) + + + stateQueryTr <- mkCardanoTracer + trBase trForward mbTrEKG + "StateQueryClient" + namesForTStateQuery + severityTStateQuery + allPublic + configureTracers trConfig docTStateQuery [stateQueryTr] + stateQueryTrDoc <- documentTracer trConfig stateQueryTr + (docTStateQuery :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (LocalStateQuery blk (Point blk) (Query blk))))) + +-- Node to Node + + chainSyncNodeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncNode" + namesForTChainSyncNode + severityTChainSyncNode + allPublic + configureTracers trConfig docTChainSync [chainSyncNodeTr] + chainSyncNodeTrDoc <- documentTracer trConfig chainSyncNodeTr + (docTChainSync :: Documented (BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync x (Point blk) (Tip blk))))) + + chainSyncSerialisedTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncSerialised" + namesForTChainSyncSerialised + severityTChainSyncSerialised + allPublic + configureTracers trConfig docTChainSync [chainSyncSerialisedTr] + chainSyncSerialisedTrDoc <- documentTracer trConfig chainSyncSerialisedTr + (docTChainSync :: Documented (BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync x (Point blk) (Tip blk))))) + + blockFetchTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetch" + namesForTBlockFetch + severityTBlockFetch + allPublic + configureTracers trConfig docTBlockFetch [blockFetchTr] + blockFetchTrDoc <- documentTracer trConfig blockFetchTr + (docTBlockFetch :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (BlockFetch x (Point blk))))) + + blockFetchSerialisedTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetchSerialised" + namesForTBlockFetchSerialised + severityTBlockFetchSerialised + allPublic + configureTracers trConfig docTBlockFetch [blockFetchSerialisedTr] + blockFetchSerialisedTrDoc <- documentTracer trConfig blockFetchSerialisedTr + (docTBlockFetch :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (BlockFetch x (Point blk))))) + + txSubmissionNodeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxSubmission" + namesForTxSubmissionNode + severityTxSubmissionNode + allPublic + configureTracers trConfig docTTxSubmissionNode [txSubmissionNodeTr] + txSubmissionNodeTrDoc <- documentTracer trConfig txSubmissionNodeTr + (docTTxSubmissionNode :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (TxSubmission (GenTxId blk) (GenTx blk))))) + + txSubmission2Tr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxSubmission2" + namesForTxSubmission2Node + severityTxSubmission2Node + allPublic + configureTracers trConfig docTTxSubmission2Node [txSubmission2Tr] + txSubmission2TrDoc <- documentTracer trConfig txSubmission2Tr + (docTTxSubmission2Node :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (TxSubmission2 (GenTxId blk) (GenTx blk))))) + +-- -- Diffusion + dtMuxTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Mux" + namesForMux + severityMux + allPublic + configureTracers trConfig docMuxRemote [dtMuxTr] + dtMuxTrDoc <- documentTracer trConfig dtMuxTr + (docMuxRemote :: Documented (WithMuxBearer (ConnectionId RemoteAddress) MuxTrace)) + + dtLocalMuxTr <- mkCardanoTracer + trBase trForward mbTrEKG + "MuxLocal" + namesForMux + severityMux + allPublic + configureTracers trConfig docMuxLocal [dtLocalMuxTr] + dtLocalMuxTrDoc <- documentTracer trConfig dtLocalMuxTr + (docMuxLocal :: Documented (WithMuxBearer (ConnectionId LocalAddress) MuxTrace)) + + dtHandshakeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Handshake" + namesForHandshake + severityHandshake + allPublic + configureTracers trConfig docHandshake [dtHandshakeTr] + dtHandshakeTrDoc <- documentTracer trConfig dtHandshakeTr + (docHandshake :: + Documented (NtN.HandshakeTr NtN.RemoteAddress NtN.NodeToNodeVersion)) + + dtLocalHandshakeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalHandshake" + namesForLocalHandshake + severityLocalHandshake + allPublic + configureTracers trConfig docLocalHandshake [dtLocalHandshakeTr] + dtLocalHandshakeTrDoc <- documentTracer trConfig dtLocalHandshakeTr + (docLocalHandshake :: + Documented (NtC.HandshakeTr LocalAddress NtC.NodeToClientVersion)) + + dtDiffusionInitializationTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DiffusionInit" + namesForDiffusionInit + severityDiffusionInit + allPublic + configureTracers trConfig docDiffusionInit [dtDiffusionInitializationTr] + dtDiffusionInitializationTrDoc <- documentTracer trConfig dtDiffusionInitializationTr + (docDiffusionInit :: + Documented (Diffusion.InitializationTracer Socket.SockAddr LocalAddress)) + + dtLedgerPeersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LedgerPeers" + namesForLedgerPeers + severityLedgerPeers + allPublic + configureTracers trConfig docLedgerPeers [dtLedgerPeersTr] + dtLedgerPeersTrDoc <- documentTracer trConfig dtLedgerPeersTr + (docLedgerPeers :: Documented TraceLedgerPeers) + +-- DiffusionTracersExtra P2P + localRootPeersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalRootPeers" + namesForLocalRootPeers + severityLocalRootPeers + allPublic + configureTracers trConfig docLocalRootPeers [localRootPeersTr] + localRootPeersTrDoc <- documentTracer trConfig localRootPeersTr + (docLocalRootPeers :: Documented (TraceLocalRootPeers RemoteAddress resolverError)) + + publicRootPeersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "PublicRootPeers" + namesForPublicRootPeers + severityPublicRootPeers + allPublic + configureTracers trConfig docPublicRootPeers [publicRootPeersTr] + publicRootPeersTrDoc <- documentTracer trConfig publicRootPeersTr + (docPublicRootPeers :: Documented TracePublicRootPeers) + + peerSelectionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "PeerSelection" + namesForPeerSelection + severityPeerSelection + allPublic + configureTracers trConfig docPeerSelection [peerSelectionTr] + peerSelectionTrDoc <- documentTracer trConfig peerSelectionTr + (docPeerSelection :: Documented (TracePeerSelection Socket.SockAddr)) + + debugPeerSelectionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DebugPeerSelection" + namesForDebugPeerSelection + severityDebugPeerSelection + allPublic + configureTracers trConfig docDebugPeerSelection [debugPeerSelectionTr] + debugPeerSelectionTrDoc <- documentTracer trConfig debugPeerSelectionTr + (docDebugPeerSelection :: Documented (DebugPeerSelection Socket.SockAddr peerConn)) + + debugPeerSelectionResponderTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DebugPeerSelectionResponder" + namesForDebugPeerSelection + severityDebugPeerSelection + allPublic + configureTracers trConfig docDebugPeerSelection [debugPeerSelectionResponderTr] + debugPeerSelectionResponderTrDoc <- documentTracer trConfig debugPeerSelectionResponderTr + (docDebugPeerSelection :: Documented (DebugPeerSelection Socket.SockAddr peerConn)) + + peerSelectionCountersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "PeerSelectionCounters" + namesForPeerSelectionCounters + severityPeerSelectionCounters + allPublic + configureTracers trConfig docPeerSelectionCounters [peerSelectionCountersTr] + peerSelectionCountersTrDoc <- documentTracer trConfig peerSelectionCountersTr + (docPeerSelectionCounters :: Documented PeerSelectionCounters) + + peerSelectionActionsTr <- mkCardanoTracer + trBase trForward mbTrEKG + "PeerSelectionActions" + namesForPeerSelectionActions + severityPeerSelectionActions + allPublic + configureTracers trConfig docPeerSelectionActions [peerSelectionActionsTr] + peerSelectionActionsTrDoc <- documentTracer trConfig peerSelectionActionsTr + (docPeerSelectionActions :: + Documented (PeerSelectionActionsTrace Socket.SockAddr)) + + connectionManagerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ConnectionManager" + namesForConnectionManager + severityConnectionManager + allPublic + configureTracers trConfig docConnectionManager [connectionManagerTr] + connectionManagerTrDoc <- documentTracer trConfig connectionManagerTr + (docConnectionManager :: Documented + (ConnectionManagerTrace + Socket.SockAddr + (ConnectionHandlerTrace ntnVersion ntnVersionData))) + + serverTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Server" + namesForServer + severityServer + allPublic + configureTracers trConfig docServer [serverTr] + serverTrDoc <- documentTracer trConfig serverTr + (docServer :: Documented (ServerTrace Socket.SockAddr)) + + inboundGovernorTr <- mkCardanoTracer + trBase trForward mbTrEKG + "InboundGovernor" + namesForInboundGovernor + severityInboundGovernor + allPublic + configureTracers trConfig docInboundGovernorRemote [inboundGovernorTr] + inboundGovernorTrDoc <- documentTracer trConfig inboundGovernorTr + (docInboundGovernorRemote :: Documented (InboundGovernorTrace Socket.SockAddr)) + + localConnectionManagerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalConnectionManager" + namesForConnectionManager + severityConnectionManager + allPublic + configureTracers trConfig docConnectionManager [localConnectionManagerTr] + localConnectionManagerTrDoc <- documentTracer trConfig localConnectionManagerTr + (docConnectionManager :: Documented + (ConnectionManagerTrace + Socket.SockAddr + (ConnectionHandlerTrace + ntnVersion + ntnVersionData))) + + localServerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalServer" + namesForServer + severityServer + allPublic + configureTracers trConfig docServer [localServerTr] + localServerTrDoc <- documentTracer trConfig localServerTr + (docServer :: Documented (ServerTrace LocalAddress)) + + + localInboundGovernorTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalInboundGovernor" + namesForInboundGovernor + severityInboundGovernor + allPublic + configureTracers trConfig docInboundGovernorLocal [localInboundGovernorTr] + localInboundGovernorTrDoc <- documentTracer trConfig localInboundGovernorTr + (docInboundGovernorLocal :: Documented (InboundGovernorTrace LocalAddress)) + +-- DiffusionTracersExtra nonP2P + + dtIpSubscriptionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "IpSubscription" + namesForIPSubscription + severityIPSubscription + allPublic + configureTracers trConfig docIPSubscription [dtIpSubscriptionTr] + dtIpSubscriptionTrDoc <- documentTracer trConfig dtIpSubscriptionTr + (docIPSubscription :: + Documented (WithIPList (SubscriptionTrace Socket.SockAddr))) + + dtDnsSubscriptionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DNSSubscription" + namesForDNSSubscription + severityDNSSubscription + allPublic + configureTracers trConfig docDNSSubscription [dtDnsSubscriptionTr] + dtDnsSubscriptionTrDoc <- documentTracer trConfig dtDnsSubscriptionTr + (docDNSSubscription :: + Documented (WithDomainName (SubscriptionTrace Socket.SockAddr))) + + dtDnsResolverTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DNSResolver" + namesForDNSResolver + severityDNSResolver + allPublic + configureTracers trConfig docDNSResolver [dtDnsResolverTr] + dtDnsResolverTrDoc <- documentTracer trConfig dtDnsResolverTr + (docDNSResolver :: Documented (WithDomainName DnsTrace)) + + dtErrorPolicyTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ErrorPolicy" + namesForErrorPolicy + severityErrorPolicy + allPublic + configureTracers trConfig docErrorPolicy [dtErrorPolicyTr] + dtErrorPolicyTrDoc <- documentTracer trConfig dtErrorPolicyTr + (docErrorPolicy :: Documented (WithAddr Socket.SockAddr ErrorPolicyTrace)) + + dtLocalErrorPolicyTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalErrorPolicy" + namesForLocalErrorPolicy + severityLocalErrorPolicy + allPublic + configureTracers trConfig docLocalErrorPolicy [dtLocalErrorPolicyTr] + dtLocalErrorPolicyTrDoc <- documentTracer trConfig dtLocalErrorPolicyTr + (docLocalErrorPolicy :: Documented (WithAddr LocalAddress ErrorPolicyTrace)) + + dtAcceptPolicyTr <- mkCardanoTracer + trBase trForward mbTrEKG + "AcceptPolicy" + namesForAcceptPolicy + severityAcceptPolicy + allPublic + configureTracers trConfig docAcceptPolicy [dtAcceptPolicyTr] + dtAcceptPolicyTrDoc <- documentTracer trConfig dtAcceptPolicyTr + (docAcceptPolicy :: Documented NtN.AcceptConnectionsPolicyTrace) + + let bl = nodeInfoTrDoc + <> resourcesTrDoc + <> startupTrDoc + <> shutdownTrDoc + <> peersTrDoc + <> chainDBTrDoc + <> replayBlockTrDoc +-- Consensus + <> chainSyncClientTrDoc + <> chainSyncServerHeaderTrDoc + <> chainSyncServerBlockTrDoc + <> blockFetchDecisionTrDoc + <> blockFetchClientTrDoc + <> blockFetchServerTrDoc + <> forgeKESInfoTrDoc + <> txInboundTrDoc + <> txOutboundTrDoc + <> localTxSubmissionServerTrDoc + <> mempoolTrDoc + <> forgeTrDoc + <> blockchainTimeTrDoc +-- NodeToClient + <> keepAliveClientTrDoc + <> chainSyncTrDoc + <> txSubmissionTrDoc + <> stateQueryTrDoc +-- Node to Node + <> chainSyncNodeTrDoc + <> chainSyncSerialisedTrDoc + <> blockFetchTrDoc + <> blockFetchSerialisedTrDoc + <> txSubmissionNodeTrDoc + <> txSubmission2TrDoc +-- Diffusion + <> dtMuxTrDoc + <> dtLocalMuxTrDoc + <> dtHandshakeTrDoc + <> dtLocalHandshakeTrDoc + <> dtDiffusionInitializationTrDoc + <> dtLedgerPeersTrDoc +-- DiffusionTracersExtra P2P + <> localRootPeersTrDoc + <> publicRootPeersTrDoc + <> peerSelectionTrDoc + <> debugPeerSelectionTrDoc + <> debugPeerSelectionResponderTrDoc + <> peerSelectionCountersTrDoc + <> peerSelectionActionsTrDoc + <> connectionManagerTrDoc + <> serverTrDoc + <> inboundGovernorTrDoc + <> localConnectionManagerTrDoc + <> localServerTrDoc + <> localInboundGovernorTrDoc +-- DiffusionTracersExtra nonP2P + <> dtIpSubscriptionTrDoc + <> dtDnsSubscriptionTrDoc + <> dtDnsResolverTrDoc + <> dtErrorPolicyTrDoc + <> dtLocalErrorPolicyTrDoc + <> dtAcceptPolicyTrDoc + + res <- buildersToText bl trConfig + T.writeFile outputFileName res + pure () diff --git a/cardano-node/src/Cardano/Node/Tracing/Era/Byron.hs b/cardano-node/src/Cardano/Node/Tracing/Era/Byron.hs new file mode 100644 index 00000000000..66b7c69e5ee --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Era/Byron.hs @@ -0,0 +1,214 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-orphans #-} +{-# OPTIONS_GHC -Wno-unused-imports #-} + +module Cardano.Node.Tracing.Era.Byron () where + +-- TODO: Temporary hack for toJSON instances +-- Will be moved when old tracing will be removed +import Cardano.Tracing.OrphanInstances.Byron () + +import Cardano.Logging +import Cardano.Prelude +import Data.Aeson (Value (String), (.=)) + +import qualified Data.Set as Set +import qualified Data.Text as Text + +import Ouroboros.Consensus.Block (Header) +import Ouroboros.Network.Block (blockHash, blockNo, blockSlot) + +import Ouroboros.Consensus.Byron.Ledger (ByronBlock (..), + ByronOtherHeaderEnvelopeError (..), TxId (..), byronHeaderRaw) +import Ouroboros.Consensus.Byron.Ledger.Inspect (ByronLedgerUpdate (..), + ProtocolUpdate (..), UpdateState (..)) +import Ouroboros.Consensus.Ledger.SupportsMempool (GenTx, txId) +import Ouroboros.Consensus.Util.Condense (condense) + +import Cardano.Chain.Block (ABlockOrBoundaryHdr (..), AHeader (..), + ChainValidationError (..), delegationCertificate) +import Cardano.Chain.Byron.API (ApplyMempoolPayloadErr (..)) +import Cardano.Chain.Delegation (delegateVK) +import Cardano.Crypto.Signing (VerificationKey) + +{- HLINT ignore "Use :" -} + +-- +-- | instances of @LogFormatting@ +-- +-- NOTE: this list is sorted by the unqualified name of the outermost type. + +instance LogFormatting ApplyMempoolPayloadErr where + forMachine _dtal (MempoolTxErr utxoValidationErr) = + mkObject + [ "kind" .= String "MempoolTxErr" + , "error" .= String (show utxoValidationErr) + ] + forMachine _dtal (MempoolDlgErr delegScheduleError) = + mkObject + [ "kind" .= String "MempoolDlgErr" + , "error" .= String (show delegScheduleError) + ] + forMachine _dtal (MempoolUpdateProposalErr iFaceErr) = + mkObject + [ "kind" .= String "MempoolUpdateProposalErr" + , "error" .= String (show iFaceErr) + ] + forMachine _dtal (MempoolUpdateVoteErr iFaceErrr) = + mkObject + [ "kind" .= String "MempoolUpdateVoteErr" + , "error" .= String (show iFaceErrr) + ] + +instance LogFormatting ByronLedgerUpdate where + forMachine dtal (ByronUpdatedProtocolUpdates protocolUpdates) = + mkObject + [ "kind" .= String "ByronUpdatedProtocolUpdates" + , "protocolUpdates" .= map (forMachine dtal) protocolUpdates + ] + +instance LogFormatting ProtocolUpdate where + forMachine dtal (ProtocolUpdate updateVersion updateState) = + mkObject + [ "kind" .= String "ProtocolUpdate" + , "protocolUpdateVersion" .= updateVersion + , "protocolUpdateState" .= forMachine dtal updateState + ] + +instance LogFormatting UpdateState where + forMachine _dtal updateState = case updateState of + UpdateRegistered slot -> + mkObject + [ "kind" .= String "UpdateRegistered" + , "slot" .= slot + ] + UpdateActive votes -> + mkObject + [ "kind" .= String "UpdateActive" + , "votes" .= map (Text.pack . show) (Set.toList votes) + ] + UpdateConfirmed slot -> + mkObject + [ "kind" .= String "UpdateConfirmed" + , "slot" .= slot + ] + UpdateStablyConfirmed endorsements -> + mkObject + [ "kind" .= String "UpdateStablyConfirmed" + , "endorsements" .= map (Text.pack . show) (Set.toList endorsements) + ] + UpdateCandidate slot epoch -> + mkObject + [ "kind" .= String "UpdateCandidate" + , "slot" .= slot + , "epoch" .= epoch + ] + UpdateStableCandidate transitionEpoch -> + mkObject + [ "kind" .= String "UpdateStableCandidate" + , "transitionEpoch" .= transitionEpoch + ] + +instance LogFormatting (GenTx ByronBlock) where + forMachine dtal tx = + mkObject $ + ( "txid" .= txId tx ) + : [ "tx" .= condense tx | dtal == DDetailed ] + +instance LogFormatting ChainValidationError where + forMachine _dtal ChainValidationBoundaryTooLarge = + mkObject + [ "kind" .= String "ChainValidationBoundaryTooLarge" ] + forMachine _dtal ChainValidationBlockAttributesTooLarge = + mkObject + [ "kind" .= String "ChainValidationBlockAttributesTooLarge" ] + forMachine _dtal (ChainValidationBlockTooLarge _ _) = + mkObject + [ "kind" .= String "ChainValidationBlockTooLarge" ] + forMachine _dtal ChainValidationHeaderAttributesTooLarge = + mkObject + [ "kind" .= String "ChainValidationHeaderAttributesTooLarge" ] + forMachine _dtal (ChainValidationHeaderTooLarge _ _) = + mkObject + [ "kind" .= String "ChainValidationHeaderTooLarge" ] + forMachine _dtal (ChainValidationDelegationPayloadError err) = + mkObject + [ "kind" .= String err ] + forMachine _dtal (ChainValidationInvalidDelegation _ _) = + mkObject + [ "kind" .= String "ChainValidationInvalidDelegation" ] + forMachine _dtal (ChainValidationGenesisHashMismatch _ _) = + mkObject + [ "kind" .= String "ChainValidationGenesisHashMismatch" ] + forMachine _dtal (ChainValidationExpectedGenesisHash _ _) = + mkObject + [ "kind" .= String "ChainValidationExpectedGenesisHash" ] + forMachine _dtal (ChainValidationExpectedHeaderHash _ _) = + mkObject + [ "kind" .= String "ChainValidationExpectedHeaderHash" ] + forMachine _dtal (ChainValidationInvalidHash _ _) = + mkObject + [ "kind" .= String "ChainValidationInvalidHash" ] + forMachine _dtal (ChainValidationMissingHash _) = + mkObject + [ "kind" .= String "ChainValidationMissingHash" ] + forMachine _dtal (ChainValidationUnexpectedGenesisHash _) = + mkObject + [ "kind" .= String "ChainValidationUnexpectedGenesisHash" ] + forMachine _dtal (ChainValidationInvalidSignature _) = + mkObject + [ "kind" .= String "ChainValidationInvalidSignature" ] + forMachine _dtal (ChainValidationDelegationSchedulingError _) = + mkObject + [ "kind" .= String "ChainValidationDelegationSchedulingError" ] + forMachine _dtal (ChainValidationProtocolMagicMismatch _ _) = + mkObject + [ "kind" .= String "ChainValidationProtocolMagicMismatch" ] + forMachine _dtal ChainValidationSignatureLight = + mkObject + [ "kind" .= String "ChainValidationSignatureLight" ] + forMachine _dtal (ChainValidationTooManyDelegations _) = + mkObject + [ "kind" .= String "ChainValidationTooManyDelegations" ] + forMachine _dtal (ChainValidationUpdateError _ _) = + mkObject + [ "kind" .= String "ChainValidationUpdateError" ] + forMachine _dtal (ChainValidationUTxOValidationError _) = + mkObject + [ "kind" .= String "ChainValidationUTxOValidationError" ] + forMachine _dtal (ChainValidationProofValidationError _) = + mkObject + [ "kind" .= String "ChainValidationProofValidationError" ] + + +instance LogFormatting (Header ByronBlock) where + forMachine _dtal b = + mkObject $ + [ "kind" .= String "ByronBlock" + , "hash" .= condense (blockHash b) + , "slotNo" .= condense (blockSlot b) + , "blockNo" .= condense (blockNo b) + ] <> + case byronHeaderRaw b of + ABOBBoundaryHdr{} -> [] + ABOBBlockHdr h -> + [ "delegate" .= condense (headerSignerVk h) ] + where + headerSignerVk :: AHeader ByteString -> VerificationKey + headerSignerVk = + delegateVK . delegationCertificate . headerSignature + + +instance LogFormatting ByronOtherHeaderEnvelopeError where + forMachine _dtal (UnexpectedEBBInSlot slot) = + mkObject + [ "kind" .= String "UnexpectedEBBInSlot" + , "slot" .= slot + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Era/HardFork.hs b/cardano-node/src/Cardano/Node/Tracing/Era/HardFork.hs new file mode 100644 index 00000000000..d876fac81c7 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Era/HardFork.hs @@ -0,0 +1,348 @@ +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Era.HardFork () + where + +import Cardano.Prelude hiding (All) + +import Cardano.Tracing.OrphanInstances.HardFork () + +import Data.Aeson +import Data.SOP.Strict + +import Cardano.Logging + +import Cardano.Slotting.Slot (EpochSize (..)) +import Ouroboros.Consensus.Block (BlockProtocol, CannotForge, ForgeStateInfo, + ForgeStateUpdateError) +import Ouroboros.Consensus.BlockchainTime (getSlotLength) +import Ouroboros.Consensus.Cardano.Condense () +import Ouroboros.Consensus.HardFork.Combinator +import Ouroboros.Consensus.HardFork.Combinator.AcrossEras (EraMismatch (..), + OneEraCannotForge (..), OneEraEnvelopeErr (..), OneEraForgeStateInfo (..), + OneEraForgeStateUpdateError (..), OneEraLedgerError (..), + OneEraLedgerUpdate (..), OneEraLedgerWarning (..), OneEraValidationErr (..), + mkEraMismatch) +import Ouroboros.Consensus.HardFork.Combinator.Condense () +import Ouroboros.Consensus.HardFork.History + (EraParams (eraEpochSize, eraSafeZone, eraSlotLength)) +import Ouroboros.Consensus.HardFork.History.EraParams (EraParams (EraParams)) +import Ouroboros.Consensus.HeaderValidation (OtherHeaderEnvelopeError) +import Ouroboros.Consensus.Ledger.Abstract (LedgerError) +import Ouroboros.Consensus.Ledger.Inspect (LedgerUpdate, LedgerWarning) +import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr) +import Ouroboros.Consensus.Protocol.Abstract (ValidationErr) +import Ouroboros.Consensus.TypeFamilyWrappers +import Ouroboros.Consensus.Util.Condense (Condense (..)) + + +-- +-- instances for Header HardForkBlock +-- + +instance All (LogFormatting `Compose` Header) xs => LogFormatting (Header (HardForkBlock xs)) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` Header)) (K . forMachine dtal) + . getOneEraHeader + . getHardForkHeader + + +-- +-- instances for GenTx HardForkBlock +-- + +instance All (Compose LogFormatting GenTx) xs => LogFormatting (GenTx (HardForkBlock xs)) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` GenTx)) (K . forMachine dtal) + . getOneEraGenTx + . getHardForkGenTx + + +-- +-- instances for HardForkApplyTxErr +-- + +instance All (LogFormatting `Compose` WrapApplyTxErr) xs => LogFormatting (HardForkApplyTxErr xs) where + forMachine dtal (HardForkApplyTxErrFromEra err) = forMachine dtal err + forMachine _dtal (HardForkApplyTxErrWrongEra mismatch) = + mkObject + [ "kind" .= String "HardForkApplyTxErrWrongEra" + , "currentEra" .= ledgerEraName + , "txEra" .= otherEraName + ] + where + EraMismatch {ledgerEraName, otherEraName} = mkEraMismatch mismatch + +instance All (LogFormatting `Compose` WrapApplyTxErr) xs => LogFormatting (OneEraApplyTxErr xs) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapApplyTxErr)) (K . forMachine dtal) + . getOneEraApplyTxErr + +instance LogFormatting (ApplyTxErr blk) => LogFormatting (WrapApplyTxErr blk) where + forMachine dtal = forMachine dtal . unwrapApplyTxErr + + +-- +-- instances for HardForkLedgerError +-- + +instance All (LogFormatting `Compose` WrapLedgerErr) xs => LogFormatting (HardForkLedgerError xs) where + forMachine dtal (HardForkLedgerErrorFromEra err) = forMachine dtal err + + forMachine _dtal (HardForkLedgerErrorWrongEra mismatch) = + mkObject + [ "kind" .= String "HardForkLedgerErrorWrongEra" + , "currentEra" .= ledgerEraName + , "blockEra" .= otherEraName + ] + where + EraMismatch {ledgerEraName, otherEraName} = mkEraMismatch mismatch + +instance All (LogFormatting `Compose` WrapLedgerErr) xs => LogFormatting (OneEraLedgerError xs) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapLedgerErr)) (K . forMachine dtal) + . getOneEraLedgerError + +instance LogFormatting (LedgerError blk) => LogFormatting (WrapLedgerErr blk) where + forMachine dtal = forMachine dtal . unwrapLedgerErr + + +-- +-- instances for HardForkLedgerWarning +-- + +instance ( All (LogFormatting `Compose` WrapLedgerWarning) xs + , All SingleEraBlock xs + ) => LogFormatting (HardForkLedgerWarning xs) where + forMachine dtal warning = case warning of + HardForkWarningInEra err -> forMachine dtal err + + HardForkWarningTransitionMismatch toEra eraParams epoch -> + mkObject + [ "kind" .= String "HardForkWarningTransitionMismatch" + , "toEra" .= condense toEra + , "eraParams" .= forMachine dtal eraParams + , "transitionEpoch" .= epoch + ] + + HardForkWarningTransitionInFinalEra fromEra epoch -> + mkObject + [ "kind" .= String "HardForkWarningTransitionInFinalEra" + , "fromEra" .= condense fromEra + , "transitionEpoch" .= epoch + ] + + HardForkWarningTransitionUnconfirmed toEra -> + mkObject + [ "kind" .= String "HardForkWarningTransitionUnconfirmed" + , "toEra" .= condense toEra + ] + + HardForkWarningTransitionReconfirmed fromEra toEra prevEpoch newEpoch -> + mkObject + [ "kind" .= String "HardForkWarningTransitionReconfirmed" + , "fromEra" .= condense fromEra + , "toEra" .= condense toEra + , "prevTransitionEpoch" .= prevEpoch + , "newTransitionEpoch" .= newEpoch + ] + +instance All (LogFormatting `Compose` WrapLedgerWarning) xs => LogFormatting (OneEraLedgerWarning xs) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapLedgerWarning)) (K . forMachine dtal) + . getOneEraLedgerWarning + +instance LogFormatting (LedgerWarning blk) => LogFormatting (WrapLedgerWarning blk) where + forMachine dtal = forMachine dtal . unwrapLedgerWarning + +instance LogFormatting EraParams where + forMachine _dtal EraParams{ eraEpochSize, eraSlotLength, eraSafeZone} = + mkObject + [ "epochSize" .= unEpochSize eraEpochSize + , "slotLength" .= getSlotLength eraSlotLength + , "safeZone" .= eraSafeZone + ] + +-- deriving instance ToJSON SafeZone + + +-- +-- instances for HardForkLedgerUpdate +-- + +instance ( All (LogFormatting `Compose` WrapLedgerUpdate) xs + , All SingleEraBlock xs + ) => LogFormatting (HardForkLedgerUpdate xs) where + forMachine dtal update = case update of + HardForkUpdateInEra err -> forMachine dtal err + + HardForkUpdateTransitionConfirmed fromEra toEra epoch -> + mkObject + [ "kind" .= String "HardForkUpdateTransitionConfirmed" + , "fromEra" .= condense fromEra + , "toEra" .= condense toEra + , "transitionEpoch" .= epoch + ] + + HardForkUpdateTransitionDone fromEra toEra epoch -> + mkObject + [ "kind" .= String "HardForkUpdateTransitionDone" + , "fromEra" .= condense fromEra + , "toEra" .= condense toEra + , "transitionEpoch" .= epoch + ] + + HardForkUpdateTransitionRolledBack fromEra toEra -> + mkObject + [ "kind" .= String "HardForkUpdateTransitionRolledBack" + , "fromEra" .= condense fromEra + , "toEra" .= condense toEra + ] + +instance All (LogFormatting `Compose` WrapLedgerUpdate) xs => LogFormatting (OneEraLedgerUpdate xs) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapLedgerUpdate)) (K . forMachine dtal) + . getOneEraLedgerUpdate + +instance LogFormatting (LedgerUpdate blk) => LogFormatting (WrapLedgerUpdate blk) where + forMachine dtal = forMachine dtal . unwrapLedgerUpdate + + +-- +-- instances for HardForkEnvelopeErr +-- + +instance All (LogFormatting `Compose` WrapEnvelopeErr) xs => LogFormatting (HardForkEnvelopeErr xs) where + forMachine dtal (HardForkEnvelopeErrFromEra err) = forMachine dtal err + + forMachine _dtal (HardForkEnvelopeErrWrongEra mismatch) = + mkObject + [ "kind" .= String "HardForkEnvelopeErrWrongEra" + , "currentEra" .= ledgerEraName + , "blockEra" .= otherEraName + ] + where + EraMismatch {ledgerEraName, otherEraName} = mkEraMismatch mismatch + +instance All (LogFormatting `Compose` WrapEnvelopeErr) xs => LogFormatting (OneEraEnvelopeErr xs) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapEnvelopeErr)) (K . forMachine dtal) + . getOneEraEnvelopeErr + +instance LogFormatting (OtherHeaderEnvelopeError blk) => LogFormatting (WrapEnvelopeErr blk) where + forMachine dtal = forMachine dtal . unwrapEnvelopeErr + + +-- +-- instances for HardForkValidationErr +-- + +instance All (LogFormatting `Compose` WrapValidationErr) xs => LogFormatting (HardForkValidationErr xs) where + forMachine dtal (HardForkValidationErrFromEra err) = forMachine dtal err + + forMachine _dtal (HardForkValidationErrWrongEra mismatch) = + mkObject + [ "kind" .= String "HardForkValidationErrWrongEra" + , "currentEra" .= ledgerEraName + , "blockEra" .= otherEraName + ] + where + EraMismatch {ledgerEraName, otherEraName} = mkEraMismatch mismatch + +instance All (LogFormatting `Compose` WrapValidationErr) xs => LogFormatting (OneEraValidationErr xs) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapValidationErr)) (K . forMachine dtal) + . getOneEraValidationErr + +instance LogFormatting (ValidationErr (BlockProtocol blk)) => LogFormatting (WrapValidationErr blk) where + forMachine dtal = forMachine dtal . unwrapValidationErr + + +-- +-- instances for HardForkCannotForge +-- + +-- It's a type alias: +-- type HardForkCannotForge xs = OneEraCannotForge xs + +instance All (LogFormatting `Compose` WrapCannotForge) xs => LogFormatting (OneEraCannotForge xs) where + forMachine dtal = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapCannotForge)) + (K . forMachine dtal) + . getOneEraCannotForge + +instance LogFormatting (CannotForge blk) => LogFormatting (WrapCannotForge blk) where + forMachine dtal = forMachine dtal . unwrapCannotForge + + +-- +-- instances for HardForkForgeStateInfo +-- + +-- It's a type alias: +-- type HardForkForgeStateInfo xs = OneEraForgeStateInfo xs + +instance All (LogFormatting `Compose` WrapForgeStateInfo) xs => LogFormatting (OneEraForgeStateInfo xs) where + forMachine dtal forgeStateInfo = + mkObject + [ "kind" .= String "HardForkForgeStateInfo" + , "forgeStateInfo" .= toJSON forgeStateInfo' + ] + where + forgeStateInfo' :: Object + forgeStateInfo' = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapForgeStateInfo)) + (K . forMachine dtal) + . getOneEraForgeStateInfo + $ forgeStateInfo + +instance LogFormatting (ForgeStateInfo blk) => LogFormatting (WrapForgeStateInfo blk) where + forMachine dtal = forMachine dtal . unwrapForgeStateInfo + + +-- +-- instances for HardForkForgeStateUpdateError +-- + +-- It's a type alias: +-- type HardForkForgeStateUpdateError xs = OneEraForgeStateUpdateError xs + +instance All (LogFormatting `Compose` WrapForgeStateUpdateError) xs => LogFormatting (OneEraForgeStateUpdateError xs) where + forMachine dtal forgeStateUpdateError = + mkObject + [ "kind" .= String "HardForkForgeStateUpdateError" + , "forgeStateUpdateError" .= toJSON forgeStateUpdateError' + ] + where + forgeStateUpdateError' :: Object + forgeStateUpdateError' = + hcollapse + . hcmap (Proxy @ (LogFormatting `Compose` WrapForgeStateUpdateError)) + (K . forMachine dtal) + . getOneEraForgeStateUpdateError + $ forgeStateUpdateError + +instance LogFormatting (ForgeStateUpdateError blk) => LogFormatting (WrapForgeStateUpdateError blk) where + forMachine dtal = forMachine dtal . unwrapForgeStateUpdateError diff --git a/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs b/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs new file mode 100644 index 00000000000..789dfaf487c --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs @@ -0,0 +1,1033 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DisambiguateRecordFields #-} +{-# LANGUAGE EmptyCase #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Era.Shelley () where + +import Data.Aeson (ToJSON (..), Value (..), (.=)) +import qualified Data.Aeson as Aeson +import qualified Data.Aeson.Types as Aeson +import qualified Data.HashMap.Strict as HMS +import qualified Data.Set as Set +import qualified Data.Text as Text + +import qualified Cardano.Api as Api +import Cardano.Api.Orphans () +import qualified Cardano.Api.Shelley as Api +import qualified Cardano.Crypto.Hash.Class as Crypto +import Cardano.Ledger.Crypto (StandardCrypto) +import Cardano.Logging +import Cardano.Prelude +import Cardano.Slotting.Block (BlockNo (..)) + +import Ouroboros.Network.Block (SlotNo (..), blockHash, blockNo, blockSlot) +import Ouroboros.Network.Point (WithOrigin, withOriginToMaybe) + +import Ouroboros.Consensus.Ledger.SupportsMempool (txId) +import qualified Ouroboros.Consensus.Ledger.SupportsMempool as SupportsMempool +import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey +import Ouroboros.Consensus.Protocol.TPraos (TPraosCannotForge (..)) +import Ouroboros.Consensus.Shelley.Ledger hiding (TxId) +import Ouroboros.Consensus.Shelley.Ledger.Inspect +import Ouroboros.Consensus.Util.Condense (condense) + +import Cardano.Protocol.TPraos.BHeader (LastAppliedBlock, labBlockNo) +import Cardano.Protocol.TPraos.Rules.OCert +import Cardano.Protocol.TPraos.Rules.Overlay +import Cardano.Protocol.TPraos.Rules.Updn + + +import qualified Cardano.Ledger.Alonzo as Alonzo +import Cardano.Ledger.Alonzo.Rules.Bbody (AlonzoBbodyPredFail) +import qualified Cardano.Ledger.Alonzo.Rules.Utxo as Alonzo +import qualified Cardano.Ledger.Alonzo.Rules.Utxos as Alonzo +import Cardano.Ledger.Alonzo.Rules.Utxow (AlonzoPredFail (..)) +import qualified Cardano.Ledger.Alonzo.Tx as Alonzo +import qualified Cardano.Ledger.AuxiliaryData as Core +import Cardano.Ledger.BaseTypes (strictMaybeToMaybe) +import Cardano.Ledger.Chain +import qualified Cardano.Ledger.Core as Core +import qualified Cardano.Ledger.Crypto as Core +import qualified Cardano.Ledger.Era as Ledger +import qualified Cardano.Ledger.SafeHash as SafeHash +import qualified Cardano.Ledger.ShelleyMA.Rules.Utxo as MA +import qualified Cardano.Ledger.ShelleyMA.Timelocks as MA + +-- TODO: this should be exposed via Cardano.Api +import Cardano.Ledger.Shelley.API hiding (ShelleyBasedEra) + +import Cardano.Ledger.Shelley.Rules.Bbody +import Cardano.Ledger.Shelley.Rules.Deleg +import Cardano.Ledger.Shelley.Rules.Delegs +import Cardano.Ledger.Shelley.Rules.Delpl +import Cardano.Ledger.Shelley.Rules.Epoch +import Cardano.Ledger.Shelley.Rules.Ledger +import Cardano.Ledger.Shelley.Rules.Ledgers +import Cardano.Ledger.Shelley.Rules.Mir +import Cardano.Ledger.Shelley.Rules.NewEpoch +import Cardano.Ledger.Shelley.Rules.Newpp +import Cardano.Ledger.Shelley.Rules.Pool +import Cardano.Ledger.Shelley.Rules.PoolReap +import Cardano.Ledger.Shelley.Rules.Ppup +import Cardano.Ledger.Shelley.Rules.Rupd +import Cardano.Ledger.Shelley.Rules.Snap +import Cardano.Ledger.Shelley.Rules.Tick +import Cardano.Ledger.Shelley.Rules.Upec +import Cardano.Ledger.Shelley.Rules.Utxo +import Cardano.Ledger.Shelley.Rules.Utxow + +import Cardano.Tracing.OrphanInstances.Shelley () + +{- HLINT ignore "Use :" -} + +-- +-- | instances of @LogFormatting@ +-- +-- NOTE: this list is sorted in roughly topological order. + +instance ( ToJSON (SupportsMempool.TxId (GenTx (ShelleyBlock era))) + , ShelleyBasedEra era) + => LogFormatting (GenTx (ShelleyBlock era)) where + forMachine dtal tx = + mkObject $ + ( "txid" .= txId tx ) + : [ "tx" .= condense tx | dtal == DDetailed ] + +instance ShelleyBasedEra era => LogFormatting (Header (ShelleyBlock era)) where + forMachine _dtal b = mkObject + [ "kind" .= String "ShelleyBlock" + , "hash" .= condense (blockHash b) + , "slotNo" .= condense (blockSlot b) + , "blockNo" .= condense (blockNo b) +-- , "delegate" .= condense (headerSignerVk h) + ] + +instance ( ShelleyBasedEra era + , LogFormatting (PredicateFailure (UTXO era)) + , LogFormatting (PredicateFailure (UTXOW era)) + , LogFormatting (PredicateFailure (Core.EraRule "LEDGER" era)) + ) => LogFormatting (ApplyTxError era) where + forMachine dtal (ApplyTxError predicateFailures) = + HMS.unions $ map (forMachine dtal) predicateFailures + +instance Core.Crypto era => LogFormatting (TPraosCannotForge era) where + forMachine _dtal (TPraosCannotForgeKeyNotUsableYet wallClockPeriod keyStartPeriod) = + mkObject + [ "kind" .= String "TPraosCannotForgeKeyNotUsableYet" + , "keyStart" .= keyStartPeriod + , "wallClock" .= wallClockPeriod + ] + forMachine _dtal (TPraosCannotForgeWrongVRF genDlgVRFHash coreNodeVRFHash) = + mkObject + [ "kind" .= String "TPraosCannotLeadWrongVRF" + , "expected" .= genDlgVRFHash + , "actual" .= coreNodeVRFHash + ] + + +instance LogFormatting HotKey.KESInfo where + forMachine _dtal forgeStateInfo = + let maxKesEvos = endKesPeriod - startKesPeriod + oCertExpiryKesPeriod = startKesPeriod + maxKesEvos + kesPeriodsUntilExpiry = max 0 (oCertExpiryKesPeriod - currKesPeriod) + in + if kesPeriodsUntilExpiry > 7 + then mkObject + [ "kind" .= String "KESInfo" + , "startPeriod" .= startKesPeriod + , "endPeriod" .= currKesPeriod + , "evolution" .= endKesPeriod + ] + else mkObject + [ "kind" .= String "ExpiryLogMessage" + , "keyExpiresIn" .= kesPeriodsUntilExpiry + , "startPeriod" .= startKesPeriod + , "endPeriod" .= currKesPeriod + , "evolution" .= endKesPeriod + ] + where + HotKey.KESInfo + { kesStartPeriod = KESPeriod startKesPeriod + , kesEvolution = currKesPeriod + , kesEndPeriod = KESPeriod endKesPeriod + } = forgeStateInfo + + forHuman forgeStateInfo = + let maxKesEvos = endKesPeriod - startKesPeriod + oCertExpiryKesPeriod = startKesPeriod + maxKesEvos + kesPeriodsUntilExpiry = max 0 (oCertExpiryKesPeriod - currKesPeriod) + in if kesPeriodsUntilExpiry > 7 + then "KES info startPeriod " <> show startKesPeriod + <> " currPeriod " <> show currKesPeriod + <> " endPeriod " <> show endKesPeriod + <> (Text.pack . show) kesPeriodsUntilExpiry + <> " KES periods." + else "Operational key will expire in " + <> (Text.pack . show) kesPeriodsUntilExpiry + <> " KES periods." + where + HotKey.KESInfo + { kesStartPeriod = KESPeriod startKesPeriod + , kesEvolution = currKesPeriod + , kesEndPeriod = KESPeriod endKesPeriod + } = forgeStateInfo + + asMetrics forgeStateInfo = + let maxKesEvos = endKesPeriod - startKesPeriod + oCertExpiryKesPeriod = startKesPeriod + maxKesEvos + in [ + IntM "operationalCertificateStartKESPeriod" + (fromIntegral startKesPeriod) + , IntM "operationalCertificateExpiryKESPeriod" + (fromIntegral (startKesPeriod + maxKesEvos)) + , IntM "currentKESPeriod" + (fromIntegral currKesPeriod) + , IntM "remainingKESPeriods" + (fromIntegral (max 0 (oCertExpiryKesPeriod - currKesPeriod))) + ] + where + HotKey.KESInfo + { kesStartPeriod = KESPeriod startKesPeriod + , kesEvolution = currKesPeriod + , kesEndPeriod = KESPeriod endKesPeriod + } = forgeStateInfo + + +instance LogFormatting HotKey.KESEvolutionError where + forMachine dtal (HotKey.KESCouldNotEvolve kesInfo targetPeriod) = + mkObject + [ "kind" .= String "KESCouldNotEvolve" + , "kesInfo" .= forMachine dtal kesInfo + , "targetPeriod" .= targetPeriod + ] + forMachine dtal (HotKey.KESKeyAlreadyPoisoned kesInfo targetPeriod) = + mkObject + [ "kind" .= String "KESKeyAlreadyPoisoned" + , "kesInfo" .= forMachine dtal kesInfo + , "targetPeriod" .= targetPeriod + ] + +instance ( ShelleyBasedEra era + , LogFormatting (PredicateFailure (UTXO era)) + , LogFormatting (PredicateFailure (UTXOW era)) + , LogFormatting (PredicateFailure (Core.EraRule "BBODY" era)) + ) => LogFormatting (ShelleyLedgerError era) where + forMachine dtal (BBodyError (BlockTransitionError fs)) = + mkObject [ "kind" .= String "BBodyError" + , "failures" .= map (forMachine dtal) fs + ] + +instance ( ShelleyBasedEra era + , ToJSON (Core.PParamsDelta era) + ) => LogFormatting (ShelleyLedgerUpdate era) where + forMachine dtal (ShelleyUpdatedProtocolUpdates updates) = + mkObject [ "kind" .= String "ShelleyUpdatedProtocolUpdates" + , "updates" .= map (forMachine dtal) updates + ] + +instance (Ledger.Era era, ToJSON (Core.PParamsDelta era)) + => LogFormatting (ProtocolUpdate era) where + forMachine dtal ProtocolUpdate{protocolUpdateProposal, protocolUpdateState} = + mkObject [ "proposal" .= forMachine dtal protocolUpdateProposal + , "state" .= forMachine dtal protocolUpdateState + ] + +instance ToJSON (Core.PParamsDelta era) + => LogFormatting (UpdateProposal era) where + forMachine _dtal UpdateProposal{proposalParams, proposalVersion, proposalEpoch} = + mkObject [ "params" .= proposalParams + , "version" .= proposalVersion + , "epoch" .= proposalEpoch + ] + +instance Core.Crypto crypto => LogFormatting (UpdateState crypto) where + forMachine _dtal UpdateState{proposalVotes, proposalReachedQuorum} = + mkObject [ "proposal" .= proposalVotes + , "reachedQuorum" .= proposalReachedQuorum + ] + +instance Core.Crypto crypto => LogFormatting (ChainTransitionError crypto) where + forMachine dtal (ChainTransitionError fs) = + mkObject [ "kind" .= String "ChainTransitionError" + , "failures" .= map (forMachine dtal) fs + ] + +instance ( ShelleyBasedEra era + ) => LogFormatting (ChainPredicateFailure era) where + forMachine _dtal (HeaderSizeTooLargeCHAIN hdrSz maxHdrSz) = + mkObject [ "kind" .= String "HeaderSizeTooLarge" + , "headerSize" .= hdrSz + , "maxHeaderSize" .= maxHdrSz + ] + forMachine _dtal (BlockSizeTooLargeCHAIN blkSz maxBlkSz) = + mkObject [ "kind" .= String "BlockSizeTooLarge" + , "blockSize" .= blkSz + , "maxBlockSize" .= maxBlkSz + ] + forMachine _dtal (ObsoleteNodeCHAIN currentPtcl supportedPtcl) = + mkObject [ "kind" .= String "ObsoleteNode" + , "explanation" .= String explanation + , "currentProtocol" .= currentPtcl + , "supportedProtocol" .= supportedPtcl ] + where + explanation = "A scheduled major protocol version change (hard fork) \ + \has taken place on the chain, but this node does not \ + \understand the new major protocol version. This node \ + \must be upgraded before it can continue with the new \ + \protocol version." + +instance LogFormatting (PrtlSeqFailure crypto) where + forMachine _dtal (WrongSlotIntervalPrtclSeq (SlotNo lastSlot) (SlotNo currSlot)) = + mkObject [ "kind" .= String "WrongSlotInterval" + , "lastSlot" .= lastSlot + , "currentSlot" .= currSlot + ] + forMachine _dtal (WrongBlockNoPrtclSeq lab currentBlockNo) = + mkObject [ "kind" .= String "WrongBlockNo" + , "lastAppliedBlockNo" .= showLastAppBlockNo lab + , "currentBlockNo" .= (String . textShow $ unBlockNo currentBlockNo) + ] + forMachine _dtal (WrongBlockSequencePrtclSeq lastAppliedHash currentHash) = + mkObject [ "kind" .= String "WrongBlockSequence" + , "lastAppliedBlockHash" .= String (textShow lastAppliedHash) + , "currentBlockHash" .= String (textShow currentHash) + ] + +instance ( ShelleyBasedEra era + , LogFormatting (PredicateFailure (UTXO era)) + , LogFormatting (PredicateFailure (UTXOW era)) + , LogFormatting (PredicateFailure (Core.EraRule "LEDGER" era)) + , LogFormatting (PredicateFailure (Core.EraRule "LEDGERS" era)) + ) => LogFormatting (BbodyPredicateFailure era) where + forMachine _dtal (WrongBlockBodySizeBBODY actualBodySz claimedBodySz) = + mkObject [ "kind" .= String "WrongBlockBodySizeBBODY" + , "actualBlockBodySize" .= actualBodySz + , "claimedBlockBodySize" .= claimedBodySz + ] + forMachine _dtal (InvalidBodyHashBBODY actualHash claimedHash) = + mkObject [ "kind" .= String "InvalidBodyHashBBODY" + , "actualBodyHash" .= textShow actualHash + , "claimedBodyHash" .= textShow claimedHash + ] + forMachine dtal (LedgersFailure f) = forMachine dtal f + + +instance ( ShelleyBasedEra era + , LogFormatting (PredicateFailure (UTXO era)) + , LogFormatting (PredicateFailure (UTXOW era)) + , LogFormatting (PredicateFailure (Core.EraRule "LEDGER" era)) + ) => LogFormatting (LedgersPredicateFailure era) where + forMachine dtal (LedgerFailure f) = forMachine dtal f + + +instance ( ShelleyBasedEra era + , ToJSON (Core.AuxiliaryDataHash (Ledger.Crypto era)) + , LogFormatting (PredicateFailure (UTXO era)) + , LogFormatting (PredicateFailure (UTXOW era)) + , LogFormatting (PredicateFailure (Core.EraRule "DELEGS" era)) + , LogFormatting (PredicateFailure (Core.EraRule "UTXOW" era)) + ) => LogFormatting (LedgerPredicateFailure era) where + forMachine dtal (UtxowFailure f) = forMachine dtal f + forMachine dtal (DelegsFailure f) = forMachine dtal f + +instance LogFormatting (AlonzoPredFail (Alonzo.AlonzoEra StandardCrypto)) where + forMachine dtal (WrappedShelleyEraFailure utxoPredFail) = + forMachine dtal utxoPredFail + forMachine _ (MissingRedeemers scripts) = + mkObject [ "kind" .= String "MissingRedeemers" + , "scripts" .= renderMissingRedeemers scripts + ] + forMachine _ (MissingRequiredDatums required received) = + mkObject [ "kind" .= String "MissingRequiredDatums" + , "required" .= map (Crypto.hashToTextAsHex . SafeHash.extractHash) + (Set.toList required) + , "received" .= map (Crypto.hashToTextAsHex . SafeHash.extractHash) + (Set.toList received) + ] + forMachine _ (PPViewHashesDontMatch ppHashInTxBody ppHashFromPParams) = + mkObject [ "kind" .= String "PPViewHashesDontMatch" + , "fromTxBody" .= renderScriptIntegrityHash + (strictMaybeToMaybe ppHashInTxBody) + , "fromPParams" .= renderScriptIntegrityHash + (strictMaybeToMaybe ppHashFromPParams) + ] + forMachine _ (MissingRequiredSigners missingKeyWitnesses) = + mkObject [ "kind" .= String "MissingRequiredSigners" + , "witnesses" .= Set.toList missingKeyWitnesses + ] + forMachine _ (UnspendableUTxONoDatumHash txins) = + mkObject [ "kind" .= String "MissingRequiredSigners" + , "txins" .= Set.toList txins + ] + forMachine _ (NonOutputSupplimentaryDatums disallowed acceptable) = + mkObject [ "kind" .= String "NonOutputSupplimentaryDatums" + , "disallowed" .= Set.toList disallowed + , "acceptable" .= Set.toList acceptable + ] + forMachine _ (ExtraRedeemers rdmrs) = + mkObject [ "kind" .= String "ExtraRedeemers" + , "rdmrs" .= map (Api.renderScriptWitnessIndex . Api.fromAlonzoRdmrPtr) rdmrs + ] + + +renderScriptIntegrityHash :: Maybe (Alonzo.ScriptIntegrityHash StandardCrypto) -> Aeson.Value +renderScriptIntegrityHash (Just witPPDataHash) = + Aeson.String . Crypto.hashToTextAsHex $ SafeHash.extractHash witPPDataHash +renderScriptIntegrityHash Nothing = Aeson.Null + +renderScriptHash :: ScriptHash StandardCrypto -> Text +renderScriptHash = Api.serialiseToRawBytesHexText . Api.fromShelleyScriptHash + +renderMissingRedeemers :: [(Alonzo.ScriptPurpose StandardCrypto, ScriptHash StandardCrypto)] -> Aeson.Value +renderMissingRedeemers scripts = Aeson.object $ map renderTuple scripts + where + renderTuple :: (Alonzo.ScriptPurpose StandardCrypto, ScriptHash StandardCrypto) -> Aeson.Pair + renderTuple (scriptPurpose, sHash) = renderScriptHash sHash .= renderScriptPurpose scriptPurpose + +renderScriptPurpose :: Alonzo.ScriptPurpose StandardCrypto -> Aeson.Value +renderScriptPurpose (Alonzo.Minting pid) = + Aeson.object [ "minting" .= toJSON pid] +renderScriptPurpose (Alonzo.Spending txin) = + Aeson.object [ "spending" .= Api.fromShelleyTxIn txin] +renderScriptPurpose (Alonzo.Rewarding rwdAcct) = + Aeson.object [ "rewarding" .= Aeson.String (Api.serialiseAddress $ Api.fromShelleyStakeAddr rwdAcct)] +renderScriptPurpose (Alonzo.Certifying cert) = + Aeson.object [ "certifying" .= toJSON (Api.textEnvelopeDefaultDescr $ Api.fromShelleyCertificate cert)] + + +instance ( ShelleyBasedEra era + , Ledger.Crypto era ~ StandardCrypto + , ToJSON (Core.AuxiliaryDataHash (Ledger.Crypto era)) + , LogFormatting (PredicateFailure (UTXO era)) + , LogFormatting (PredicateFailure (Core.EraRule "UTXO" era)) + ) => LogFormatting (UtxowPredicateFailure era) where + forMachine _dtal (InvalidWitnessesUTXOW wits') = + mkObject [ "kind" .= String "InvalidWitnessesUTXOW" + , "invalidWitnesses" .= map textShow wits' + ] + forMachine _dtal (MissingVKeyWitnessesUTXOW (WitHashes wits')) = + mkObject [ "kind" .= String "MissingVKeyWitnessesUTXOW" + , "missingWitnesses" .= wits' + ] + forMachine _dtal (MissingScriptWitnessesUTXOW missingScripts) = + mkObject [ "kind" .= String "MissingScriptWitnessesUTXOW" + , "missingScripts" .= missingScripts + ] + forMachine _dtal (ScriptWitnessNotValidatingUTXOW failedScripts) = + mkObject [ "kind" .= String "ScriptWitnessNotValidatingUTXOW" + , "failedScripts" .= failedScripts + ] + forMachine dtal (UtxoFailure f) = forMachine dtal f + forMachine _dtal (MIRInsufficientGenesisSigsUTXOW genesisSigs) = + mkObject [ "kind" .= String "MIRInsufficientGenesisSigsUTXOW" + , "genesisSigs" .= genesisSigs + ] + forMachine _dtal (MissingTxBodyMetadataHash metadataHash) = + mkObject [ "kind" .= String "MissingTxBodyMetadataHash" + , "metadataHash" .= metadataHash + ] + forMachine _dtal (MissingTxMetadata txBodyMetadataHash) = + mkObject [ "kind" .= String "MissingTxMetadata" + , "txBodyMetadataHash" .= txBodyMetadataHash + ] + forMachine _dtal (ConflictingMetadataHash txBodyMetadataHash fullMetadataHash) = + mkObject [ "kind" .= String "ConflictingMetadataHash" + , "txBodyMetadataHash" .= txBodyMetadataHash + , "fullMetadataHash" .= fullMetadataHash + ] + forMachine _dtal InvalidMetadata = + mkObject [ "kind" .= String "InvalidMetadata" + ] + forMachine _dtal (ExtraneousScriptWitnessesUTXOW shashes) = + mkObject [ "kind" .= String "ExtraneousScriptWitnessesUTXOW" + , "scriptHashes" .= Set.map Api.fromShelleyScriptHash shashes + ] + +instance ( ShelleyBasedEra era + , ToJSON (Core.Value era) + , ToJSON (Core.TxOut era) + , LogFormatting (PredicateFailure (Core.EraRule "PPUP" era)) + ) + => LogFormatting (UtxoPredicateFailure era) where + forMachine _dtal (BadInputsUTxO badInputs) = + mkObject [ "kind" .= String "BadInputsUTxO" + , "badInputs" .= badInputs + , "error" .= renderBadInputsUTxOErr badInputs + ] + forMachine _dtal (ExpiredUTxO ttl slot) = + mkObject [ "kind" .= String "ExpiredUTxO" + , "ttl" .= ttl + , "slot" .= slot ] + forMachine _dtal (MaxTxSizeUTxO txsize maxtxsize) = + mkObject [ "kind" .= String "MaxTxSizeUTxO" + , "size" .= txsize + , "maxSize" .= maxtxsize ] + -- TODO: Add the minimum allowed UTxO value to OutputTooSmallUTxO + forMachine _dtal (OutputTooSmallUTxO badOutputs) = + mkObject [ "kind" .= String "OutputTooSmallUTxO" + , "outputs" .= badOutputs + , "error" .= String "The output is smaller than the allow minimum \ + \UTxO value defined in the protocol parameters" + ] + forMachine _dtal (OutputBootAddrAttrsTooBig badOutputs) = + mkObject [ "kind" .= String "OutputBootAddrAttrsTooBig" + , "outputs" .= badOutputs + , "error" .= String "The Byron address attributes are too big" + ] + forMachine _dtal InputSetEmptyUTxO = + mkObject [ "kind" .= String "InputSetEmptyUTxO" ] + forMachine _dtal (FeeTooSmallUTxO minfee txfee) = + mkObject [ "kind" .= String "FeeTooSmallUTxO" + , "minimum" .= minfee + , "fee" .= txfee ] + forMachine _dtal (ValueNotConservedUTxO consumed produced) = + mkObject [ "kind" .= String "ValueNotConservedUTxO" + , "consumed" .= consumed + , "produced" .= produced + , "error" .= renderValueNotConservedErr consumed produced + ] + forMachine dtal (UpdateFailure f) = forMachine dtal f + + forMachine _dtal (WrongNetwork network addrs) = + mkObject [ "kind" .= String "WrongNetwork" + , "network" .= network + , "addrs" .= addrs + ] + forMachine _dtal (WrongNetworkWithdrawal network addrs) = + mkObject [ "kind" .= String "WrongNetworkWithdrawal" + , "network" .= network + , "addrs" .= addrs + ] + +instance ( ShelleyBasedEra era + , ToJSON (Core.Value era) + , ToJSON (Core.TxOut era) + , ToJSON MA.ValidityInterval + , LogFormatting (PredicateFailure (Core.EraRule "PPUP" era)) + ) => LogFormatting (MA.UtxoPredicateFailure era) where + forMachine _dtal (MA.BadInputsUTxO badInputs) = + mkObject [ "kind" .= String "BadInputsUTxO" + , "badInputs" .= badInputs + , "error" .= renderBadInputsUTxOErr badInputs + ] + forMachine _dtal (MA.OutsideValidityIntervalUTxO validityInterval slot) = + mkObject [ "kind" .= String "ExpiredUTxO" + , "validityInterval" .= validityInterval + , "slot" .= slot ] + forMachine _dtal (MA.MaxTxSizeUTxO txsize maxtxsize) = + mkObject [ "kind" .= String "MaxTxSizeUTxO" + , "size" .= txsize + , "maxSize" .= maxtxsize ] + forMachine _dtal MA.InputSetEmptyUTxO = + mkObject [ "kind" .= String "InputSetEmptyUTxO" ] + forMachine _dtal (MA.FeeTooSmallUTxO minfee txfee) = + mkObject [ "kind" .= String "FeeTooSmallUTxO" + , "minimum" .= minfee + , "fee" .= txfee ] + forMachine _dtal (MA.ValueNotConservedUTxO consumed produced) = + mkObject [ "kind" .= String "ValueNotConservedUTxO" + , "consumed" .= consumed + , "produced" .= produced + , "error" .= renderValueNotConservedErr consumed produced + ] + forMachine _dtal (MA.WrongNetwork network addrs) = + mkObject [ "kind" .= String "WrongNetwork" + , "network" .= network + , "addrs" .= addrs + ] + forMachine _dtal (MA.WrongNetworkWithdrawal network addrs) = + mkObject [ "kind" .= String "WrongNetworkWithdrawal" + , "network" .= network + , "addrs" .= addrs + ] + -- TODO: Add the minimum allowed UTxO value to OutputTooSmallUTxO + forMachine _dtal (MA.OutputTooSmallUTxO badOutputs) = + mkObject [ "kind" .= String "OutputTooSmallUTxO" + , "outputs" .= badOutputs + , "error" .= String "The output is smaller than the allow minimum \ + \UTxO value defined in the protocol parameters" + ] + forMachine dtal (MA.UpdateFailure f) = forMachine dtal f + forMachine _dtal (MA.OutputBootAddrAttrsTooBig badOutputs) = + mkObject [ "kind" .= String "OutputBootAddrAttrsTooBig" + , "outputs" .= badOutputs + , "error" .= String "The Byron address attributes are too big" + ] + forMachine _dtal MA.TriesToForgeADA = + mkObject [ "kind" .= String "TriesToForgeADA" ] + forMachine _dtal (MA.OutputTooBigUTxO badOutputs) = + mkObject [ "kind" .= String "OutputTooBigUTxO" + , "outputs" .= badOutputs + , "error" .= String "Too many asset ids in the tx output" + ] + +renderBadInputsUTxOErr :: Set (TxIn era) -> Value +renderBadInputsUTxOErr txIns + | Set.null txIns = String "The transaction contains no inputs." + | otherwise = String "The transaction contains inputs that do not exist in the UTxO set." + +renderValueNotConservedErr :: Show val => val -> val -> Value +renderValueNotConservedErr consumed produced = String $ + "This transaction consumed " <> show consumed <> " but produced " <> show produced + +instance Core.Crypto (Ledger.Crypto era) => LogFormatting (PpupPredicateFailure era) where + forMachine _dtal (NonGenesisUpdatePPUP proposalKeys genesisKeys) = + mkObject [ "kind" .= String "NonGenesisUpdatePPUP" + , "keys" .= proposalKeys Set.\\ genesisKeys ] + forMachine _dtal (PPUpdateWrongEpoch currEpoch intendedEpoch votingPeriod) = + mkObject [ "kind" .= String "PPUpdateWrongEpoch" + , "currentEpoch" .= currEpoch + , "intendedEpoch" .= intendedEpoch + , "votingPeriod" .= String (show votingPeriod) + ] + forMachine _dtal (PVCannotFollowPPUP badPv) = + mkObject [ "kind" .= String "PVCannotFollowPPUP" + , "badProtocolVersion" .= badPv + ] + + +instance ( ShelleyBasedEra era + , LogFormatting (PredicateFailure (Core.EraRule "DELPL" era)) + ) => LogFormatting (DelegsPredicateFailure era) where + forMachine _dtal (DelegateeNotRegisteredDELEG targetPool) = + mkObject [ "kind" .= String "DelegateeNotRegisteredDELEG" + , "targetPool" .= targetPool + ] + forMachine _dtal (WithdrawalsNotInRewardsDELEGS incorrectWithdrawals) = + mkObject [ "kind" .= String "WithdrawalsNotInRewardsDELEGS" + , "incorrectWithdrawals" .= incorrectWithdrawals + ] + forMachine dtal (DelplFailure f) = forMachine dtal f + + +instance ( LogFormatting (PredicateFailure (Core.EraRule "POOL" era)) + , LogFormatting (PredicateFailure (Core.EraRule "DELEG" era)) + , Crypto.HashAlgorithm (Core.HASH (Ledger.Crypto era)) + ) => LogFormatting (DelplPredicateFailure era) where + forMachine dtal (PoolFailure f) = forMachine dtal f + forMachine dtal (DelegFailure f) = forMachine dtal f + +instance Crypto.HashAlgorithm (Core.HASH (Ledger.Crypto era)) + => LogFormatting (DelegPredicateFailure era) where + forMachine _dtal (StakeKeyAlreadyRegisteredDELEG alreadyRegistered) = + mkObject [ "kind" .= String "StakeKeyAlreadyRegisteredDELEG" + , "credential" .= String (textShow alreadyRegistered) + , "error" .= String "Staking credential already registered" + ] + forMachine _dtal (StakeKeyInRewardsDELEG alreadyRegistered) = + mkObject [ "kind" .= String "StakeKeyInRewardsDELEG" + , "credential" .= String (textShow alreadyRegistered) + , "error" .= String "Staking credential registered in rewards map" + ] + forMachine _dtal (StakeKeyNotRegisteredDELEG notRegistered) = + mkObject [ "kind" .= String "StakeKeyNotRegisteredDELEG" + , "credential" .= String (textShow notRegistered) + , "error" .= String "Staking credential not registered" + ] + forMachine _dtal (StakeKeyNonZeroAccountBalanceDELEG remBalance) = + mkObject [ "kind" .= String "StakeKeyNonZeroAccountBalanceDELEG" + , "remainingBalance" .= remBalance + ] + forMachine _dtal (StakeDelegationImpossibleDELEG unregistered) = + mkObject [ "kind" .= String "StakeDelegationImpossibleDELEG" + , "credential" .= String (textShow unregistered) + , "error" .= String "Cannot delegate this stake credential because it is not registered" + ] + forMachine _dtal WrongCertificateTypeDELEG = + mkObject [ "kind" .= String "WrongCertificateTypeDELEG" ] + forMachine _dtal (GenesisKeyNotInMappingDELEG (KeyHash genesisKeyHash)) = + mkObject [ "kind" .= String "GenesisKeyNotInMappingDELEG" + , "unknownKeyHash" .= String (textShow genesisKeyHash) + , "error" .= String "This genesis key is not in the delegation mapping" + ] + forMachine _dtal (DuplicateGenesisDelegateDELEG (KeyHash genesisKeyHash)) = + mkObject [ "kind" .= String "DuplicateGenesisDelegateDELEG" + , "duplicateKeyHash" .= String (textShow genesisKeyHash) + , "error" .= String "This genesis key has already been delegated to" + ] + forMachine _dtal (InsufficientForInstantaneousRewardsDELEG mirpot neededMirAmount reserves) = + mkObject [ "kind" .= String "InsufficientForInstantaneousRewardsDELEG" + , "pot" .= String (case mirpot of + ReservesMIR -> "Reserves" + TreasuryMIR -> "Treasury") + , "neededAmount" .= neededMirAmount + , "reserves" .= reserves + ] + forMachine _dtal (MIRCertificateTooLateinEpochDELEG currSlot boundSlotNo) = + mkObject [ "kind" .= String "MIRCertificateTooLateinEpochDELEG" + , "currentSlotNo" .= currSlot + , "mustBeSubmittedBeforeSlotNo" .= boundSlotNo + ] + forMachine _dtal (DuplicateGenesisVRFDELEG vrfKeyHash) = + mkObject [ "kind" .= String "DuplicateGenesisVRFDELEG" + , "keyHash" .= vrfKeyHash + ] + forMachine _dtal MIRTransferNotCurrentlyAllowed = + mkObject [ "kind" .= String "MIRTransferNotCurrentlyAllowed" + ] + forMachine _dtal MIRNegativesNotCurrentlyAllowed = + mkObject [ "kind" .= String "MIRNegativesNotCurrentlyAllowed" + ] + forMachine _dtal (InsufficientForTransferDELEG mirpot attempted available) = + mkObject [ "kind" .= String "DuplicateGenesisVRFDELEG" + , "pot" .= String (case mirpot of + ReservesMIR -> "Reserves" + TreasuryMIR -> "Treasury") + , "attempted" .= attempted + , "available" .= available + ] + forMachine _dtal MIRProducesNegativeUpdate = + mkObject [ "kind" .= String "MIRProducesNegativeUpdate" + ] + +instance LogFormatting (PoolPredicateFailure era) where + forMachine _dtal (StakePoolNotRegisteredOnKeyPOOL (KeyHash unregStakePool)) = + mkObject [ "kind" .= String "StakePoolNotRegisteredOnKeyPOOL" + , "unregisteredKeyHash" .= String (textShow unregStakePool) + , "error" .= String "This stake pool key hash is unregistered" + ] + forMachine _dtal (StakePoolRetirementWrongEpochPOOL currentEpoch intendedRetireEpoch maxRetireEpoch) = + mkObject [ "kind" .= String "StakePoolRetirementWrongEpochPOOL" + , "currentEpoch" .= String (textShow currentEpoch) + , "intendedRetirementEpoch" .= String (textShow intendedRetireEpoch) + , "maxEpochForRetirement" .= String (textShow maxRetireEpoch) + ] + forMachine _dtal (StakePoolCostTooLowPOOL certCost protCost) = + mkObject [ "kind" .= String "StakePoolCostTooLowPOOL" + , "certificateCost" .= String (textShow certCost) + , "protocolParCost" .= String (textShow protCost) + , "error" .= String "The stake pool cost is too low" + ] + forMachine _dtal (PoolMedataHashTooBig poolID hashSize) = + mkObject [ "kind" .= String "PoolMedataHashTooBig" + , "hashSize" .= String (textShow poolID) + , "poolID" .= String (textShow hashSize) + , "error" .= String "The stake pool metadata hash is too large" + ] + +-- Apparently this should never happen according to the Shelley exec spec + forMachine _dtal (WrongCertificateTypePOOL index) = + case index of + 0 -> mkObject [ "kind" .= String "WrongCertificateTypePOOL" + , "error" .= String "Wrong certificate type: Delegation certificate" + ] + 1 -> mkObject [ "kind" .= String "WrongCertificateTypePOOL" + , "error" .= String "Wrong certificate type: MIR certificate" + ] + 2 -> mkObject [ "kind" .= String "WrongCertificateTypePOOL" + , "error" .= String "Wrong certificate type: Genesis certificate" + ] + k -> mkObject [ "kind" .= String "WrongCertificateTypePOOL" + , "certificateType" .= k + , "error" .= String "Wrong certificate type: Unknown certificate type" + ] + + forMachine _dtal (WrongNetworkPOOL networkId listedNetworkId poolId) = + mkObject [ "kind" .= String "WrongNetworkPOOL" + , "networkId" .= String (textShow networkId) + , "listedNetworkId" .= String (textShow listedNetworkId) + , "poolId" .= String (textShow poolId) + , "error" .= String "Wrong network ID in pool registration certificate" + ] + + +instance ( LogFormatting (PredicateFailure (Core.EraRule "NEWEPOCH" era)) + , LogFormatting (PredicateFailure (Core.EraRule "RUPD" era)) + ) => LogFormatting (TickPredicateFailure era) where + forMachine dtal (NewEpochFailure f) = forMachine dtal f + forMachine dtal (RupdFailure f) = forMachine dtal f + +instance LogFormatting TicknPredicateFailure where + forMachine _dtal x = case x of {} -- no constructors + +instance ( LogFormatting (PredicateFailure (Core.EraRule "EPOCH" era)) + , LogFormatting (PredicateFailure (Core.EraRule "MIR" era)) + ) => LogFormatting (NewEpochPredicateFailure era) where + forMachine dtal (EpochFailure f) = forMachine dtal f + forMachine dtal (MirFailure f) = forMachine dtal f + forMachine _dtal (CorruptRewardUpdate update) = + mkObject [ "kind" .= String "CorruptRewardUpdate" + , "update" .= String (show update) ] + + +instance ( LogFormatting (PredicateFailure (Core.EraRule "POOLREAP" era)) + , LogFormatting (PredicateFailure (Core.EraRule "SNAP" era)) + , LogFormatting (PredicateFailure (Core.EraRule "UPEC" era)) + ) => LogFormatting (EpochPredicateFailure era) where + forMachine dtal (PoolReapFailure f) = forMachine dtal f + forMachine dtal (SnapFailure f) = forMachine dtal f + forMachine dtal (UpecFailure f) = forMachine dtal f + + +instance LogFormatting (PoolreapPredicateFailure era) where + forMachine _dtal x = case x of {} -- no constructors + + +instance LogFormatting (SnapPredicateFailure era) where + forMachine _dtal x = case x of {} -- no constructors + +-- TODO: Need to elaborate more on this error +instance LogFormatting (NewppPredicateFailure era) where + forMachine _dtal (UnexpectedDepositPot outstandingDeposits depositPot) = + mkObject [ "kind" .= String "UnexpectedDepositPot" + , "outstandingDeposits" .= String (textShow outstandingDeposits) + , "depositPot" .= String (textShow depositPot) + ] + + +instance LogFormatting (MirPredicateFailure era) where + forMachine _dtal x = case x of {} -- no constructors + + +instance LogFormatting (RupdPredicateFailure era) where + forMachine _dtal x = case x of {} -- no constructors + + +instance Core.Crypto crypto => LogFormatting (PrtclPredicateFailure crypto) where + forMachine dtal (OverlayFailure f) = forMachine dtal f + forMachine dtal (UpdnFailure f) = forMachine dtal f + + +instance Core.Crypto crypto => LogFormatting (OverlayPredicateFailure crypto) where + forMachine _dtal (UnknownGenesisKeyOVERLAY (KeyHash genKeyHash)) = + mkObject [ "kind" .= String "UnknownGenesisKeyOVERLAY" + , "unknownKeyHash" .= String (textShow genKeyHash) + ] + forMachine _dtal (VRFKeyBadLeaderValue seedNonce (SlotNo currSlotNo) prevHashNonce leaderElecVal) = + mkObject [ "kind" .= String "VRFKeyBadLeaderValueOVERLAY" + , "seedNonce" .= String (textShow seedNonce) + , "currentSlot" .= String (textShow currSlotNo) + , "previousHashAsNonce" .= String (textShow prevHashNonce) + , "leaderElectionValue" .= String (textShow leaderElecVal) + ] + forMachine _dtal (VRFKeyBadNonce seedNonce (SlotNo currSlotNo) prevHashNonce blockNonce) = + mkObject [ "kind" .= String "VRFKeyBadNonceOVERLAY" + , "seedNonce" .= String (textShow seedNonce) + , "currentSlot" .= String (textShow currSlotNo) + , "previousHashAsNonce" .= String (textShow prevHashNonce) + , "blockNonce" .= String (textShow blockNonce) + ] + forMachine _dtal (VRFKeyWrongVRFKey issuerHash regVRFKeyHash unregVRFKeyHash) = + mkObject [ "kind" .= String "VRFKeyWrongVRFKeyOVERLAY" + , "poolHash" .= textShow issuerHash + , "registeredVRFKeHash" .= textShow regVRFKeyHash + , "unregisteredVRFKeyHash" .= textShow unregVRFKeyHash + ] + --TODO: Pipe slot number with VRFKeyUnknown + forMachine _dtal (VRFKeyUnknown (KeyHash kHash)) = + mkObject [ "kind" .= String "VRFKeyUnknownOVERLAY" + , "keyHash" .= String (textShow kHash) + ] + forMachine _dtal (VRFLeaderValueTooBig leadElecVal weightOfDelegPool actSlotCoefff) = + mkObject [ "kind" .= String "VRFLeaderValueTooBigOVERLAY" + , "leaderElectionValue" .= String (textShow leadElecVal) + , "delegationPoolWeight" .= String (textShow weightOfDelegPool) + , "activeSlotCoefficient" .= String (textShow actSlotCoefff) + ] + forMachine _dtal (NotActiveSlotOVERLAY notActiveSlotNo) = + -- TODO: Elaborate on NotActiveSlot error + mkObject [ "kind" .= String "NotActiveSlotOVERLAY" + , "slot" .= String (textShow notActiveSlotNo) + ] + forMachine _dtal (WrongGenesisColdKeyOVERLAY actual expected) = + mkObject [ "kind" .= String "WrongGenesisColdKeyOVERLAY" + , "actual" .= actual + , "expected" .= expected ] + forMachine _dtal (WrongGenesisVRFKeyOVERLAY issuer actual expected) = + mkObject [ "kind" .= String "WrongGenesisVRFKeyOVERLAY" + , "issuer" .= issuer + , "actual" .= actual + , "expected" .= expected ] + forMachine dtal (OcertFailure f) = forMachine dtal f + + +instance LogFormatting (OcertPredicateFailure crypto) where + forMachine _dtal (KESBeforeStartOCERT (KESPeriod oCertstart) (KESPeriod current)) = + mkObject [ "kind" .= String "KESBeforeStartOCERT" + , "opCertKESStartPeriod" .= String (textShow oCertstart) + , "currentKESPeriod" .= String (textShow current) + , "error" .= String "Your operational certificate's KES start period \ + \is before the KES current period." + ] + forMachine _dtal (KESAfterEndOCERT (KESPeriod current) (KESPeriod oCertstart) maxKESEvolutions) = + mkObject [ "kind" .= String "KESAfterEndOCERT" + , "currentKESPeriod" .= String (textShow current) + , "opCertKESStartPeriod" .= String (textShow oCertstart) + , "maxKESEvolutions" .= String (textShow maxKESEvolutions) + , "error" .= String "The operational certificate's KES start period is \ + \greater than the max number of KES + the KES current period" + ] + forMachine _dtal (CounterTooSmallOCERT lastKEScounterUsed currentKESCounter) = + mkObject [ "kind" .= String "CounterTooSmallOCert" + , "currentKESCounter" .= String (textShow currentKESCounter) + , "lastKESCounter" .= String (textShow lastKEScounterUsed) + , "error" .= String "The operational certificate's last KES counter is greater \ + \than the current KES counter." + ] + forMachine _dtal (InvalidSignatureOCERT oCertCounter oCertKESStartPeriod) = + mkObject [ "kind" .= String "InvalidSignatureOCERT" + , "opCertKESStartPeriod" .= String (textShow oCertKESStartPeriod) + , "opCertCounter" .= String (textShow oCertCounter) + ] + forMachine _dtal (InvalidKesSignatureOCERT currKESPeriod startKESPeriod expectedKESEvolutions err) = + mkObject [ "kind" .= String "InvalidKesSignatureOCERT" + , "opCertKESStartPeriod" .= String (textShow startKESPeriod) + , "opCertKESCurrentPeriod" .= String (textShow currKESPeriod) + , "opCertExpectedKESEvolutions" .= String (textShow expectedKESEvolutions) + , "error" .= err ] + forMachine _dtal (NoCounterForKeyHashOCERT (KeyHash stakePoolKeyHash)) = + mkObject [ "kind" .= String "NoCounterForKeyHashOCERT" + , "stakePoolKeyHash" .= String (textShow stakePoolKeyHash) + , "error" .= String "A counter was not found for this stake pool key hash" + ] + + +instance LogFormatting (UpdnPredicateFailure crypto) where + forMachine _dtal x = case x of {} -- no constructors + +instance LogFormatting (UpecPredicateFailure era) where + forMachine _dtal (NewPpFailure (UnexpectedDepositPot totalOutstanding depositPot)) = + mkObject [ "kind" .= String "UnexpectedDepositPot" + , "totalOutstanding" .= String (textShow totalOutstanding) + , "depositPot" .= String (textShow depositPot) + ] + +-------------------------------------------------------------------------------- +-- Alonzo related +-------------------------------------------------------------------------------- + +instance LogFormatting (Alonzo.UtxoPredicateFailure (Alonzo.AlonzoEra StandardCrypto)) where + forMachine _dtal (Alonzo.BadInputsUTxO badInputs) = + mkObject [ "kind" .= String "BadInputsUTxO" + , "badInputs" .= badInputs + , "error" .= renderBadInputsUTxOErr badInputs + ] + forMachine _dtal (Alonzo.OutsideValidityIntervalUTxO validtyInterval slot) = + mkObject [ "kind" .= String "ExpiredUTxO" + , "validityInterval" .= validtyInterval + , "slot" .= slot + ] + forMachine _dtal (Alonzo.MaxTxSizeUTxO txsize maxtxsize) = + mkObject [ "kind" .= String "MaxTxSizeUTxO" + , "size" .= txsize + , "maxSize" .= maxtxsize + ] + forMachine _dtal Alonzo.InputSetEmptyUTxO = + mkObject [ "kind" .= String "InputSetEmptyUTxO" ] + forMachine _dtal (Alonzo.FeeTooSmallUTxO minfee currentFee) = + mkObject [ "kind" .= String "FeeTooSmallUTxO" + , "minimum" .= minfee + , "fee" .= currentFee + ] + forMachine _dtal (Alonzo.ValueNotConservedUTxO consumed produced) = + mkObject [ "kind" .= String "ValueNotConservedUTxO" + , "consumed" .= consumed + , "produced" .= produced + , "error" .= renderValueNotConservedErr consumed produced + ] + forMachine _dtal (Alonzo.WrongNetwork network addrs) = + mkObject [ "kind" .= String "WrongNetwork" + , "network" .= network + , "addrs" .= addrs + ] + forMachine _dtal (Alonzo.WrongNetworkWithdrawal network addrs) = + mkObject [ "kind" .= String "WrongNetworkWithdrawal" + , "network" .= network + , "addrs" .= addrs + ] + forMachine _dtal (Alonzo.OutputTooSmallUTxO badOutputs) = + mkObject [ "kind" .= String "OutputTooSmallUTxO" + , "outputs" .= badOutputs + , "error" .= String "The output is smaller than the allow minimum \ + \UTxO value defined in the protocol parameters" + ] + forMachine dtal (Alonzo.UtxosFailure predFailure) = + forMachine dtal predFailure + forMachine _dtal (Alonzo.OutputBootAddrAttrsTooBig txouts) = + mkObject [ "kind" .= String "OutputBootAddrAttrsTooBig" + , "outputs" .= txouts + , "error" .= String "The Byron address attributes are too big" + ] + forMachine _dtal Alonzo.TriesToForgeADA = + mkObject [ "kind" .= String "TriesToForgeADA" ] + forMachine _dtal (Alonzo.OutputTooBigUTxO badOutputs) = + mkObject [ "kind" .= String "OutputTooBigUTxO" + , "outputs" .= badOutputs + , "error" .= String "Too many asset ids in the tx output" + ] + forMachine _dtal (Alonzo.InsufficientCollateral computedBalance suppliedFee) = + mkObject [ "kind" .= String "InsufficientCollateral" + , "balance" .= computedBalance + , "txfee" .= suppliedFee + ] + forMachine _dtal (Alonzo.ScriptsNotPaidUTxO utxos) = + mkObject [ "kind" .= String "ScriptsNotPaidUTxO" + , "utxos" .= utxos + ] + forMachine _dtal (Alonzo.ExUnitsTooBigUTxO pParamsMaxExUnits suppliedExUnits) = + mkObject [ "kind" .= String "ExUnitsTooBigUTxO" + , "maxexunits" .= pParamsMaxExUnits + , "exunits" .= suppliedExUnits + ] + forMachine _dtal (Alonzo.CollateralContainsNonADA inputs) = + mkObject [ "kind" .= String "CollateralContainsNonADA" + , "inputs" .= inputs + ] + forMachine _dtal (Alonzo.WrongNetworkInTxBody actualNetworkId netIdInTxBody) = + mkObject [ "kind" .= String "WrongNetworkInTxBody" + , "networkid" .= actualNetworkId + , "txbodyNetworkId" .= netIdInTxBody + ] + forMachine _dtal (Alonzo.OutsideForecast slotNum) = + mkObject [ "kind" .= String "OutsideForecast" + , "slot" .= slotNum + ] + forMachine _dtal (Alonzo.TooManyCollateralInputs maxCollateralInputs numberCollateralInputs) = + mkObject [ "kind" .= String "TooManyCollateralInputs" + , "max" .= maxCollateralInputs + , "inputs" .= numberCollateralInputs + ] + forMachine _dtal Alonzo.NoCollateralInputs = + mkObject [ "kind" .= String "NoCollateralInputs" ] + +instance LogFormatting (Alonzo.UtxosPredicateFailure (Alonzo.AlonzoEra StandardCrypto)) where + forMachine _ (Alonzo.ValidationTagMismatch isValidating reason) = + mkObject [ "kind" .= String "ValidationTagMismatch" + , "isvalidating" .= isValidating + , "reason" .= reason + ] + forMachine _ (Alonzo.CollectErrors errors) = + mkObject [ "kind" .= String "CollectErrors" + , "errors" .= errors + ] + forMachine dtal (Alonzo.UpdateFailure pFailure) = + forMachine dtal pFailure + +instance LogFormatting (AlonzoBbodyPredFail (Alonzo.AlonzoEra StandardCrypto)) where + forMachine _ err = mkObject [ "kind" .= String "AlonzoBbodyPredFail" + , "error" .= String (show err) + ] + + +-------------------------------------------------------------------------------- +-- Helper functions +-------------------------------------------------------------------------------- + +textShow :: Show a => a -> Text +textShow = Text.pack . show + +showLastAppBlockNo :: WithOrigin (LastAppliedBlock crypto) -> Text +showLastAppBlockNo wOblk = case withOriginToMaybe wOblk of + Nothing -> "Genesis Block" + Just blk -> textShow . unBlockNo $ labBlockNo blk diff --git a/cardano-node/src/Cardano/Node/Tracing/Formatting.hs b/cardano-node/src/Cardano/Node/Tracing/Formatting.hs new file mode 100644 index 00000000000..e2aa0ef2e3d --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Formatting.hs @@ -0,0 +1,55 @@ +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Formatting + ( + ) where + +import Cardano.Prelude () +import Data.Aeson (Value (String), toJSON, (.=)) + +import Cardano.Logging (LogFormatting (..), mkObject) +import Cardano.Prelude hiding (Show, show) + +import Cardano.Node.Tracing.Render (renderHeaderHashForDetails) + +import Ouroboros.Consensus.Block (ConvertRawHash (..), RealPoint, realPointHash, + realPointSlot) +import Ouroboros.Network.Block + +-- | A bit of a weird one, but needed because some of the very general +-- consensus interfaces are sometimes instantiated to 'Void', when there are +-- no cases needed. +-- +instance LogFormatting Void where + forMachine _dtal _x = mempty + +instance LogFormatting () where + forMachine _dtal _x = mempty + +instance LogFormatting SlotNo where + forMachine _dtal slot = + mkObject [ "kind" .= String "SlotNo" + , "slot" .= toJSON (unSlotNo slot) ] + +instance forall blk. ConvertRawHash blk + => LogFormatting (Point blk) where + forMachine _dtal GenesisPoint = + mkObject + [ "kind" .= String "GenesisPoint" ] + forMachine dtal (BlockPoint slot h) = + mkObject + [ "kind" .= String "BlockPoint" + , "slot" .= toJSON (unSlotNo slot) + , "headerHash" .= renderHeaderHashForDetails (Proxy @blk) dtal h + ] + +instance ConvertRawHash blk + => LogFormatting (RealPoint blk) where + forMachine dtal p = mkObject + [ "kind" .= String "Point" + , "slot" .= unSlotNo (realPointSlot p) + , "hash" .= renderHeaderHashForDetails (Proxy @blk) dtal (realPointHash p) + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Render.hs b/cardano-node/src/Cardano/Node/Tracing/Render.hs new file mode 100644 index 00000000000..0412f71c79c --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Render.hs @@ -0,0 +1,159 @@ +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} + + +module Cardano.Node.Tracing.Render + ( renderChunkNo + , renderHeaderHash + , renderHeaderHashForDetails + , renderChainHash + , renderTipBlockNo + , renderTipHash + , condenseT + , showT + , renderPoint + , renderPointAsPhrase + , renderPointForDetails + , renderRealPoint + , renderRealPointAsPhrase + , renderSlotNo + , renderTip + , renderTipForDetails + , renderTxId + , renderTxIdForDetails + , renderWithOrigin + ) where + +import Cardano.Prelude +import Prelude (id) + +import qualified Data.ByteString.Base16 as B16 +import qualified Data.Text as Text +import qualified Data.Text.Encoding as Text + +import Cardano.Logging +import Cardano.Node.Queries (ConvertTxId (..)) +import Cardano.Slotting.Slot (SlotNo (..), WithOrigin (..)) +import Ouroboros.Consensus.Block (BlockNo (..), ConvertRawHash (..), RealPoint (..)) +import Ouroboros.Consensus.Block.Abstract (Point (..)) +import Ouroboros.Consensus.Ledger.SupportsMempool (GenTx, TxId) +import qualified Ouroboros.Consensus.Storage.ImmutableDB.API as ImmDB +import Ouroboros.Consensus.Storage.ImmutableDB.Chunks.Internal (ChunkNo (..)) +import Ouroboros.Consensus.Util.Condense (Condense, condense) +import Ouroboros.Network.Block (ChainHash (..), HeaderHash, StandardHash, Tip, + getTipPoint) + +condenseT :: Condense a => a -> Text +condenseT = Text.pack . condense + +renderChunkNo :: ChunkNo -> Text +renderChunkNo = Text.pack . show . unChunkNo + +renderTipBlockNo :: ImmDB.Tip blk -> Text +renderTipBlockNo = Text.pack . show . unBlockNo . ImmDB.tipBlockNo + +renderTipHash :: StandardHash blk => ImmDB.Tip blk -> Text +renderTipHash tInfo = Text.pack . show $ ImmDB.tipHash tInfo + +renderTxIdForDetails + :: ConvertTxId blk + => DetailLevel + -> TxId (GenTx blk) + -> Text +renderTxIdForDetails dtal = trimHashTextForDetails dtal . renderTxId + +renderTxId :: ConvertTxId blk => TxId (GenTx blk) -> Text +renderTxId = Text.decodeLatin1 . B16.encode . txIdToRawBytes + +renderWithOrigin :: (a -> Text) -> WithOrigin a -> Text +renderWithOrigin _ Origin = "origin" +renderWithOrigin render (At a) = render a + +renderSlotNo :: SlotNo -> Text +renderSlotNo = Text.pack . show . unSlotNo + +renderRealPoint + :: forall blk. + ConvertRawHash blk + => RealPoint blk + -> Text +renderRealPoint (RealPoint slotNo headerHash) = + renderHeaderHash (Proxy @blk) headerHash + <> "@" + <> renderSlotNo slotNo + +-- | Render a short phrase describing a 'RealPoint'. +-- e.g. "62292d753b2ee7e903095bc5f10b03cf4209f456ea08f55308e0aaab4350dda4 at +-- slot 39920" +renderRealPointAsPhrase + :: forall blk. + ConvertRawHash blk + => RealPoint blk + -> Text +renderRealPointAsPhrase (RealPoint slotNo headerHash) = + renderHeaderHash (Proxy @blk) headerHash + <> " at slot " + <> renderSlotNo slotNo + +renderPointForDetails + :: forall blk. + ConvertRawHash blk + => DetailLevel + -> Point blk + -> Text +renderPointForDetails dtal point = + case point of + GenesisPoint -> "genesis (origin)" + BlockPoint slot h -> + renderHeaderHashForDetails (Proxy @blk) dtal h + <> "@" + <> renderSlotNo slot + +renderPoint :: ConvertRawHash blk => Point blk -> Text +renderPoint = renderPointForDetails DDetailed + +-- | Render a short phrase describing a 'Point'. +-- e.g. "62292d753b2ee7e903095bc5f10b03cf4209f456ea08f55308e0aaab4350dda4 at +-- slot 39920" or "genesis (origin)" in the case of a genesis point. +renderPointAsPhrase :: forall blk. ConvertRawHash blk => Point blk -> Text +renderPointAsPhrase point = + case point of + GenesisPoint -> "genesis (origin)" + BlockPoint slot h -> + renderHeaderHash (Proxy @blk) h + <> " at slot " + <> renderSlotNo slot + +renderTipForDetails + :: ConvertRawHash blk + => DetailLevel + -> Tip blk + -> Text +renderTipForDetails dtal = renderPointForDetails dtal . getTipPoint + +renderTip :: ConvertRawHash blk => Tip blk -> Text +renderTip = renderTipForDetails DDetailed + +renderHeaderHashForDetails + :: ConvertRawHash blk + => proxy blk + -> DetailLevel + -> HeaderHash blk + -> Text +renderHeaderHashForDetails p dtal = + trimHashTextForDetails dtal . renderHeaderHash p + + +-- | Hex encode and render a 'HeaderHash' as text. +renderHeaderHash :: ConvertRawHash blk => proxy blk -> HeaderHash blk -> Text +renderHeaderHash p = Text.decodeLatin1 . B16.encode . toRawHash p + +renderChainHash :: (HeaderHash blk -> Text) -> ChainHash blk -> Text +renderChainHash _ GenesisHash = "GenesisHash" +renderChainHash p (BlockHash hash) = p hash + +trimHashTextForDetails :: DetailLevel -> Text -> Text +trimHashTextForDetails dtal = + case dtal of + DMinimal -> Text.take 7 + _ -> id diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers.hs new file mode 100644 index 00000000000..1e4b473d72d --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers.hs @@ -0,0 +1,711 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE PackageImports #-} +{-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} + +module Cardano.Node.Tracing.Tracers + ( mkDispatchTracers + ) where + +import Codec.CBOR.Read (DeserialiseFailure) + +import Cardano.Logging +import Cardano.Logging.Resources.Types +import Cardano.Prelude hiding (trace) + +import Cardano.Node.Tracing.Formatting () +import Cardano.Node.Tracing.Tracers.BlockReplayProgress +import Cardano.Node.Tracing.Tracers.ChainDB +import Cardano.Node.Tracing.Tracers.Consensus +import Cardano.Node.Tracing.Tracers.Diffusion +import Cardano.Node.Tracing.Tracers.ForgingThreadStats (forgeThreadStats) +import Cardano.Node.Tracing.Tracers.KESInfo +import Cardano.Node.Tracing.Tracers.NodeToClient +import Cardano.Node.Tracing.Tracers.NodeToNode +import Cardano.Node.Tracing.Tracers.NonP2P +import Cardano.Node.Tracing.Tracers.P2P +import Cardano.Node.Tracing.Tracers.Peer +import Cardano.Node.Tracing.Tracers.Shutdown +import Cardano.Node.Tracing.Tracers.Startup +import Trace.Forward.Utils.DataPoint (DataPoint) + +import Cardano.Node.Queries (NodeKernelData) +import Cardano.Node.Startup +import Cardano.Node.TraceConstraints +import Cardano.Node.Tracing +import "contra-tracer" Control.Tracer (Tracer (..)) +import Ouroboros.Consensus.Ledger.Inspect (LedgerEvent) +import Ouroboros.Consensus.MiniProtocol.ChainSync.Client (TraceChainSyncClientEvent) +import qualified Ouroboros.Consensus.Network.NodeToClient as NodeToClient +import qualified Ouroboros.Consensus.Network.NodeToClient as NtC +import qualified Ouroboros.Consensus.Network.NodeToNode as NodeToNode +import qualified Ouroboros.Consensus.Network.NodeToNode as NtN +import Ouroboros.Consensus.Node (NetworkP2PMode (..)) +import qualified Ouroboros.Consensus.Node.Run as Consensus +import qualified Ouroboros.Consensus.Node.Tracers as Consensus +import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB +import qualified Ouroboros.Consensus.Storage.LedgerDB.OnDisk as LedgerDB + +import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch +import Ouroboros.Network.ConnectionId (ConnectionId) +import qualified Ouroboros.Network.Diffusion as Diffusion +import qualified Ouroboros.Network.Diffusion.NonP2P as NonP2P +import qualified Ouroboros.Network.Diffusion.P2P as P2P +import Ouroboros.Network.NodeToClient (LocalAddress, NodeToClientVersion) +import Ouroboros.Network.NodeToNode (NodeToNodeVersion, RemoteAddress) + +-- | Construct tracers for all system components. +-- +mkDispatchTracers + :: forall blk p2p. + ( Consensus.RunNode blk + , TraceConstraints blk + + , LogFormatting (LedgerEvent blk) + , LogFormatting + (BlockFetch.TraceLabelPeer + (ConnectionId RemoteAddress) (TraceChainSyncClientEvent blk)) + ) + => NodeKernelData blk + -> Trace IO FormattedMessage + -> Trace IO FormattedMessage + -> Maybe (Trace IO FormattedMessage) + -> Trace IO DataPoint + -> TraceConfig + -> NetworkP2PMode p2p + -> IO (Tracers (ConnectionId RemoteAddress) (ConnectionId LocalAddress) blk p2p) +mkDispatchTracers nodeKernel trBase trForward mbTrEKG trDataPoint trConfig enableP2P = do + -- Some special tracers + -- NodeInfo tracer + nodeInfoTr <- mkDataPointTracer + trDataPoint + (const ["NodeInfo"]) + configureTracers trConfig docNodeInfoTraceEvent [nodeInfoTr] + + -- Resource tracer + resourcesTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Resources" + (const []) + (const Info) + allPublic + configureTracers trConfig docResourceStats [resourcesTr] + + -- BasicInfo tracer + startupTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Startup" + namesStartupInfo + (const Notice) + allPublic + configureTracers trConfig docStartupInfo [startupTr] + + shutdownTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Shutdown" + namesForShutdown + severityShutdown + allPublic + configureTracers trConfig docShutdown [shutdownTr] + + -- Peers tracer + peersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Peers" + namesForPeers + severityPeers + allPublic + configureTracers trConfig docPeers [peersTr] + + chainDBTr <- mkCardanoTracer' + trBase trForward mbTrEKG + "ChainDB" + namesForChainDBTraceEvents + severityChainDB + allPublic + withAddedToCurrentChainEmptyLimited + configureTracers trConfig docChainDBTraceEvent [chainDBTr] + + replayBlockTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ReplayBlock" + namesForReplayBlockStats + severityReplayBlockStats + allPublic + configureTracers trConfig docReplayedBlock [replayBlockTr] + + -- This tracer handles replayed blocks specially + replayBlockTr' <- withReplayedBlock replayBlockTr + -- Filter out replayed blocks for this tracer + let chainDBTr' = filterTrace + (\case (_, Nothing, ChainDB.TraceLedgerReplayEvent + LedgerDB.ReplayedBlock {}) -> False + (_, _, _) -> True) + chainDBTr + + consensusTr :: Consensus.Tracers + IO + (ConnectionId RemoteAddress) + (ConnectionId LocalAddress) + blk <- + mkConsensusTracers trBase trForward mbTrEKG trDataPoint trConfig nodeKernel + + nodeToClientTr :: NodeToClient.Tracers + IO + (ConnectionId LocalAddress) + blk + DeserialiseFailure <- + mkNodeToClientTracers trBase trForward mbTrEKG trDataPoint trConfig + + nodeToNodeTr :: NodeToNode.Tracers + IO + (ConnectionId RemoteAddress) + blk + DeserialiseFailure <- + mkNodeToNodeTracers trBase trForward mbTrEKG trDataPoint trConfig + + diffusionTr :: Diffusion.Tracers + RemoteAddress + NodeToNodeVersion + LocalAddress + NodeToClientVersion + IO <- + mkDiffusionTracers trBase trForward mbTrEKG trDataPoint trConfig + + diffusionTrExtra :: Diffusion.ExtraTracers p2p <- + mkDiffusionTracersExtra trBase trForward mbTrEKG trDataPoint trConfig enableP2P + pure Tracers + { chainDBTracer = Tracer (traceWith chainDBTr') + <> Tracer (traceWith replayBlockTr') + , consensusTracers = consensusTr + , nodeToClientTracers = nodeToClientTr + , nodeToNodeTracers = nodeToNodeTr + , diffusionTracers = diffusionTr + , diffusionTracersExtra = diffusionTrExtra + , startupTracer = Tracer (traceWith startupTr) + , shutdownTracer = Tracer (traceWith shutdownTr) + , nodeInfoTracer = Tracer (traceWith nodeInfoTr) + , resourcesTracer = Tracer (traceWith resourcesTr) + , peersTracer = Tracer (traceWith peersTr) + } + +mkConsensusTracers :: forall blk. + ( Consensus.RunNode blk + , LogFormatting (ChainDB.InvalidBlockReason blk) + , TraceConstraints blk + , LogFormatting (BlockFetch.TraceLabelPeer + (ConnectionId RemoteAddress) (TraceChainSyncClientEvent blk)) + ) + => Trace IO FormattedMessage + -> Trace IO FormattedMessage + -> Maybe (Trace IO FormattedMessage) + -> Trace IO DataPoint + -> TraceConfig + -> NodeKernelData blk + -> IO (Consensus.Tracers IO (ConnectionId RemoteAddress) (ConnectionId LocalAddress) blk) +mkConsensusTracers trBase trForward mbTrEKG _trDataPoint trConfig nodeKernel = do + chainSyncClientTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncClient" + namesForChainSyncClientEvent + severityChainSyncClientEvent + allPublic + configureTracers trConfig docChainSyncClientEvent [chainSyncClientTr] + chainSyncServerHeaderTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncServerHeader" + namesForChainSyncServerEvent + severityChainSyncServerEvent + allPublic + configureTracers trConfig docChainSyncServerEvent [chainSyncServerHeaderTr] + chainSyncServerBlockTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncServerBlock" + namesForChainSyncServerEvent + severityChainSyncServerEvent + allPublic + configureTracers trConfig docChainSyncServerEvent [chainSyncServerBlockTr] + blockFetchDecisionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetchDecision" + namesForBlockFetchDecision + severityBlockFetchDecision + allConfidential + configureTracers trConfig docBlockFetchDecision [blockFetchDecisionTr] + blockFetchClientTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetchClient" + namesForBlockFetchClient + severityBlockFetchClient + allPublic + configureTracers trConfig docBlockFetchClient [blockFetchClientTr] + blockFetchServerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetchServer" + namesForBlockFetchServer + severityBlockFetchServer + allPublic + configureTracers trConfig docBlockFetchServer [blockFetchServerTr] + forgeKESInfoTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ForgeStateInfo" + namesForKESInfo + severityKESInfo + allPublic + configureTracers trConfig docForgeKESInfo [forgeKESInfoTr] + txInboundTr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxInbound" + namesForTxInbound + severityTxInbound + allPublic + configureTracers trConfig docTxInbound [txInboundTr] + txOutboundTr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxOutbound" + namesForTxOutbound + severityTxOutbound + allPublic + configureTracers trConfig docTxOutbound [txOutboundTr] + localTxSubmissionServerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalTxSubmissionServer" + namesForLocalTxSubmissionServer + severityLocalTxSubmissionServer + allPublic + configureTracers trConfig docLocalTxSubmissionServer [localTxSubmissionServerTr] + mempoolTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Mempool" + namesForMempool + severityMempool + allPublic + configureTracers trConfig docMempool [mempoolTr] + forgeTr <- mkCardanoTracer' + trBase trForward mbTrEKG + "Forge" + namesForForge + severityForge + allPublic + (forgeTracerTransform nodeKernel) + forgeThreadStatsTr <- mkCardanoTracer' + trBase trForward mbTrEKG + "ForgeStats" + namesForForge + severityForge + allPublic + forgeThreadStats + configureTracers trConfig docForge [forgeTr, forgeThreadStatsTr] + blockchainTimeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockchainTime" + namesForBlockchainTime + severityBlockchainTime + allPublic + configureTracers trConfig docBlockchainTime [blockchainTimeTr] + keepAliveClientTr <- mkCardanoTracer + trBase trForward mbTrEKG + "KeepAliveClient" + namesForKeepAliveClient + severityKeepAliveClient + allPublic + configureTracers trConfig docKeepAliveClient [keepAliveClientTr] + pure $ Consensus.Tracers + { Consensus.chainSyncClientTracer = Tracer $ + traceWith chainSyncClientTr + , Consensus.chainSyncServerHeaderTracer = Tracer $ + traceWith chainSyncServerHeaderTr + , Consensus.chainSyncServerBlockTracer = Tracer $ + traceWith chainSyncServerBlockTr + , Consensus.blockFetchDecisionTracer = Tracer $ + traceWith blockFetchDecisionTr + , Consensus.blockFetchClientTracer = Tracer $ + traceWith blockFetchClientTr + , Consensus.blockFetchServerTracer = Tracer $ + traceWith blockFetchServerTr + , Consensus.forgeStateInfoTracer = Tracer $ + traceWith (traceAsKESInfo (Proxy @blk) forgeKESInfoTr) + , Consensus.txInboundTracer = Tracer $ + traceWith txInboundTr + , Consensus.txOutboundTracer = Tracer $ + traceWith txOutboundTr + , Consensus.localTxSubmissionServerTracer = Tracer $ + traceWith localTxSubmissionServerTr + , Consensus.mempoolTracer = Tracer $ + traceWith mempoolTr + , Consensus.forgeTracer = + Tracer (traceWith (contramap Left forgeTr)) + <> Tracer (traceWith (contramap Left forgeThreadStatsTr)) + , Consensus.blockchainTimeTracer = Tracer $ + traceWith blockchainTimeTr + , Consensus.keepAliveClientTracer = Tracer $ + traceWith keepAliveClientTr + } + +mkNodeToClientTracers :: forall blk. + Consensus.RunNode blk + => Trace IO FormattedMessage + -> Trace IO FormattedMessage + -> Maybe (Trace IO FormattedMessage) + -> Trace IO DataPoint + -> TraceConfig + -> IO (NodeToClient.Tracers IO (ConnectionId LocalAddress) blk DeserialiseFailure) +mkNodeToClientTracers trBase trForward mbTrEKG _trDataPoint trConfig = do + chainSyncTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncClient" + namesForTChainSync + severityTChainSync + allPublic + configureTracers trConfig docTChainSync [chainSyncTr] + txSubmissionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxSubmissionClient" + namesForTTxSubmission + severityTTxSubmission + allPublic + configureTracers trConfig docTTxSubmission [txSubmissionTr] + stateQueryTr <- mkCardanoTracer + trBase trForward mbTrEKG + "StateQueryClient" + namesForTStateQuery + severityTStateQuery + allPublic + configureTracers trConfig docTStateQuery [stateQueryTr] + pure $ NtC.Tracers + { NtC.tChainSyncTracer = Tracer $ + traceWith chainSyncTr + , NtC.tTxSubmissionTracer = Tracer $ + traceWith txSubmissionTr + , NtC.tStateQueryTracer = Tracer $ + traceWith stateQueryTr + } + +mkNodeToNodeTracers :: forall blk. + ( Consensus.RunNode blk + , TraceConstraints blk) + => Trace IO FormattedMessage + -> Trace IO FormattedMessage + -> Maybe (Trace IO FormattedMessage) + -> Trace IO DataPoint + -> TraceConfig + -> IO (NodeToNode.Tracers IO (ConnectionId RemoteAddress) blk DeserialiseFailure) +mkNodeToNodeTracers trBase trForward mbTrEKG _trDataPoint trConfig = do + chainSyncTracer <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncNode" + namesForTChainSyncNode + severityTChainSyncNode + allPublic + configureTracers trConfig docTChainSync [chainSyncTracer] + chainSyncSerialisedTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ChainSyncSerialised" + namesForTChainSyncSerialised + severityTChainSyncSerialised + allPublic + configureTracers trConfig docTChainSync [chainSyncSerialisedTr] + blockFetchTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetch" + namesForTBlockFetch + severityTBlockFetch + allPublic + configureTracers trConfig docTBlockFetch [blockFetchTr] + blockFetchSerialisedTr <- mkCardanoTracer + trBase trForward mbTrEKG + "BlockFetchSerialised" + namesForTBlockFetchSerialised + severityTBlockFetchSerialised + allPublic + configureTracers trConfig docTBlockFetch [blockFetchSerialisedTr] + txSubmissionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "TxSubmission" + namesForTxSubmissionNode + severityTxSubmissionNode + allPublic + configureTracers trConfig docTTxSubmissionNode [txSubmissionTr] + txSubmission2Tracer <- mkCardanoTracer + trBase trForward mbTrEKG + "TxSubmission2" + namesForTxSubmission2Node + severityTxSubmission2Node + allPublic + configureTracers trConfig docTTxSubmission2Node [txSubmission2Tracer] + pure $ NtN.Tracers + { NtN.tChainSyncTracer = Tracer $ + traceWith chainSyncTracer + , NtN.tChainSyncSerialisedTracer = Tracer $ + traceWith chainSyncSerialisedTr + , NtN.tBlockFetchTracer = Tracer $ + traceWith blockFetchTr + , NtN.tBlockFetchSerialisedTracer = Tracer $ + traceWith blockFetchSerialisedTr + , NtN.tTxSubmissionTracer = Tracer $ + traceWith txSubmissionTr + , NtN.tTxSubmission2Tracer = Tracer $ + traceWith txSubmission2Tracer + } + +mkDiffusionTracers + :: Trace IO FormattedMessage + -> Trace IO FormattedMessage + -> Maybe (Trace IO FormattedMessage) + -> Trace IO DataPoint + -> TraceConfig + -> IO (Diffusion.Tracers RemoteAddress NodeToNodeVersion + LocalAddress NodeToClientVersion IO) +mkDiffusionTracers trBase trForward mbTrEKG _trDataPoint trConfig = do + dtMuxTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Mux" + namesForMux + severityMux + allPublic + configureTracers trConfig docMuxRemote [dtMuxTr] + dtLocalMuxTr <- mkCardanoTracer + trBase trForward mbTrEKG + "MuxLocal" + namesForMux + severityMux + allPublic + configureTracers trConfig docMuxLocal [dtLocalMuxTr] + dtHandshakeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Handshake" + namesForHandshake + severityHandshake + allPublic + configureTracers trConfig docHandshake [dtHandshakeTr] + dtLocalHandshakeTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalHandshake" + namesForLocalHandshake + severityLocalHandshake + allPublic + configureTracers trConfig docLocalHandshake [dtLocalHandshakeTr] + dtDiffusionInitializationTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DiffusionInit" + namesForDiffusionInit + severityDiffusionInit + allPublic + configureTracers trConfig docDiffusionInit [dtDiffusionInitializationTr] + dtLedgerPeersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LedgerPeers" + namesForLedgerPeers + severityLedgerPeers + allPublic + configureTracers trConfig docLedgerPeers [dtLedgerPeersTr] + pure $ Diffusion.Tracers + { Diffusion.dtMuxTracer = Tracer $ + traceWith dtMuxTr + , Diffusion.dtHandshakeTracer = Tracer $ + traceWith dtHandshakeTr + , Diffusion.dtLocalMuxTracer = Tracer $ + traceWith dtLocalMuxTr + , Diffusion.dtLocalHandshakeTracer = Tracer $ + traceWith dtLocalHandshakeTr + , Diffusion.dtDiffusionInitializationTracer = Tracer $ + traceWith dtDiffusionInitializationTr + , Diffusion.dtLedgerPeersTracer = Tracer $ + traceWith dtLedgerPeersTr + } + +mkDiffusionTracersExtra :: forall p2p. + Trace IO FormattedMessage + -> Trace IO FormattedMessage + -> Maybe (Trace IO FormattedMessage) + -> Trace IO DataPoint + -> TraceConfig + -> NetworkP2PMode p2p + -> IO (Diffusion.ExtraTracers p2p) +mkDiffusionTracersExtra trBase trForward mbTrEKG _trDataPoint trConfig EnabledP2PMode = do + localRootPeersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalRootPeers" + namesForLocalRootPeers + severityLocalRootPeers + allPublic + configureTracers trConfig docLocalRootPeers [localRootPeersTr] + publicRootPeersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "PublicRootPeers" + namesForPublicRootPeers + severityPublicRootPeers + allPublic + configureTracers trConfig docPublicRootPeers [publicRootPeersTr] + peerSelectionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "PeerSelection" + namesForPeerSelection + severityPeerSelection + allPublic + configureTracers trConfig docPeerSelection [peerSelectionTr] + debugPeerSelectionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DebugPeerSelection" + namesForDebugPeerSelection + severityDebugPeerSelection + allPublic + configureTracers trConfig docDebugPeerSelection [debugPeerSelectionTr] + debugPeerSelectionResponderTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DebugPeerSelectionResponder" + namesForDebugPeerSelection + severityDebugPeerSelection + allPublic + configureTracers trConfig docDebugPeerSelection [debugPeerSelectionResponderTr] + peerSelectionCountersTr <- mkCardanoTracer + trBase trForward mbTrEKG + "PeerSelectionCounters" + namesForPeerSelectionCounters + severityPeerSelectionCounters + allPublic + configureTracers trConfig docPeerSelectionCounters [peerSelectionCountersTr] + peerSelectionActionsTr <- mkCardanoTracer + trBase trForward mbTrEKG + "PeerSelectionActions" + namesForPeerSelectionActions + severityPeerSelectionActions + allPublic + configureTracers trConfig docPeerSelectionActions [peerSelectionActionsTr] + connectionManagerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ConnectionManager" + namesForConnectionManager + severityConnectionManager + allPublic + configureTracers trConfig docConnectionManager [connectionManagerTr] + serverTr <- mkCardanoTracer + trBase trForward mbTrEKG + "Server" + namesForServer + severityServer + allPublic + configureTracers trConfig docServer [serverTr] + inboundGovernorTr <- mkCardanoTracer + trBase trForward mbTrEKG + "InboundGovernor" + namesForInboundGovernor + severityInboundGovernor + allPublic + configureTracers trConfig docInboundGovernorRemote [inboundGovernorTr] + localConnectionManagerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalConnectionManager" + namesForConnectionManager + severityConnectionManager + allPublic + configureTracers trConfig docConnectionManager [localConnectionManagerTr] + localServerTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalServer" + namesForServer + severityServer + allPublic + configureTracers trConfig docServer [localServerTr] + localInboundGovernorTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalInboundGovernor" + namesForInboundGovernor + severityInboundGovernor + allPublic + configureTracers trConfig docInboundGovernorLocal [localInboundGovernorTr] + pure $ Diffusion.P2PTracers P2P.TracersExtra + { P2P.dtTraceLocalRootPeersTracer = Tracer $ + traceWith localRootPeersTr + , P2P.dtTracePublicRootPeersTracer = Tracer $ + traceWith publicRootPeersTr + , P2P.dtTracePeerSelectionTracer = Tracer $ + traceWith peerSelectionTr + , P2P.dtDebugPeerSelectionInitiatorTracer = Tracer $ + traceWith debugPeerSelectionTr + , P2P.dtDebugPeerSelectionInitiatorResponderTracer = Tracer $ + traceWith debugPeerSelectionResponderTr + , P2P.dtTracePeerSelectionCounters = Tracer $ + traceWith peerSelectionCountersTr + , P2P.dtPeerSelectionActionsTracer = Tracer $ + traceWith peerSelectionActionsTr + , P2P.dtConnectionManagerTracer = Tracer $ + traceWith connectionManagerTr + , P2P.dtConnectionManagerTransitionTracer = mempty + --TODO Add transition tracers later + , P2P.dtServerTracer = Tracer $ + traceWith serverTr + , P2P.dtInboundGovernorTracer = Tracer $ + traceWith inboundGovernorTr + , P2P.dtInboundGovernorTransitionTracer = mempty + --TODO Add transition tracers later + , P2P.dtLocalConnectionManagerTracer = Tracer $ + traceWith localConnectionManagerTr + , P2P.dtLocalServerTracer = Tracer $ + traceWith localServerTr + , P2P.dtLocalInboundGovernorTracer = Tracer $ + traceWith localInboundGovernorTr + } + +mkDiffusionTracersExtra trBase trForward mbTrEKG _trDataPoint trConfig DisabledP2PMode = do + dtIpSubscriptionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "IpSubscription" + namesForIPSubscription + severityIPSubscription + allPublic + configureTracers trConfig docIPSubscription [dtIpSubscriptionTr] + dtDnsSubscriptionTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DNSSubscription" + namesForDNSSubscription + severityDNSSubscription + allPublic + configureTracers trConfig docDNSSubscription [dtDnsSubscriptionTr] + dtDnsResolverTr <- mkCardanoTracer + trBase trForward mbTrEKG + "DNSResolver" + namesForDNSResolver + severityDNSResolver + allPublic + configureTracers trConfig docDNSResolver [dtDnsResolverTr] + dtErrorPolicyTr <- mkCardanoTracer + trBase trForward mbTrEKG + "ErrorPolicy" + namesForErrorPolicy + severityErrorPolicy + allPublic + configureTracers trConfig docErrorPolicy [dtErrorPolicyTr] + dtLocalErrorPolicyTr <- mkCardanoTracer + trBase trForward mbTrEKG + "LocalErrorPolicy" + namesForLocalErrorPolicy + severityLocalErrorPolicy + allPublic + configureTracers trConfig docLocalErrorPolicy [dtLocalErrorPolicyTr] + dtAcceptPolicyTr <- mkCardanoTracer + trBase trForward mbTrEKG + "AcceptPolicy" + namesForAcceptPolicy + severityAcceptPolicy + allPublic + configureTracers trConfig docAcceptPolicy [dtAcceptPolicyTr] + pure $ Diffusion.NonP2PTracers NonP2P.TracersExtra + { NonP2P.dtIpSubscriptionTracer = Tracer $ + traceWith dtIpSubscriptionTr + , NonP2P.dtDnsSubscriptionTracer = Tracer $ + traceWith dtDnsSubscriptionTr + , NonP2P.dtDnsResolverTracer = Tracer $ + traceWith dtDnsResolverTr + , NonP2P.dtErrorPolicyTracer = Tracer $ + traceWith dtErrorPolicyTr + , NonP2P.dtLocalErrorPolicyTracer = Tracer $ + traceWith dtLocalErrorPolicyTr + , NonP2P.dtAcceptPolicyTracer = Tracer $ + traceWith dtAcceptPolicyTr + } diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/BlockReplayProgress.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/BlockReplayProgress.hs new file mode 100644 index 00000000000..597676d4062 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/BlockReplayProgress.hs @@ -0,0 +1,88 @@ +{-# LANGUAGE RecordWildCards #-} + +module Cardano.Node.Tracing.Tracers.BlockReplayProgress + ( severityReplayBlockStats + , namesForReplayBlockStats + , withReplayedBlock + , docReplayedBlock + , ReplayBlockStats(..) + ) where + +import Data.Aeson (Value (String), (.=)) +import Data.Text (pack) + +import Cardano.Logging +import Cardano.Prelude + +import Ouroboros.Consensus.Block (realPointSlot) +import Ouroboros.Network.Block (pointSlot, unSlotNo) +import Ouroboros.Network.Point (withOrigin) + +import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB +import qualified Ouroboros.Consensus.Storage.LedgerDB.OnDisk as LedgerDB + +data ReplayBlockStats = ReplayBlockStats + { rpsDisplay :: Bool + , rpsProgress :: Double + , rpsLastProgress :: Double + } + +emptyReplayBlockStats :: ReplayBlockStats +emptyReplayBlockStats = ReplayBlockStats False 0.0 0.0 + +-------------------------------------------------------------------------------- +-- ReplayBlockStats Tracer +-------------------------------------------------------------------------------- + +namesForReplayBlockStats :: ReplayBlockStats -> Namespace +namesForReplayBlockStats _ = ["LedgerReplay"] + +severityReplayBlockStats :: ReplayBlockStats -> SeverityS +severityReplayBlockStats _ = Info + +instance LogFormatting ReplayBlockStats where + forMachine _dtal ReplayBlockStats {..} = + mkObject + [ "kind" .= String "ReplayBlockStats" + , "progress" .= String (pack $ show rpsProgress) + ] + forHuman ReplayBlockStats {..} = "Block replay progress " <> show rpsProgress <> "%" + asMetrics ReplayBlockStats {..} = + [DoubleM "Block replay progress (%)" rpsProgress] + +docReplayedBlock :: Documented ReplayBlockStats +docReplayedBlock = Documented [ + DocMsg + emptyReplayBlockStats + [("Block replay progress (%)", + "Progress in percent")] + "Counts up the percent of a block replay." + ] + +withReplayedBlock :: Trace IO ReplayBlockStats + -> IO (Trace IO (ChainDB.TraceEvent blk)) +withReplayedBlock tr = + let tr' = filterTrace filterFunction tr + tr'' = contramap unfold tr' + in foldMTraceM replayBlockStats emptyReplayBlockStats tr'' + where + filterFunction(_, Just _, _) = True + filterFunction(_, Nothing, ReplayBlockStats {..}) = rpsDisplay + +replayBlockStats :: MonadIO m + => ReplayBlockStats + -> LoggingContext + -> Maybe TraceControl + -> ChainDB.TraceEvent blk + -> m ReplayBlockStats +replayBlockStats ReplayBlockStats {..} _context _mbCtrl + (ChainDB.TraceLedgerReplayEvent (LedgerDB.ReplayedBlock pt [] + (LedgerDB.ReplayStart replayTo) _)) = do + let slotno = toInteger $ unSlotNo (realPointSlot pt) + endslot = toInteger $ withOrigin 0 unSlotNo (pointSlot replayTo) + progress' = (fromInteger slotno * 100.0) / fromInteger (max slotno endslot) + pure $ if (progress' == 0.0 && not rpsDisplay) + || ((progress' - rpsLastProgress) > 1.0) + then ReplayBlockStats True progress' progress' + else ReplayBlockStats False progress' rpsLastProgress +replayBlockStats st@ReplayBlockStats {} _context _mbCtrl _ = pure st diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/ChainDB.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/ChainDB.hs new file mode 100644 index 00000000000..6c71b6cd8dc --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/ChainDB.hs @@ -0,0 +1,1761 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.ChainDB + ( severityChainDB + , namesForChainDBTraceEvents + , withAddedToCurrentChainEmptyLimited + , docChainDBTraceEvent + ) where + +import Data.Aeson (Value (String), toJSON, (.=)) +import qualified Data.Aeson as A +import Data.HashMap.Strict (insertWith) +import qualified Data.Text as Text +import qualified Data.Text.Encoding as Text +import Numeric (showFFloat) +import Prelude (id) +import Text.Show + +import Cardano.Logging +import Cardano.Node.Tracing.Era.Byron () +import Cardano.Node.Tracing.Era.Shelley () +import Cardano.Node.Tracing.Formatting () +import Cardano.Node.Tracing.Render +import Cardano.Prelude hiding (Show, show, trace) + +import Ouroboros.Consensus.Block +import Ouroboros.Consensus.HeaderValidation (HeaderEnvelopeError (..), HeaderError (..), + OtherHeaderEnvelopeError) +import Ouroboros.Consensus.Ledger.Abstract (LedgerError) +import Ouroboros.Consensus.Ledger.Extended (ExtValidationError (..)) +import Ouroboros.Consensus.Ledger.Inspect (InspectLedger, LedgerEvent (..)) +import Ouroboros.Consensus.Ledger.SupportsProtocol (LedgerSupportsProtocol) +import Ouroboros.Consensus.Protocol.Abstract (ValidationErr) +import qualified Ouroboros.Consensus.Protocol.PBFT as PBFT +import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB +import qualified Ouroboros.Consensus.Storage.ImmutableDB as ImmDB +import Ouroboros.Consensus.Storage.ImmutableDB.Chunks.Internal (chunkNoToInt) +import qualified Ouroboros.Consensus.Storage.ImmutableDB.Impl.Types as ImmDB +import qualified Ouroboros.Consensus.Storage.LedgerDB.OnDisk as LedgerDB +import Ouroboros.Consensus.Storage.LedgerDB.Types (UpdateLedgerDbTraceEvent (..)) +import qualified Ouroboros.Consensus.Storage.LedgerDB.Types as LedgerDB +import qualified Ouroboros.Consensus.Storage.VolatileDB as VolDB +import qualified Ouroboros.Consensus.Storage.VolatileDB.Impl as VolDb +import Ouroboros.Consensus.Util.Condense (condense) + +import qualified Ouroboros.Network.AnchoredFragment as AF + +{-# ANN module ("HLint: ignore Redundant bracket" :: Text) #-} + +withAddedToCurrentChainEmptyLimited + :: Trace IO (ChainDB.TraceEvent blk) + -> IO (Trace IO (ChainDB.TraceEvent blk)) +withAddedToCurrentChainEmptyLimited tr = do + ltr <- limitFrequency 1.25 "AddedToCurrentChainLimiter" tr mempty + routingTrace (selecting ltr) tr + where + selecting + ltr + (ChainDB.TraceAddBlockEvent (ChainDB.AddedToCurrentChain events _ _ _)) = + if null events + then pure ltr + else pure tr + selecting _ _ = pure tr + +kindContext :: Text -> A.Object -> A.Object +kindContext toAdd = insertWith f "kind" (String toAdd) + where + f (String new) (String old) = String (new <> "." <> old) + f (String new) _ = String new + f _ o = o + +-------------------------------------------------------------------------------- +-- ChainDB Tracer +-------------------------------------------------------------------------------- + +severityChainDB :: ChainDB.TraceEvent blk -> SeverityS +severityChainDB (ChainDB.TraceAddBlockEvent v) = sevTraceAddBlockEvent v +severityChainDB (ChainDB.TraceFollowerEvent v) = sevTraceFollowerEvent v +severityChainDB (ChainDB.TraceCopyToImmutableDBEvent v) = sevTraceCopyToImmutableDBEvent v +severityChainDB (ChainDB.TraceGCEvent v) = sevTraceGCEvent v +severityChainDB (ChainDB.TraceInitChainSelEvent v) = sevTraceInitChainSelEvent v +severityChainDB (ChainDB.TraceOpenEvent v) = sevTraceOpenEvent v +severityChainDB (ChainDB.TraceIteratorEvent v) = sevTraceIteratorEvent v +severityChainDB (ChainDB.TraceLedgerEvent v) = sevTraceLedgerEvent v +severityChainDB (ChainDB.TraceLedgerReplayEvent v) = sevTraceLedgerReplayEvent v +severityChainDB (ChainDB.TraceImmutableDBEvent v) = sevTraceImmutableDBEvent v +severityChainDB (ChainDB.TraceVolatileDBEvent v) = sevTraceVolatileDBEvent v + +namesForChainDBTraceEvents :: ChainDB.TraceEvent blk -> [Text] +namesForChainDBTraceEvents (ChainDB.TraceAddBlockEvent ev) = + "AddBlockEvent" : namesForChainDBAddBlock ev +namesForChainDBTraceEvents (ChainDB.TraceFollowerEvent ev) = + "FollowerEvent" : namesForChainDBFollower ev +namesForChainDBTraceEvents (ChainDB.TraceCopyToImmutableDBEvent ev) = + "CopyToImmutableDBEvent" : namesForChainDBCopyToImmutable ev +namesForChainDBTraceEvents (ChainDB.TraceGCEvent ev) = + "GCEvent" : namesForChainDBGCEvent ev +namesForChainDBTraceEvents (ChainDB.TraceInitChainSelEvent ev) = + "InitChainSelEvent" : namesForInitChainSel ev +namesForChainDBTraceEvents (ChainDB.TraceOpenEvent ev) = + "OpenEvent" : namesForChainDBOpenEvent ev +namesForChainDBTraceEvents (ChainDB.TraceIteratorEvent ev) = + "IteratorEvent" : namesForChainDBIteratorEvent ev +namesForChainDBTraceEvents (ChainDB.TraceLedgerEvent ev) = + "LedgerEvent" : namesForChainDBLedgerEvent ev +namesForChainDBTraceEvents (ChainDB.TraceLedgerReplayEvent ev) = + "LedgerEvent" : namesForChainDBLedgerReplayEvent ev +namesForChainDBTraceEvents (ChainDB.TraceImmutableDBEvent ev) = + "ImmDbEvent" : namesForChainDBImmutableDBEvent ev +namesForChainDBTraceEvents (ChainDB.TraceVolatileDBEvent ev) = + "VolatileDbEvent" : namesForChainDBVolatileDBEvent ev + + +instance ( LogFormatting (Header blk) + , LogFormatting (LedgerEvent blk) + , LogFormatting (RealPoint blk) + , ConvertRawHash blk + , ConvertRawHash (Header blk) + , HasHeader (Header blk) + , LedgerSupportsProtocol blk + , InspectLedger blk + ) => LogFormatting (ChainDB.TraceEvent blk) where + forHuman (ChainDB.TraceAddBlockEvent v) = forHuman v + forHuman (ChainDB.TraceFollowerEvent v) = forHuman v + forHuman (ChainDB.TraceCopyToImmutableDBEvent v) = forHuman v + forHuman (ChainDB.TraceGCEvent v) = forHuman v + forHuman (ChainDB.TraceInitChainSelEvent v) = forHuman v + forHuman (ChainDB.TraceOpenEvent v) = forHuman v + forHuman (ChainDB.TraceIteratorEvent v) = forHuman v + forHuman (ChainDB.TraceLedgerEvent v) = forHuman v + forHuman (ChainDB.TraceLedgerReplayEvent v) = forHuman v + forHuman (ChainDB.TraceImmutableDBEvent v) = forHuman v + forHuman (ChainDB.TraceVolatileDBEvent v) = forHuman v + + forMachine details (ChainDB.TraceAddBlockEvent v) = + kindContext "AddBlockEvent" $ forMachine details v + forMachine details (ChainDB.TraceFollowerEvent v) = + kindContext "FollowerEvent" $ forMachine details v + forMachine details (ChainDB.TraceCopyToImmutableDBEvent v) = + kindContext "CopyToImmutableDBEvent" $ forMachine details v + forMachine details (ChainDB.TraceGCEvent v) = + kindContext "TraceGCEvent" $ forMachine details v + forMachine details (ChainDB.TraceInitChainSelEvent v) = + kindContext "InitChainSelEvent" $ forMachine details v + forMachine details (ChainDB.TraceOpenEvent v) = + kindContext "OpenEvent" $ forMachine details v + forMachine details (ChainDB.TraceIteratorEvent v) = + kindContext "IteratorEvent" $ forMachine details v + forMachine details (ChainDB.TraceLedgerEvent v) = + kindContext "LedgerEvent" $ forMachine details v + forMachine details (ChainDB.TraceLedgerReplayEvent v) = + kindContext "LedgerReplayEvent" $ forMachine details v + forMachine details (ChainDB.TraceImmutableDBEvent v) = + kindContext "ImmDbEvent" $ forMachine details v + forMachine details (ChainDB.TraceVolatileDBEvent v) = + kindContext "VolatileDBEvent" $ forMachine details v + + asMetrics (ChainDB.TraceAddBlockEvent v) = asMetrics v + asMetrics (ChainDB.TraceFollowerEvent v) = asMetrics v + asMetrics (ChainDB.TraceCopyToImmutableDBEvent v) = asMetrics v + asMetrics (ChainDB.TraceGCEvent v) = asMetrics v + asMetrics (ChainDB.TraceInitChainSelEvent v) = asMetrics v + asMetrics (ChainDB.TraceOpenEvent v) = asMetrics v + asMetrics (ChainDB.TraceIteratorEvent v) = asMetrics v + asMetrics (ChainDB.TraceLedgerEvent v) = asMetrics v + asMetrics (ChainDB.TraceLedgerReplayEvent v) = asMetrics v + asMetrics (ChainDB.TraceImmutableDBEvent v) = asMetrics v + asMetrics (ChainDB.TraceVolatileDBEvent v) = asMetrics v + +docChainDBTraceEvent :: Documented (ChainDB.TraceEvent blk) +docChainDBTraceEvent = Documented $ + mapDoc ChainDB.TraceAddBlockEvent docChainDBAddBlock + <> mapDoc ChainDB.TraceFollowerEvent docChainDBFollower + <> mapDoc ChainDB.TraceCopyToImmutableDBEvent docChainDBImmtable + <> mapDoc ChainDB.TraceGCEvent docChainDBGCEvent + <> mapDoc ChainDB.TraceInitChainSelEvent docChainDBInitChainSel + <> mapDoc ChainDB.TraceOpenEvent docChainDBOpenEvent + <> mapDoc ChainDB.TraceIteratorEvent docChainDBIteratorEvent + <> mapDoc ChainDB.TraceLedgerEvent docChainDBLedgerEvent + <> mapDoc ChainDB.TraceLedgerReplayEvent docChainDBLedgerReplayEvent + <> mapDoc ChainDB.TraceImmutableDBEvent docChainDBImmutableDBEvent + <> mapDoc ChainDB.TraceVolatileDBEvent docChainDBVolatileDBEvent + +-------------------------------------------------------------------------------- +-- AddBlockEvent +-------------------------------------------------------------------------------- + +sevTraceAddBlockEvent :: ChainDB.TraceAddBlockEvent blk -> SeverityS +sevTraceAddBlockEvent ChainDB.IgnoreBlockOlderThanK {} = Info +sevTraceAddBlockEvent ChainDB.IgnoreBlockAlreadyInVolatileDB {} = Info +sevTraceAddBlockEvent ChainDB.IgnoreInvalidBlock {} = Info +sevTraceAddBlockEvent ChainDB.AddedBlockToQueue {} = Debug +sevTraceAddBlockEvent ChainDB.BlockInTheFuture {} = Info +sevTraceAddBlockEvent ChainDB.AddedBlockToVolatileDB {} = Debug +sevTraceAddBlockEvent ChainDB.TryAddToCurrentChain {} = Debug +sevTraceAddBlockEvent ChainDB.TrySwitchToAFork {} = Info +sevTraceAddBlockEvent ChainDB.StoreButDontChange {} = Debug +sevTraceAddBlockEvent (ChainDB.AddedToCurrentChain events _ _ _) = + maximumDef Notice (map sevLedgerEvent events) +sevTraceAddBlockEvent (ChainDB.SwitchedToAFork events _ _ _) = + maximumDef Notice (map sevLedgerEvent events) +sevTraceAddBlockEvent (ChainDB.AddBlockValidation ev') = sevTraceValidationEvent ev' +sevTraceAddBlockEvent ChainDB.ChainSelectionForFutureBlock{} = Debug + +sevLedgerEvent :: LedgerEvent blk -> SeverityS +sevLedgerEvent (LedgerUpdate _) = Notice +sevLedgerEvent (LedgerWarning _) = Critical + +sevTraceValidationEvent :: ChainDB.TraceValidationEvent blk -> SeverityS +sevTraceValidationEvent ChainDB.InvalidBlock {} = Error +sevTraceValidationEvent ChainDB.ValidCandidate {} = Info +sevTraceValidationEvent ChainDB.CandidateContainsFutureBlocks {} = Debug +sevTraceValidationEvent ChainDB.UpdateLedgerDbTraceEvent {} = Debug +sevTraceValidationEvent ChainDB.CandidateContainsFutureBlocksExceedingClockSkew{} = Error + +namesForChainDBAddBlock :: ChainDB.TraceAddBlockEvent blk -> [Text] +namesForChainDBAddBlock (ChainDB.IgnoreBlockOlderThanK _) = + ["IgnoreBlockOlderThanK"] +namesForChainDBAddBlock (ChainDB.IgnoreBlockAlreadyInVolatileDB _) = + ["IgnoreBlockAlreadyInVolatileDB"] +namesForChainDBAddBlock (ChainDB.IgnoreInvalidBlock {}) = + ["IgnoreBlockAlreadyInVolatileDB"] +namesForChainDBAddBlock (ChainDB.AddedBlockToQueue {}) = + ["AddedBlockToQueue"] +namesForChainDBAddBlock (ChainDB.BlockInTheFuture {}) = + ["BlockInTheFuture"] +namesForChainDBAddBlock (ChainDB.AddedBlockToVolatileDB {}) = + ["AddedBlockToVolatileDB"] +namesForChainDBAddBlock (ChainDB.TryAddToCurrentChain {}) = + ["TryAddToCurrentChain"] +namesForChainDBAddBlock (ChainDB.TrySwitchToAFork {}) = + ["TrySwitchToAFork"] +namesForChainDBAddBlock (ChainDB.StoreButDontChange {}) = + ["StoreButDontChange"] +namesForChainDBAddBlock (ChainDB.AddedToCurrentChain {}) = + ["AddedToCurrentChain"] +namesForChainDBAddBlock (ChainDB.SwitchedToAFork {}) = + ["SwitchedToAFork"] +namesForChainDBAddBlock (ChainDB.AddBlockValidation ev') = + "AddBlockValidation" : namesForChainDBAddBlockValidation ev' +namesForChainDBAddBlock (ChainDB.ChainSelectionForFutureBlock {}) = + ["ChainSelectionForFutureBlock"] + +namesForChainDBAddBlockValidation :: ChainDB.TraceValidationEvent blk -> [Text] +namesForChainDBAddBlockValidation (ChainDB.ValidCandidate {}) = + ["ValidCandidate"] +namesForChainDBAddBlockValidation (ChainDB.CandidateContainsFutureBlocks {}) = + ["CandidateContainsFutureBlocks"] +namesForChainDBAddBlockValidation (ChainDB.CandidateContainsFutureBlocksExceedingClockSkew {}) = + ["CandidateContainsFutureBlocksExceedingClockSkew"] +namesForChainDBAddBlockValidation (ChainDB.InvalidBlock {}) = + ["InvalidBlock"] +namesForChainDBAddBlockValidation (ChainDB.UpdateLedgerDbTraceEvent {}) = + ["UpdateLedgerDb"] + +instance ( LogFormatting (Header blk) + , LogFormatting (LedgerEvent blk) + , LogFormatting (RealPoint blk) + , ConvertRawHash blk + , ConvertRawHash (Header blk) + , HasHeader (Header blk) + , LedgerSupportsProtocol blk + , InspectLedger blk + ) => LogFormatting (ChainDB.TraceAddBlockEvent blk) where + forHuman (ChainDB.IgnoreBlockOlderThanK pt) = + "Ignoring block older than K: " <> renderRealPointAsPhrase pt + forHuman (ChainDB.IgnoreBlockAlreadyInVolatileDB pt) = + "Ignoring block already in DB: " <> renderRealPointAsPhrase pt + forHuman (ChainDB.IgnoreInvalidBlock pt _reason) = + "Ignoring previously seen invalid block: " <> renderRealPointAsPhrase pt + forHuman (ChainDB.AddedBlockToQueue pt sz) = + "Block added to queue: " <> renderRealPointAsPhrase pt <> " queue size " <> condenseT sz + forHuman (ChainDB.BlockInTheFuture pt slot) = + "Ignoring block from future: " <> renderRealPointAsPhrase pt <> ", slot " <> condenseT slot + forHuman (ChainDB.StoreButDontChange pt) = + "Ignoring block: " <> renderRealPointAsPhrase pt + forHuman (ChainDB.TryAddToCurrentChain pt) = + "Block fits onto the current chain: " <> renderRealPointAsPhrase pt + forHuman (ChainDB.TrySwitchToAFork pt _) = + "Block fits onto some fork: " <> renderRealPointAsPhrase pt + forHuman (ChainDB.AddedToCurrentChain es _ _ c) = + "Chain extended, new tip: " <> renderPointAsPhrase (AF.headPoint c) <> + Text.concat [ "\nEvent: " <> showT e | e <- es ] + forHuman (ChainDB.SwitchedToAFork es _ _ c) = + "Switched to a fork, new tip: " <> renderPointAsPhrase (AF.headPoint c) <> + Text.concat [ "\nEvent: " <> showT e | e <- es ] + forHuman (ChainDB.AddBlockValidation ev') = forHuman ev' + forHuman (ChainDB.AddedBlockToVolatileDB pt _ _) = + "Chain added block " <> renderRealPointAsPhrase pt + forHuman (ChainDB.ChainSelectionForFutureBlock pt) = + "Chain selection run for block previously from future: " <> renderRealPointAsPhrase pt + + forMachine dtal (ChainDB.IgnoreBlockOlderThanK pt) = + mkObject [ "kind" .= String "IgnoreBlockOlderThanK" + , "block" .= forMachine dtal pt ] + forMachine dtal (ChainDB.IgnoreBlockAlreadyInVolatileDB pt) = + mkObject [ "kind" .= String "IgnoreBlockAlreadyInVolatileDB" + , "block" .= forMachine dtal pt ] + forMachine dtal (ChainDB.IgnoreInvalidBlock pt reason) = + mkObject [ "kind" .= String "IgnoreInvalidBlock" + , "block" .= forMachine dtal pt + , "reason" .= showT reason ] + forMachine dtal (ChainDB.AddedBlockToQueue pt sz) = + mkObject [ "kind" .= String "AddedBlockToQueue" + , "block" .= forMachine dtal pt + , "queueSize" .= toJSON sz ] + forMachine dtal (ChainDB.BlockInTheFuture pt slot) = + mkObject [ "kind" .= String "BlockInTheFuture" + , "block" .= forMachine dtal pt + , "slot" .= forMachine dtal slot ] + forMachine dtal (ChainDB.StoreButDontChange pt) = + mkObject [ "kind" .= String "StoreButDontChange" + , "block" .= forMachine dtal pt ] + forMachine dtal (ChainDB.TryAddToCurrentChain pt) = + mkObject [ "kind" .= String "TryAddToCurrentChain" + , "block" .= forMachine dtal pt ] + forMachine dtal (ChainDB.TrySwitchToAFork pt _) = + mkObject [ "kind" .= String "TraceAddBlockEvent.TrySwitchToAFork" + , "block" .= forMachine dtal pt ] + forMachine dtal (ChainDB.AddedToCurrentChain events _ base extended) = + mkObject $ + [ "kind" .= String "AddedToCurrentChain" + , "newtip" .= renderPointForDetails dtal (AF.headPoint extended) + ] + ++ [ "headers" .= toJSON (forMachine dtal `map` addedHdrsNewChain base extended) + | dtal == DDetailed ] + ++ [ "events" .= toJSON (map (forMachine dtal) events) + | not (null events) ] + forMachine dtal (ChainDB.SwitchedToAFork events _ old new) = + mkObject $ + [ "kind" .= String "TraceAddBlockEvent.SwitchedToAFork" + , "newtip" .= renderPointForDetails dtal (AF.headPoint new) + ] + ++ [ "headers" .= toJSON (forMachine dtal `map` addedHdrsNewChain old new) + | dtal == DDetailed ] + ++ [ "events" .= toJSON (map (forMachine dtal) events) + | not (null events) ] + forMachine dtal (ChainDB.AddBlockValidation ev') = + kindContext "AddBlockEvent" $ forMachine dtal ev' + forMachine dtal (ChainDB.AddedBlockToVolatileDB pt (BlockNo bn) _) = + mkObject [ "kind" .= String "AddedBlockToVolatileDB" + , "block" .= forMachine dtal pt + , "blockNo" .= showT bn ] + forMachine dtal (ChainDB.ChainSelectionForFutureBlock pt) = + mkObject [ "kind" .= String "TChainSelectionForFutureBlock" + , "block" .= forMachine dtal pt ] + + asMetrics (ChainDB.SwitchedToAFork _warnings newTipInfo _oldChain newChain) = + let ChainInformation { slots, blocks, density, epoch, slotInEpoch } = + chainInformation newTipInfo newChain 0 + in [ DoubleM "cardano.node.density" (fromRational density) + , IntM "cardano.node.slotNum" (fromIntegral slots) + , IntM "cardano.node.blockNum" (fromIntegral blocks) + , IntM "cardano.node.slotInEpoch" (fromIntegral slotInEpoch) + , IntM "cardano.node.epoch" (fromIntegral (unEpochNo epoch)) + ] + asMetrics (ChainDB.AddedToCurrentChain _warnings newTipInfo _oldChain newChain) = + let ChainInformation { slots, blocks, density, epoch, slotInEpoch } = + chainInformation newTipInfo newChain 0 + in [ DoubleM "cardano.node.density" (fromRational density) + , IntM "cardano.node.slotNum" (fromIntegral slots) + , IntM "cardano.node.blockNum" (fromIntegral blocks) + , IntM "cardano.node.slotInEpoch" (fromIntegral slotInEpoch) + , IntM "cardano.node.epoch" (fromIntegral (unEpochNo epoch)) + ] + asMetrics _ = [] + +addedHdrsNewChain :: HasHeader (Header blk) + => AF.AnchoredFragment (Header blk) + -> AF.AnchoredFragment (Header blk) + -> [Header blk] +addedHdrsNewChain fro to_ = + case AF.intersect fro to_ of + Just (_, _, _, s2 :: AF.AnchoredFragment (Header blk)) -> + AF.toOldestFirst s2 + Nothing -> [] -- No sense to do validation here. + +instance ( HasHeader (Header blk) + , LedgerSupportsProtocol blk + , ConvertRawHash (Header blk) + , ConvertRawHash blk + , LogFormatting (RealPoint blk)) + => LogFormatting (ChainDB.TraceValidationEvent blk) where + forHuman (ChainDB.InvalidBlock err pt) = + "Invalid block " <> renderRealPointAsPhrase pt <> ": " <> showT err + forHuman (ChainDB.ValidCandidate c) = + "Valid candidate " <> renderPointAsPhrase (AF.headPoint c) + forHuman (ChainDB.CandidateContainsFutureBlocks c hdrs) = + "Candidate contains blocks from near future: " <> + renderPointAsPhrase (AF.headPoint c) <> ", slots " <> + Text.intercalate ", " (map (renderPoint . headerPoint) hdrs) + forHuman (ChainDB.CandidateContainsFutureBlocksExceedingClockSkew c hdrs) = + "Candidate contains blocks from future exceeding clock skew limit: " <> + renderPointAsPhrase (AF.headPoint c) <> ", slots " <> + Text.intercalate ", " (map (renderPoint . headerPoint) hdrs) + forHuman (ChainDB.UpdateLedgerDbTraceEvent + (StartedPushingBlockToTheLedgerDb + (LedgerDB.PushStart start) + (LedgerDB.PushGoal goal) + (LedgerDB.Pushing curr))) = + let fromSlot = unSlotNo $ realPointSlot start + atSlot = unSlotNo $ realPointSlot curr + atDiff = atSlot - fromSlot + toSlot = unSlotNo $ realPointSlot goal + toDiff = toSlot - fromSlot + in + "Pushing ledger state for block " <> renderRealPointAsPhrase curr <> ". Progress: " <> + showProgressT (fromIntegral atDiff) (fromIntegral toDiff) <> "%" + + forMachine dtal (ChainDB.InvalidBlock err pt) = + mkObject [ "kind" .= String "InvalidBlock" + , "block" .= forMachine dtal pt + , "error" .= showT err ] + forMachine dtal (ChainDB.ValidCandidate c) = + mkObject [ "kind" .= String "ValidCandidate" + , "block" .= renderPointForDetails dtal (AF.headPoint c) ] + forMachine dtal (ChainDB.CandidateContainsFutureBlocks c hdrs) = + mkObject [ "kind" .= String "CandidateContainsFutureBlocks" + , "block" .= renderPointForDetails dtal (AF.headPoint c) + , "headers" .= map (renderPointForDetails dtal . headerPoint) hdrs ] + forMachine dtal (ChainDB.CandidateContainsFutureBlocksExceedingClockSkew c hdrs) = + mkObject [ "kind" .= String "CandidateContainsFutureBlocksExceedingClockSkew" + , "block" .= renderPointForDetails dtal (AF.headPoint c) + , "headers" .= map (renderPointForDetails dtal . headerPoint) hdrs ] + forMachine _dtal (ChainDB.UpdateLedgerDbTraceEvent + (StartedPushingBlockToTheLedgerDb + (LedgerDB.PushStart start) + (LedgerDB.PushGoal goal) + (LedgerDB.Pushing curr))) = + mkObject [ "kind" .= String "UpdateLedgerDbTraceEvent.StartedPushingBlockToTheLedgerDb" + , "startingBlock" .= renderRealPoint start + , "currentBlock" .= renderRealPoint curr + , "targetBlock" .= renderRealPoint goal + ] + +showProgressT :: Int -> Int -> Text +showProgressT chunkNo outOf = + Text.pack (showFFloat + (Just 2) + (100 * fromIntegral chunkNo / fromIntegral outOf :: Float) + mempty) + +data ChainInformation = ChainInformation + { slots :: Word64 + , blocks :: Word64 + , density :: Rational + -- ^ the actual number of blocks created over the maximum expected number + -- of blocks that could be created over the span of the last @k@ blocks. + , epoch :: EpochNo + -- ^ In which epoch is the tip of the current chain + , slotInEpoch :: Word64 + -- ^ Relative slot number of the tip of the current chain within the + -- epoch. + , blocksUncoupledDelta :: Int64 + -- ^ The net change in number of blocks forged since last restart not on the + -- current chain. + } + +chainInformation + :: forall blk. HasHeader (Header blk) + => ChainDB.NewTipInfo blk + -> AF.AnchoredFragment (Header blk) + -> Int64 + -> ChainInformation +chainInformation newTipInfo frag blocksUncoupledDelta = ChainInformation + { slots = unSlotNo $ fromWithOrigin 0 (AF.headSlot frag) + , blocks = unBlockNo $ fromWithOrigin (BlockNo 1) (AF.headBlockNo frag) + , density = fragmentChainDensity frag + , epoch = ChainDB.newTipEpoch newTipInfo + , slotInEpoch = ChainDB.newTipSlotInEpoch newTipInfo + , blocksUncoupledDelta = blocksUncoupledDelta + } + +fragmentChainDensity :: + HasHeader (Header blk) + => AF.AnchoredFragment (Header blk) -> Rational +fragmentChainDensity frag = calcDensity blockD slotD + where + calcDensity :: Word64 -> Word64 -> Rational + calcDensity bl sl + | sl > 0 = toRational bl / toRational sl + | otherwise = 0 + slotN = unSlotNo $ fromWithOrigin 0 (AF.headSlot frag) + -- Slot of the tip - slot @k@ blocks back. Use 0 as the slot for genesis + -- includes EBBs + slotD = slotN + - unSlotNo (fromWithOrigin 0 (AF.lastSlot frag)) + -- Block numbers start at 1. We ignore the genesis EBB, which has block number 0. + blockD = blockN - firstBlock + blockN = unBlockNo $ fromWithOrigin (BlockNo 1) (AF.headBlockNo frag) + firstBlock = case unBlockNo . blockNo <$> AF.last frag of + -- Empty fragment, no blocks. We have that @blocks = 1 - 1 = 0@ + Left _ -> 1 + -- The oldest block is the genesis EBB with block number 0, + -- don't let it contribute to the number of blocks + Right 0 -> 1 + Right b -> b + + +docChainDBAddBlock :: [DocMsg (ChainDB.TraceAddBlockEvent blk)] +docChainDBAddBlock = [ + DocMsg + (ChainDB.IgnoreBlockOlderThanK anyProto) + [] + "A block with a 'BlockNo' more than @k@ back than the current tip\ + \ was ignored." + , DocMsg + (ChainDB.IgnoreBlockAlreadyInVolatileDB anyProto) + [] + "A block that is already in the Volatile DB was ignored." + , DocMsg + (ChainDB.IgnoreInvalidBlock anyProto anyProto) + [] + "A block that is already in the Volatile DB was ignored." + , DocMsg + (ChainDB.AddedBlockToQueue + anyProto anyProto) + [] + "The block was added to the queue and will be added to the ChainDB by\ + \ the background thread. The size of the queue is included.." + , DocMsg + (ChainDB.BlockInTheFuture anyProto anyProto) + [] + "The block is from the future, i.e., its slot number is greater than\ + \ the current slot (the second argument)." + , DocMsg + (ChainDB.AddedBlockToVolatileDB anyProto anyProto anyProto) + [] + "A block was added to the Volatile DB" + , DocMsg + (ChainDB.TryAddToCurrentChain anyProto) + [] + "The block fits onto the current chain, we'll try to use it to extend\ + \ our chain." + , DocMsg + (ChainDB.TrySwitchToAFork anyProto anyProto) + [] + "The block fits onto some fork, we'll try to switch to that fork (if\ + \ it is preferable to our chain)" + , DocMsg + (ChainDB.StoreButDontChange anyProto) + [] + "The block fits onto some fork, we'll try to switch to that fork (if\ + \ it is preferable to our chain)." + , DocMsg + (ChainDB.AddedToCurrentChain [] anyProto anyProto anyProto) + [("cardano.node.density", + "The actual number of blocks created over the maximum expected number\ + \ of blocks that could be created over the span of the last @k@ blocks.") + , ("cardano.node.slots", + "Number of slots in this chain fragment.") + , ("cardano.node.blocks", + "Number of blocks in this chain fragment.") + , ("cardano.node.slotInEpoch", + "Relative slot number of the tip of the current chain within the\ + \epoch..") + , ("cardano.node.epoch", + "In which epoch is the tip of the current chain.") + ] + "The new block fits onto the current chain (first\ + \ fragment) and we have successfully used it to extend our (new) current\ + \ chain (second fragment)." + , DocMsg + (ChainDB.SwitchedToAFork [] anyProto anyProto anyProto) + [ ("cardano.node.density", + "The actual number of blocks created over the maximum expected number\ + \ of blocks that could be created over the span of the last @k@ blocks.") + , ("cardano.node.slots", + "Number of slots in this chain fragment.") + , ("cardano.node.blocks", + "Number of blocks in this chain fragment.") + , ("cardano.node.slotInEpoch", + "Relative slot number of the tip of the current chain within the\ + \epoch..") + , ("cardano.node.epoch", + "In which epoch is the tip of the current chain.") + ] + "The new block fits onto some fork and we have switched to that fork\ + \ (second fragment), as it is preferable to our (previous) current chain\ + \ (first fragment)." + , DocMsg + (ChainDB.AddBlockValidation + (ChainDB.InvalidBlock anyProto anyProto)) + [] + "An event traced during validating performed while adding a block.\ + \ A point was found to be invalid." + , DocMsg + (ChainDB.AddBlockValidation + (ChainDB.ValidCandidate anyProto)) + [] + "An event traced during validating performed while adding a block.\ + \ A candidate chain was valid." + , DocMsg + (ChainDB.AddBlockValidation + (ChainDB.CandidateContainsFutureBlocks anyProto anyProto)) + [] + "An event traced during validating performed while adding a block.\ + \ Candidate contains headers from the future which do no exceed the\ + \ clock skew." + , DocMsg + (ChainDB.AddBlockValidation + (ChainDB.CandidateContainsFutureBlocksExceedingClockSkew anyProto anyProto)) + [] + "An event traced during validating performed while adding a block.\ + \ Candidate contains headers from the future which exceed the\ + \ clock skew." + , DocMsg + (ChainDB.ChainSelectionForFutureBlock anyProto) + [] + "Run chain selection for a block that was previously from the future.\ + \ This is done for all blocks from the future each time a new block is\ + \ added." + ] + + +-------------------------------------------------------------------------------- +-- FollowerEvent +-------------------------------------------------------------------------------- + +sevTraceFollowerEvent :: ChainDB.TraceFollowerEvent blk -> SeverityS +sevTraceFollowerEvent ChainDB.NewFollower {} = Debug +sevTraceFollowerEvent ChainDB.FollowerNoLongerInMem {} = Debug +sevTraceFollowerEvent ChainDB.FollowerSwitchToMem {} = Debug +sevTraceFollowerEvent ChainDB.FollowerNewImmIterator {} = Debug + +namesForChainDBFollower :: ChainDB.TraceFollowerEvent blk -> [Text] +namesForChainDBFollower ChainDB.NewFollower = + ["NewFollower"] +namesForChainDBFollower (ChainDB.FollowerNoLongerInMem {}) = + ["FollowerNoLongerInMem"] +namesForChainDBFollower (ChainDB.FollowerSwitchToMem {}) = + ["FollowerSwitchToMem"] +namesForChainDBFollower (ChainDB.FollowerNewImmIterator {}) = + ["FollowerNewImmIterator"] + +docChainDBFollower :: [DocMsg (ChainDB.TraceFollowerEvent ev)] +docChainDBFollower = [ + DocMsg + ChainDB.NewFollower + [] + "A new follower was created." + , DocMsg + (ChainDB.FollowerNoLongerInMem anyProto) + [] + "The follower was in the 'FollowerInImmutableDB' state and is switched to\ + \ the 'FollowerInMem' state." + , DocMsg + (ChainDB.FollowerSwitchToMem anyProto anyProto) + [] + "The follower was in the 'FollowerInImmutableDB' state and is switched to\ + \ the 'FollowerInMem' state." + , DocMsg + (ChainDB.FollowerNewImmIterator anyProto anyProto) + [] + "The follower is in the 'FollowerInImmutableDB' state but the iterator is\ + \ exhausted while the ImmDB has grown, so we open a new iterator to\ + \ stream these blocks too." + ] + +-------------------------------------------------------------------------------- +-- CopiedBlockToImmutableDB +-------------------------------------------------------------------------------- + +sevTraceCopyToImmutableDBEvent :: ChainDB.TraceCopyToImmutableDBEvent blk -> SeverityS +sevTraceCopyToImmutableDBEvent ChainDB.CopiedBlockToImmutableDB {} = Debug +sevTraceCopyToImmutableDBEvent ChainDB.NoBlocksToCopyToImmutableDB = Debug + +namesForChainDBCopyToImmutable :: ChainDB.TraceCopyToImmutableDBEvent blk -> [Text] +namesForChainDBCopyToImmutable (ChainDB.CopiedBlockToImmutableDB {}) = + ["CopiedBlockToImmutableDB"] +namesForChainDBCopyToImmutable ChainDB.NoBlocksToCopyToImmutableDB = + ["NoBlocksToCopyToImmutableDB"] + +instance ConvertRawHash blk + => LogFormatting (ChainDB.TraceCopyToImmutableDBEvent blk) where + forHuman (ChainDB.CopiedBlockToImmutableDB pt) = + "Copied block " <> renderPointAsPhrase pt <> " to the ImmDB" + forHuman ChainDB.NoBlocksToCopyToImmutableDB = + "There are no blocks to copy to the ImmDB" + + forMachine dtals (ChainDB.CopiedBlockToImmutableDB pt) = + mkObject [ "kind" .= String "CopiedBlockToImmutableDB" + , "slot" .= forMachine dtals pt ] + forMachine _dtals ChainDB.NoBlocksToCopyToImmutableDB = + mkObject [ "kind" .= String "NoBlocksToCopyToImmutableDB" ] + +docChainDBImmtable :: [DocMsg (ChainDB.TraceCopyToImmutableDBEvent blk)] +docChainDBImmtable = [ + DocMsg + (ChainDB.CopiedBlockToImmutableDB anyProto) + [] + "A block was successfully copied to the ImmDB." + , DocMsg + ChainDB.NoBlocksToCopyToImmutableDB + [] + "There are no block to copy to the ImmDB." + ] + +-------------------------------------------------------------------------------- +-- GCEvent +-------------------------------------------------------------------------------- + +sevTraceGCEvent :: ChainDB.TraceGCEvent blk -> SeverityS +sevTraceGCEvent ChainDB.PerformedGC {} = Debug +sevTraceGCEvent ChainDB.ScheduledGC {} = Debug + +namesForChainDBGCEvent :: ChainDB.TraceGCEvent blk -> [Text] +namesForChainDBGCEvent (ChainDB.ScheduledGC {}) = + ["ScheduledGC"] +namesForChainDBGCEvent (ChainDB.PerformedGC {}) = + ["PerformedGC"] + +instance LogFormatting (ChainDB.TraceGCEvent blk) where + forHuman (ChainDB.PerformedGC slot) = + "Performed a garbage collection for " <> condenseT slot + forHuman (ChainDB.ScheduledGC slot _difft) = + "Scheduled a garbage collection for " <> condenseT slot + + forMachine dtals (ChainDB.PerformedGC slot) = + mkObject [ "kind" .= String "PerformedGC" + , "slot" .= forMachine dtals slot ] + forMachine dtals (ChainDB.ScheduledGC slot difft) = + mkObject $ [ "kind" .= String "ScheduledGC" + , "slot" .= forMachine dtals slot ] <> + [ "difft" .= String ((Text.pack . show) difft) | dtals >= DDetailed] + +docChainDBGCEvent :: [DocMsg (ChainDB.TraceGCEvent blk)] +docChainDBGCEvent = [ + DocMsg + (ChainDB.ScheduledGC anyProto anyProto) + [] + "There are no block to copy to the ImmDB." + , DocMsg + (ChainDB.PerformedGC anyProto) + [] + "There are no block to copy to the ImmDB." + ] + +-------------------------------------------------------------------------------- +-- TraceInitChainSelEvent +-------------------------------------------------------------------------------- + +sevTraceInitChainSelEvent :: ChainDB.TraceInitChainSelEvent blk -> SeverityS +sevTraceInitChainSelEvent ChainDB.StartedInitChainSelection {} = Info +sevTraceInitChainSelEvent ChainDB.InitalChainSelected {} = Info +sevTraceInitChainSelEvent (ChainDB.InitChainSelValidation ev') = + case ev' of + ChainDB.InvalidBlock{} -> Debug + ChainDB.ValidCandidate {} -> Info + ChainDB.CandidateContainsFutureBlocks {} -> Debug + ChainDB.CandidateContainsFutureBlocksExceedingClockSkew {} -> Debug + ChainDB.UpdateLedgerDbTraceEvent {} -> Info + +namesForInitChainSel :: ChainDB.TraceInitChainSelEvent blk -> [Text] +namesForInitChainSel (ChainDB.InitChainSelValidation + (ChainDB.InvalidBlock {})) = + ["InvalidBlock"] +namesForInitChainSel (ChainDB.InitChainSelValidation + (ChainDB.ValidCandidate {})) = + ["ValidCandidate"] +namesForInitChainSel (ChainDB.InitChainSelValidation + (ChainDB.CandidateContainsFutureBlocks {})) = + ["CandidateContainsFutureBlocks"] +namesForInitChainSel (ChainDB.InitChainSelValidation + (ChainDB.CandidateContainsFutureBlocksExceedingClockSkew {})) = + ["CandidateContainsFutureBlocksExceedingClockSkew"] +namesForInitChainSel (ChainDB.InitChainSelValidation + (ChainDB.UpdateLedgerDbTraceEvent {})) = + ["UpdateLedgerDb"] +namesForInitChainSel (ChainDB.StartedInitChainSelection {}) = + ["StartedInitChainSelection"] +namesForInitChainSel (ChainDB.InitalChainSelected {}) = + ["InitalChainSelected"] + +instance (ConvertRawHash blk, LedgerSupportsProtocol blk) + => LogFormatting (ChainDB.TraceInitChainSelEvent blk) where + forHuman (ChainDB.InitChainSelValidation v) = forHuman v + forHuman (ChainDB.InitalChainSelected {}) = + "Inital chain selected" + forHuman (ChainDB.StartedInitChainSelection {}) = + "Started initial chain selection" + + forMachine dtal (ChainDB.InitChainSelValidation v) = forMachine dtal v + forMachine _dtal ChainDB.InitalChainSelected = + mkObject ["kind" .= String "Follower.InitalChainSelected"] + forMachine _dtal ChainDB.StartedInitChainSelection = + mkObject ["kind" .= String "Follower.StartedInitChainSelection"] + + asMetrics (ChainDB.InitChainSelValidation v) = asMetrics v + asMetrics ChainDB.InitalChainSelected = [] + asMetrics ChainDB.StartedInitChainSelection = [] + + +docChainDBInitChainSel :: [DocMsg (ChainDB.TraceInitChainSelEvent blk)] +docChainDBInitChainSel = [ + DocMsg + (ChainDB.InitChainSelValidation + (ChainDB.InvalidBlock anyProto anyProto)) + [] + "A point was found to be invalid." + , DocMsg + (ChainDB.InitChainSelValidation + (ChainDB.ValidCandidate anyProto)) + [] + "A candidate chain was valid." + , DocMsg + (ChainDB.InitChainSelValidation + (ChainDB.CandidateContainsFutureBlocks anyProto anyProto)) + [] + "Candidate contains headers from the future which do not exceed the\ + \ clock skew." + , DocMsg + (ChainDB.InitChainSelValidation + (ChainDB.CandidateContainsFutureBlocksExceedingClockSkew anyProto anyProto)) + [] + "Candidate contains headers from the future which exceed the\ + \ clock skew, making them invalid." + ] + +-------------------------------------------------------------------------------- +-- TraceOpenEvent +-------------------------------------------------------------------------------- + +sevTraceOpenEvent :: ChainDB.TraceOpenEvent blk -> SeverityS +sevTraceOpenEvent ChainDB.OpenedDB {} = Info +sevTraceOpenEvent ChainDB.ClosedDB {} = Info +sevTraceOpenEvent ChainDB.OpenedImmutableDB {} = Info +sevTraceOpenEvent ChainDB.OpenedVolatileDB = Info +sevTraceOpenEvent ChainDB.OpenedLgrDB = Info +sevTraceOpenEvent ChainDB.StartedOpeningDB = Info +sevTraceOpenEvent ChainDB.StartedOpeningImmutableDB = Info +sevTraceOpenEvent ChainDB.StartedOpeningVolatileDB = Info +sevTraceOpenEvent ChainDB.StartedOpeningLgrDB = Info + +namesForChainDBOpenEvent :: ChainDB.TraceOpenEvent blk -> [Text] +namesForChainDBOpenEvent (ChainDB.OpenedDB {}) = + ["OpenedDB"] +namesForChainDBOpenEvent (ChainDB.ClosedDB {}) = + ["ClosedDB"] +namesForChainDBOpenEvent (ChainDB.OpenedImmutableDB {}) = + ["OpenedImmutableDB"] +namesForChainDBOpenEvent ChainDB.OpenedVolatileDB = + ["OpenedVolatileDB"] +namesForChainDBOpenEvent ChainDB.OpenedLgrDB = + ["OpenedLgrDB"] +namesForChainDBOpenEvent ChainDB.StartedOpeningDB = + ["StartedOpeningDB"] +namesForChainDBOpenEvent ChainDB.StartedOpeningImmutableDB = + ["StartedOpeningImmutableDB"] +namesForChainDBOpenEvent ChainDB.StartedOpeningVolatileDB = + ["StartedOpeningVolatileDB"] +namesForChainDBOpenEvent ChainDB.StartedOpeningLgrDB = + ["StartedOpeningLgrDB"] + + +instance ConvertRawHash blk + => LogFormatting (ChainDB.TraceOpenEvent blk) where + forHuman (ChainDB.OpenedDB immTip tip') = + "Opened db with immutable tip at " <> renderPointAsPhrase immTip <> + " and tip " <> renderPointAsPhrase tip' + forHuman (ChainDB.ClosedDB immTip tip') = + "Closed db with immutable tip at " <> renderPointAsPhrase immTip <> + " and tip " <> renderPointAsPhrase tip' + forHuman (ChainDB.OpenedImmutableDB immTip chunk) = + "Opened imm db with immutable tip at " <> renderPointAsPhrase immTip <> + " and chunk " <> showT chunk + forHuman ChainDB.OpenedVolatileDB = "Opened vol db" + forHuman ChainDB.OpenedLgrDB = "Opened lgr db" + forHuman ChainDB.StartedOpeningDB = "Started opening Chain DB" + forHuman ChainDB.StartedOpeningImmutableDB = "Started opening Immutable DB" + forHuman ChainDB.StartedOpeningVolatileDB = "Started opening Volatile DB" + forHuman ChainDB.StartedOpeningLgrDB = "Started opening Ledger DB" + + forMachine dtal (ChainDB.OpenedDB immTip tip')= + mkObject [ "kind" .= String "OpenedDB" + , "immtip" .= forMachine dtal immTip + , "tip" .= forMachine dtal tip' ] + forMachine dtal (ChainDB.ClosedDB immTip tip') = + mkObject [ "kind" .= String "TraceOpenEvent.ClosedDB" + , "immtip" .= forMachine dtal immTip + , "tip" .= forMachine dtal tip' ] + forMachine dtal (ChainDB.OpenedImmutableDB immTip epoch) = + mkObject [ "kind" .= String "OpenedImmutableDB" + , "immtip" .= forMachine dtal immTip + , "epoch" .= String ((Text.pack . show) epoch) ] + forMachine _dtal ChainDB.OpenedVolatileDB = + mkObject [ "kind" .= String "OpenedVolatileDB" ] + forMachine _dtal ChainDB.OpenedLgrDB = + mkObject [ "kind" .= String "OpenedLgrDB" ] + forMachine _dtal ChainDB.StartedOpeningDB = + mkObject ["kind" .= String "StartedOpeningDB"] + forMachine _dtal ChainDB.StartedOpeningImmutableDB = + mkObject ["kind" .= String "StartedOpeningImmutableDB"] + forMachine _dtal ChainDB.StartedOpeningVolatileDB = + mkObject ["kind" .= String "StartedOpeningVolatileDB"] + forMachine _dtal ChainDB.StartedOpeningLgrDB = + mkObject ["kind" .= String "StartedOpeningLgrDB"] + + +docChainDBOpenEvent :: [DocMsg (ChainDB.TraceOpenEvent blk)] +docChainDBOpenEvent = + [ DocMsg + (ChainDB.OpenedDB anyProto anyProto) + [] + "The ChainDB was opened." + , DocMsg + (ChainDB.ClosedDB anyProto anyProto) + [] + "The ChainDB was closed." + , DocMsg + (ChainDB.OpenedImmutableDB anyProto anyProto) + [] + "The ImmDB was opened." + , DocMsg + ChainDB.OpenedVolatileDB + [] + "The VolatileDB was opened." + , DocMsg + ChainDB.OpenedLgrDB + [] + "The LedgerDB was opened." + ] + +-------------------------------------------------------------------------------- +-- IteratorEvent +-------------------------------------------------------------------------------- + +sevTraceIteratorEvent :: ChainDB.TraceIteratorEvent blk -> SeverityS +sevTraceIteratorEvent ChainDB.StreamFromVolatileDB {} = Debug +sevTraceIteratorEvent _ = Debug + +namesForChainDBIteratorEvent :: ChainDB.TraceIteratorEvent blk -> [Text] +namesForChainDBIteratorEvent (ChainDB.UnknownRangeRequested {}) = + ["UnknownRangeRequested"] +namesForChainDBIteratorEvent (ChainDB.StreamFromVolatileDB {}) = + ["StreamFromVolatileDB"] +namesForChainDBIteratorEvent (ChainDB.StreamFromImmutableDB {}) = + ["StreamFromImmutableDB"] +namesForChainDBIteratorEvent (ChainDB.StreamFromBoth {}) = + ["StreamFromBoth"] +namesForChainDBIteratorEvent (ChainDB.BlockMissingFromVolatileDB {}) = + ["BlockMissingFromVolatileDB"] +namesForChainDBIteratorEvent (ChainDB.BlockWasCopiedToImmutableDB {}) = + ["BlockWasCopiedToImmutableDB"] +namesForChainDBIteratorEvent (ChainDB.BlockGCedFromVolatileDB {}) = + ["BlockGCedFromVolatileDB"] +namesForChainDBIteratorEvent ChainDB.SwitchBackToVolatileDB = + ["SwitchBackToVolatileDB"] + +instance ( StandardHash blk + , ConvertRawHash blk + ) => LogFormatting (ChainDB.TraceIteratorEvent blk) where + forHuman (ChainDB.UnknownRangeRequested ev') = forHuman ev' + forHuman (ChainDB.BlockMissingFromVolatileDB realPt) = + "This block is no longer in the VolatileDB because it has been garbage\ + \ collected. It might now be in the ImmDB if it was part of the\ + \ current chain. Block: " <> renderRealPoint realPt + forHuman (ChainDB.StreamFromImmutableDB sFrom sTo) = + "Stream only from the ImmDB. StreamFrom:" <> showT sFrom <> + " StreamTo: " <> showT sTo + forHuman (ChainDB.StreamFromBoth sFrom sTo pts) = + "Stream from both the VolatileDB and the ImmDB." + <> " StreamFrom: " <> showT sFrom <> " StreamTo: " <> showT sTo + <> " Points: " <> showT (map renderRealPoint pts) + forHuman (ChainDB.StreamFromVolatileDB sFrom sTo pts) = + "Stream only from the VolatileDB." + <> " StreamFrom: " <> showT sFrom <> " StreamTo: " <> showT sTo + <> " Points: " <> showT (map renderRealPoint pts) + forHuman (ChainDB.BlockWasCopiedToImmutableDB pt) = + "This block has been garbage collected from the VolatileDB is now\ + \ found and streamed from the ImmDB. Block: " <> renderRealPoint pt + forHuman (ChainDB.BlockGCedFromVolatileDB pt) = + "This block no longer in the VolatileDB and isn't in the ImmDB\ + \ either; it wasn't part of the current chain. Block: " <> renderRealPoint pt + forHuman ChainDB.SwitchBackToVolatileDB = "SwitchBackToVolatileDB" + + forMachine _dtal (ChainDB.UnknownRangeRequested unkRange) = + mkObject [ "kind" .= String "UnknownRangeRequested" + , "range" .= String (showT unkRange) + ] + forMachine _dtal (ChainDB.StreamFromVolatileDB streamFrom streamTo realPt) = + mkObject [ "kind" .= String "StreamFromVolatileDB" + , "from" .= String (showT streamFrom) + , "to" .= String (showT streamTo) + , "point" .= String (Text.pack . show $ map renderRealPoint realPt) + ] + forMachine _dtal (ChainDB.StreamFromImmutableDB streamFrom streamTo) = + mkObject [ "kind" .= String "StreamFromImmutableDB" + , "from" .= String (showT streamFrom) + , "to" .= String (showT streamTo) + ] + forMachine _dtal (ChainDB.StreamFromBoth streamFrom streamTo realPt) = + mkObject [ "kind" .= String "StreamFromBoth" + , "from" .= String (showT streamFrom) + , "to" .= String (showT streamTo) + , "point" .= String (Text.pack . show $ map renderRealPoint realPt) + ] + forMachine _dtal (ChainDB.BlockMissingFromVolatileDB realPt) = + mkObject [ "kind" .= String "BlockMissingFromVolatileDB" + , "point" .= String (renderRealPoint realPt) + ] + forMachine _dtal (ChainDB.BlockWasCopiedToImmutableDB realPt) = + mkObject [ "kind" .= String "BlockWasCopiedToImmutableDB" + , "point" .= String (renderRealPoint realPt) + ] + forMachine _dtal (ChainDB.BlockGCedFromVolatileDB realPt) = + mkObject [ "kind" .= String "BlockGCedFromVolatileDB" + , "point" .= String (renderRealPoint realPt) + ] + forMachine _dtal ChainDB.SwitchBackToVolatileDB = + mkObject ["kind" .= String "SwitchBackToVolatileDB" + ] + +instance ( StandardHash blk + , ConvertRawHash blk + ) => LogFormatting (ChainDB.UnknownRange blk) where + forHuman (ChainDB.MissingBlock realPt) = + "The block at the given point was not found in the ChainDB." + <> renderRealPoint realPt + forHuman (ChainDB.ForkTooOld streamFrom) = + "The requested range forks off too far in the past" + <> showT streamFrom + + forMachine _dtal (ChainDB.MissingBlock realPt) = + mkObject [ "kind" .= String "MissingBlock" + , "point" .= String (renderRealPoint realPt) + ] + forMachine _dtal (ChainDB.ForkTooOld streamFrom) = + mkObject [ "kind" .= String "ForkTooOld" + , "from" .= String (showT streamFrom) + ] + +docChainDBIteratorEvent :: [DocMsg (ChainDB.TraceIteratorEvent blk)] +docChainDBIteratorEvent = [ + DocMsg + (ChainDB.UnknownRangeRequested anyProto) + [] + "An unknown range was requested, see 'UnknownRange'." + , DocMsg + (ChainDB.StreamFromVolatileDB anyProto anyProto anyProto) + [] + "Stream only from the VolatileDB." + , DocMsg + (ChainDB.StreamFromImmutableDB anyProto anyProto) + [] + "Stream only from the ImmDB." + , DocMsg + (ChainDB.StreamFromBoth anyProto anyProto anyProto) + [] + "Stream from both the VolatileDB and the ImmDB." + , DocMsg + (ChainDB.BlockMissingFromVolatileDB anyProto) + [] + "A block is no longer in the VolatileDB because it has been garbage\ + \ collected. It might now be in the ImmDB if it was part of the\ + \ current chain." + , DocMsg + (ChainDB.BlockWasCopiedToImmutableDB anyProto) + [] + "A block that has been garbage collected from the VolatileDB is now\ + \ found and streamed from the ImmDB." + , DocMsg + (ChainDB.BlockGCedFromVolatileDB anyProto) + [] + "A block is no longer in the VolatileDB and isn't in the ImmDB\ + \ either; it wasn't part of the current chain." + , DocMsg + ChainDB.SwitchBackToVolatileDB + [] + "We have streamed one or more blocks from the ImmDB that were part\ + \ of the VolatileDB when initialising the iterator. Now, we have to look\ + \ back in the VolatileDB again because the ImmDB doesn't have the\ + \ next block we're looking for." + ] + + +-------------------------------------------------------------------------------- +-- LedgerDB.TraceEvent +-------------------------------------------------------------------------------- + +sevTraceLedgerEvent :: LedgerDB.TraceEvent blk -> SeverityS +sevTraceLedgerEvent LedgerDB.TookSnapshot {} = Info +sevTraceLedgerEvent LedgerDB.DeletedSnapshot {} = Debug +sevTraceLedgerEvent LedgerDB.InvalidSnapshot {} = Error + +namesForChainDBLedgerEvent :: LedgerDB.TraceEvent blk -> [Text] +namesForChainDBLedgerEvent (LedgerDB.InvalidSnapshot {}) = + ["InvalidSnapshot"] +namesForChainDBLedgerEvent (LedgerDB.TookSnapshot {}) = + ["TookSnapshot"] +namesForChainDBLedgerEvent (LedgerDB.DeletedSnapshot {}) = + ["DeletedSnapshot"] + +instance ( StandardHash blk + , ConvertRawHash blk) + => LogFormatting (LedgerDB.TraceEvent blk) where + forHuman (LedgerDB.TookSnapshot snap pt) = + "Took ledger snapshot " <> showT snap <> + " at " <> renderRealPointAsPhrase pt + forHuman (LedgerDB.DeletedSnapshot snap) = + "Deleted old snapshot " <> showT snap + forHuman (LedgerDB.InvalidSnapshot snap failure) = + "Invalid snapshot " <> showT snap <> showT failure + + forMachine dtals (LedgerDB.TookSnapshot snap pt) = + mkObject [ "kind" .= String "TookSnapshot" + , "snapshot" .= forMachine dtals snap + , "tip" .= show pt ] + forMachine dtals (LedgerDB.DeletedSnapshot snap) = + mkObject [ "kind" .= String "DeletedSnapshot" + , "snapshot" .= forMachine dtals snap ] + forMachine dtals (LedgerDB.InvalidSnapshot snap failure) = + mkObject [ "kind" .= String "TraceLedgerEvent.InvalidSnapshot" + , "snapshot" .= forMachine dtals snap + , "failure" .= show failure ] + +docChainDBLedgerEvent :: [DocMsg (LedgerDB.TraceEvent blk)] +docChainDBLedgerEvent = [ + DocMsg + (LedgerDB.InvalidSnapshot anyProto anyProto) + [] + "An on disk snapshot was skipped because it was invalid." + , DocMsg + (LedgerDB.TookSnapshot anyProto anyProto) + [] + "A snapshot was written to disk." + , DocMsg + (LedgerDB.DeletedSnapshot anyProto) + [] + "An old or invalid on-disk snapshot was deleted." + ] + +-------------------------------------------------------------------------------- +-- LedgerReplayEvent +-------------------------------------------------------------------------------- + +sevTraceLedgerReplayEvent :: LedgerDB.TraceReplayEvent blk -> SeverityS +sevTraceLedgerReplayEvent LedgerDB.ReplayFromGenesis {} = Info +sevTraceLedgerReplayEvent LedgerDB.ReplayFromSnapshot {} = Info +sevTraceLedgerReplayEvent LedgerDB.ReplayedBlock {} = Info + +namesForChainDBLedgerReplayEvent :: LedgerDB.TraceReplayEvent blk -> [Text] +namesForChainDBLedgerReplayEvent (LedgerDB.ReplayFromGenesis {}) = + ["ReplayFromGenesis"] +namesForChainDBLedgerReplayEvent (LedgerDB.ReplayFromSnapshot {}) = + ["ReplayFromSnapshot"] +namesForChainDBLedgerReplayEvent (LedgerDB.ReplayedBlock {}) = + ["ReplayedBlock"] + +instance (StandardHash blk, ConvertRawHash blk) + => LogFormatting (LedgerDB.TraceReplayEvent blk) where + forHuman (LedgerDB.ReplayFromGenesis _replayTo) = + "Replaying ledger from genesis" + forHuman (LedgerDB.ReplayFromSnapshot snap tip' _ _) = + "Replaying ledger from snapshot " <> showT snap <> " at " <> + renderRealPointAsPhrase tip' + forHuman (LedgerDB.ReplayedBlock + pt + _ledgerEvents + (LedgerDB.ReplayStart replayFrom) + (LedgerDB.ReplayGoal replayTo)) = + let fromSlot = withOrigin 0 id $ unSlotNo <$> pointSlot replayFrom + atSlot = unSlotNo $ realPointSlot pt + atDiff = atSlot - fromSlot + toSlot = withOrigin 0 id $ unSlotNo <$> pointSlot replayTo + toDiff = toSlot - fromSlot + in + "Replayed block: slot " + <> showT atSlot + <> " out of " + <> showT toSlot + <> ". Progress: " + <> showProgressT (fromIntegral atDiff) (fromIntegral toDiff) + <> "%" + + forMachine _dtal (LedgerDB.ReplayFromGenesis _replayTo) = + mkObject [ "kind" .= String "ReplayFromGenesis" ] + forMachine dtal (LedgerDB.ReplayFromSnapshot snap tip' _ _) = + mkObject [ "kind" .= String "ReplayFromSnapshot" + , "snapshot" .= forMachine dtal snap + , "tip" .= show tip' ] + forMachine _dtal (LedgerDB.ReplayedBlock + pt + _ledgerEvents + _ + (LedgerDB.ReplayGoal replayTo)) = + mkObject [ "kind" .= String "ReplayedBlock" + , "slot" .= unSlotNo (realPointSlot pt) + , "tip" .= withOrigin 0 unSlotNo (pointSlot replayTo) ] + + +docChainDBLedgerReplayEvent :: [DocMsg (ChainDB.TraceReplayEvent ev)] +docChainDBLedgerReplayEvent = [ + DocMsg + (LedgerDB.ReplayFromGenesis anyProto) + [] + "There were no LedgerDB snapshots on disk, so we're replaying all\ + \ blocks starting from Genesis against the initial ledger.\ + \ The @replayTo@ parameter corresponds to the block at the tip of the\ + \ ImmDB, i.e., the last block to replay." + , DocMsg + (LedgerDB.ReplayFromSnapshot anyProto anyProto anyProto anyProto) + [] + "There was a LedgerDB snapshot on disk corresponding to the given tip.\ + \ We're replaying more recent blocks against it.\ + \ The @replayTo@ parameter corresponds to the block at the tip of the\ + \ ImmDB, i.e., the last block to replay." + , DocMsg + (LedgerDB.ReplayedBlock anyProto anyProto anyProto anyProto) + [] + "We replayed the given block (reference) on the genesis snapshot\ + \ during the initialisation of the LedgerDB.\ + \\n\ + \ The @blockInfo@ parameter corresponds replayed block and the @replayTo@\ + \ parameter corresponds to the block at the tip of the ImmDB, i.e.,\ + \ the last block to replay." + ] + +-------------------------------------------------------------------------------- +-- TraceImmutableDBEvent +-------------------------------------------------------------------------------- + +sevTraceImmutableDBEvent :: ImmDB.TraceEvent blk -> SeverityS +sevTraceImmutableDBEvent ImmDB.NoValidLastLocation {} = Info +sevTraceImmutableDBEvent ImmDB.ValidatedLastLocation {} = Info +sevTraceImmutableDBEvent (ImmDB.ChunkValidationEvent ev') = + case ev' of + ImmDB.StartedValidatingChunk{} -> Info + ImmDB.ValidatedChunk{} -> Info + ImmDB.MissingChunkFile{} -> Warning + ImmDB.InvalidChunkFile {} -> Warning + ImmDB.MissingPrimaryIndex{} -> Warning + ImmDB.MissingSecondaryIndex{} -> Warning + ImmDB.InvalidPrimaryIndex{} -> Warning + ImmDB.InvalidSecondaryIndex{} -> Warning + ImmDB.RewritePrimaryIndex{} -> Warning + ImmDB.RewriteSecondaryIndex{} -> Warning +sevTraceImmutableDBEvent ImmDB.ChunkFileDoesntFit{} = Warning +sevTraceImmutableDBEvent ImmDB.Migrating{} = Debug +sevTraceImmutableDBEvent ImmDB.DeletingAfter{} = Debug +sevTraceImmutableDBEvent ImmDB.DBAlreadyClosed{} = Error +sevTraceImmutableDBEvent ImmDB.DBClosed{} = Info +sevTraceImmutableDBEvent ImmDB.TraceCacheEvent{} = Debug + +namesForChainDBImmutableDBEvent :: ImmDB.TraceEvent blk -> [Text] +namesForChainDBImmutableDBEvent ImmDB.NoValidLastLocation = + ["NoValidLastLocation"] +namesForChainDBImmutableDBEvent (ImmDB.ValidatedLastLocation {}) = + ["ValidatedLastLocation"] + +namesForChainDBImmutableDBEvent (ImmDB.ChunkValidationEvent ev) = + "ChunkValidation" : namesForChainDBImmutableChunkValidation ev +namesForChainDBImmutableDBEvent (ImmDB.ChunkFileDoesntFit {}) = + ["ChunkFileDoesntFit"] +namesForChainDBImmutableDBEvent (ImmDB.Migrating {}) = + ["Migrating"] +namesForChainDBImmutableDBEvent (ImmDB.DeletingAfter {}) = + ["DeletingAfter"] +namesForChainDBImmutableDBEvent ImmDB.DBAlreadyClosed = + ["DBAlreadyClosed"] +namesForChainDBImmutableDBEvent ImmDB.DBClosed = + ["DBClosed"] +namesForChainDBImmutableDBEvent (ImmDB.TraceCacheEvent ev') = + "CacheEvent" : namesForChainDBImmutableDBCacheEvent ev' + +namesForChainDBImmutableChunkValidation :: + ImmDB.TraceChunkValidation blk ImmDB.ChunkNo + -> [Text] +namesForChainDBImmutableChunkValidation (ImmDB.StartedValidatingChunk {}) = + ["StartedValidatingChunk"] +namesForChainDBImmutableChunkValidation (ImmDB.ValidatedChunk {}) = + ["ValidatedChunk"] +namesForChainDBImmutableChunkValidation (ImmDB.MissingChunkFile {}) = + ["MissingChunkFile"] +namesForChainDBImmutableChunkValidation (ImmDB.InvalidChunkFile {}) = + ["InvalidChunkFile"] +namesForChainDBImmutableChunkValidation (ImmDB.MissingPrimaryIndex {}) = + ["MissingPrimaryIndex"] +namesForChainDBImmutableChunkValidation (ImmDB.MissingSecondaryIndex {}) = + ["MissingSecondaryIndex"] +namesForChainDBImmutableChunkValidation (ImmDB.InvalidPrimaryIndex {}) = + ["InvalidPrimaryIndex"] +namesForChainDBImmutableChunkValidation (ImmDB.InvalidSecondaryIndex {}) = + ["InvalidSecondaryIndex"] +namesForChainDBImmutableChunkValidation (ImmDB.RewritePrimaryIndex {}) = + ["RewritePrimaryIndex"] +namesForChainDBImmutableChunkValidation (ImmDB.RewriteSecondaryIndex {}) = + ["RewriteSecondaryIndex"] + + +namesForChainDBImmutableDBCacheEvent :: ImmDB.TraceCacheEvent -> [Text] +namesForChainDBImmutableDBCacheEvent (ImmDB.TraceCurrentChunkHit {}) = + ["CurrentChunkHit"] +namesForChainDBImmutableDBCacheEvent (ImmDB.TracePastChunkHit {}) = + ["PastChunkHit"] +namesForChainDBImmutableDBCacheEvent (ImmDB.TracePastChunkMiss {}) = + ["PastChunkMiss"] +namesForChainDBImmutableDBCacheEvent (ImmDB.TracePastChunkEvict {}) = + ["PastChunkEvict"] +namesForChainDBImmutableDBCacheEvent (ImmDB.TracePastChunksExpired {}) = + ["PastChunkExpired"] + +instance (ConvertRawHash blk, StandardHash blk) + => LogFormatting (ImmDB.TraceEvent blk) where + forMachine _dtal ImmDB.NoValidLastLocation = + mkObject [ "kind" .= String "NoValidLastLocation" ] + forMachine _dtal (ImmDB.ValidatedLastLocation chunkNo immTip) = + mkObject [ "kind" .= String "ValidatedLastLocation" + , "chunkNo" .= String (renderChunkNo chunkNo) + , "immTip" .= String (renderTipHash immTip) + , "blockNo" .= String (renderTipBlockNo immTip) + ] + forMachine dtal (ImmDB.ChunkValidationEvent traceChunkValidation) = + forMachine dtal traceChunkValidation + forMachine _dtal (ImmDB.DeletingAfter immTipWithInfo) = + mkObject [ "kind" .= String "DeletingAfter" + , "immTipHash" .= String (renderWithOrigin renderTipHash immTipWithInfo) + , "immTipBlockNo" .= String (renderWithOrigin renderTipBlockNo immTipWithInfo) + ] + forMachine _dtal ImmDB.DBAlreadyClosed = + mkObject [ "kind" .= String "DBAlreadyClosed" ] + forMachine _dtal ImmDB.DBClosed = + mkObject [ "kind" .= String "DBClosed" ] + forMachine dtal (ImmDB.TraceCacheEvent cacheEv) = + kindContext "TraceCacheEvent" $ forMachine dtal cacheEv + forMachine _dtal (ImmDB.ChunkFileDoesntFit expectPrevHash actualPrevHash) = + mkObject [ "kind" .= String "ChunkFileDoesntFit" + , "expectedPrevHash" .= String (renderChainHash (Text.decodeLatin1 . + toRawHash (Proxy @blk)) expectPrevHash) + , "actualPrevHash" .= String (renderChainHash (Text.decodeLatin1 . + toRawHash (Proxy @blk)) actualPrevHash) + ] + forMachine _dtal (ImmDB.Migrating txt) = + mkObject [ "kind" .= String "Migrating" + , "info" .= String txt + ] + + forHuman ImmDB.NoValidLastLocation = + "No valid last location was found. Starting from Genesis." + forHuman (ImmDB.ValidatedLastLocation cn t) = + "Found a valid last location at chunk " + <> showT cn + <> " with tip " + <> renderRealPoint (ImmDB.tipToRealPoint t) + <> "." + forHuman (ImmDB.ChunkValidationEvent e) = case e of + ImmDB.StartedValidatingChunk chunkNo outOf -> + "Validating chunk no. " <> showT chunkNo <> " out of " <> showT outOf + <> ". Progress: " <> showProgressT (max (chunkNoToInt chunkNo - 1) 0) (chunkNoToInt outOf) <> "%" + ImmDB.ValidatedChunk chunkNo outOf -> + "Validated chunk no. " <> showT chunkNo <> " out of " <> showT outOf + <> ". Progress: " <> showProgressT (chunkNoToInt chunkNo) (chunkNoToInt outOf) <> "%" + ImmDB.MissingChunkFile cn -> + "The chunk file with number " <> showT cn <> " is missing." + ImmDB.InvalidChunkFile cn er -> + "The chunk file with number " <> showT cn <> " is invalid: " <> showT er + ImmDB.MissingPrimaryIndex cn -> + "The primary index of the chunk file with number " <> showT cn <> " is missing." + ImmDB.MissingSecondaryIndex cn -> + "The secondary index of the chunk file with number " <> showT cn <> " is missing." + ImmDB.InvalidPrimaryIndex cn -> + "The primary index of the chunk file with number " <> showT cn <> " is invalid." + ImmDB.InvalidSecondaryIndex cn -> + "The secondary index of the chunk file with number " <> showT cn <> " is invalid." + ImmDB.RewritePrimaryIndex cn -> + "Rewriting the primary index for the chunk file with number " <> showT cn <> "." + ImmDB.RewriteSecondaryIndex cn -> + "Rewriting the secondary index for the chunk file with number " <> showT cn <> "." + forHuman (ImmDB.ChunkFileDoesntFit ch1 ch2 ) = + "Chunk file doesn't fit. The hash of the block " <> showT ch2 <> " doesn't match the previous hash of the first block in the current epoch: " <> showT ch1 <> "." + forHuman (ImmDB.Migrating t) = "Migrating: " <> t + forHuman (ImmDB.DeletingAfter wot) = "Deleting chunk files after " <> showT wot + forHuman ImmDB.DBAlreadyClosed {} = "Immutable DB was already closed. Double closing." + forHuman ImmDB.DBClosed {} = "Closed Immutable DB." + forHuman (ImmDB.TraceCacheEvent ev') = "Cache event: " <> case ev' of + ImmDB.TraceCurrentChunkHit cn curr -> "Current chunk hit: " <> showT cn <> ", cache size: " <> showT curr + ImmDB.TracePastChunkHit cn curr -> "Past chunk hit: " <> showT cn <> ", cache size: " <> showT curr + ImmDB.TracePastChunkMiss cn curr -> "Past chunk miss: " <> showT cn <> ", cache size: " <> showT curr + ImmDB.TracePastChunkEvict cn curr -> "Past chunk evict: " <> showT cn <> ", cache size: " <> showT curr + ImmDB.TracePastChunksExpired cns curr -> "Past chunks expired: " <> showT cns <> ", cache size: " <> showT curr + +instance ConvertRawHash blk => LogFormatting (ImmDB.TraceChunkValidation blk ImmDB.ChunkNo) where + forMachine _dtal (ImmDB.RewriteSecondaryIndex chunkNo) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.RewriteSecondaryIndex" + , "chunkNo" .= String (renderChunkNo chunkNo) + ] + forMachine _dtal (ImmDB.RewritePrimaryIndex chunkNo) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.RewritePrimaryIndex" + , "chunkNo" .= String (renderChunkNo chunkNo) + ] + forMachine _dtal (ImmDB.MissingPrimaryIndex chunkNo) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.MissingPrimaryIndex" + , "chunkNo" .= String (renderChunkNo chunkNo) + ] + forMachine _dtal (ImmDB.MissingSecondaryIndex chunkNo) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.MissingSecondaryIndex" + , "chunkNo" .= String (renderChunkNo chunkNo) + ] + forMachine _dtal (ImmDB.InvalidPrimaryIndex chunkNo) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.InvalidPrimaryIndex" + , "chunkNo" .= String (renderChunkNo chunkNo) + ] + forMachine _dtal (ImmDB.InvalidSecondaryIndex chunkNo) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.InvalidSecondaryIndex" + , "chunkNo" .= String (renderChunkNo chunkNo) + ] + forMachine _dtal (ImmDB.InvalidChunkFile chunkNo + (ImmDB.ChunkErrHashMismatch hashPrevBlock prevHashOfBlock)) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.InvalidChunkFile.ChunkErrHashMismatch" + , "chunkNo" .= String (renderChunkNo chunkNo) + , "hashPrevBlock" .= String (Text.decodeLatin1 . toRawHash (Proxy @blk) $ hashPrevBlock) + , "prevHashOfBlock" .= String (renderChainHash (Text.decodeLatin1 . toRawHash (Proxy @blk)) prevHashOfBlock) + ] + forMachine dtal (ImmDB.InvalidChunkFile chunkNo (ImmDB.ChunkErrCorrupt pt)) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.InvalidChunkFile.ChunkErrCorrupt" + , "chunkNo" .= String (renderChunkNo chunkNo) + , "block" .= String (renderPointForDetails dtal pt) + ] + forMachine _dtal (ImmDB.ValidatedChunk chunkNo _) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.ValidatedChunk" + , "chunkNo" .= String (renderChunkNo chunkNo) + ] + forMachine _dtal (ImmDB.MissingChunkFile chunkNo) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.MissingChunkFile" + , "chunkNo" .= String (renderChunkNo chunkNo) + ] + forMachine _dtal (ImmDB.InvalidChunkFile chunkNo (ImmDB.ChunkErrRead readIncErr)) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.InvalidChunkFile.ChunkErrRead" + , "chunkNo" .= String (renderChunkNo chunkNo) + , "error" .= String (showT readIncErr) + ] + forMachine _dtal (ImmDB.StartedValidatingChunk initialChunk finalChunk) = + mkObject [ "kind" .= String "TraceImmutableDBEvent.StartedValidatingChunk" + , "initialChunk" .= renderChunkNo initialChunk + , "finalChunk" .= renderChunkNo finalChunk + ] + +instance LogFormatting ImmDB.TraceCacheEvent where + forMachine _dtal (ImmDB.TraceCurrentChunkHit chunkNo nbPastChunksInCache) = + mkObject [ "kind" .= String "TraceCurrentChunkHit" + , "chunkNo" .= String (renderChunkNo chunkNo) + , "noPastChunks" .= String (showT nbPastChunksInCache) + ] + forMachine _dtal (ImmDB.TracePastChunkHit chunkNo nbPastChunksInCache) = + mkObject [ "kind" .= String "TracePastChunkHit" + , "chunkNo" .= String (renderChunkNo chunkNo) + , "noPastChunks" .= String (showT nbPastChunksInCache) + ] + forMachine _dtal (ImmDB.TracePastChunkMiss chunkNo nbPastChunksInCache) = + mkObject [ "kind" .= String "TracePastChunkMiss" + , "chunkNo" .= String (renderChunkNo chunkNo) + , "noPastChunks" .= String (showT nbPastChunksInCache) + ] + forMachine _dtal (ImmDB.TracePastChunkEvict chunkNo nbPastChunksInCache) = + mkObject [ "kind" .= String "TracePastChunkEvict" + , "chunkNo" .= String (renderChunkNo chunkNo) + , "noPastChunks" .= String (showT nbPastChunksInCache) + ] + forMachine _dtal (ImmDB.TracePastChunksExpired chunkNos nbPastChunksInCache) = + mkObject [ "kind" .= String "TracePastChunksExpired" + , "chunkNos" .= String (Text.pack . show $ map renderChunkNo chunkNos) + , "noPastChunks" .= String (showT nbPastChunksInCache) + ] + +docChainDBImmutableDBEvent :: [DocMsg (ImmDB.TraceEvent blk)] +docChainDBImmutableDBEvent = [ + DocMsg + ImmDB.NoValidLastLocation + [] + "No valid last location was found" + , DocMsg + (ImmDB.ValidatedLastLocation anyProto anyProto) + [] + "The last location was validatet" + , DocMsg + (ImmDB.ChunkFileDoesntFit anyProto anyProto) + [] + "The hash of the last block in the previous epoch doesn't match the\ + \ previous hash of the first block in the current epoch" + , DocMsg + (ImmDB.Migrating "") + [] + "Performing a migration of the on-disk files." + , DocMsg + (ImmDB.DeletingAfter anyProto) + [] + "Delete after" + , DocMsg + ImmDB.DBAlreadyClosed + [] + "The immutable DB is already closed" + , DocMsg + ImmDB.DBClosed + [] + "Closing the immutable DB" + ] + <> mapDoc ImmDB.ChunkValidationEvent docChainDBImmutableDBChunkValidation + <> mapDoc ImmDB.TraceCacheEvent docChainDBImmutableDBCacheEvent + +docChainDBImmutableDBChunkValidation :: + [DocMsg (ImmDB.TraceChunkValidation blk ImmDB.ChunkNo)] +docChainDBImmutableDBChunkValidation = [ + DocMsg + (ImmDB.MissingChunkFile anyProto) + [] + "Chunk file is missing" + , DocMsg + (ImmDB.InvalidChunkFile anyProto anyProto) + [] + "Chunk file is invalid" + , DocMsg + (ImmDB.MissingPrimaryIndex anyProto) + [] + "The primary index is missing." + , DocMsg + (ImmDB.MissingSecondaryIndex anyProto) + [] + "The secondary index is missing." + , DocMsg + (ImmDB.InvalidPrimaryIndex anyProto) + [] + "The primary index is invalid." + , DocMsg + (ImmDB.InvalidSecondaryIndex anyProto) + [] + "" + ] + +docChainDBImmutableDBCacheEvent :: [DocMsg ImmDB.TraceCacheEvent] +docChainDBImmutableDBCacheEvent = [ + DocMsg + (ImmDB.TraceCurrentChunkHit anyProto anyProto) + [] + "Current chunk found in the cache." + , DocMsg + (ImmDB.TracePastChunkHit anyProto anyProto) + [] + "Past chunk found in the cache" + , DocMsg + (ImmDB.TracePastChunkMiss anyProto anyProto) + [] + "Past chunk was not found in the cache" + , DocMsg + (ImmDB.TracePastChunkEvict anyProto anyProto) + [] + "The least recently used past chunk was evicted because the cache\ + \ was full." + , DocMsg + (ImmDB.TracePastChunksExpired anyProto anyProto) + [] + "" + ] + +-------------------------------------------------------------------------------- +-- VolatileDBEvent +-------------------------------------------------------------------------------- + +sevTraceVolatileDBEvent :: VolDB.TraceEvent blk -> SeverityS +sevTraceVolatileDBEvent _ = Debug + +namesForChainDBVolatileDBEvent :: VolDB.TraceEvent blk -> [Text] +namesForChainDBVolatileDBEvent VolDb.DBAlreadyClosed = + ["DBAlreadyClosed"] +namesForChainDBVolatileDBEvent (VolDb.Truncate {}) = + ["Truncate"] +namesForChainDBVolatileDBEvent (VolDb.InvalidFileNames {}) = + ["InvalidFileNames"] +namesForChainDBVolatileDBEvent (VolDb.BlockAlreadyHere {}) = + ["BlockAlreadyHere"] + + +instance StandardHash blk => LogFormatting (VolDB.TraceEvent blk) where + forMachine _dtal VolDB.DBAlreadyClosed = + mkObject [ "kind" .= String "DBAlreadyClosed"] + forMachine _dtal (VolDB.BlockAlreadyHere blockId) = + mkObject [ "kind" .= String "BlockAlreadyHere" + , "blockId" .= String (showT blockId) + ] + forMachine _dtal (VolDB.Truncate pErr fsPath blockOffset) = + mkObject [ "kind" .= String "Truncate" + , "parserError" .= String (showT pErr) + , "file" .= String (showT fsPath) + , "blockOffset" .= String (showT blockOffset) + ] + forMachine _dtal (VolDB.InvalidFileNames fsPaths) = + mkObject [ "kind" .= String "InvalidFileNames" + , "files" .= String (Text.pack . show $ map show fsPaths) + ] + +docChainDBVolatileDBEvent :: [DocMsg (VolDB.TraceEvent blk)] +docChainDBVolatileDBEvent = [ + DocMsg + VolDB.DBAlreadyClosed + [] + "When closing the DB it was found itis closed already." + , DocMsg + (VolDB.Truncate anyProto anyProto anyProto) + [] + "Truncates a file up to offset because of the error." + , DocMsg + (VolDB.InvalidFileNames anyProto) + [] + "Reports a list of invalid file paths." + , DocMsg + (VolDB.BlockAlreadyHere anyProto) + [] + "A block was found to be already in the DB." + ] + +-------------------------------------------------------------------------------- +-- Other orophans +-------------------------------------------------------------------------------- + +instance ( StandardHash blk + , LogFormatting (ValidationErr (BlockProtocol blk)) + , LogFormatting (OtherHeaderEnvelopeError blk) + ) + => LogFormatting (HeaderError blk) where + forMachine dtal (HeaderProtocolError err) = + mkObject + [ "kind" .= String "HeaderProtocolError" + , "error" .= forMachine dtal err + ] + forMachine dtal (HeaderEnvelopeError err) = + mkObject + [ "kind" .= String "HeaderEnvelopeError" + , "error" .= forMachine dtal err + ] + +instance ( StandardHash blk + , LogFormatting (OtherHeaderEnvelopeError blk) + ) + => LogFormatting (HeaderEnvelopeError blk) where + forMachine _dtal (UnexpectedBlockNo expect act) = + mkObject + [ "kind" .= String "UnexpectedBlockNo" + , "expected" .= condense expect + , "actual" .= condense act + ] + forMachine _dtal (UnexpectedSlotNo expect act) = + mkObject + [ "kind" .= String "UnexpectedSlotNo" + , "expected" .= condense expect + , "actual" .= condense act + ] + forMachine _dtal (UnexpectedPrevHash expect act) = + mkObject + [ "kind" .= String "UnexpectedPrevHash" + , "expected" .= String (Text.pack $ show expect) + , "actual" .= String (Text.pack $ show act) + ] + forMachine dtal (OtherHeaderEnvelopeError err) = + forMachine dtal err + + +instance ( LogFormatting (LedgerError blk) + , LogFormatting (HeaderError blk)) + => LogFormatting (ExtValidationError blk) where + forMachine dtal (ExtValidationErrorLedger err) = forMachine dtal err + forMachine dtal (ExtValidationErrorHeader err) = forMachine dtal err + + forHuman (ExtValidationErrorLedger err) = forHuman err + forHuman (ExtValidationErrorHeader err) = forHuman err + + asMetrics (ExtValidationErrorLedger err) = asMetrics err + asMetrics (ExtValidationErrorHeader err) = asMetrics err + +instance LogFormatting LedgerDB.DiskSnapshot where + forMachine DDetailed snap = + mkObject [ "kind" .= String "snapshot" + , "snapshot" .= String (Text.pack $ show snap) ] + forMachine _ _snap = mkObject [ "kind" .= String "snapshot" ] + + + +instance (Show (PBFT.PBftVerKeyHash c)) + => LogFormatting (PBFT.PBftValidationErr c) where + forMachine _dtal (PBFT.PBftInvalidSignature text) = + mkObject + [ "kind" .= String "PBftInvalidSignature" + , "error" .= String text + ] + forMachine _dtal (PBFT.PBftNotGenesisDelegate vkhash _ledgerView) = + mkObject + [ "kind" .= String "PBftNotGenesisDelegate" + , "vk" .= String (Text.pack $ show vkhash) + ] + forMachine _dtal (PBFT.PBftExceededSignThreshold vkhash numForged) = + mkObject + [ "kind" .= String "PBftExceededSignThreshold" + , "vk" .= String (Text.pack $ show vkhash) + , "numForged" .= String (Text.pack (show numForged)) + ] + forMachine _dtal PBFT.PBftInvalidSlot = + mkObject + [ "kind" .= String "PBftInvalidSlot" + ] + +instance (Show (PBFT.PBftVerKeyHash c)) + => LogFormatting (PBFT.PBftCannotForge c) where + forMachine _dtal (PBFT.PBftCannotForgeInvalidDelegation vkhash) = + mkObject + [ "kind" .= String "PBftCannotForgeInvalidDelegation" + , "vk" .= String (Text.pack $ show vkhash) + ] + forMachine _dtal (PBFT.PBftCannotForgeThresholdExceeded numForged) = + mkObject + [ "kind" .= String "PBftCannotForgeThresholdExceeded" + , "numForged" .= numForged + ] + +instance (ConvertRawHash blk, StandardHash blk) => LogFormatting (ChainDB.TraceFollowerEvent blk) where + forHuman ChainDB.NewFollower = "A new Follower was created" + forHuman (ChainDB.FollowerNoLongerInMem _rrs) = + "The follower was in the 'FollowerInMem' state but its point is no longer on\ + \ the in-memory chain fragment, so it has to switch to the\ + \ 'FollowerInImmutableDB' state" + forHuman (ChainDB.FollowerSwitchToMem point slot) = + "The follower was in the 'FollowerInImmutableDB' state and is switched to\ + \ the 'FollowerInMem' state. Point: " <> showT point <> " slot: " <> showT slot + forHuman (ChainDB.FollowerNewImmIterator point slot) = + "The follower is in the 'FollowerInImmutableDB' state but the iterator is\ + \ exhausted while the ImmDB has grown, so we open a new iterator to\ + \ stream these blocks too. Point: " <> showT point <> " slot: " <> showT slot + + forMachine _dtal ChainDB.NewFollower = + mkObject [ "kind" .= String "NewFollower" ] + forMachine _dtal (ChainDB.FollowerNoLongerInMem _) = + mkObject [ "kind" .= String "FollowerNoLongerInMem" ] + forMachine _dtal (ChainDB.FollowerSwitchToMem _ _) = + mkObject [ "kind" .= String "FollowerSwitchToMem" ] + forMachine _dtal (ChainDB.FollowerNewImmIterator _ _) = + mkObject [ "kind" .= String "FollowerNewImmIterator" ] + +instance ( ConvertRawHash blk + , StandardHash blk + , LogFormatting (LedgerError blk) + , LogFormatting (RealPoint blk) + , LogFormatting (OtherHeaderEnvelopeError blk) + , LogFormatting (ExtValidationError blk) + , LogFormatting (ValidationErr (BlockProtocol blk)) + ) + => LogFormatting (ChainDB.InvalidBlockReason blk) where + forMachine dtal (ChainDB.ValidationError extvalerr) = + mkObject + [ "kind" .= String "ValidationError" + , "error" .= forMachine dtal extvalerr + ] + forMachine dtal (ChainDB.InFutureExceedsClockSkew point) = + mkObject + [ "kind" .= String "InFutureExceedsClockSkew" + , "point" .= forMachine dtal point + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Consensus.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Consensus.hs new file mode 100644 index 00000000000..9a348174a65 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/Consensus.hs @@ -0,0 +1,1522 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.Consensus + ( severityChainSyncClientEvent + , namesForChainSyncClientEvent + , docChainSyncClientEvent + + , severityChainSyncServerEvent + , namesForChainSyncServerEvent + , docChainSyncServerEvent + + , severityBlockFetchDecision + , namesForBlockFetchDecision + , docBlockFetchDecision + + , severityBlockFetchClient + , namesForBlockFetchClient + , docBlockFetchClient + + , severityBlockFetchServer + , namesForBlockFetchServer + , docBlockFetchServer + + , severityTxInbound + , namesForTxInbound + , docTxInbound + + , severityTxOutbound + , namesForTxOutbound + , docTxOutbound + + , severityLocalTxSubmissionServer + , namesForLocalTxSubmissionServer + , docLocalTxSubmissionServer + + , severityMempool + , namesForMempool + , docMempool + + , TraceStartLeadershipCheckPlus (..) + , ForgeTracerType + , forgeTracerTransform + , severityForge + , namesForForge + , docForge + + , namesForBlockchainTime + , severityBlockchainTime + , docBlockchainTime + + , namesForKeepAliveClient + , severityKeepAliveClient + , docKeepAliveClient + + ) where + + +import Control.Monad.Class.MonadTime (Time (..)) +import Data.Aeson (ToJSON, Value (Number, String), toJSON, (.=)) +import Data.SOP.Strict +import qualified Data.Text as Text +import Data.Time (DiffTime) +import Text.Show + +import Cardano.Logging +import Cardano.Node.Queries (HasKESInfo (..)) +import Cardano.Node.Tracing.Era.Byron () +import Cardano.Node.Tracing.Era.Shelley () +import Cardano.Node.Tracing.Formatting () +import Cardano.Node.Tracing.Render +import Cardano.Node.Tracing.Tracers.StartLeadershipCheck +import Cardano.Prelude hiding (All, Show, show) + +import Cardano.Protocol.TPraos.OCert (KESPeriod (..)) + +import Ouroboros.Network.BlockFetch.ClientState (TraceLabelPeer (..)) +import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch +import Ouroboros.Network.KeepAlive (TraceKeepAliveClient (..)) +import Ouroboros.Network.TxSubmission.Inbound hiding(txId) +import Ouroboros.Network.TxSubmission.Outbound +import Ouroboros.Network.Block hiding (blockPrevHash) +import Ouroboros.Network.BlockFetch.Decision +import Ouroboros.Network.DeltaQ (GSV (..), PeerGSV (..)) + +import Ouroboros.Consensus.Block +import Ouroboros.Consensus.BlockchainTime (SystemStart (..)) +import Ouroboros.Consensus.BlockchainTime.WallClock.Util (TraceBlockchainTimeEvent (..)) +import Ouroboros.Consensus.Cardano.Block +import Ouroboros.Consensus.Ledger.Inspect (LedgerEvent (..), LedgerUpdate, LedgerWarning) +import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr, GenTxId, + LedgerSupportsMempool, txForgetValidated, txId, HasTxId) +import Ouroboros.Consensus.Ledger.SupportsProtocol +import Ouroboros.Consensus.Mempool.API (MempoolSize (..), TraceEventMempool (..)) +import Ouroboros.Consensus.MiniProtocol.BlockFetch.Server + (TraceBlockFetchServerEvent (..)) +import Ouroboros.Consensus.MiniProtocol.ChainSync.Client +import Ouroboros.Consensus.MiniProtocol.ChainSync.Server +import Ouroboros.Consensus.MiniProtocol.LocalTxSubmission.Server + (TraceLocalTxSubmissionServerEvent (..)) +import Ouroboros.Consensus.Node.Run (SerialiseNodeToNodeConstraints, estimateBlockSize) +import Ouroboros.Consensus.Node.Tracers +import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey + + + + +instance LogFormatting a => LogFormatting (TraceLabelCreds a) where + forMachine dtal (TraceLabelCreds creds a) = + mkObject [ "credentials" .= toJSON creds + , "val" .= forMachine dtal a + ] +-- TODO Trace lable creds as well + forHuman (TraceLabelCreds _t a) = forHuman a + asMetrics (TraceLabelCreds _t a) = asMetrics a + + +instance (LogFormatting (LedgerUpdate blk), LogFormatting (LedgerWarning blk)) + => LogFormatting (LedgerEvent blk) where + forMachine dtal = \case + LedgerUpdate update -> forMachine dtal update + LedgerWarning warning -> forMachine dtal warning + +tipToObject :: forall blk. ConvertRawHash blk => Tip blk -> [(Text, Value)] +tipToObject = \case + TipGenesis -> + [ "slot" .= toJSON (0 :: Int) + , "block" .= String "genesis" + , "blockNo" .= toJSON ((-1) :: Int) + ] + Tip slot hash blockno -> + [ "slot" .= slot + , "block" .= String (renderHeaderHash (Proxy @blk) hash) + , "blockNo" .= blockno + ] + +-------------------------------------------------------------------------------- +-- ChainSyncClient Tracer +-------------------------------------------------------------------------------- + +severityChainSyncClientEvent :: + BlockFetch.TraceLabelPeer peer (TraceChainSyncClientEvent blk) -> SeverityS +severityChainSyncClientEvent (BlockFetch.TraceLabelPeer _ e) = + severityChainSyncClientEvent' e + +namesForChainSyncClientEvent :: + BlockFetch.TraceLabelPeer peer (TraceChainSyncClientEvent blk) -> [Text] +namesForChainSyncClientEvent (BlockFetch.TraceLabelPeer _ e) = + namesForChainSyncClientEvent' e + +severityChainSyncClientEvent' :: TraceChainSyncClientEvent blk -> SeverityS +severityChainSyncClientEvent' TraceDownloadedHeader {} = Info +severityChainSyncClientEvent' TraceFoundIntersection {} = Info +severityChainSyncClientEvent' TraceRolledBack {} = Notice +severityChainSyncClientEvent' TraceException {} = Warning +severityChainSyncClientEvent' TraceTermination {} = Notice + +namesForChainSyncClientEvent' :: TraceChainSyncClientEvent blk -> [Text] +namesForChainSyncClientEvent' TraceDownloadedHeader {} = + ["ChainSyncClientEvent.DownloadedHeader"] +namesForChainSyncClientEvent' TraceFoundIntersection {} = + ["ChainSyncClientEvent.FoundIntersection"] +namesForChainSyncClientEvent' TraceRolledBack {} = + ["ChainSyncClientEvent.RolledBack"] +namesForChainSyncClientEvent' TraceException {} = + ["ChainSyncClientEvent.Exception"] +namesForChainSyncClientEvent' TraceTermination {} = + ["ChainSyncClientEvent.Termination"] + +instance (Show (Header blk), ConvertRawHash blk, LedgerSupportsProtocol blk) + => LogFormatting (TraceChainSyncClientEvent blk) where + forHuman (TraceDownloadedHeader pt) = + "While following a candidate chain, we rolled forward by downloading a\ + \ header. " <> showT (headerPoint pt) + forHuman (TraceRolledBack tip) = + "While following a candidate chain, we rolled back to the given point: " + <> showT tip + forHuman (TraceException exc) = + "An exception was thrown by the Chain Sync Client. " + <> showT exc + forHuman TraceFoundIntersection {} = + "We found an intersection between our chain fragment and the\ + \ candidate's chain." + forHuman (TraceTermination res) = + "The client has terminated. " <> showT res + + forMachine _dtal (TraceDownloadedHeader h) = + mkObject $ + [ "kind" .= String "DownloadedHeader" + ] <> tipToObject (tipFromHeader h) + forMachine dtal (TraceRolledBack tip) = + mkObject [ "kind" .= String "RolledBack" + , "tip" .= forMachine dtal tip ] + forMachine _dtal (TraceException exc) = + mkObject [ "kind" .= String "Exception" + , "exception" .= String (Text.pack $ show exc) ] + forMachine _dtal TraceFoundIntersection {} = + mkObject [ "kind" .= String "FoundIntersection" ] + forMachine _dtal (TraceTermination reason) = + mkObject [ "kind" .= String "Termination" + , "reason" .= String (Text.pack $ show reason) ] + +docChainSyncClientEvent :: + Documented (BlockFetch.TraceLabelPeer peer (TraceChainSyncClientEvent blk)) +docChainSyncClientEvent = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceDownloadedHeader anyProto)) + [] + "While following a candidate chain, we rolled forward by downloading a\ + \ header." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceRolledBack anyProto)) + [] + "While following a candidate chain, we rolled back to the given point." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceFoundIntersection anyProto anyProto anyProto)) + [] + "We found an intersection between our chain fragment and the\ + \ candidate's chain." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceException anyProto)) + [] + "An exception was thrown by the Chain Sync Client." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceTermination anyProto)) + [] + "The client has terminated." + ] + +-------------------------------------------------------------------------------- +-- ChainSyncServer Tracer +-------------------------------------------------------------------------------- + +severityChainSyncServerEvent :: TraceChainSyncServerEvent blk -> SeverityS +severityChainSyncServerEvent TraceChainSyncServerRead {} = Info +severityChainSyncServerEvent TraceChainSyncServerReadBlocked {} = Info +severityChainSyncServerEvent TraceChainSyncRollForward {} = Info +severityChainSyncServerEvent TraceChainSyncRollBackward {} = Info + +namesForChainSyncServerEvent :: TraceChainSyncServerEvent blk -> [Text] +namesForChainSyncServerEvent TraceChainSyncServerRead {} = + ["ChainSyncServerEvent.ServerRead"] +namesForChainSyncServerEvent TraceChainSyncServerReadBlocked {} = + ["ChainSyncServerEvent.ServerReadBlocked"] +namesForChainSyncServerEvent TraceChainSyncRollForward {} = + ["ChainSyncServerEvent.RollForward"] +namesForChainSyncServerEvent TraceChainSyncRollBackward {} = + ["ChainSyncServerEvent.RollBackward"] + +instance ConvertRawHash blk + => LogFormatting (TraceChainSyncServerEvent blk) where + forMachine _dtal (TraceChainSyncServerRead tip (AddBlock _hdr)) = + mkObject $ + [ "kind" .= String "ChainSyncServerRead.AddBlock" + ] <> tipToObject tip + forMachine _dtal (TraceChainSyncServerRead tip (RollBack _pt)) = + mkObject $ + [ "kind" .= String "ChainSyncServerRead.RollBack" + ] <> tipToObject tip + forMachine _dtal (TraceChainSyncServerReadBlocked tip (AddBlock _hdr)) = + mkObject $ + [ "kind" .= String "ChainSyncServerReadBlocked.AddBlock" + ] <> tipToObject tip + forMachine _dtal (TraceChainSyncServerReadBlocked tip (RollBack _pt)) = + mkObject $ + [ "kind" .= String "ChainSyncServerReadBlocked.RollBack" + ] <> tipToObject tip + forMachine dtal (TraceChainSyncRollForward point) = + mkObject [ "kind" .= String "ChainSyncServerRead.RollForward" + , "point" .= forMachine dtal point + ] + forMachine dtal (TraceChainSyncRollBackward point) = + mkObject [ "kind" .= String "ChainSyncServerRead.ChainSyncRollBackward" + , "point" .= forMachine dtal point + ] + + asMetrics (TraceChainSyncRollForward _point) = + [CounterM "cardano.node.chainSync.rollForward" Nothing] + asMetrics _ = [] + + +docChainSyncServerEvent :: Documented (TraceChainSyncServerEvent blk) +docChainSyncServerEvent = Documented [ + DocMsg + (TraceChainSyncServerRead anyProto anyProto) + [] + "A server read has occured, either for an add block or a rollback" + , DocMsg + (TraceChainSyncServerReadBlocked anyProto anyProto) + [] + "A server read has blocked, either for an add block or a rollback" + , DocMsg + (TraceChainSyncRollForward anyProto) + [("cardano.node.chainSync.rollForward", "")] + "Roll forward to the given point." + , DocMsg + (TraceChainSyncRollBackward anyProto) + [] + "" + ] + +-------------------------------------------------------------------------------- +-- BlockFetchDecision Tracer +-------------------------------------------------------------------------------- + +severityBlockFetchDecision :: + [BlockFetch.TraceLabelPeer peer (FetchDecision [Point header])] + -> SeverityS +severityBlockFetchDecision [] = Info +severityBlockFetchDecision l = maximum $ + map (\(BlockFetch.TraceLabelPeer _ a) -> fetchDecisionSeverity a) l + where + fetchDecisionSeverity :: FetchDecision a -> SeverityS + fetchDecisionSeverity fd = + case fd of + Left FetchDeclineChainNotPlausible -> Debug + Left FetchDeclineChainNoIntersection -> Notice + Left FetchDeclineAlreadyFetched -> Debug + Left FetchDeclineInFlightThisPeer -> Debug + Left FetchDeclineInFlightOtherPeer -> Debug + Left FetchDeclinePeerShutdown -> Info + Left FetchDeclinePeerSlow -> Info + Left FetchDeclineReqsInFlightLimit {} -> Info + Left FetchDeclineBytesInFlightLimit {} -> Info + Left FetchDeclinePeerBusy {} -> Info + Left FetchDeclineConcurrencyLimit {} -> Info + Right _ -> Info + +namesForBlockFetchDecision :: + [BlockFetch.TraceLabelPeer peer (FetchDecision [Point header])] + -> [Text] +namesForBlockFetchDecision _ = [] + +instance (LogFormatting peer, Show peer) => + LogFormatting [TraceLabelPeer peer (FetchDecision [Point header])] where + forMachine DMinimal _ = emptyObject + forMachine _ [] = mkObject + [ "kind" .= String "EmptyPeersFetch"] + forMachine _ xs = mkObject + [ "kind" .= String "PeersFetch" + , "peers" .= toJSON + (foldl' (\acc x -> forMachine DDetailed x : acc) [] xs) ] + + asMetrics peers = [IntM "cardano.node.connectedPeers" (fromIntegral (length peers))] + +instance (LogFormatting peer, Show peer, LogFormatting a) + => LogFormatting (TraceLabelPeer peer a) where + forMachine dtal (TraceLabelPeer peerid a) = + mkObject [ "peer" .= forMachine dtal peerid ] <> forMachine dtal a + forHuman (TraceLabelPeer peerid a) = "Peer is " <> showT peerid + <> ". " <> forHuman a + asMetrics (TraceLabelPeer _peerid a) = asMetrics a + +instance LogFormatting (FetchDecision [Point header]) where + forMachine _dtal (Left decline) = + mkObject [ "kind" .= String "FetchDecision declined" + , "declined" .= String (showT decline) + ] + forMachine _dtal (Right results) = + mkObject [ "kind" .= String "FetchDecision results" + , "length" .= String (showT $ length results) + ] + +docBlockFetchDecision :: + Documented [BlockFetch.TraceLabelPeer remotePeer (FetchDecision [Point (Header blk)])] +docBlockFetchDecision = Documented [ + DocMsg + [BlockFetch.TraceLabelPeer anyProto (Right anyProto)] + [("cardano.node.connectedPeers", "Number of connected peers")] + "Throughout the decision making process we accumulate reasons to decline\ + \ to fetch any blocks. This message carries the intermediate and final\ + \ results." + ] + +-------------------------------------------------------------------------------- +-- BlockFetchClient Tracer +-------------------------------------------------------------------------------- + +severityBlockFetchClient :: + BlockFetch.TraceLabelPeer peer (BlockFetch.TraceFetchClientState header) + -> SeverityS +severityBlockFetchClient (BlockFetch.TraceLabelPeer _p bf) = severityBlockFetchClient' bf + +severityBlockFetchClient' :: + BlockFetch.TraceFetchClientState header + -> SeverityS +severityBlockFetchClient' BlockFetch.AddedFetchRequest {} = Info +severityBlockFetchClient' BlockFetch.AcknowledgedFetchRequest {} = Info +severityBlockFetchClient' BlockFetch.SendFetchRequest {} = Info +severityBlockFetchClient' BlockFetch.StartedFetchBatch {} = Info +severityBlockFetchClient' BlockFetch.CompletedBlockFetch {} = Info +severityBlockFetchClient' BlockFetch.CompletedFetchBatch {} = Info +severityBlockFetchClient' BlockFetch.RejectedFetchBatch {} = Info +severityBlockFetchClient' BlockFetch.ClientTerminating {} = Notice + +namesForBlockFetchClient :: + BlockFetch.TraceLabelPeer peer (BlockFetch.TraceFetchClientState header) + -> [Text] +namesForBlockFetchClient (BlockFetch.TraceLabelPeer _p bf) = namesForBlockFetchClient' bf + +namesForBlockFetchClient' :: + BlockFetch.TraceFetchClientState header + -> [Text] +namesForBlockFetchClient' BlockFetch.AddedFetchRequest {} = + ["AddedFetchRequest"] +namesForBlockFetchClient' BlockFetch.AcknowledgedFetchRequest {} = + ["AcknowledgedFetchRequest"] +namesForBlockFetchClient' BlockFetch.SendFetchRequest {} = + ["SendFetchRequest"] +namesForBlockFetchClient' BlockFetch.StartedFetchBatch {} = + ["StartedFetchBatch"] +namesForBlockFetchClient' BlockFetch.CompletedBlockFetch {} = + ["CompletedBlockFetch"] +namesForBlockFetchClient' BlockFetch.CompletedFetchBatch {} = + ["CompletedFetchBatch"] +namesForBlockFetchClient' BlockFetch.RejectedFetchBatch {} = + ["RejectedFetchBatch"] +namesForBlockFetchClient' BlockFetch.ClientTerminating {} = + ["ClientTerminating"] + +instance LogFormatting (BlockFetch.TraceFetchClientState header) where + forMachine _dtal BlockFetch.AddedFetchRequest {} = + mkObject [ "kind" .= String "AddedFetchRequest" ] + forMachine _dtal BlockFetch.AcknowledgedFetchRequest {} = + mkObject [ "kind" .= String "AcknowledgedFetchRequest" ] + forMachine _dtal BlockFetch.SendFetchRequest {} = + mkObject [ "kind" .= String "SendFetchRequest" ] + forMachine _dtal BlockFetch.CompletedBlockFetch {} = + mkObject [ "kind" .= String "CompletedBlockFetch" ] + forMachine _dtal BlockFetch.CompletedFetchBatch {} = + mkObject [ "kind" .= String "CompletedFetchBatch" ] + forMachine _dtal BlockFetch.StartedFetchBatch {} = + mkObject [ "kind" .= String "StartedFetchBatch" ] + forMachine _dtal BlockFetch.RejectedFetchBatch {} = + mkObject [ "kind" .= String "RejectedFetchBatch" ] + forMachine _dtal BlockFetch.ClientTerminating {} = + mkObject [ "kind" .= String "ClientTerminating" ] + +docBlockFetchClient :: + Documented (BlockFetch.TraceLabelPeer remotePeer (BlockFetch.TraceFetchClientState (Header blk))) +docBlockFetchClient = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (BlockFetch.AddedFetchRequest + anyProto + anyProto + anyProto + anyProto)) + [] + "The block fetch decision thread has added a new fetch instruction\ + \ consisting of one or more individual request ranges." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (BlockFetch.AcknowledgedFetchRequest + anyProto)) + [] + "Mark the point when the fetch client picks up the request added\ + \ by the block fetch decision thread. Note that this event can happen\ + \ fewer times than the 'AddedFetchRequest' due to fetch request merging." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (BlockFetch.StartedFetchBatch + anyProto + anyProto + anyProto + anyProto)) + [] + "Mark the start of receiving a streaming batch of blocks. This will\ + \ be followed by one or more 'CompletedBlockFetch' and a final\ + \ 'CompletedFetchBatch'" + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (BlockFetch.CompletedFetchBatch + anyProto + anyProto + anyProto + anyProto)) + [] + "Mark the successful end of receiving a streaming batch of blocks." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (BlockFetch.RejectedFetchBatch + anyProto + anyProto + anyProto + anyProto)) + [] + "If the other peer rejects our request then we have this event\ + \ instead of 'StartedFetchBatch' and 'CompletedFetchBatch'." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (BlockFetch.ClientTerminating 1)) + [] + "The client is terminating. Log the number of outstanding\ + \ requests." + ] + +-------------------------------------------------------------------------------- +-- BlockFetchServer Tracer +-------------------------------------------------------------------------------- + +severityBlockFetchServer :: + TraceBlockFetchServerEvent blk + -> SeverityS +severityBlockFetchServer _ = Info + +namesForBlockFetchServer :: + TraceBlockFetchServerEvent blk + -> [Text] +namesForBlockFetchServer TraceBlockFetchServerSendBlock {} = ["SendBlock"] + +instance ConvertRawHash blk => LogFormatting (TraceBlockFetchServerEvent blk) where + forMachine _dtal (TraceBlockFetchServerSendBlock blk) = + mkObject [ "kind" .= String "BlockFetchServer" + , "block" .= String (renderChainHash + @blk + (renderHeaderHash (Proxy @blk)) + $ pointHash blk)] +-- TODO JNF + asMetrics (TraceBlockFetchServerSendBlock _p) = + [CounterM "cardano.node.served.block" Nothing] + +docBlockFetchServer :: + Documented (TraceBlockFetchServerEvent blk) +docBlockFetchServer = Documented [ + DocMsg + (TraceBlockFetchServerSendBlock GenesisPoint) + [("cardano.node.served.block", "")] + "The server sent a block to the peer." + ] + + +-------------------------------------------------------------------------------- +-- TxInbound Tracer +-------------------------------------------------------------------------------- + +severityTxInbound :: + BlockFetch.TraceLabelPeer peer (TraceTxSubmissionInbound (GenTxId blk) (GenTx blk)) + -> SeverityS +severityTxInbound (BlockFetch.TraceLabelPeer _p ti) = severityTxInbound' ti + +severityTxInbound' :: + TraceTxSubmissionInbound (GenTxId blk) (GenTx blk) + -> SeverityS +severityTxInbound' TraceTxSubmissionCollected {} = Debug +severityTxInbound' TraceTxSubmissionProcessed {} = Debug +severityTxInbound' TraceTxInboundTerminated = Notice +severityTxInbound' TraceTxInboundCannotRequestMoreTxs {} = Debug +severityTxInbound' TraceTxInboundCanRequestMoreTxs {} = Debug + +namesForTxInbound :: + BlockFetch.TraceLabelPeer peer (TraceTxSubmissionInbound (GenTxId blk) (GenTx blk)) + -> [Text] +namesForTxInbound (BlockFetch.TraceLabelPeer _p ti) = namesForTxInbound' ti + +namesForTxInbound' :: + TraceTxSubmissionInbound (GenTxId blk) (GenTx blk) + -> [Text] +namesForTxInbound' (TraceTxSubmissionCollected _) = + ["TxSubmissionCollected"] +namesForTxInbound' (TraceTxSubmissionProcessed _) = + ["TxSubmissionProcessed"] +namesForTxInbound' TraceTxInboundTerminated = + ["TxInboundTerminated"] +namesForTxInbound' TraceTxInboundCanRequestMoreTxs {} = + ["TxInboundCanRequestMoreTxs"] +namesForTxInbound' TraceTxInboundCannotRequestMoreTxs {} = + ["TxInboundCannotRequestMoreTxs"] + +instance LogFormatting (TraceTxSubmissionInbound txid tx) where + forMachine _dtal (TraceTxSubmissionCollected count) = + mkObject + [ "kind" .= String "TraceTxSubmissionCollected" + , "count" .= toJSON count + ] + forMachine _dtal (TraceTxSubmissionProcessed processed) = + mkObject + [ "kind" .= String "TraceTxSubmissionProcessed" + , "accepted" .= toJSON (ptxcAccepted processed) + , "rejected" .= toJSON (ptxcRejected processed) + ] + forMachine _dtal TraceTxInboundTerminated = + mkObject + [ "kind" .= String "TraceTxInboundTerminated" + ] + forMachine _dtal (TraceTxInboundCanRequestMoreTxs count) = + mkObject + [ "kind" .= String "TraceTxInboundCanRequestMoreTxs" + , "count" .= toJSON count + ] + forMachine _dtal (TraceTxInboundCannotRequestMoreTxs count) = + mkObject + [ "kind" .= String "TraceTxInboundCannotRequestMoreTxs" + , "count" .= toJSON count + ] + + asMetrics (TraceTxSubmissionCollected count)= + [CounterM "cardano.node.submissions.submitted" (Just count)] + asMetrics (TraceTxSubmissionProcessed processed) = + [ CounterM "cardano.node.submissions.accepted" + (Just (ptxcAccepted processed)) + , CounterM "cardano.node.submissions.rejected" + (Just (ptxcRejected processed)) + ] + asMetrics _ = [] + +docTxInbound :: + Documented (BlockFetch.TraceLabelPeer remotePeer + (TraceTxSubmissionInbound txid tx)) +docTxInbound = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceTxSubmissionCollected 1)) + [ ("cardano.node.submissions.submitted", "")] + "Number of transactions just about to be inserted." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceTxSubmissionProcessed (ProcessedTxCount 1 2))) + [ ("cardano.node.submissions.accepted", "") + , ("cardano.node.submissions.rejected", "") + ] + "Just processed transaction pass/fail breakdown." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + TraceTxInboundTerminated) + [] + "Server received 'MsgDone'." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceTxInboundCanRequestMoreTxs 1)) + [] + "There are no replies in flight, but we do know some more txs we\ + \ can ask for, so lets ask for them and more txids." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceTxInboundCannotRequestMoreTxs 1)) + [] + "There's no replies in flight, and we have no more txs we can\ + \ ask for so the only remaining thing to do is to ask for more\ + \ txids. Since this is the only thing to do now, we make this a\ + \ blocking call." + ] + + +-------------------------------------------------------------------------------- +-- TxOutbound Tracer +-------------------------------------------------------------------------------- + +severityTxOutbound :: + BlockFetch.TraceLabelPeer peer (TraceTxSubmissionOutbound (GenTxId blk) (GenTx blk)) + -> SeverityS +severityTxOutbound (BlockFetch.TraceLabelPeer _p _ti) = Info + +namesForTxOutbound :: + BlockFetch.TraceLabelPeer peer (TraceTxSubmissionOutbound (GenTxId blk) (GenTx blk)) + -> [Text] +namesForTxOutbound (BlockFetch.TraceLabelPeer _p ti) = namesForTxOutbound' ti + +namesForTxOutbound' :: + TraceTxSubmissionOutbound (GenTxId blk) (GenTx blk) + -> [Text] +namesForTxOutbound' TraceTxSubmissionOutboundRecvMsgRequestTxs {} = + ["TxSubmissionOutboundRecvMsgRequest"] +namesForTxOutbound' TraceTxSubmissionOutboundSendMsgReplyTxs {} = + ["TxSubmissionOutboundSendMsgReply"] +namesForTxOutbound' TraceControlMessage {} = + ["ControlMessage"] + +instance (Show txid, Show tx) + => LogFormatting (TraceTxSubmissionOutbound txid tx) where + forMachine DDetailed (TraceTxSubmissionOutboundRecvMsgRequestTxs txids) = + mkObject + [ "kind" .= String "TraceTxSubmissionOutboundRecvMsgRequestTxs" + , "txIds" .= String (Text.pack $ show txids) + ] + forMachine _dtal (TraceTxSubmissionOutboundRecvMsgRequestTxs _txids) = + mkObject + [ "kind" .= String "TraceTxSubmissionOutboundRecvMsgRequestTxs" + ] + forMachine DDetailed (TraceTxSubmissionOutboundSendMsgReplyTxs txs) = + mkObject + [ "kind" .= String "TraceTxSubmissionOutboundSendMsgReplyTxs" + , "txs" .= String (Text.pack $ show txs) + ] + forMachine _dtal (TraceTxSubmissionOutboundSendMsgReplyTxs _txs) = + mkObject + [ "kind" .= String "TraceTxSubmissionOutboundSendMsgReplyTxs" + ] + forMachine _dtal (TraceControlMessage _msg) = + mkObject + [ "kind" .= String "TraceControlMessage" + ] + +docTxOutbound :: forall remotePeer txid tx. + Documented (BlockFetch.TraceLabelPeer remotePeer + (TraceTxSubmissionOutbound txid tx)) +docTxOutbound = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceTxSubmissionOutboundRecvMsgRequestTxs anyProto)) + [] + "The IDs of the transactions requested." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceTxSubmissionOutboundSendMsgReplyTxs anyProto)) + [] + "The transactions to be sent in the response." + , + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceControlMessage anyProto)) + [] + "" + ] + +-------------------------------------------------------------------------------- +-- TxSubmissionServer Tracer +-------------------------------------------------------------------------------- + +severityLocalTxSubmissionServer :: + TraceLocalTxSubmissionServerEvent blk + -> SeverityS +severityLocalTxSubmissionServer _ = Info + +namesForLocalTxSubmissionServer :: + TraceLocalTxSubmissionServerEvent blk + -> [Text] +namesForLocalTxSubmissionServer TraceReceivedTx {} = ["ReceivedTx"] + +instance LogFormatting (TraceLocalTxSubmissionServerEvent blk) where + forMachine _dtal (TraceReceivedTx _gtx) = + mkObject [ "kind" .= String "ReceivedTx" ] + +docLocalTxSubmissionServer :: Documented (TraceLocalTxSubmissionServerEvent blk) +docLocalTxSubmissionServer = Documented [ + DocMsg + (TraceReceivedTx anyProto) + [] + "A transaction was received." + ] + +-------------------------------------------------------------------------------- +-- Mempool Tracer +-------------------------------------------------------------------------------- + +severityMempool :: + TraceEventMempool blk + -> SeverityS +severityMempool _ = Info + +namesForMempool :: TraceEventMempool blk -> [Text] +namesForMempool TraceMempoolAddedTx {} = ["AddedTx"] +namesForMempool TraceMempoolRejectedTx {} = ["RejectedTx"] +namesForMempool TraceMempoolRemoveTxs {} = ["RemoveTxs"] +namesForMempool TraceMempoolManuallyRemovedTxs {} = ["ManuallyRemovedTxs"] + +instance + ( Show (ApplyTxErr blk) + , LogFormatting (ApplyTxErr blk) + , LogFormatting (GenTx blk) + , ToJSON (GenTxId blk) + , LedgerSupportsMempool blk + ) => LogFormatting (TraceEventMempool blk) where + forMachine dtal (TraceMempoolAddedTx tx _mpSzBefore mpSzAfter) = + mkObject + [ "kind" .= String "TraceMempoolAddedTx" + , "tx" .= forMachine dtal (txForgetValidated tx) + , "mempoolSize" .= forMachine dtal mpSzAfter + ] + forMachine dtal (TraceMempoolRejectedTx tx txApplyErr mpSz) = + mkObject + [ "kind" .= String "TraceMempoolRejectedTx" + , "err" .= forMachine dtal txApplyErr + , "tx" .= forMachine dtal tx + , "mempoolSize" .= forMachine dtal mpSz + ] + forMachine dtal (TraceMempoolRemoveTxs txs mpSz) = + mkObject + [ "kind" .= String "TraceMempoolRemoveTxs" + , "txs" .= map (forMachine dtal . txForgetValidated) txs + , "mempoolSize" .= forMachine dtal mpSz + ] + forMachine dtal (TraceMempoolManuallyRemovedTxs txs0 txs1 mpSz) = + mkObject + [ "kind" .= String "TraceMempoolManuallyRemovedTxs" + , "txsRemoved" .= txs0 + , "txsInvalidated" .= map (forMachine dtal . txForgetValidated) txs1 + , "mempoolSize" .= forMachine dtal mpSz + ] + + asMetrics (TraceMempoolAddedTx _tx _mpSzBefore mpSz) = + [ IntM "cardano.node.txsInMempool" (fromIntegral $ msNumTxs mpSz) + , IntM "cardano.node.mempoolBytes" (fromIntegral $ msNumBytes mpSz) + ] + asMetrics (TraceMempoolRejectedTx _tx _txApplyErr mpSz) = + [ IntM "cardano.node.txsInMempool" (fromIntegral $ msNumTxs mpSz) + , IntM "cardano.node.mempoolBytes" (fromIntegral $ msNumBytes mpSz) + ] + asMetrics (TraceMempoolRemoveTxs _txs mpSz) = + [ IntM "cardano.node.txsInMempool" (fromIntegral $ msNumTxs mpSz) + , IntM "cardano.node.mempoolBytes" (fromIntegral $ msNumBytes mpSz) + ] + asMetrics (TraceMempoolManuallyRemovedTxs [] _txs1 mpSz) = + [ IntM "cardano.node.txsInMempool" (fromIntegral $ msNumTxs mpSz) + , IntM "cardano.node.mempoolBytes" (fromIntegral $ msNumBytes mpSz) + ] + asMetrics (TraceMempoolManuallyRemovedTxs txs _txs1 mpSz) = + [ IntM "cardano.node.txsInMempool" (fromIntegral $ msNumTxs mpSz) + , IntM "cardano.node.mempoolBytes" (fromIntegral $ msNumBytes mpSz) + , CounterM "cardano.node.txsProcessedNum" (Just (fromIntegral $ length txs)) + ] + +instance LogFormatting MempoolSize where + forMachine _dtal MempoolSize{msNumTxs, msNumBytes} = + mkObject + [ "numTxs" .= msNumTxs + , "bytes" .= msNumBytes + ] + +docMempool :: forall blk. Documented (TraceEventMempool blk) +docMempool = Documented [ + DocMsg + (TraceMempoolAddedTx anyProto anyProto anyProto) + [ ("cardano.node.txsInMempool","Transactions in mempool") + , ("cardano.node.mempoolBytes", "Byte size of the mempool") + ] + "New, valid transaction that was added to the Mempool." + , DocMsg + (TraceMempoolRejectedTx anyProto anyProto anyProto) + [ ("cardano.node.txsInMempool","Transactions in mempool") + , ("cardano.node.mempoolBytes", "Byte size of the mempool") + ] + "New, invalid transaction thas was rejected and thus not added to\ + \ the Mempool." + , DocMsg + (TraceMempoolRemoveTxs [anyProto] anyProto) + [ ("cardano.node.txsInMempool","Transactions in mempool") + , ("cardano.node.mempoolBytes", "Byte size of the mempool") + ] + "Previously valid transactions that are no longer valid because of\ + \ changes in the ledger state. These transactions have been removed\ + \ from the Mempool." + , DocMsg + (TraceMempoolManuallyRemovedTxs [anyProto] [anyProto] anyProto) + [ ("cardano.node.txsInMempool","Transactions in mempool") + , ("cardano.node.mempoolBytes", "Byte size of the mempool") + , ("cardano.node.txsProcessedNum", "") + ] + "Transactions that have been manually removed from the Mempool." + ] + + +-------------------------------------------------------------------------------- +-- ForgeEvent Tracer +-------------------------------------------------------------------------------- + +severityForge :: ForgeTracerType blk -> SeverityS +severityForge (Left t) = severityForge' t +severityForge (Right t) = severityForge''' t + +severityForge' :: TraceLabelCreds (TraceForgeEvent blk) -> SeverityS +severityForge' (TraceLabelCreds _t e) = severityForge'' e + +severityForge'' :: TraceForgeEvent blk -> SeverityS +severityForge'' TraceStartLeadershipCheck {} = Info +severityForge'' TraceSlotIsImmutable {} = Error +severityForge'' TraceBlockFromFuture {} = Error +severityForge'' TraceBlockContext {} = Debug +severityForge'' TraceNoLedgerState {} = Error +severityForge'' TraceLedgerState {} = Debug +severityForge'' TraceNoLedgerView {} = Error +severityForge'' TraceLedgerView {} = Debug +severityForge'' TraceForgeStateUpdateError {} = Error +severityForge'' TraceNodeCannotForge {} = Error +severityForge'' TraceNodeNotLeader {} = Info +severityForge'' TraceNodeIsLeader {} = Info +severityForge'' TraceForgedBlock {} = Info +severityForge'' TraceDidntAdoptBlock {} = Error +severityForge'' TraceForgedInvalidBlock {} = Error +severityForge'' TraceAdoptedBlock {} = Info + +severityForge''' :: TraceLabelCreds TraceStartLeadershipCheckPlus -> SeverityS +severityForge''' _ = Info + +namesForForge :: ForgeTracerType blk -> [Text] +namesForForge (Left t) = namesForForge' t +namesForForge (Right t) = namesForForge''' t + +namesForForge' :: TraceLabelCreds (TraceForgeEvent blk) -> [Text] +namesForForge' (TraceLabelCreds _t e) = namesForForge'' e + +namesForForge'' :: TraceForgeEvent blk -> [Text] +namesForForge'' TraceStartLeadershipCheck {} = ["StartLeadershipCheck"] +namesForForge'' TraceSlotIsImmutable {} = ["SlotIsImmutable"] +namesForForge'' TraceBlockFromFuture {} = ["BlockFromFuture"] +namesForForge'' TraceBlockContext {} = ["BlockContext"] +namesForForge'' TraceNoLedgerState {} = ["NoLedgerState"] +namesForForge'' TraceLedgerState {} = ["LedgerState"] +namesForForge'' TraceNoLedgerView {} = ["NoLedgerView"] +namesForForge'' TraceLedgerView {} = ["LedgerView"] +namesForForge'' TraceForgeStateUpdateError {} = ["ForgeStateUpdateError"] +namesForForge'' TraceNodeCannotForge {} = ["NodeCannotForge"] +namesForForge'' TraceNodeNotLeader {} = ["NodeNotLeader"] +namesForForge'' TraceNodeIsLeader {} = ["NodeIsLeader"] +namesForForge'' TraceForgedBlock {} = ["ForgedBlock"] +namesForForge'' TraceDidntAdoptBlock {} = ["DidntAdoptBlock"] +namesForForge'' TraceForgedInvalidBlock {} = ["ForgedInvalidBlock"] +namesForForge'' TraceAdoptedBlock {} = ["AdoptedBlock"] + +namesForForge''' :: TraceLabelCreds TraceStartLeadershipCheckPlus -> [Text] +namesForForge''' (TraceLabelCreds _ TraceStartLeadershipCheckPlus {}) = + ["StartLeadershipCheckPlus"] + + +instance ( tx ~ GenTx blk + , ConvertRawHash blk + , GetHeader blk + , HasHeader blk + , HasKESInfo blk + , HasTxId (GenTx blk) + , LedgerSupportsProtocol blk + , LedgerSupportsMempool blk + , SerialiseNodeToNodeConstraints blk + , Show (ForgeStateUpdateError blk) + , Show (CannotForge blk) + , Show (TxId (GenTx blk)) + , LogFormatting (InvalidBlockReason blk) + , LogFormatting (CannotForge blk) + , LogFormatting (ForgeStateUpdateError blk)) + => LogFormatting (TraceForgeEvent blk) where + forMachine _dtal (TraceStartLeadershipCheck slotNo) = + mkObject + [ "kind" .= String "TraceStartLeadershipCheck" + , "slot" .= toJSON (unSlotNo slotNo) + ] + forMachine dtal (TraceSlotIsImmutable slotNo tipPoint tipBlkNo) = + mkObject + [ "kind" .= String "TraceSlotIsImmutable" + , "slot" .= toJSON (unSlotNo slotNo) + , "tip" .= renderPointForDetails dtal tipPoint + , "tipBlockNo" .= toJSON (unBlockNo tipBlkNo) + ] + forMachine _dtal (TraceBlockFromFuture currentSlot tip) = + mkObject + [ "kind" .= String "TraceBlockFromFuture" + , "current slot" .= toJSON (unSlotNo currentSlot) + , "tip" .= toJSON (unSlotNo tip) + ] + forMachine dtal (TraceBlockContext currentSlot tipBlkNo tipPoint) = + mkObject + [ "kind" .= String "TraceBlockContext" + , "current slot" .= toJSON (unSlotNo currentSlot) + , "tip" .= renderPointForDetails dtal tipPoint + , "tipBlockNo" .= toJSON (unBlockNo tipBlkNo) + ] + forMachine _dtal (TraceNoLedgerState slotNo _pt) = + mkObject + [ "kind" .= String "TraceNoLedgerState" + , "slot" .= toJSON (unSlotNo slotNo) + ] + forMachine _dtal (TraceLedgerState slotNo _pt) = + mkObject + [ "kind" .= String "TraceLedgerState" + , "slot" .= toJSON (unSlotNo slotNo) + ] + forMachine _dtal (TraceNoLedgerView slotNo _) = + mkObject + [ "kind" .= String "TraceNoLedgerView" + , "slot" .= toJSON (unSlotNo slotNo) + ] + forMachine _dtal (TraceLedgerView slotNo) = + mkObject + [ "kind" .= String "TraceLedgerView" + , "slot" .= toJSON (unSlotNo slotNo) + ] + forMachine dtal (TraceForgeStateUpdateError slotNo reason) = + mkObject + [ "kind" .= String "TraceForgeStateUpdateError" + , "slot" .= toJSON (unSlotNo slotNo) + , "reason" .= forMachine dtal reason + ] + forMachine dtal (TraceNodeCannotForge slotNo reason) = + mkObject + [ "kind" .= String "TraceNodeCannotForge" + , "slot" .= toJSON (unSlotNo slotNo) + , "reason" .= forMachine dtal reason + ] + forMachine _dtal (TraceNodeNotLeader slotNo) = + mkObject + [ "kind" .= String "TraceNodeNotLeader" + , "slot" .= toJSON (unSlotNo slotNo) + ] + forMachine _dtal (TraceNodeIsLeader slotNo) = + mkObject + [ "kind" .= String "TraceNodeIsLeader" + , "slot" .= toJSON (unSlotNo slotNo) + ] + forMachine _dtal (TraceForgedBlock slotNo _ blk _) = + mkObject + [ "kind" .= String "TraceForgedBlock" + , "slot" .= toJSON (unSlotNo slotNo) + , "block" .= String (renderHeaderHash (Proxy @blk) $ blockHash blk) + , "blockNo" .= toJSON (unBlockNo $ blockNo blk) + , "blockPrev" .= String (renderChainHash + @blk + (renderHeaderHash (Proxy @blk)) + $ blockPrevHash blk) + ] + forMachine _dtal (TraceDidntAdoptBlock slotNo _) = + mkObject + [ "kind" .= String "TraceDidntAdoptBlock" + , "slot" .= toJSON (unSlotNo slotNo) + ] + forMachine dtal (TraceForgedInvalidBlock slotNo _ reason) = + mkObject + [ "kind" .= String "TraceForgedInvalidBlock" + , "slot" .= toJSON (unSlotNo slotNo) + , "reason" .= forMachine dtal reason + ] + forMachine DDetailed (TraceAdoptedBlock slotNo blk txs) = + mkObject + [ "kind" .= String "TraceAdoptedBlock" + , "slot" .= toJSON (unSlotNo slotNo) + , "blockHash" .= renderHeaderHashForDetails + (Proxy @blk) + DDetailed + (blockHash blk) + , "blockSize" .= toJSON (estimateBlockSize (getHeader blk)) + , "txIds" .= toJSON (map (show . txId . txForgetValidated) txs) + ] + forMachine dtal (TraceAdoptedBlock slotNo blk _txs) = + mkObject + [ "kind" .= String "TraceAdoptedBlock" + , "slot" .= toJSON (unSlotNo slotNo) + , "blockHash" .= renderHeaderHashForDetails + (Proxy @blk) + dtal + (blockHash blk) + , "blockSize" .= toJSON (estimateBlockSize (getHeader blk)) + ] + + forHuman (TraceStartLeadershipCheck slotNo) = + "Checking for leadership in slot " <> showT (unSlotNo slotNo) + forHuman (TraceSlotIsImmutable slotNo immutableTipPoint immutableTipBlkNo) = + "Couldn't forge block because current slot is immutable: " + <> "immutable tip: " <> renderPointAsPhrase immutableTipPoint + <> ", immutable tip block no: " <> showT (unBlockNo immutableTipBlkNo) + <> ", current slot: " <> showT (unSlotNo slotNo) + forHuman (TraceBlockFromFuture currentSlot tipSlot) = + "Couldn't forge block because current tip is in the future: " + <> "current tip slot: " <> showT (unSlotNo tipSlot) + <> ", current slot: " <> showT (unSlotNo currentSlot) + forHuman (TraceBlockContext currentSlot tipBlockNo tipPoint) = + "New block will fit onto: " + <> "tip: " <> renderPointAsPhrase tipPoint + <> ", tip block no: " <> showT (unBlockNo tipBlockNo) + <> ", current slot: " <> showT (unSlotNo currentSlot) + forHuman (TraceNoLedgerState slotNo pt) = + "Could not obtain ledger state for point " + <> renderPointAsPhrase pt + <> ", current slot: " + <> showT (unSlotNo slotNo) + forHuman (TraceLedgerState slotNo pt) = + "Obtained a ledger state for point " + <> renderPointAsPhrase pt + <> ", current slot: " + <> showT (unSlotNo slotNo) + forHuman (TraceNoLedgerView slotNo _) = + "Could not obtain ledger view for slot " <> showT (unSlotNo slotNo) + forHuman (TraceLedgerView slotNo) = + "Obtained a ledger view for slot " <> showT (unSlotNo slotNo) + forHuman (TraceForgeStateUpdateError slotNo reason) = + "Updating the forge state in slot " + <> showT (unSlotNo slotNo) + <> " failed because: " + <> showT reason + forHuman (TraceNodeCannotForge slotNo reason) = + "We are the leader in slot " + <> showT (unSlotNo slotNo) + <> ", but we cannot forge because: " + <> showT reason + forHuman (TraceNodeNotLeader slotNo) = + "Not leading slot " <> showT (unSlotNo slotNo) + forHuman (TraceNodeIsLeader slotNo) = + "Leading slot " <> showT (unSlotNo slotNo) + forHuman (TraceForgedBlock slotNo _ _ _) = + "Forged block in slot " <> showT (unSlotNo slotNo) + forHuman (TraceDidntAdoptBlock slotNo _) = + "Didn't adopt forged block in slot " <> showT (unSlotNo slotNo) + forHuman (TraceForgedInvalidBlock slotNo _ reason) = + "Forged invalid block in slot " + <> showT (unSlotNo slotNo) + <> ", reason: " <> showT reason + forHuman (TraceAdoptedBlock slotNo blk _txs) = + "Adopted block forged in slot " + <> showT (unSlotNo slotNo) + <> ": " <> renderHeaderHash (Proxy @blk) (blockHash blk) + -- <> ", TxIds: " <> showT (map txId txs) TODO Fix + + asMetrics (TraceForgeStateUpdateError slot reason) = + IntM "cardano.node.forgeStateUpdateError" (fromIntegral $ unSlotNo slot) : + (case getKESInfo (Proxy @blk) reason of + Nothing -> [] + Just kesInfo -> + [ IntM + "cardano.node.operationalCertificateStartKESPeriod" + (fromIntegral . unKESPeriod . HotKey.kesStartPeriod $ kesInfo) + , IntM + "cardano.node.operationalCertificateExpiryKESPeriod" + (fromIntegral . unKESPeriod . HotKey.kesEndPeriod $ kesInfo) + , IntM + "cardano.node.currentKESPeriod" + 0 + , IntM + "cardano.node.remainingKESPeriods" + 0 + ]) + + asMetrics (TraceStartLeadershipCheck slot) = + [IntM "cardano.node.aboutToLeadSlotLast" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceSlotIsImmutable slot _tipPoint _tipBlkNo) = + [IntM "cardano.node.slotIsImmutable" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceBlockFromFuture slot _slotNo) = + [IntM "cardano.node.blockFromFuture" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceBlockContext slot _tipBlkNo _tipPoint) = + [IntM "cardano.node.blockContext" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceNoLedgerState slot _) = + [IntM "cardano.node.couldNotForgeSlotLast" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceLedgerState slot _) = + [IntM "cardano.node.ledgerState" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceNoLedgerView slot _) = + [IntM "cardano.node.couldNotForgeSlotLast" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceLedgerView slot) = + [IntM "cardano.node.ledgerView" (fromIntegral $ unSlotNo slot)] + -- see above + asMetrics (TraceNodeCannotForge slot _reason) = + [IntM "cardano.node.nodeCannotForge" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceNodeNotLeader slot) = + [IntM "cardano.node.nodeNotLeader" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceNodeIsLeader slot) = + [IntM "cardano.node.nodeIsLeader" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceForgedBlock slot _ _ _) = + [IntM "cardano.node.forgedSlotLast" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceDidntAdoptBlock slot _) = + [IntM "cardano.node.notAdoptedSlotLast" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceForgedInvalidBlock slot _ _) = + [IntM "cardano.node.forgedInvalidSlotLast" (fromIntegral $ unSlotNo slot)] + asMetrics (TraceAdoptedBlock slot _ _) = + [IntM "cardano.node.adoptedSlotLast" (fromIntegral $ unSlotNo slot)] + +instance LogFormatting TraceStartLeadershipCheckPlus where + forMachine _dtal TraceStartLeadershipCheckPlus {..} = + mkObject [ "kind" .= String "TraceStartLeadershipCheckPlus" + , "slotNo" .= toJSON (unSlotNo tsSlotNo) + , "utxoSize" .= Number (fromIntegral tsUtxoSize) + , "delegMapSize" .= Number (fromIntegral tsUtxoSize) + , "chainDensity" .= Number (fromRational (toRational tsChainDensity)) + ] + forHuman TraceStartLeadershipCheckPlus {..} = + "Checking for leadership in slot " <> showT (unSlotNo tsSlotNo) + <> " utxoSize " <> showT tsUtxoSize + <> " delegMapSize " <> showT tsDelegMapSize + <> " chainDensity " <> showT tsChainDensity + asMetrics TraceStartLeadershipCheckPlus {..} = + [IntM "cardano.node.utxoSize" (fromIntegral tsUtxoSize), + IntM "cardano.node.delegMapSize" (fromIntegral tsDelegMapSize)] + -- TODO JNF: Why not deleg map size? + + +docForge :: Documented (Either (TraceLabelCreds (TraceForgeEvent blk)) + (TraceLabelCreds TraceStartLeadershipCheckPlus)) +docForge = Documented [ + DocMsg + (Left (TraceLabelCreds anyProto + (TraceStartLeadershipCheck anyProto))) + [("cardano.node.aboutToLeadSlotLast", "")] + "Start of the leadership check." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceSlotIsImmutable anyProto anyProto anyProto))) + [("cardano.node.slotIsImmutable", "")] + "Leadership check failed: the tip of the ImmutableDB inhabits the\ + \ current slot\ + \ \ + \ This might happen in two cases.\ + \ \ + \ 1. the clock moved backwards, on restart we ignored everything from the\ + \ VolatileDB since it's all in the future, and now the tip of the\ + \ ImmutableDB points to a block produced in the same slot we're trying\ + \ to produce a block in\ + \ \ + \ 2. k = 0 and we already adopted a block from another leader of the same\ + \ slot.\ + \ \ + \ We record both the current slot number as well as the tip of the\ + \ ImmutableDB.\ + \ \ + \ See also " + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceBlockFromFuture anyProto anyProto))) + [("cardano.node.blockFromFuture", "")] + "Leadership check failed: the current chain contains a block from a slot\ + \ /after/ the current slot\ + \ \ + \ This can only happen if the system is under heavy load.\ + \ \ + \ We record both the current slot number as well as the slot number of the\ + \ block at the tip of the chain.\ + \ \ + \ See also " + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceBlockContext anyProto anyProto anyProto))) + [("cardano.node.blockContext", "")] + "We found out to which block we are going to connect the block we are about\ + \ to forge.\ + \ \ + \ We record the current slot number, the block number of the block to\ + \ connect to and its point.\ + \ \ + \ Note that block number of the block we will try to forge is one more than\ + \ the recorded block number." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceNoLedgerState anyProto anyProto))) + [("cardano.node.couldNotForgeSlotLast", "")] + "Leadership check failed: we were unable to get the ledger state for the\ + \ point of the block we want to connect to\ + \ \ + \ This can happen if after choosing which block to connect to the node\ + \ switched to a different fork. We expect this to happen only rather\ + \ rarely, so this certainly merits a warning; if it happens a lot, that\ + \ merits an investigation.\ + \ \ + \ We record both the current slot number as well as the point of the block\ + \ we attempt to connect the new block to (that we requested the ledger\ + \ state for)." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceLedgerState anyProto anyProto))) + [("cardano.node.ledgerState", "")] + "We obtained a ledger state for the point of the block we want to\ + \ connect to\ + \ \ + \ We record both the current slot number as well as the point of the block\ + \ we attempt to connect the new block to (that we requested the ledger\ + \ state for)." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceNoLedgerView anyProto anyProto))) + [("cardano.node.couldNotForgeSlotLast", "")] + "Leadership check failed: we were unable to get the ledger view for the\ + \ current slot number\ + \ \ + \ This will only happen if there are many missing blocks between the tip of\ + \ our chain and the current slot.\ + \ \ + \ We record also the failure returned by 'forecastFor'." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceLedgerView anyProto))) + [("cardano.node.ledgerView", "")] + "We obtained a ledger view for the current slot number\ + \ \ + \ We record the current slot number." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceForgeStateUpdateError anyProto anyProto))) + [ ("cardano.node.operationalCertificateStartKESPeriod", "") + , ("cardano.node.operationalCertificateExpiryKESPeriod", "") + , ("cardano.node.currentKESPeriod", "") + , ("cardano.node.remainingKESPeriods", "") + ] + "Updating the forge state failed.\ + \ \ + \ For example, the KES key could not be evolved anymore.\ + \ \ + \ We record the error returned by 'updateForgeState'." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceNodeCannotForge anyProto anyProto))) + [("cardano.node.nodeCannotForge", "")] + "We did the leadership check and concluded that we should lead and forge\ + \ a block, but cannot.\ + \ \ + \ This should only happen rarely and should be logged with warning severity.\ + \ \ + \ Records why we cannot forge a block." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceNodeNotLeader anyProto))) + [("cardano.node.nodeNotLeader", "")] + "We did the leadership check and concluded we are not the leader\ + \ \ + \ We record the current slot number" + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceNodeIsLeader anyProto))) + [("cardano.node.nodeIsLeader", "")] + "We did the leadership check and concluded we /are/ the leader\ + \\n\ + \ The node will soon forge; it is about to read its transactions from the\ + \ Mempool. This will be followed by ForgedBlock." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceForgedBlock anyProto anyProto anyProto anyProto))) + [("cardano.node.forgedSlotLast", "")] + "We forged a block.\ + \\n\ + \ We record the current slot number, the point of the predecessor, the block\ + \ itself, and the total size of the mempool snapshot at the time we produced\ + \ the block (which may be significantly larger than the block, due to\ + \ maximum block size)\ + \\n\ + \ This will be followed by one of three messages:\ + \\n\ + \ * AdoptedBlock (normally)\ + \\n\ + \ * DidntAdoptBlock (rarely)\ + \\n\ + \ * ForgedInvalidBlock (hopefully never -- this would indicate a bug)" + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceDidntAdoptBlock anyProto anyProto))) + [("cardano.node.notAdoptedSlotLast", "")] + "We did not adopt the block we produced, but the block was valid. We\ + \ must have adopted a block that another leader of the same slot produced\ + \ before we got the chance of adopting our own block. This is very rare,\ + \ this warrants a warning." + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceForgedInvalidBlock anyProto anyProto anyProto))) + [("cardano.node.forgedInvalidSlotLast", "")] + "We forged a block that is invalid according to the ledger in the\ + \ ChainDB. This means there is an inconsistency between the mempool\ + \ validation and the ledger validation. This is a serious error!" + , DocMsg + (Left (TraceLabelCreds anyProto + (TraceAdoptedBlock anyProto anyProto [anyProto]))) + [("cardano.node.adoptedSlotLast", "")] + "We adopted the block we produced, we also trace the transactions\ + \ that were adopted." + , DocMsg + (Right (TraceLabelCreds anyProto + (TraceStartLeadershipCheckPlus anyProto 0 0 0.0))) + [ ("cardano.node.aboutToLeadSlotLast", "") + , ("cardano.node.utxoSize", "") + , ("cardano.node.delegMapSize", "") + ] + "We adopted the block we produced, we also trace the transactions\ + \ that were adopted." + + ] + +instance ( tx ~ GenTx blk + , ConvertRawHash blk + , GetHeader blk + , HasHeader blk + , HasKESInfo blk + , LedgerSupportsProtocol blk + , LedgerSupportsMempool blk + , SerialiseNodeToNodeConstraints blk + , HasTxId (GenTx blk) + , Show (ForgeStateUpdateError blk) + , Show (CannotForge blk) + , LogFormatting (InvalidBlockReason blk) + , LogFormatting (CannotForge blk) + , LogFormatting (ForgeStateUpdateError blk)) + => LogFormatting (ForgeTracerType blk) where + forMachine dtal (Left i) = forMachine dtal i + forMachine dtal (Right i) = forMachine dtal i + forHuman (Left i) = forHuman i + forHuman (Right i) = forHuman i + asMetrics (Left i) = asMetrics i + asMetrics (Right i) = asMetrics i + +-------------------------------------------------------------------------------- +-- BlockchainTimeEvent Tracer +-------------------------------------------------------------------------------- + +namesForBlockchainTime :: TraceBlockchainTimeEvent t -> [Text] +namesForBlockchainTime TraceStartTimeInTheFuture {} = ["StartTimeInTheFuture"] +namesForBlockchainTime TraceCurrentSlotUnknown {} = ["CurrentSlotUnknown"] +namesForBlockchainTime TraceSystemClockMovedBack {} = ["SystemClockMovedBack"] + +severityBlockchainTime :: TraceBlockchainTimeEvent t -> SeverityS +severityBlockchainTime TraceStartTimeInTheFuture {} = Warning +severityBlockchainTime TraceCurrentSlotUnknown {} = Warning +severityBlockchainTime TraceSystemClockMovedBack {} = Warning + +instance Show t => LogFormatting (TraceBlockchainTimeEvent t) where + forMachine _dtal (TraceStartTimeInTheFuture (SystemStart start) toWait) = + mkObject [ "kind" .= String "TStartTimeInTheFuture" + , "systemStart" .= String (showT start) + , "toWait" .= String (showT toWait) + ] + forMachine _dtal (TraceCurrentSlotUnknown time _) = + mkObject [ "kind" .= String "CurrentSlotUnknown" + , "time" .= String (showT time) + ] + forMachine _dtal (TraceSystemClockMovedBack prevTime newTime) = + mkObject [ "kind" .= String "SystemClockMovedBack" + , "prevTime" .= String (showT prevTime) + , "newTime" .= String (showT newTime) + ] + forHuman (TraceStartTimeInTheFuture (SystemStart start) toWait) = + "Waiting " + <> (Text.pack . show) toWait + <> " until genesis start time at " + <> (Text.pack . show) start + forHuman (TraceCurrentSlotUnknown time _) = + "Too far from the chain tip to determine the current slot number for the time " + <> (Text.pack . show) time + forHuman (TraceSystemClockMovedBack prevTime newTime) = + "The system wall clock time moved backwards, but within our tolerance " + <> "threshold. Previous 'current' time: " + <> (Text.pack . show) prevTime + <> ". New 'current' time: " + <> (Text.pack . show) newTime + + +docBlockchainTime :: Documented (TraceBlockchainTimeEvent t) +docBlockchainTime = Documented [ + DocMsg + (TraceStartTimeInTheFuture anyProto anyProto) + [] + "The start time of the blockchain time is in the future\ + \\n\ + \ We have to block (for 'NominalDiffTime') until that time comes." + , DocMsg + (TraceCurrentSlotUnknown anyProto anyProto) + [] + "Current slot is not yet known\ + \\n\ + \ This happens when the tip of our current chain is so far in the past that\ + \ we cannot translate the current wallclock to a slot number, typically\ + \ during syncing. Until the current slot number is known, we cannot\ + \ produce blocks. Seeing this message during syncing therefore is\ + \ normal and to be expected.\ + \\n\ + \ We record the current time (the time we tried to translate to a 'SlotNo')\ + \ as well as the 'PastHorizonException', which provides detail on the\ + \ bounds between which we /can/ do conversions. The distance between the\ + \ current time and the upper bound should rapidly decrease with consecutive\ + \ 'CurrentSlotUnknown' messages during syncing." + , DocMsg + (TraceSystemClockMovedBack anyProto anyProto) + [] + "The system clock moved back an acceptable time span, e.g., because of\ + \ an NTP sync.\ + \\n\ + \ The system clock moved back such that the new current slot would be\ + \ smaller than the previous one. If this is within the configured limit, we\ + \ trace this warning but *do not change the current slot*. The current slot\ + \ never decreases, but the current slot may stay the same longer than\ + \ expected.\ + \\n\ + \ When the system clock moved back more than the configured limit, we shut\ + \ down with a fatal exception." + ] + +-------------------------------------------------------------------------------- +-- KeepAliveClient Tracer +-------------------------------------------------------------------------------- + +namesForKeepAliveClient :: TraceKeepAliveClient peer -> [Text] +namesForKeepAliveClient _ = ["KeepAliveClient"] + +severityKeepAliveClient :: TraceKeepAliveClient peer -> SeverityS +severityKeepAliveClient _ = Info + +instance Show remotePeer => LogFormatting (TraceKeepAliveClient remotePeer) where + forMachine _dtal (AddSample peer rtt pgsv) = + mkObject + [ "kind" .= String "AddSample" + , "address" .= show peer + , "rtt" .= rtt + , "sampleTime" .= show (dTime $ sampleTime pgsv) + , "outboundG" .= (realToFrac $ gGSV (outboundGSV pgsv) :: Double) + , "inboundG" .= (realToFrac $ gGSV (inboundGSV pgsv) :: Double) + ] + where + gGSV :: GSV -> DiffTime + gGSV (GSV g _ _) = g + + dTime :: Time -> Double + dTime (Time d) = realToFrac d + + forHuman = showT + +docKeepAliveClient :: Documented (TraceKeepAliveClient peer) +docKeepAliveClient = Documented [ + DocMsg + (AddSample anyProto anyProto anyProto) + [] + "" + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Diffusion.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Diffusion.hs new file mode 100644 index 00000000000..ea27c869e64 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/Diffusion.hs @@ -0,0 +1,749 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE ScopedTypeVariables #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.Diffusion + ( + severityMux + , namesForMux + , docMuxLocal + , docMuxRemote + + , severityHandshake + , namesForHandshake + , docHandshake + + , severityLocalHandshake + , namesForLocalHandshake + , docLocalHandshake + + , severityDiffusionInit + , namesForDiffusionInit + , docDiffusionInit + + , severityLedgerPeers + , namesForLedgerPeers + , docLedgerPeers + ) where + +import Cardano.Logging +import Cardano.Prelude hiding (Show, show) +import qualified Codec.CBOR.Term as CBOR +import Data.Aeson (Value (String), (.=)) +import Data.Text (pack) +import Network.Mux (MuxTrace (..), WithMuxBearer (..)) +import qualified Network.Socket as Socket +import Network.TypedProtocol.Codec (AnyMessageAndAgency (..)) +import Text.Show + +import Cardano.Node.Configuration.TopologyP2P (UseLedger (..)) + +import qualified Ouroboros.Network.Diffusion as ND +import Ouroboros.Network.Driver.Simple (TraceSendRecv (..)) +import qualified Ouroboros.Network.NodeToClient as NtC +import qualified Ouroboros.Network.NodeToNode as NtN +import Ouroboros.Network.PeerSelection.LedgerPeers (AccPoolStake (..), NumberOfPeers (..), + PoolStake (..), TraceLedgerPeers (..), UseLedgerAfter (..)) +import Ouroboros.Network.PeerSelection.RelayAccessPoint (RelayAccessPoint (..)) +import Ouroboros.Network.Protocol.BlockFetch.Type (Message (..)) +import qualified Ouroboros.Network.Protocol.Handshake.Type as HS +import Ouroboros.Network.Snocket (LocalAddress (..)) + +protoRemoteAddr :: NtN.RemoteAddress +protoRemoteAddr = Socket.SockAddrUnix "loopback" + +protoLocalAddress :: LocalAddress +protoLocalAddress = LocalAddress "loopback" + +protoSomeException :: SomeException +protoSomeException = SomeException (AssertionFailed "just fooled") + +protoPeerLocal :: NtN.ConnectionId LocalAddress +protoPeerLocal = NtN.ConnectionId protoLocalAddress protoLocalAddress + +protoPeerRemote :: NtN.ConnectionId NtN.RemoteAddress +protoPeerRemote = NtN.ConnectionId protoRemoteAddr protoRemoteAddr + +-------------------------------------------------------------------------------- +-- Mux Tracer +-------------------------------------------------------------------------------- + +severityMux :: WithMuxBearer peer MuxTrace -> SeverityS +severityMux (WithMuxBearer _ mt) = severityMux' mt + +severityMux' :: MuxTrace -> SeverityS +severityMux' MuxTraceRecvHeaderStart {} = Debug +severityMux' MuxTraceRecvHeaderEnd {} = Debug +severityMux' MuxTraceRecvStart {} = Debug +severityMux' MuxTraceRecvEnd {} = Debug +severityMux' MuxTraceSendStart {} = Debug +severityMux' MuxTraceSendEnd = Debug +severityMux' MuxTraceState {} = Info +severityMux' MuxTraceCleanExit {} = Notice +severityMux' MuxTraceExceptionExit {} = Notice +severityMux' MuxTraceChannelRecvStart {} = Debug +severityMux' MuxTraceChannelRecvEnd {} = Debug +severityMux' MuxTraceChannelSendStart {} = Debug +severityMux' MuxTraceChannelSendEnd {} = Debug +severityMux' MuxTraceHandshakeStart = Debug +severityMux' MuxTraceHandshakeClientEnd {} = Info +severityMux' MuxTraceHandshakeServerEnd = Debug +severityMux' MuxTraceHandshakeClientError {} = Error +severityMux' MuxTraceHandshakeServerError {} = Error +severityMux' MuxTraceRecvDeltaQObservation {} = Debug +severityMux' MuxTraceRecvDeltaQSample {} = Debug +severityMux' MuxTraceSDUReadTimeoutException = Notice +severityMux' MuxTraceSDUWriteTimeoutException = Notice +severityMux' MuxTraceStartEagerly {} = Debug +severityMux' MuxTraceStartOnDemand {} = Debug +severityMux' MuxTraceStartedOnDemand {} = Debug +severityMux' MuxTraceTerminating {} = Debug +severityMux' MuxTraceShutdown {} = Debug + +namesForMux :: WithMuxBearer peer MuxTrace -> [Text] +namesForMux (WithMuxBearer _ mt) = namesForMux' mt + +namesForMux' :: MuxTrace -> [Text] +namesForMux' MuxTraceRecvHeaderStart {} = ["RecvHeaderStart"] +namesForMux' MuxTraceRecvHeaderEnd {} = ["RecvHeaderEnd"] +namesForMux' MuxTraceRecvStart {} = ["RecvStart"] +namesForMux' MuxTraceRecvEnd {} = ["RecvEnd"] +namesForMux' MuxTraceSendStart {} = ["SendStart"] +namesForMux' MuxTraceSendEnd = ["SendEnd"] +namesForMux' MuxTraceState {} = ["State"] +namesForMux' MuxTraceCleanExit {} = ["CleanExit"] +namesForMux' MuxTraceExceptionExit {} = ["ExceptionExit"] +namesForMux' MuxTraceChannelRecvStart {} = ["ChannelRecvStart"] +namesForMux' MuxTraceChannelRecvEnd {} = ["ChannelRecvEnd"] +namesForMux' MuxTraceChannelSendStart {} = ["ChannelSendStart"] +namesForMux' MuxTraceChannelSendEnd {} = ["ChannelSendEnd"] +namesForMux' MuxTraceHandshakeStart = ["HandshakeStart "] +namesForMux' MuxTraceHandshakeClientEnd {} = ["HandshakeClientEnd"] +namesForMux' MuxTraceHandshakeServerEnd = ["HandshakeServerEnd"] +namesForMux' MuxTraceHandshakeClientError {} = ["HandshakeClientError"] +namesForMux' MuxTraceHandshakeServerError {} = ["HandshakeServerError"] +namesForMux' MuxTraceRecvDeltaQObservation {} = ["RecvDeltaQObservation"] +namesForMux' MuxTraceRecvDeltaQSample {} = ["RecvDeltaQSample"] +namesForMux' MuxTraceSDUReadTimeoutException = ["SDUReadTimeoutException"] +namesForMux' MuxTraceSDUWriteTimeoutException = ["SDUWriteTimeoutException"] +namesForMux' MuxTraceStartEagerly {} = ["StartEagerly"] +namesForMux' MuxTraceStartOnDemand {} = ["StartOnDemand"] +namesForMux' MuxTraceStartedOnDemand {} = ["StartedOnDemand"] +namesForMux' MuxTraceTerminating {} = ["Terminating"] +namesForMux' MuxTraceShutdown {} = ["Shutdown"] + + + +instance (LogFormatting peer, Show peer) => + LogFormatting (WithMuxBearer peer MuxTrace) where + forMachine dtal (WithMuxBearer b ev) = + mkObject [ "kind" .= String "MuxTrace" + , "bearer" .= forMachine dtal b + , "event" .= showT ev ] + forHuman (WithMuxBearer b ev) = "With mux bearer " <> showT b + <> ". " <> showT ev + + +docMuxLocal :: Documented (WithMuxBearer (NtN.ConnectionId LocalAddress) MuxTrace) +docMuxLocal = docMux protoPeerLocal + +docMuxRemote :: Documented (WithMuxBearer (NtN.ConnectionId NtN.RemoteAddress) MuxTrace) +docMuxRemote = docMux protoPeerRemote + + +docMux :: peer -> Documented (WithMuxBearer peer MuxTrace) +docMux peer = Documented [ + DocMsg + (WithMuxBearer peer + MuxTraceRecvHeaderStart) + [] + "Bearer receive header start." + , DocMsg + (WithMuxBearer peer + (MuxTraceRecvHeaderEnd anyProto)) + [] + "Bearer receive header end." + , DocMsg + (WithMuxBearer peer + (MuxTraceRecvDeltaQObservation anyProto anyProto)) + [] + "Bearer DeltaQ observation." + , DocMsg + (WithMuxBearer peer + (MuxTraceRecvDeltaQSample 1.0 1 1 1.0 1.0 1.0 1.0 "")) + [] + "Bearer DeltaQ sample." + , DocMsg + (WithMuxBearer peer + (MuxTraceRecvStart 1)) + [] + "Bearer receive start." + , DocMsg + (WithMuxBearer peer + (MuxTraceRecvEnd 1)) + [] + "Bearer receive end." + , DocMsg + (WithMuxBearer peer + (MuxTraceSendStart anyProto)) + [] + "Bearer send start." + , DocMsg + (WithMuxBearer peer + MuxTraceSendEnd) + [] + "Bearer send end." + , DocMsg + (WithMuxBearer peer + (MuxTraceState anyProto)) + [] + "State." + , DocMsg + (WithMuxBearer peer + (MuxTraceCleanExit anyProto anyProto)) + [] + "Miniprotocol terminated cleanly." + , DocMsg + (WithMuxBearer peer + (MuxTraceExceptionExit + anyProto anyProto anyProto)) + [] + "Miniprotocol terminated with exception." + , DocMsg + (WithMuxBearer peer + (MuxTraceChannelRecvStart anyProto)) + [] + "Channel receive start." + , DocMsg + (WithMuxBearer peer + (MuxTraceChannelRecvEnd anyProto 1)) + [] + "Channel receive end." + , DocMsg + (WithMuxBearer peer + (MuxTraceChannelSendStart anyProto 1)) + [] + "Channel send start." + , DocMsg + (WithMuxBearer peer + (MuxTraceChannelSendEnd anyProto)) + [] + "Channel send end." + , DocMsg + (WithMuxBearer peer + MuxTraceHandshakeStart) + [] + "Handshake start." + , DocMsg + (WithMuxBearer peer + (MuxTraceHandshakeClientEnd anyProto)) + [] + "Handshake client end." + , DocMsg + (WithMuxBearer peer + (MuxTraceHandshakeClientError protoSomeException anyProto)) + [] + "Handshake client error." + , DocMsg + (WithMuxBearer peer + (MuxTraceHandshakeServerError protoSomeException)) + [] + "Handshake server error." + , DocMsg + (WithMuxBearer peer + MuxTraceSDUReadTimeoutException) + [] + "Timed out reading SDU." + , DocMsg + (WithMuxBearer peer + MuxTraceSDUWriteTimeoutException) + [] + "Timed out writing SDU." + , DocMsg + (WithMuxBearer peer + (MuxTraceStartEagerly anyProto anyProto)) + [] + "Eagerly started." + , DocMsg + (WithMuxBearer peer + (MuxTraceStartOnDemand anyProto anyProto)) + [] + "Preparing to start." + , DocMsg + (WithMuxBearer peer + (MuxTraceStartedOnDemand anyProto anyProto)) + [] + "Started on demand." + , DocMsg + (WithMuxBearer peer + (MuxTraceTerminating anyProto anyProto)) + [] + "Terminating." + , DocMsg + (WithMuxBearer peer + MuxTraceShutdown) + [] + "Mux shutdown." + ] + +-------------------------------------------------------------------------------- +-- Handshake Tracer +-------------------------------------------------------------------------------- + +severityHandshake :: NtN.HandshakeTr adr ver -> SeverityS +severityHandshake (WithMuxBearer _ e) = severityHandshake' e + +severityHandshake' :: + TraceSendRecv (HS.Handshake nt CBOR.Term) + -> SeverityS +severityHandshake' (TraceSendMsg m) = severityHandshake'' m +severityHandshake' (TraceRecvMsg m) = severityHandshake'' m + +severityHandshake'' :: AnyMessageAndAgency (HS.Handshake nt CBOR.Term) -> SeverityS +severityHandshake'' (AnyMessageAndAgency _agency msg) = severityHandshake''' msg + +severityHandshake''' :: Message (HS.Handshake nt CBOR.Term) from to -> SeverityS +severityHandshake''' HS.MsgProposeVersions {} = Info +severityHandshake''' HS.MsgReplyVersions {} = Info +severityHandshake''' HS.MsgAcceptVersion {} = Info +severityHandshake''' HS.MsgRefuse {} = Info + +namesForHandshake :: NtN.HandshakeTr adr ver -> [Text] +namesForHandshake (WithMuxBearer _ e) = namesForHandshake' e + +namesForHandshake' :: + TraceSendRecv (HS.Handshake nt CBOR.Term) + -> [Text] +namesForHandshake' (TraceSendMsg m) = namesForHandshake'' m +namesForHandshake' (TraceRecvMsg m) = namesForHandshake'' m + +namesForHandshake'' :: AnyMessageAndAgency (HS.Handshake nt CBOR.Term) -> [Text] +namesForHandshake'' (AnyMessageAndAgency _agency msg) = namesForHandshake''' msg + +namesForHandshake''' :: Message (HS.Handshake nt CBOR.Term) from to -> [Text] +namesForHandshake''' HS.MsgProposeVersions {} = ["ProposeVersions"] +namesForHandshake''' HS.MsgReplyVersions {} = ["ReplyVersions"] +namesForHandshake''' HS.MsgAcceptVersion {} = ["AcceptVersion"] +namesForHandshake''' HS.MsgRefuse {} = ["Refuse"] + +instance LogFormatting (NtN.HandshakeTr NtN.RemoteAddress NtN.NodeToNodeVersion) where + forMachine _dtal (WithMuxBearer b ev) = + mkObject [ "kind" .= String "HandshakeTrace" + , "bearer" .= show b + , "event" .= show ev ] + forHuman (WithMuxBearer b ev) = "With mux bearer " <> showT b + <> ". " <> showT ev + +docHandshake :: Documented (NtN.HandshakeTr NtN.RemoteAddress ver) +docHandshake = Documented [ + DocMsg + (WithMuxBearer protoPeerRemote + (TraceSendMsg + (AnyMessageAndAgency anyProto + (HS.MsgProposeVersions anyProto)))) + [] + "Propose versions together with version parameters. It must be\ + \ encoded to a sorted list.." + , DocMsg + (WithMuxBearer protoPeerRemote + (TraceSendMsg + (AnyMessageAndAgency anyProto + (HS.MsgAcceptVersion anyProto anyProto)))) + [] + "The remote end decides which version to use and sends chosen version.\ + \The server is allowed to modify version parameters." + , DocMsg + (WithMuxBearer protoPeerRemote + (TraceSendMsg + (AnyMessageAndAgency anyProto + (HS.MsgRefuse anyProto)))) + [] + "It refuses to run any version." + ] + +-------------------------------------------------------------------------------- +-- LocalHandshake Tracer +-------------------------------------------------------------------------------- + +severityLocalHandshake :: NtC.HandshakeTr adr ver -> SeverityS +severityLocalHandshake (WithMuxBearer _ e) = severityLocalHandshake' e + +severityLocalHandshake' :: + TraceSendRecv (HS.Handshake nt CBOR.Term) + -> SeverityS +severityLocalHandshake' (TraceSendMsg m) = severityLocalHandshake'' m +severityLocalHandshake' (TraceRecvMsg m) = severityLocalHandshake'' m + +severityLocalHandshake'' :: AnyMessageAndAgency (HS.Handshake nt CBOR.Term) -> SeverityS +severityLocalHandshake'' (AnyMessageAndAgency _agency msg) = severityLocalHandshake''' msg + +severityLocalHandshake''' :: Message (HS.Handshake nt CBOR.Term) from to -> SeverityS +severityLocalHandshake''' HS.MsgProposeVersions {} = Info +severityLocalHandshake''' HS.MsgReplyVersions {} = Info +severityLocalHandshake''' HS.MsgAcceptVersion {} = Info +severityLocalHandshake''' HS.MsgRefuse {} = Info + +namesForLocalHandshake :: NtC.HandshakeTr adr ver -> [Text] +namesForLocalHandshake (WithMuxBearer _ e) = namesForLocalHandshake' e + +namesForLocalHandshake' :: + TraceSendRecv (HS.Handshake nt CBOR.Term) + -> [Text] +namesForLocalHandshake' (TraceSendMsg m) = namesForLocalHandshake'' m +namesForLocalHandshake' (TraceRecvMsg m) = namesForLocalHandshake'' m + +namesForLocalHandshake'' :: AnyMessageAndAgency (HS.Handshake nt CBOR.Term) -> [Text] +namesForLocalHandshake'' (AnyMessageAndAgency _agency msg) = namesForLocalHandshake''' msg + +namesForLocalHandshake''' :: Message (HS.Handshake nt CBOR.Term) from to -> [Text] +namesForLocalHandshake''' HS.MsgProposeVersions {} = ["ProposeVersions"] +namesForLocalHandshake''' HS.MsgReplyVersions {} = ["ReplyVersions"] +namesForLocalHandshake''' HS.MsgAcceptVersion {} = ["AcceptVersion"] +namesForLocalHandshake''' HS.MsgRefuse {} = ["Refuse"] + +instance LogFormatting (NtC.HandshakeTr NtC.LocalAddress NtC.NodeToClientVersion) where + forMachine _dtal (WithMuxBearer b ev) = + mkObject [ "kind" .= String "LocalHandshakeTrace" + , "bearer" .= show b + , "event" .= show ev ] + forHuman (WithMuxBearer b ev) = "With mux bearer " <> showT b + <> ". " <> showT ev + +docLocalHandshake :: Documented (NtC.HandshakeTr LocalAddress ver) +docLocalHandshake = Documented [ + DocMsg + (WithMuxBearer protoPeerLocal + (TraceSendMsg + (AnyMessageAndAgency anyProto + (HS.MsgProposeVersions anyProto)))) + [] + "Propose versions together with version parameters. It must be\ + \ encoded to a sorted list.." + , DocMsg + (WithMuxBearer protoPeerLocal + (TraceSendMsg + (AnyMessageAndAgency anyProto + (HS.MsgAcceptVersion anyProto anyProto)))) + [] + "The remote end decides which version to use and sends chosen version.\ + \The server is allowed to modify version parameters." + , DocMsg + (WithMuxBearer protoPeerLocal + (TraceSendMsg + (AnyMessageAndAgency anyProto + (HS.MsgRefuse anyProto)))) + [] + "It refuses to run any version." + ] + +-------------------------------------------------------------------------------- +-- DiffusionInit Tracer +-------------------------------------------------------------------------------- + +severityDiffusionInit :: ND.InitializationTracer rard ladr -> SeverityS +severityDiffusionInit ND.RunServer {} = Info +severityDiffusionInit ND.RunLocalServer {} = Info +severityDiffusionInit ND.UsingSystemdSocket {} = Info +severityDiffusionInit ND.CreateSystemdSocketForSnocketPath {} = Info +severityDiffusionInit ND.CreatedLocalSocket {} = Info +severityDiffusionInit ND.ConfiguringLocalSocket {} = Info +severityDiffusionInit ND.ListeningLocalSocket {} = Info +severityDiffusionInit ND.LocalSocketUp {} = Info +severityDiffusionInit ND.CreatingServerSocket {} = Info +severityDiffusionInit ND.ConfiguringServerSocket {} = Info +severityDiffusionInit ND.ListeningServerSocket {} = Info +severityDiffusionInit ND.ServerSocketUp {} = Info +severityDiffusionInit ND.UnsupportedLocalSystemdSocket {} = Info +severityDiffusionInit ND.UnsupportedReadySocketCase {} = Info +severityDiffusionInit ND.DiffusionErrored {} = Info + +namesForDiffusionInit :: ND.InitializationTracer rard ladr -> [Text] +namesForDiffusionInit ND.RunServer {} = + ["RunServer"] +namesForDiffusionInit ND.RunLocalServer {} = + ["RunLocalServer"] +namesForDiffusionInit ND.UsingSystemdSocket {} = + ["UsingSystemdSocket"] +namesForDiffusionInit ND.CreateSystemdSocketForSnocketPath {} = + ["CreateSystemdSocketForSnocketPath"] +namesForDiffusionInit ND.CreatedLocalSocket {} = + ["CreatedLocalSocket"] +namesForDiffusionInit ND.ConfiguringLocalSocket {} = + ["ConfiguringLocalSocket"] +namesForDiffusionInit ND.ListeningLocalSocket {} = + ["ListeningLocalSocket"] +namesForDiffusionInit ND.LocalSocketUp {} = + ["LocalSocketUp"] +namesForDiffusionInit ND.CreatingServerSocket {} = + ["CreatingServerSocket"] +namesForDiffusionInit ND.ConfiguringServerSocket {} = + ["ConfiguringServerSocket"] +namesForDiffusionInit ND.ListeningServerSocket {} = + ["ListeningServerSocket"] +namesForDiffusionInit ND.ServerSocketUp {} = + ["ServerSocketUp"] +namesForDiffusionInit ND.UnsupportedLocalSystemdSocket {} = + ["UnsupportedLocalSystemdSocket"] +namesForDiffusionInit ND.UnsupportedReadySocketCase {} = + ["UnsupportedReadySocketCase"] +namesForDiffusionInit ND.DiffusionErrored {} = + ["DiffusionErrored"] + +instance (Show ntnAddr, Show ntcAddr) => + LogFormatting (ND.InitializationTracer ntnAddr ntcAddr) where + forMachine _dtal (ND.RunServer sockAddr) = mkObject + [ "kind" .= String "RunServer" + , "socketAddress" .= String (pack (show sockAddr)) + ] + + forMachine _dtal (ND.RunLocalServer localAddress) = mkObject + [ "kind" .= String "RunLocalServer" + , "localAddress" .= String (pack (show localAddress)) + ] + forMachine _dtal (ND.UsingSystemdSocket localAddress) = mkObject + [ "kind" .= String "UsingSystemdSocket" + , "path" .= String (pack . show $ localAddress) + ] + + forMachine _dtal (ND.CreateSystemdSocketForSnocketPath localAddress) = mkObject + [ "kind" .= String "CreateSystemdSocketForSnocketPath" + , "path" .= String (pack . show $ localAddress) + ] + forMachine _dtal (ND.CreatedLocalSocket localAddress) = mkObject + [ "kind" .= String "CreatedLocalSocket" + , "path" .= String (pack . show $ localAddress) + ] + forMachine _dtal (ND.ConfiguringLocalSocket localAddress socket) = mkObject + [ "kind" .= String "ConfiguringLocalSocket" + , "path" .= String (pack . show $ localAddress) + , "socket" .= String (pack (show socket)) + ] + forMachine _dtal (ND.ListeningLocalSocket localAddress socket) = mkObject + [ "kind" .= String "ListeningLocalSocket" + , "path" .= String (pack . show $ localAddress) + , "socket" .= String (pack (show socket)) + ] + forMachine _dtal (ND.LocalSocketUp localAddress fd) = mkObject + [ "kind" .= String "LocalSocketUp" + , "path" .= String (pack . show $ localAddress) + , "socket" .= String (pack (show fd)) + ] + forMachine _dtal (ND.CreatingServerSocket socket) = mkObject + [ "kind" .= String "CreatingServerSocket" + , "socket" .= String (pack (show socket)) + ] + forMachine _dtal (ND.ListeningServerSocket socket) = mkObject + [ "kind" .= String "ListeningServerSocket" + , "socket" .= String (pack (show socket)) + ] + forMachine _dtal (ND.ServerSocketUp socket) = mkObject + [ "kind" .= String "ServerSocketUp" + , "socket" .= String (pack (show socket)) + ] + forMachine _dtal (ND.ConfiguringServerSocket socket) = mkObject + [ "kind" .= String "ConfiguringServerSocket" + , "socket" .= String (pack (show socket)) + ] + forMachine _dtal (ND.UnsupportedLocalSystemdSocket path) = mkObject + [ "kind" .= String "UnsupportedLocalSystemdSocket" + , "path" .= String (pack (show path)) + ] + forMachine _dtal ND.UnsupportedReadySocketCase = mkObject + [ "kind" .= String "UnsupportedReadySocketCase" + ] + forMachine _dtal (ND.DiffusionErrored exception) = mkObject + [ "kind" .= String "DiffusionErrored" + , "path" .= String (pack (show exception)) + ] + +docDiffusionInit :: Documented (ND.InitializationTracer Socket.SockAddr NtC.LocalAddress) +docDiffusionInit = Documented [ + DocMsg + (ND.RunServer (pure anyProto)) + [] + "RunServer " + , DocMsg + (ND.RunLocalServer anyProto) + [] + "RunLocalServer " + , DocMsg + (ND.UsingSystemdSocket anyProto) + [] + "UsingSystemdSocket " + , DocMsg + (ND.CreateSystemdSocketForSnocketPath anyProto) + [] + "CreateSystemdSocketForSnocketPath " + , DocMsg + (ND.CreatedLocalSocket anyProto) + [] + "CreatedLocalSocket " + , DocMsg + (ND.ConfiguringLocalSocket anyProto anyProto) + [] + "ConfiguringLocalSocket " + , DocMsg + (ND.ListeningLocalSocket anyProto anyProto) + [] + "ListeningLocalSocket " + , DocMsg + (ND.LocalSocketUp anyProto anyProto) + [] + "LocalSocketUp " + , DocMsg + (ND.CreatingServerSocket anyProto) + [] + "CreatingServerSocket " + , DocMsg + (ND.ConfiguringServerSocket anyProto) + [] + "ConfiguringServerSocket " + , DocMsg + (ND.ListeningServerSocket anyProto) + [] + "ListeningServerSocket " + , DocMsg + (ND.ServerSocketUp anyProto) + [] + "ServerSocketUp " + , DocMsg + (ND.UnsupportedLocalSystemdSocket anyProto) + [] + "UnsupportedLocalSystemdSocket " + , DocMsg + ND.UnsupportedReadySocketCase + [] + "UnsupportedReadySocketCase " + , DocMsg + (ND.DiffusionErrored anyProto) + [] + "DiffusionErrored " + ] + +-------------------------------------------------------------------------------- +-- LedgerPeers Tracer +-------------------------------------------------------------------------------- + +severityLedgerPeers :: TraceLedgerPeers -> SeverityS +severityLedgerPeers PickedPeer {} = Debug +severityLedgerPeers PickedPeers {} = Info +severityLedgerPeers FetchingNewLedgerState {} = Info +severityLedgerPeers DisabledLedgerPeers {} = Info +severityLedgerPeers TraceUseLedgerAfter {} = Info +severityLedgerPeers WaitingOnRequest {} = Debug +severityLedgerPeers RequestForPeers {} = Debug +severityLedgerPeers ReusingLedgerState {} = Debug +severityLedgerPeers FallingBackToBootstrapPeers {} = Info + +namesForLedgerPeers :: TraceLedgerPeers -> [Text] +namesForLedgerPeers PickedPeer {} = ["PickedPeer"] +namesForLedgerPeers PickedPeers {} = ["PickedPeers"] +namesForLedgerPeers FetchingNewLedgerState {} = ["FetchingNewLedgerState"] +namesForLedgerPeers DisabledLedgerPeers {} = ["DisabledLedgerPeers"] +namesForLedgerPeers TraceUseLedgerAfter {} = ["TraceUseLedgerAfter"] +namesForLedgerPeers WaitingOnRequest {} = ["WaitingOnRequest"] +namesForLedgerPeers RequestForPeers {} = ["RequestForPeers"] +namesForLedgerPeers ReusingLedgerState {} = ["ReusingLedgerState"] +namesForLedgerPeers FallingBackToBootstrapPeers {} = ["FallingBackToBootstrapPeers"] + + +instance LogFormatting TraceLedgerPeers where + forMachine _dtal (PickedPeer addr _ackStake stake) = + mkObject + [ "kind" .= String "PickedPeer" + , "address" .= show addr + , "relativeStake" .= (realToFrac (unPoolStake stake) :: Double) + ] + forMachine _dtal (PickedPeers (NumberOfPeers n) addrs) = + mkObject + [ "kind" .= String "PickedPeers" + , "desiredCount" .= n + , "count" .= length addrs + , "addresses" .= show addrs + ] + forMachine _dtal (FetchingNewLedgerState cnt) = + mkObject + [ "kind" .= String "FetchingNewLedgerState" + , "numberOfPools" .= cnt + ] + forMachine _dtal DisabledLedgerPeers = + mkObject + [ "kind" .= String "DisabledLedgerPeers" + ] + forMachine _dtal (TraceUseLedgerAfter ula) = + mkObject + [ "kind" .= String "UseLedgerAfter" + , "useLedgerAfter" .= UseLedger ula + ] + forMachine _dtal WaitingOnRequest = + mkObject + [ "kind" .= String "WaitingOnRequest" + ] + forMachine _dtal (RequestForPeers (NumberOfPeers np)) = + mkObject + [ "kind" .= String "RequestForPeers" + , "numberOfPeers" .= np + ] + forMachine _dtal (ReusingLedgerState cnt age) = + mkObject + [ "kind" .= String "ReusingLedgerState" + , "numberOfPools" .= cnt + , "ledgerStateAge" .= age + ] + forMachine _dtal FallingBackToBootstrapPeers = + mkObject + [ "kind" .= String "FallingBackToBootstrapPeers" + ] + + +docLedgerPeers :: Documented TraceLedgerPeers +docLedgerPeers = Documented [ + DocMsg + (PickedPeer + (RelayAccessDomain anyProto 1) + (AccPoolStake 0.5) + (PoolStake 0.5)) + [] + "Trace for a peer picked with accumulated and relative stake of its pool." + , DocMsg + (PickedPeers (NumberOfPeers 1) []) + [] + "Trace for the number of peers we wanted to pick and the list of peers picked." + , DocMsg + (FetchingNewLedgerState 1) + [] + "Trace for fetching a new list of peers from the ledger. Int is the number of peers\ + \ returned." + , DocMsg + DisabledLedgerPeers + [] + "Trace for when getting peers from the ledger is disabled, that is DontUseLedger." + , DocMsg + DisabledLedgerPeers + [] + "Trace for when getting peers from the ledger is disabled, that is DontUseLedger." + , DocMsg + (TraceUseLedgerAfter DontUseLedger) + [] + "Trace UseLedgerAfter value." + , DocMsg + WaitingOnRequest + [] + "" + , DocMsg + WaitingOnRequest + [] + "RequestForPeers (NumberOfPeers 1)" + , DocMsg + (ReusingLedgerState 1 anyProto) + [] + "" + , DocMsg + FallingBackToBootstrapPeers + [] + "" + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/ForgingThreadStats.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/ForgingThreadStats.hs new file mode 100644 index 00000000000..ea803ed985b --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/ForgingThreadStats.hs @@ -0,0 +1,187 @@ +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE RecordWildCards #-} + +module Cardano.Node.Tracing.Tracers.ForgingThreadStats + ( ForgingStats (..) + , ForgeThreadStats (..) + , forgeThreadStats + , docForgeStats + ) where + +import Cardano.Logging +import Cardano.Prelude hiding (All, concat, (:.:)) +import Data.Aeson (Value (..), (.=)) +import qualified Data.Map.Strict as Map + +import Cardano.Node.Tracing.Tracers.StartLeadershipCheck (ForgeTracerType) +import Cardano.Slotting.Slot (SlotNo (..)) +import Ouroboros.Consensus.Node.Tracers +import Ouroboros.Consensus.Shelley.Node () + +-------------------------------------------------------------------------------- +-- ForgeThreadStats Tracer +-------------------------------------------------------------------------------- + +-- | Per-forging-thread statistics. +data ForgeThreadStats = ForgeThreadStats + { ftsNodeCannotForgeNum :: !Int + , ftsNodeIsLeaderNum :: !Int + , ftsBlocksForgedNum :: !Int + , ftsSlotsMissedNum :: !Int + -- ^ Potentially missed slots. Note that this is not the same as the number + -- of missed blocks, since this includes all occurences of not reaching a + -- leadership check decision, whether or not leadership was possible or not. + -- + -- Also note that when the aggregate total for this metric is reported in the + -- multi-pool case, it can be much larger than the actual number of slots + -- occuring since node start, for it is a sum total for all threads. + , ftsLastSlot :: !Int + } + +instance LogFormatting ForgeThreadStats where + forHuman ForgeThreadStats {..} = + "Node cannot forge " <> showT ftsNodeCannotForgeNum + <> " node is leader " <> showT ftsNodeIsLeaderNum + <> " blocks forged " <> showT ftsBlocksForgedNum + <> " slots missed " <> showT ftsSlotsMissedNum + <> " last slot " <> showT ftsLastSlot + forMachine _dtal ForgeThreadStats {..} = + mkObject [ "kind" .= String "ForgeThreadStats" + , "nodeCannotForgeNum" .= String (show ftsNodeCannotForgeNum) + , "nodeIsLeaderNum" .= String (show ftsNodeIsLeaderNum) + , "blocksForgedNum" .= String (show ftsBlocksForgedNum) + , "slotsMissed" .= String (show ftsSlotsMissedNum) + , "lastSlot" .= String (show ftsLastSlot) + ] + asMetrics ForgeThreadStats {..} = + [ IntM "nodeCannotForgeNum" (fromIntegral ftsNodeCannotForgeNum) + , IntM "nodeIsLeaderNum" (fromIntegral ftsNodeIsLeaderNum) + , IntM "blocksForgedNum" (fromIntegral ftsBlocksForgedNum) + , IntM "slotsMissed" (fromIntegral ftsSlotsMissedNum) + , IntM "lastSlot" (fromIntegral ftsLastSlot) + ] + + +emptyForgeThreadStats :: ForgeThreadStats +emptyForgeThreadStats = ForgeThreadStats 0 0 0 0 0 + +docForgeStats :: Documented ForgeThreadStats +docForgeStats = Documented [ + DocMsg + emptyForgeThreadStats + [("nodeCannotForgeNum", + "How many times this node could not forge?") + ,("nodeIsLeaderNum", + "How many times this node was leader?") + ,("blocksForgedNum", + "How many blocks did forge in this node?") + ,("slotsMissed", + "How many slots were missed in this node?") + ] + "nodeCannotForgeNum shows how many times this node could not forge.\ + \\nnodeIsLeaderNum shows how many times this node was leader.\ + \\nblocksForgedNum shows how many blocks did forge in this node.\ + \\nslotsMissed shows how many slots were missed in this node." + ] + +-------------------------------------------------------------------------------- +-- ForgingStats Tracer +-------------------------------------------------------------------------------- + +-- | This structure stores counters of blockchain-related events, +-- per individual thread in fsStats. +data ForgingStats + = ForgingStats + { fsStats :: !(Map ThreadId ForgeThreadStats) + , fsNodeCannotForgeNum :: !Int + , fsNodeIsLeaderNum :: !Int + , fsBlocksForgedNum :: !Int + , fsSlotsMissedNum :: !Int + } + +instance LogFormatting ForgingStats where + forHuman ForgingStats {..} = + "Node cannot forge " <> showT fsNodeCannotForgeNum + <> " node is leader " <> showT fsNodeIsLeaderNum + <> " blocks forged " <> showT fsBlocksForgedNum + <> " slots missed " <> showT fsSlotsMissedNum + forMachine _dtal ForgingStats {..} = + mkObject [ "kind" .= String "ForgingStats" + , "nodeCannotForgeNum" .= String (show fsNodeCannotForgeNum) + , "nodeIsLeaderNum" .= String (show fsNodeIsLeaderNum) + , "blocksForgedNum" .= String (show fsBlocksForgedNum) + , "slotsMissed" .= String (show fsSlotsMissedNum) + ] + asMetrics ForgingStats {..} = + [ IntM "nodeCannotForgeNum" (fromIntegral fsNodeCannotForgeNum) + , IntM "nodeIsLeaderNum" (fromIntegral fsNodeIsLeaderNum) + , IntM "blocksForgedNum" (fromIntegral fsBlocksForgedNum) + , IntM "slotsMissed" (fromIntegral fsSlotsMissedNum) + ] + +emptyForgingStats :: ForgingStats +emptyForgingStats = ForgingStats mempty 0 0 0 0 + +forgeThreadStats :: Trace IO (Folding (ForgeTracerType blk) ForgingStats) + -> IO (Trace IO (ForgeTracerType blk)) +forgeThreadStats = foldMTraceM calculateThreadStats emptyForgingStats + +calculateThreadStats :: MonadIO m + => ForgingStats + -> LoggingContext + -> Maybe TraceControl + -> ForgeTracerType blk + -> m ForgingStats +calculateThreadStats stats _context _mbCtrl + (Left (TraceLabelCreds _ TraceNodeCannotForge {})) = do + mapThreadStats + stats + (\fts -> (fts { ftsNodeCannotForgeNum = ftsNodeCannotForgeNum fts + 1} + , Nothing)) + (\fs _ -> (fs { fsNodeCannotForgeNum = fsNodeCannotForgeNum fs + 1 })) +calculateThreadStats stats _context _mbCtrl + (Left (TraceLabelCreds _ (TraceNodeIsLeader (SlotNo slot')))) = do + let slot = fromIntegral slot' + mapThreadStats + stats + (\fts -> (fts { ftsNodeIsLeaderNum = ftsNodeIsLeaderNum fts + 1 + , ftsLastSlot = slot}, Nothing)) + (\fs _ -> (fs { fsNodeIsLeaderNum = fsNodeIsLeaderNum fs + 1 })) +calculateThreadStats stats _context _mbCtrl + (Left (TraceLabelCreds _ TraceForgedBlock {})) = do + mapThreadStats + stats + (\fts -> (fts { ftsBlocksForgedNum = ftsBlocksForgedNum fts + 1} + , Nothing)) + (\fs _ -> (fs { fsBlocksForgedNum = fsBlocksForgedNum fs + 1 })) +calculateThreadStats stats _context _mbCtrl + (Left (TraceLabelCreds _ (TraceNodeNotLeader (SlotNo slot')))) = do + let slot = fromIntegral slot' + mapThreadStats + stats + (\fts -> + if ftsLastSlot fts == 0 || succ (ftsLastSlot fts) == slot + then (fts { ftsLastSlot = slot }, Nothing) + else + let missed = (slot - ftsLastSlot fts) + in (fts { ftsLastSlot = slot + , ftsSlotsMissedNum = ftsSlotsMissedNum fts + missed} + , Just missed)) + (\fs mbMissed -> case mbMissed of + Nothing -> fs + Just missed -> (fs { fsSlotsMissedNum = + fsSlotsMissedNum fs + missed})) +calculateThreadStats stats _context _mbCtrl _message = pure stats + +mapThreadStats :: + MonadIO m + => ForgingStats + -> (ForgeThreadStats -> (ForgeThreadStats, Maybe a)) + -> (ForgingStats -> Maybe a -> ForgingStats) + -> m ForgingStats +mapThreadStats fs@ForgingStats { fsStats } f1 f2 = do + tid <- liftIO myThreadId + let threadStats = fromMaybe emptyForgeThreadStats (Map.lookup tid fsStats) + (newStats, w) = f1 threadStats + pure $ f2 (fs {fsStats = Map.insert tid newStats fsStats}) w diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/KESInfo.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/KESInfo.hs new file mode 100644 index 00000000000..898d27f0498 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/KESInfo.hs @@ -0,0 +1,87 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-orphans #-} +{-# OPTIONS_GHC -Wno-deprecations #-} + +module Cardano.Node.Tracing.Tracers.KESInfo + ( severityKESInfo + , namesForKESInfo + , traceAsKESInfo + , docForgeKESInfo + ) where + +import Data.SOP.Strict + +import Cardano.Logging +import Cardano.Prelude hiding (All, Show, show) + +import Cardano.Node.Queries (GetKESInfo (..)) +import Cardano.Protocol.TPraos.OCert (KESPeriod (..)) + +import Ouroboros.Consensus.Block.Forging +import Ouroboros.Consensus.Node.Tracers (TraceLabelCreds (..)) +import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey + +traceAsKESInfo + :: forall m blk . (GetKESInfo blk, MonadIO m) + => Proxy blk + -> Trace m (TraceLabelCreds HotKey.KESInfo) + -> Trace m (TraceLabelCreds (ForgeStateInfo blk)) +traceAsKESInfo pr tr = traceAsMaybeKESInfo pr (filterTraceMaybe tr) + +traceAsMaybeKESInfo + :: forall m blk . (GetKESInfo blk, MonadIO m) + => Proxy blk + -> Trace m (Maybe (TraceLabelCreds HotKey.KESInfo)) + -> Trace m (TraceLabelCreds (ForgeStateInfo blk)) +traceAsMaybeKESInfo pr (Trace tr) = Trace $ + contramap + (\(lc, mbC, TraceLabelCreds c e) -> + case getKESInfoFromStateInfo pr e of + Just kesi -> (lc, mbC, Just (TraceLabelCreds c kesi)) + Nothing -> (lc, mbC, Nothing)) + tr + +-------------------------------------------------------------------------------- +-- KESInfo Tracer +-------------------------------------------------------------------------------- + +severityKESInfo :: TraceLabelCreds HotKey.KESInfo -> SeverityS +severityKESInfo (TraceLabelCreds _creds a) = severityKESInfo' a + +severityKESInfo' :: HotKey.KESInfo -> SeverityS +severityKESInfo' forgeStateInfo = + let maxKesEvos = endKesPeriod - startKesPeriod + oCertExpiryKesPeriod = startKesPeriod + maxKesEvos + kesPeriodsUntilExpiry = max 0 (oCertExpiryKesPeriod - currKesPeriod) + in if kesPeriodsUntilExpiry > 7 + then Info + else if kesPeriodsUntilExpiry <= 1 + then Alert + else Warning + where + HotKey.KESInfo + { HotKey.kesStartPeriod = KESPeriod startKesPeriod + , HotKey.kesEvolution = currKesPeriod + , HotKey.kesEndPeriod = KESPeriod endKesPeriod + } = forgeStateInfo + +namesForKESInfo :: TraceLabelCreds HotKey.KESInfo -> [Text] +namesForKESInfo (TraceLabelCreds _creds a) = namesForKESInfo' a + +namesForKESInfo' :: HotKey.KESInfo -> [Text] +namesForKESInfo' _fsi = [] + +docForgeKESInfo :: Documented (TraceLabelCreds HotKey.KESInfo) +docForgeKESInfo = Documented [ + DocMsg + (TraceLabelCreds anyProto (HotKey.KESInfo (KESPeriod 0) (KESPeriod 1) 2)) + [] + "kesStartPeriod \ + \\nkesEndPeriod is kesStartPeriod + tpraosMaxKESEvo\ + \\nkesEvolution is the current evolution or /relative period/." + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToClient.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToClient.hs new file mode 100644 index 00000000000..d80b58dda67 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToClient.hs @@ -0,0 +1,466 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.NodeToClient + ( severityTChainSync + , namesForTChainSync + , docTChainSync + + , severityTTxSubmission + , namesForTTxSubmission + , docTTxSubmission + + , severityTStateQuery + , namesForTStateQuery + , docTStateQuery + ) where + +import Cardano.Logging +import Cardano.Prelude hiding (Show, show) +import Data.Aeson (Value (String), (.=)) +import Data.Text (pack) +import Network.TypedProtocol.Codec (AnyMessageAndAgency (..)) +import Text.Show + +import Ouroboros.Consensus.Ledger.Query (Query) +import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr, GenTx) + +import Ouroboros.Network.Block (Point, Serialised, Tip) +import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch +import Ouroboros.Network.Driver.Simple (TraceSendRecv (..)) +import Ouroboros.Network.Protocol.ChainSync.Type as ChainSync +import qualified Ouroboros.Network.Protocol.LocalStateQuery.Type as LSQ +import qualified Ouroboros.Network.Protocol.LocalTxSubmission.Type as LTS + + +instance LogFormatting (AnyMessageAndAgency ps) + => LogFormatting (TraceSendRecv ps) where + forMachine dtal (TraceSendMsg m) = mkObject + [ "kind" .= String "Send" , "msg" .= forMachine dtal m ] + forMachine dtal (TraceRecvMsg m) = mkObject + [ "kind" .= String "Recv" , "msg" .= forMachine dtal m ] + + forHuman (TraceSendMsg m) = "Send: " <> forHuman m + forHuman (TraceRecvMsg m) = "Receive: " <> forHuman m + + asMetrics (TraceSendMsg m) = asMetrics m + asMetrics (TraceRecvMsg m) = asMetrics m + + +-------------------------------------------------------------------------------- +-- TChainSync Tracer +-------------------------------------------------------------------------------- + +severityTChainSync :: BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync (Serialised blk) (Point blk) (Tip blk))) -> SeverityS +severityTChainSync (BlockFetch.TraceLabelPeer _ v) = severityTChainSync' v + where + severityTChainSync' (TraceSendMsg msg) = severityTChainSync'' msg + severityTChainSync' (TraceRecvMsg msg) = severityTChainSync'' msg + + severityTChainSync'' (AnyMessageAndAgency _agency msg) = severityTChainSync''' msg + + severityTChainSync''' :: Message + (ChainSync header point tip) from to + -> SeverityS + severityTChainSync''' MsgRequestNext {} = Info + severityTChainSync''' MsgAwaitReply {} = Info + severityTChainSync''' MsgRollForward {} = Info + severityTChainSync''' MsgRollBackward {} = Info + severityTChainSync''' MsgFindIntersect {} = Info + severityTChainSync''' MsgIntersectFound {} = Info + severityTChainSync''' MsgIntersectNotFound {} = Info + severityTChainSync''' MsgDone {} = Info + +namesForTChainSync :: BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync (Serialised blk) (Point blk) (Tip blk))) -> [Text] +namesForTChainSync (BlockFetch.TraceLabelPeer _ v) = "NodeToClient" : namesTChainSync v + where + + namesTChainSync (TraceSendMsg msg) = "Send" : namesTChainSync' msg + namesTChainSync (TraceRecvMsg msg) = "Recieve" : namesTChainSync' msg + + namesTChainSync' (AnyMessageAndAgency _agency msg) = namesTChainSync'' msg + + namesTChainSync'' :: Message (ChainSync header point tip) from to + -> [Text] + namesTChainSync'' MsgRequestNext {} = ["RequestNext"] + namesTChainSync'' MsgAwaitReply {} = ["AwaitReply"] + namesTChainSync'' MsgRollForward {} = ["RollForward"] + namesTChainSync'' MsgRollBackward {} = ["RollBackward"] + namesTChainSync'' MsgFindIntersect {} = ["FindIntersect"] + namesTChainSync'' MsgIntersectFound {} = ["IntersectFound"] + namesTChainSync'' MsgIntersectNotFound {} = ["IntersectNotFound"] + namesTChainSync'' MsgDone {} = ["Done"] + + +instance LogFormatting (AnyMessageAndAgency (ChainSync blk pt tip)) where + forMachine _dtal (AnyMessageAndAgency stok ChainSync.MsgRequestNext{}) = + mkObject [ "kind" .= String "MsgRequestNext" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok ChainSync.MsgAwaitReply{}) = + mkObject [ "kind" .= String "MsgAwaitReply" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok ChainSync.MsgRollForward{}) = + mkObject [ "kind" .= String "MsgRollForward" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok ChainSync.MsgRollBackward{}) = + mkObject [ "kind" .= String "MsgRollBackward" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok ChainSync.MsgFindIntersect{}) = + mkObject [ "kind" .= String "MsgFindIntersect" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok ChainSync.MsgIntersectFound{}) = + mkObject [ "kind" .= String "MsgIntersectFound" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok ChainSync.MsgIntersectNotFound{}) = + mkObject [ "kind" .= String "MsgIntersectNotFound" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok ChainSync.MsgDone{}) = + mkObject [ "kind" .= String "MsgDone" + , "agency" .= String (pack $ show stok) + ] + + +docTChainSync :: Documented (BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync x (Point blk) (Tip blk)))) +docTChainSync = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto MsgRequestNext))) + [] + "Request the next update from the producer. The response can be a roll\ + \forward, a roll back or wait." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto MsgAwaitReply))) + [] + "Acknowledge the request but require the consumer to wait for the next\ + \update. This means that the consumer is synced with the producer, and\ + \the producer is waiting for its own chain state to change." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto MsgAwaitReply))) + [] + "Tell the consumer to extend their chain with the given header.\ + \\n\ + \The message also tells the consumer about the head point of the producer." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto + (MsgRollForward anyProto anyProto)))) + [] + "Tell the consumer to extend their chain with the given header.\ + \\n\ + \The message also tells the consumer about the head point of the producer." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto + (MsgRollBackward anyProto anyProto)))) + [] + "Tell the consumer to roll back to a given point on their chain.\ + \\n\ + \The message also tells the consumer about the head point of the producer." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto + (MsgFindIntersect [anyProto])))) + [] + "Ask the producer to try to find an improved intersection point between\ + \the consumer and producer's chains. The consumer sends a sequence of\ + \points and it is up to the producer to find the first intersection point\ + \on its chain and send it back to the consumer." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto + (MsgIntersectFound anyProto anyProto)))) + [] + "The reply to the consumer about an intersection found.\ + \The consumer can decide weather to send more points.\ + \\n\ + \The message also tells the consumer about the head point of the producer." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto + (MsgIntersectNotFound anyProto)))) + [] + "The reply to the consumer that no intersection was found: none of the\ + \points the consumer supplied are on the producer chain.\ + \\n\ + \The message also tells the consumer about the head point of the producer." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto + MsgDone))) + [] + "We have to explain to the framework what our states mean, in terms of\ + \which party has agency in each state.\ + \\n\ + \Idle states are where it is for the client to send a message,\ + \busy states are where the server is expected to send a reply." + ] + +-------------------------------------------------------------------------------- +-- LocalTxSubmission Tracer +-------------------------------------------------------------------------------- + +severityTTxSubmission :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (LTS.LocalTxSubmission (GenTx blk) (ApplyTxErr blk))) + -> SeverityS +severityTTxSubmission (BlockFetch.TraceLabelPeer _ v) = severityTTxSubmission' v + where + severityTTxSubmission' (TraceSendMsg msg) = severityTTxSubmission'' msg + severityTTxSubmission' (TraceRecvMsg msg) = severityTTxSubmission'' msg + + severityTTxSubmission'' (AnyMessageAndAgency _agency msg) = severityTTxSubmission''' msg + + severityTTxSubmission''' :: Message + (LTS.LocalTxSubmission tx reject) from to + -> SeverityS + severityTTxSubmission''' LTS.MsgSubmitTx {} = Info + severityTTxSubmission''' LTS.MsgAcceptTx {} = Info + severityTTxSubmission''' LTS.MsgRejectTx {} = Info + severityTTxSubmission''' LTS.MsgDone {} = Info + + +namesForTTxSubmission :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (LTS.LocalTxSubmission (GenTx blk) (ApplyTxErr blk))) + -> [Text] +namesForTTxSubmission (BlockFetch.TraceLabelPeer _ v) = namesTTxSubmission v + where + namesTTxSubmission (TraceSendMsg msg) = "Send" : namesTTxSubmission' msg + namesTTxSubmission (TraceRecvMsg msg) = "Recieve" : namesTTxSubmission' msg + + namesTTxSubmission' (AnyMessageAndAgency _agency msg) = namesTTxSubmission'' msg + + namesTTxSubmission'' :: Message + (LTS.LocalTxSubmission tx reject) from to + -> [Text] + namesTTxSubmission'' LTS.MsgSubmitTx {} = ["SubmitTx"] + namesTTxSubmission'' LTS.MsgAcceptTx {} = ["AcceptTx"] + namesTTxSubmission'' LTS.MsgRejectTx {} = ["RejectTx"] + namesTTxSubmission'' LTS.MsgDone {} = ["Done"] + + +instance LogFormatting (AnyMessageAndAgency (LTS.LocalTxSubmission tx err)) where + forMachine _dtal (AnyMessageAndAgency stok LTS.MsgSubmitTx{}) = + mkObject [ "kind" .= String "MsgSubmitTx" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LTS.MsgAcceptTx{}) = + mkObject [ "kind" .= String "MsgAcceptTx" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LTS.MsgRejectTx{}) = + mkObject [ "kind" .= String "MsgRejectTx" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LTS.MsgDone{}) = + mkObject [ "kind" .= String "MsgDone" + , "agency" .= String (pack $ show stok) + ] + +docTTxSubmission :: Documented + (BlockFetch.TraceLabelPeer + localPeer + (TraceSendRecv + (LTS.LocalTxSubmission + (GenTx blk) (ApplyTxErr blk)))) +docTTxSubmission = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto (LTS.MsgSubmitTx anyProto)))) + [] + "The client submits a single transaction and waits a reply." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto LTS.MsgAcceptTx))) + [] + "The server can reply to inform the client that it has accepted the\ + \transaction." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto (LTS.MsgRejectTx anyProto)))) + [] + "The server can reply to inform the client that it has rejected the\ + \transaction. A reason for the rejection is included." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto LTS.MsgDone))) + [] + "The client can terminate the protocol." + ] + +-------------------------------------------------------------------------------- +-- TStateQuery Tracer +-------------------------------------------------------------------------------- + +severityTStateQuery :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (LSQ.LocalStateQuery blk (Point blk) query)) + -> SeverityS +severityTStateQuery (BlockFetch.TraceLabelPeer _ v) = severityTStateQuery' v + where + severityTStateQuery' (TraceSendMsg msg) = severityTStateQuery'' msg + severityTStateQuery' (TraceRecvMsg msg) = severityTStateQuery'' msg + + severityTStateQuery'' (AnyMessageAndAgency _agency msg) = severityTStateQuery''' msg + + severityTStateQuery''' :: Message + (LSQ.LocalStateQuery block point query1) from to + -> SeverityS + severityTStateQuery''' LSQ.MsgAcquire {} = Info + severityTStateQuery''' LSQ.MsgAcquired {} = Info + severityTStateQuery''' LSQ.MsgFailure {} = Warning + severityTStateQuery''' LSQ.MsgQuery {} = Info + severityTStateQuery''' LSQ.MsgResult {} = Info + severityTStateQuery''' LSQ.MsgRelease {} = Info + severityTStateQuery''' LSQ.MsgReAcquire {} = Info + severityTStateQuery''' LSQ.MsgDone {} = Info + +namesForTStateQuery :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (LSQ.LocalStateQuery blk (Point blk) query)) + -> [Text] +namesForTStateQuery (BlockFetch.TraceLabelPeer _ v) = namesForTStateQuery' v + where + namesForTStateQuery' (TraceSendMsg msg) = namesForTStateQuery'' msg + namesForTStateQuery' (TraceRecvMsg msg) = namesForTStateQuery'' msg + + namesForTStateQuery'' (AnyMessageAndAgency _agency msg) = namesForTStateQuery''' msg + + namesForTStateQuery''' :: Message + (LSQ.LocalStateQuery block point query1) from to + -> [Text] + + namesForTStateQuery''' LSQ.MsgAcquire {} = ["Acquire"] + namesForTStateQuery''' LSQ.MsgAcquired {} = ["Acquired"] + namesForTStateQuery''' LSQ.MsgFailure {} = ["Acquired"] + namesForTStateQuery''' LSQ.MsgQuery {} = ["Query"] + namesForTStateQuery''' LSQ.MsgResult {} = ["Result"] + namesForTStateQuery''' LSQ.MsgRelease {} = ["Release"] + namesForTStateQuery''' LSQ.MsgReAcquire {} = ["ReAcquire"] + namesForTStateQuery''' LSQ.MsgDone {} = ["Done"] + +instance (forall result. Show (Query blk result)) + => LogFormatting (AnyMessageAndAgency (LSQ.LocalStateQuery blk pt (Query blk))) where + forMachine _dtal (AnyMessageAndAgency stok LSQ.MsgAcquire{}) = + mkObject [ "kind" .= String "MsgAcquire" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LSQ.MsgAcquired{}) = + mkObject [ "kind" .= String "MsgAcquired" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LSQ.MsgFailure{}) = + mkObject [ "kind" .= String "MsgFailure" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LSQ.MsgQuery{}) = + mkObject [ "kind" .= String "MsgQuery" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LSQ.MsgResult{}) = + mkObject [ "kind" .= String "MsgResult" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LSQ.MsgRelease{}) = + mkObject [ "kind" .= String "MsgRelease" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LSQ.MsgReAcquire{}) = + mkObject [ "kind" .= String "MsgReAcquire" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok LSQ.MsgDone{}) = + mkObject [ "kind" .= String "MsgDone" + , "agency" .= String (pack $ show stok) + ] + +docTStateQuery :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (LSQ.LocalStateQuery blk (Point blk) query))) +docTStateQuery = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto (LSQ.MsgAcquire Nothing)))) + [] + "The client requests that the state as of a particular recent point on\ + \the server's chain (within K of the tip) be made available to query,\ + \and waits for confirmation or failure.\ + \\n\ + \From 'NodeToClient_V8' onwards if the point is not specified, current tip\ + \will be acquired. For previous versions of the protocol 'point' must be\ + \given." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg (AnyMessageAndAgency anyProto LSQ.MsgAcquired))) + [] + "The server can confirm that it has the state at the requested point." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (LSQ.MsgFailure anyProto)))) + [] + "The server can report that it cannot obtain the state for the\ + \requested point." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (LSQ.MsgQuery anyProto)))) + [] + "The client can perform queries on the current acquired state." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (LSQ.MsgResult anyProto anyProto)))) + [] + "The server must reply with the queries." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + LSQ.MsgRelease))) + [] + "The client can instruct the server to release the state. This lets\ + \the server free resources." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (LSQ.MsgReAcquire Nothing)))) + [] + "This is like 'MsgAcquire' but for when the client already has a\ + \state. By moveing to another state directly without a 'MsgRelease' it\ + \enables optimisations on the server side (e.g. moving to the state for\ + \the immediate next block).\ + \\n\ + \Note that failure to re-acquire is equivalent to 'MsgRelease',\ + \rather than keeping the exiting acquired state.\ + \\n\ + \From 'NodeToClient_V8' onwards if the point is not specified, current tip\ + \will be acquired. For previous versions of the protocol 'point' must be\ + \given." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + LSQ.MsgDone))) + [] + "The client can terminate the protocol." + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToNode.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToNode.hs new file mode 100644 index 00000000000..9816b95821d --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToNode.hs @@ -0,0 +1,766 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.NodeToNode + ( + severityTChainSyncNode + , namesForTChainSyncNode + + , severityTChainSyncSerialised + , namesForTChainSyncSerialised + + , severityTBlockFetch + , namesForTBlockFetch + , docTBlockFetch + + , severityTBlockFetchSerialised + , namesForTBlockFetchSerialised + + , severityTxSubmissionNode + , namesForTxSubmissionNode + , docTTxSubmissionNode + + , severityTxSubmission2Node + , namesForTxSubmission2Node + , docTTxSubmission2Node + ) where + +import Cardano.Logging +import Cardano.Prelude hiding (Show, show) +import Data.Aeson (Value (String), toJSON, (.=)) +import Data.Text (pack) +import Network.TypedProtocol.Codec (AnyMessageAndAgency (..), PeerHasAgency (..)) +import Text.Show + +import Cardano.Node.Queries (ConvertTxId) +import Cardano.Node.Tracing.Render (renderHeaderHash, renderTxIdForDetails) + +import Ouroboros.Consensus.Block (ConvertRawHash, GetHeader, HasHeader, Header, + StandardHash, getHeader) +import Ouroboros.Consensus.Ledger.SupportsMempool (GenTx, GenTxId, HasTxId, HasTxs, + LedgerSupportsMempool, extractTxs, txId) +import Ouroboros.Consensus.Node.Run (SerialiseNodeToNodeConstraints, estimateBlockSize) +import Ouroboros.Consensus.Storage.Serialisation (SerialisedHeader) + +import Ouroboros.Network.Block (Point, Serialised, Tip, blockHash) +import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch +import Ouroboros.Network.Driver.Simple (TraceSendRecv (..)) +import Ouroboros.Network.Protocol.BlockFetch.Type (BlockFetch (..), Message (..)) +import Ouroboros.Network.Protocol.ChainSync.Type as ChainSync +import Ouroboros.Network.Protocol.Trans.Hello.Type (ClientHasAgency (..), Hello, + Message (..), ServerHasAgency (..)) +import qualified Ouroboros.Network.Protocol.TxSubmission.Type as STX +import qualified Ouroboros.Network.Protocol.TxSubmission2.Type as TXS + +-------------------------------------------------------------------------------- +-- ChainSync Tracer +-------------------------------------------------------------------------------- + +severityTChainSyncNode :: BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync (Header blk) (Point blk) (Tip blk))) -> SeverityS +severityTChainSyncNode (BlockFetch.TraceLabelPeer _ v) = severityTChainSync' v + where + severityTChainSync' (TraceSendMsg msg) = severityTChainSync'' msg + severityTChainSync' (TraceRecvMsg msg) = severityTChainSync'' msg + + severityTChainSync'' (AnyMessageAndAgency _agency msg) = severityTChainSync''' msg + + severityTChainSync''' :: Message + (ChainSync header point tip) from to + -> SeverityS + severityTChainSync''' MsgRequestNext {} = Info + severityTChainSync''' MsgAwaitReply {} = Info + severityTChainSync''' MsgRollForward {} = Info + severityTChainSync''' MsgRollBackward {} = Info + severityTChainSync''' MsgFindIntersect {} = Info + severityTChainSync''' MsgIntersectFound {} = Info + severityTChainSync''' MsgIntersectNotFound {} = Info + severityTChainSync''' MsgDone {} = Info + +namesForTChainSyncNode :: BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync (Header blk) (Point blk) (Tip blk))) -> [Text] +namesForTChainSyncNode (BlockFetch.TraceLabelPeer _ v) = "NodeToNode" : namesTChainSync v + where + + namesTChainSync (TraceSendMsg msg) = "Send" : namesTChainSync' msg + namesTChainSync (TraceRecvMsg msg) = "Recieve" : namesTChainSync' msg + + namesTChainSync' (AnyMessageAndAgency _agency msg) = namesTChainSync'' msg + + namesTChainSync'' :: Message (ChainSync header point tip) from to + -> [Text] + namesTChainSync'' MsgRequestNext {} = ["RequestNext"] + namesTChainSync'' MsgAwaitReply {} = ["AwaitReply"] + namesTChainSync'' MsgRollForward {} = ["RollForward"] + namesTChainSync'' MsgRollBackward {} = ["RollBackward"] + namesTChainSync'' MsgFindIntersect {} = ["FindIntersect"] + namesTChainSync'' MsgIntersectFound {} = ["IntersectFound"] + namesTChainSync'' MsgIntersectNotFound {} = ["IntersectNotFound"] + namesTChainSync'' MsgDone {} = ["Done"] + +-------------------------------------------------------------------------------- +-- ChainSyncSerialised Tracer +-------------------------------------------------------------------------------- + +severityTChainSyncSerialised :: BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync (SerialisedHeader blk) (Point blk) (Tip blk))) -> SeverityS +severityTChainSyncSerialised (BlockFetch.TraceLabelPeer _ v) = severityTChainSync' v + where + severityTChainSync' (TraceSendMsg msg) = severityTChainSync'' msg + severityTChainSync' (TraceRecvMsg msg) = severityTChainSync'' msg + + severityTChainSync'' (AnyMessageAndAgency _agency msg) = severityTChainSync''' msg + + severityTChainSync''' :: Message + (ChainSync header point tip) from to + -> SeverityS + severityTChainSync''' MsgRequestNext {} = Info + severityTChainSync''' MsgAwaitReply {} = Info + severityTChainSync''' MsgRollForward {} = Info + severityTChainSync''' MsgRollBackward {} = Info + severityTChainSync''' MsgFindIntersect {} = Info + severityTChainSync''' MsgIntersectFound {} = Info + severityTChainSync''' MsgIntersectNotFound {} = Info + severityTChainSync''' MsgDone {} = Info + +namesForTChainSyncSerialised :: BlockFetch.TraceLabelPeer peer (TraceSendRecv + (ChainSync (SerialisedHeader blk) (Point blk) (Tip blk))) -> [Text] +namesForTChainSyncSerialised (BlockFetch.TraceLabelPeer _ v) = + "NodeToNode" : namesTChainSync v + where + namesTChainSync (TraceSendMsg msg) = "Send" : namesTChainSync' msg + namesTChainSync (TraceRecvMsg msg) = "Recieve" : namesTChainSync' msg + + namesTChainSync' (AnyMessageAndAgency _agency msg) = namesTChainSync'' msg + + namesTChainSync'' :: Message (ChainSync header point tip) from to + -> [Text] + namesTChainSync'' MsgRequestNext {} = ["RequestNext"] + namesTChainSync'' MsgAwaitReply {} = ["AwaitReply"] + namesTChainSync'' MsgRollForward {} = ["RollForward"] + namesTChainSync'' MsgRollBackward {} = ["RollBackward"] + namesTChainSync'' MsgFindIntersect {} = ["FindIntersect"] + namesTChainSync'' MsgIntersectFound {} = ["IntersectFound"] + namesTChainSync'' MsgIntersectNotFound {} = ["IntersectNotFound"] + namesTChainSync'' MsgDone {} = ["Done"] + +-------------------------------------------------------------------------------- +-- BlockFetch Tracer +-------------------------------------------------------------------------------- + +severityTBlockFetch :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (BlockFetch blk (Point blk))) -> SeverityS +severityTBlockFetch (BlockFetch.TraceLabelPeer _ v) = severityTBlockFetch' v + where + severityTBlockFetch' (TraceSendMsg msg) = severityTBlockFetch'' msg + severityTBlockFetch' (TraceRecvMsg msg) = severityTBlockFetch'' msg + + severityTBlockFetch'' (AnyMessageAndAgency _agency msg) = severityTBlockFetch''' msg + + severityTBlockFetch''' :: Message (BlockFetch x (Point blk)) from to + -> SeverityS + severityTBlockFetch''' MsgRequestRange {} = Info + severityTBlockFetch''' MsgStartBatch {} = Info + severityTBlockFetch''' MsgNoBlocks {} = Info + severityTBlockFetch''' MsgBlock {} = Info + severityTBlockFetch''' MsgBatchDone {} = Info + severityTBlockFetch''' MsgClientDone {} = Info + +namesForTBlockFetch :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (BlockFetch blk (Point blk))) -> [Text] +namesForTBlockFetch (BlockFetch.TraceLabelPeer _ v) = + "NodeToNode" : namesTBlockFetch v + where + namesTBlockFetch (TraceSendMsg msg) = "Send" : namesTBlockFetch' msg + namesTBlockFetch (TraceRecvMsg msg) = "Recieve" : namesTBlockFetch' msg + + namesTBlockFetch' (AnyMessageAndAgency _agency msg) = namesTBlockFetch'' msg + + namesTBlockFetch'' :: Message (BlockFetch x (Point blk)) from to + -> [Text] + namesTBlockFetch'' MsgRequestRange {} = ["RequestRange"] + namesTBlockFetch'' MsgStartBatch {} = ["StartBatch"] + namesTBlockFetch'' MsgNoBlocks {} = ["NoBlocks"] + namesTBlockFetch'' MsgBlock {} = ["Block"] + namesTBlockFetch'' MsgBatchDone {} = ["BatchDone"] + namesTBlockFetch'' MsgClientDone {} = ["ClientDone"] + +instance ( ConvertTxId blk + , ConvertRawHash blk + , HasHeader blk + , GetHeader blk + , HasTxId (GenTx blk) + , SerialiseNodeToNodeConstraints blk + , HasTxs blk + , LedgerSupportsMempool blk + ) + => LogFormatting (AnyMessageAndAgency (BlockFetch blk (Point blk))) where + forMachine DMinimal (AnyMessageAndAgency stok (MsgBlock blk)) = + mkObject [ "kind" .= String "MsgBlock" + , "agency" .= String (pack $ show stok) + , "blockHash" .= renderHeaderHash (Proxy @blk) (blockHash blk) + , "blockSize" .= toJSON (estimateBlockSize (getHeader blk)) + ] + + forMachine dtal (AnyMessageAndAgency stok (MsgBlock blk)) = + mkObject [ "kind" .= String "MsgBlock" + , "agency" .= String (pack $ show stok) + , "blockHash" .= renderHeaderHash (Proxy @blk) (blockHash blk) + , "blockSize" .= toJSON (estimateBlockSize (getHeader blk)) + , "txIds" .= toJSON (presentTx <$> extractTxs blk) + ] + where + presentTx :: GenTx blk -> Value + presentTx = String . renderTxIdForDetails dtal . txId + + forMachine _v (AnyMessageAndAgency stok MsgRequestRange{}) = + mkObject [ "kind" .= String "MsgRequestRange" + , "agency" .= String (pack $ show stok) + ] + forMachine _v (AnyMessageAndAgency stok MsgStartBatch{}) = + mkObject [ "kind" .= String "MsgStartBatch" + , "agency" .= String (pack $ show stok) + ] + forMachine _v (AnyMessageAndAgency stok MsgNoBlocks{}) = + mkObject [ "kind" .= String "MsgNoBlocks" + , "agency" .= String (pack $ show stok) + ] + forMachine _v (AnyMessageAndAgency stok MsgBatchDone{}) = + mkObject [ "kind" .= String "MsgBatchDone" + , "agency" .= String (pack $ show stok) + ] + forMachine _v (AnyMessageAndAgency stok MsgClientDone{}) = + mkObject [ "kind" .= String "MsgClientDone" + , "agency" .= String (pack $ show stok) + ] + +docTBlockFetch :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (BlockFetch x (Point blk)))) +docTBlockFetch = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (MsgRequestRange anyProto)))) + [] + "Request range of blocks." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + MsgStartBatch))) + [] + "Start block streaming." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + MsgNoBlocks))) + [] + "Respond that there are no blocks." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (MsgBlock anyProto)))) + [] + "Stream a single block." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + MsgBatchDone))) + [] + "End of block streaming." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + MsgClientDone))) + [] + "Client termination message." + ] + +-------------------------------------------------------------------------------- +-- BlockFetchSerialised Tracer +-------------------------------------------------------------------------------- + +severityTBlockFetchSerialised :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (BlockFetch (Serialised blk) (Point blk))) -> SeverityS +severityTBlockFetchSerialised (BlockFetch.TraceLabelPeer _ v) = severityTBlockFetch' v + where + severityTBlockFetch' (TraceSendMsg msg) = severityTBlockFetch'' msg + severityTBlockFetch' (TraceRecvMsg msg) = severityTBlockFetch'' msg + + severityTBlockFetch'' (AnyMessageAndAgency _agency msg) = severityTBlockFetch''' msg + + severityTBlockFetch''' :: Message (BlockFetch x (Point blk)) from to + -> SeverityS + severityTBlockFetch''' MsgRequestRange {} = Info + severityTBlockFetch''' MsgStartBatch {} = Info + severityTBlockFetch''' MsgNoBlocks {} = Info + severityTBlockFetch''' MsgBlock {} = Info + severityTBlockFetch''' MsgBatchDone {} = Info + severityTBlockFetch''' MsgClientDone {} = Info + +namesForTBlockFetchSerialised :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (BlockFetch (Serialised blk) (Point blk))) -> [Text] +namesForTBlockFetchSerialised (BlockFetch.TraceLabelPeer _ v) = + "NodeToNode" : namesTBlockFetch v + where + namesTBlockFetch (TraceSendMsg msg) = "Send" : namesTBlockFetch' msg + namesTBlockFetch (TraceRecvMsg msg) = "Recieve" : namesTBlockFetch' msg + + namesTBlockFetch' (AnyMessageAndAgency _agency msg) = namesTBlockFetch'' msg + + namesTBlockFetch'' :: Message (BlockFetch x (Point blk)) from to + -> [Text] + namesTBlockFetch'' MsgRequestRange {} = ["RequestRange"] + namesTBlockFetch'' MsgStartBatch {} = ["StartBatch"] + namesTBlockFetch'' MsgNoBlocks {} = ["NoBlocks"] + namesTBlockFetch'' MsgBlock {} = ["Block"] + namesTBlockFetch'' MsgBatchDone {} = ["BatchDone"] + namesTBlockFetch'' MsgClientDone {} = ["ClientDone"] + +-- TODO Tracers +-- Provide complete implementation of forMachine +instance ( ConvertTxId blk + , HasTxId (GenTx blk) + , ConvertRawHash blk + , StandardHash blk + , HasTxs blk + ) + => LogFormatting (AnyMessageAndAgency (BlockFetch (Serialised blk) (Point blk))) where + forMachine DMinimal (AnyMessageAndAgency stok (MsgBlock _blk)) = + mkObject [ "kind" .= String "MsgBlock" + , "agency" .= String (pack $ show stok) + -- , "blockHash" .= renderHeaderHash (Proxy @blk) (blockHash blk) + -- , "blockSize" .= toJSON (estimateBlockSize (getHeader blk)) + ] + + forMachine _dtal (AnyMessageAndAgency stok (MsgBlock _blk)) = + mkObject [ "kind" .= String "MsgBlock" + , "agency" .= String (pack $ show stok) + -- , "blockHash" .= renderHeaderHash (Proxy @blk) (blockHash blk) + -- , "blockSize" .= toJSON (estimateBlockSize (getHeader blk)) + -- , "txIds" .= toJSON (presentTx <$> extractTxs blk) + ] + -- where + -- presentTx :: GenTx blk -> Value + -- presentTx = String . renderTxIdForDetails dtal . txId + + forMachine _v (AnyMessageAndAgency stok MsgRequestRange{}) = + mkObject [ "kind" .= String "MsgRequestRange" + , "agency" .= String (pack $ show stok) + ] + forMachine _v (AnyMessageAndAgency stok MsgStartBatch{}) = + mkObject [ "kind" .= String "MsgStartBatch" + , "agency" .= String (pack $ show stok) + ] + forMachine _v (AnyMessageAndAgency stok MsgNoBlocks{}) = + mkObject [ "kind" .= String "MsgNoBlocks" + , "agency" .= String (pack $ show stok) + ] + forMachine _v (AnyMessageAndAgency stok MsgBatchDone{}) = + mkObject [ "kind" .= String "MsgBatchDone" + , "agency" .= String (pack $ show stok) + ] + forMachine _v (AnyMessageAndAgency stok MsgClientDone{}) = + mkObject [ "kind" .= String "MsgClientDone" + , "agency" .= String (pack $ show stok) + ] + + forHuman = pack . show + + +-------------------------------------------------------------------------------- +-- TxSubmissionNode Tracer +-------------------------------------------------------------------------------- + +severityTxSubmissionNode :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (TXS.TxSubmission (GenTxId blk) (GenTx blk))) -> SeverityS +severityTxSubmissionNode (BlockFetch.TraceLabelPeer _ v) = severityTxSubNode v + where + severityTxSubNode (TraceSendMsg msg) = severityTxSubNode' msg + severityTxSubNode (TraceRecvMsg msg) = severityTxSubNode' msg + + severityTxSubNode' (AnyMessageAndAgency _agency msg) = severityTxSubNode'' msg + + severityTxSubNode'' :: + Message + (TXS.TxSubmission (GenTxId blk) (GenTx blk)) + from + to + -> SeverityS + severityTxSubNode'' TXS.MsgRequestTxIds {} = Info + severityTxSubNode'' TXS.MsgReplyTxIds {} = Info + severityTxSubNode'' TXS.MsgRequestTxs {} = Info + severityTxSubNode'' TXS.MsgReplyTxs {} = Info + severityTxSubNode'' TXS.MsgDone {} = Info + + +namesForTxSubmissionNode :: BlockFetch.TraceLabelPeer peer + (TraceSendRecv (TXS.TxSubmission (GenTxId blk) (GenTx blk))) -> [Text] +namesForTxSubmissionNode (BlockFetch.TraceLabelPeer _ v) = + "NodeToNode" : namesTxSubNode v + where + namesTxSubNode (TraceSendMsg msg) = "Send" : namesTxSubNode' msg + namesTxSubNode (TraceRecvMsg msg) = "Recieve" : namesTxSubNode' msg + + namesTxSubNode' (AnyMessageAndAgency _agency msg) = namesTxSubNode'' msg + + namesTxSubNode'' :: + Message + (TXS.TxSubmission (GenTxId blk) (GenTx blk)) + from + to + -> [Text] + namesTxSubNode'' TXS.MsgRequestTxIds {} = ["RequestTxIds"] + namesTxSubNode'' TXS.MsgReplyTxIds {} = ["ReplyTxIds"] + namesTxSubNode'' TXS.MsgRequestTxs {} = ["RequestTxs"] + namesTxSubNode'' TXS.MsgReplyTxs {} = ["ReplyTxs"] + namesTxSubNode'' TXS.MsgDone {} = ["Done"] + + +instance (Show txid, Show tx) + => LogFormatting (AnyMessageAndAgency (STX.TxSubmission txid tx)) where + forMachine _dtal (AnyMessageAndAgency stok (STX.MsgRequestTxs txids)) = + mkObject + [ "kind" .= String "MsgRequestTxs" + , "agency" .= String (pack $ show stok) + , "txIds" .= String (pack $ show txids) + ] + forMachine _dtal (AnyMessageAndAgency stok (STX.MsgReplyTxs txs)) = + mkObject + [ "kind" .= String "MsgReplyTxs" + , "agency" .= String (pack $ show stok) + , "txs" .= String (pack $ show txs) + ] + forMachine _dtal (AnyMessageAndAgency stok STX.MsgRequestTxIds {}) = + mkObject + [ "kind" .= String "MsgRequestTxIds" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok (STX.MsgReplyTxIds _)) = + mkObject + [ "kind" .= String "MsgReplyTxIds" + , "agency" .= String (pack $ show stok) + ] + forMachine _dtal (AnyMessageAndAgency stok STX.MsgDone) = + mkObject + [ "kind" .= String "MsgDone" + , "agency" .= String (pack $ show stok) + ] + +docTTxSubmissionNode :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (TXS.TxSubmission (GenTxId blk) (GenTx blk)))) +docTTxSubmissionNode = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (TXS.MsgRequestTxIds anyProto 1 1)))) + [] + "Request a non-empty list of transaction identifiers from the client,\ + \and confirm a number of outstanding transaction identifiers.\ + \\n\ + \With 'TokBlocking' this is a a blocking operation: the response will\ + \always have at least one transaction identifier, and it does not expect\ + \a prompt response: there is no timeout. This covers the case when there\ + \is nothing else to do but wait. For example this covers leaf nodes that\ + \rarely, if ever, create and submit a transaction.\ + \\n\ + \With 'TokNonBlocking' this is a non-blocking operation: the response\ + \may be an empty list and this does expect a prompt response. This\ + \covers high throughput use cases where we wish to pipeline, by\ + \interleaving requests for additional transaction identifiers with\ + \requests for transactions, which requires these requests not block.\ + \\n\ + \The request gives the maximum number of transaction identifiers that\ + \can be accepted in the response. This must be greater than zero in the\ + \'TokBlocking' case. In the 'TokNonBlocking' case either the numbers\ + \acknowledged or the number requested must be non-zero. In either case,\ + \the number requested must not put the total outstanding over the fixed\ + \protocol limit.\ + \\n\ + \The request also gives the number of outstanding transaction\ + \identifiers that can now be acknowledged. The actual transactions\ + \to acknowledge are known to the peer based on the FIFO order in which\ + \they were provided.\ + \\n\ + \There is no choice about when to use the blocking case versus the\ + \non-blocking case, it depends on whether there are any remaining\ + \unacknowledged transactions (after taking into account the ones\ + \acknowledged in this message):\ + \\n\ + \* The blocking case must be used when there are zero remaining\ + \ unacknowledged transactions.\ + \\n\ + \* The non-blocking case must be used when there are non-zero remaining\ + \ unacknowledged transactions." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (TXS.MsgReplyTxIds anyProto)))) + [] + "Reply with a list of transaction identifiers for available\ + \transactions, along with the size of each transaction.\ + \\n\ + \The list must not be longer than the maximum number requested.\ + \\n\ + \In the 'StTxIds' 'StBlocking' state the list must be non-empty while\ + \in the 'StTxIds' 'StNonBlocking' state the list may be empty.\ + \\n\ + \These transactions are added to the notional FIFO of outstanding\ + \transaction identifiers for the protocol.\ + \\n\ + \The order in which these transaction identifiers are returned must be\ + \the order in which they are submitted to the mempool, to preserve\ + \dependent transactions." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (TXS.MsgRequestTxs [anyProto])))) + [] + "Request one or more transactions corresponding to the given \ + \transaction identifiers. \ + \\n\ + \While it is the responsibility of the replying peer to keep within \ + \pipelining in-flight limits, the sender must also cooperate by keeping \ + \the total requested across all in-flight requests within the limits. \ + \\n\ + \It is an error to ask for transaction identifiers that were not \ + \previously announced (via 'MsgReplyTxIds'). \ + \\n\ + \It is an error to ask for transaction identifiers that are not \ + \outstanding or that were already asked for." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (TXS.MsgReplyTxs [anyProto])))) + [] + "Reply with the requested transactions, or implicitly discard.\ + \\n\ + \Transactions can become invalid between the time the transaction \ + \identifier was sent and the transaction being requested. Invalid \ + \(including committed) transactions do not need to be sent.\ + \\n\ + \Any transaction identifiers requested but not provided in this reply \ + \should be considered as if this peer had never announced them. (Note \ + \that this is no guarantee that the transaction is invalid, it may still \ + \be valid and available from another peer)." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + TXS.MsgDone))) + [] + "Termination message, initiated by the client when the server is \ + \making a blocking call for more transaction identifiers." + --TODO: Can't use 'MsgKThxBye' because NodeToNodeV_2 is not introduced yet. + ] + +-------------------------------------------------------------------------------- +-- TxSubmissionNode2 Tracer +-------------------------------------------------------------------------------- + +severityTxSubmission2Node :: forall blk peer. BlockFetch.TraceLabelPeer peer + (TraceSendRecv (TXS.TxSubmission2 (GenTxId blk) (GenTx blk))) -> SeverityS +severityTxSubmission2Node (BlockFetch.TraceLabelPeer _ v) = severityTxSubNode v + where + severityTxSubNode (TraceSendMsg msg) = severityTxSubNode' msg + severityTxSubNode (TraceRecvMsg msg) = severityTxSubNode' msg + + severityTxSubNode' (AnyMessageAndAgency _agency msg) = severityTxSubNode'' msg + + severityTxSubNode'' :: + Message + (Hello (TXS.TxSubmission (GenTxId blk) (GenTx blk)) stIdle) + from + to + -> SeverityS + severityTxSubNode'' MsgHello {} = Debug + severityTxSubNode'' (MsgTalk TXS.MsgRequestTxIds {}) = Info + severityTxSubNode'' (MsgTalk TXS.MsgReplyTxIds {}) = Info + severityTxSubNode'' (MsgTalk TXS.MsgRequestTxs {}) = Info + severityTxSubNode'' (MsgTalk TXS.MsgReplyTxs {}) = Info + severityTxSubNode'' (MsgTalk TXS.MsgDone {}) = Info + +namesForTxSubmission2Node :: forall blk peer. BlockFetch.TraceLabelPeer peer + (TraceSendRecv (TXS.TxSubmission2 (GenTxId blk) (GenTx blk))) -> [Text] +namesForTxSubmission2Node (BlockFetch.TraceLabelPeer _ v) = + "NodeToNode" : namesTxSubNode v + where + namesTxSubNode (TraceSendMsg msg) = "Send" : namesTxSubNode' msg + namesTxSubNode (TraceRecvMsg msg) = "Recieve" : namesTxSubNode' msg + + namesTxSubNode' (AnyMessageAndAgency _agency msg) = namesTxSubNode'' msg + + namesTxSubNode'' :: + Message + (Hello (TXS.TxSubmission (GenTxId blk) (GenTx blk)) stIdle) + from + to + -> [Text] + namesTxSubNode'' MsgHello {} = ["MsgHello"] + namesTxSubNode'' (MsgTalk TXS.MsgRequestTxIds {}) = ["RequestTxIds"] + namesTxSubNode'' (MsgTalk TXS.MsgReplyTxIds {}) = ["ReplyTxIds"] + namesTxSubNode'' (MsgTalk TXS.MsgRequestTxs {}) = ["RequestTxs"] + namesTxSubNode'' (MsgTalk TXS.MsgReplyTxs {}) = ["ReplyTxs"] + namesTxSubNode'' (MsgTalk TXS.MsgDone {}) = ["Done"] + + +instance (Show txid, Show tx) + => LogFormatting (AnyMessageAndAgency (TXS.TxSubmission2 txid tx)) where + forMachine _dtal (AnyMessageAndAgency + -- we need this pattern match for GHC to recognise this + -- function as total. + stok@(ClientAgency TokHello) + MsgHello) = + mkObject + [ "kind" .= String "MsgHello" + , "agency" .= String (pack $ show stok) + ] + forMachine dtal (AnyMessageAndAgency + (ClientAgency (TokClientTalk stok)) + (MsgTalk msg)) = + forMachine dtal (AnyMessageAndAgency (ClientAgency stok) msg) + forMachine dtal (AnyMessageAndAgency + (ServerAgency (TokServerTalk stok)) + (MsgTalk msg)) = + forMachine dtal (AnyMessageAndAgency (ServerAgency stok) msg) + + +docTTxSubmission2Node :: Documented + (BlockFetch.TraceLabelPeer peer + (TraceSendRecv + (TXS.TxSubmission2 (GenTxId blk) (GenTx blk)))) +docTTxSubmission2Node = Documented [ + DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + MsgHello))) + [] + "Client side hello message." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (MsgTalk (TXS.MsgRequestTxIds anyProto 1 1))))) + [] + "Request a non-empty list of transaction identifiers from the client, \ + \and confirm a number of outstanding transaction identifiers. \ + \\n\ + \With 'TokBlocking' this is a a blocking operation: the response will \ + \always have at least one transaction identifier, and it does not expect \ + \a prompt response: there is no timeout. This covers the case when there \ + \is nothing else to do but wait. For example this covers leaf nodes that \ + \rarely, if ever, create and submit a transaction. \ + \\n\ + \With 'TokNonBlocking' this is a non-blocking operation: the response \ + \may be an empty list and this does expect a prompt response. This \ + \covers high throughput use cases where we wish to pipeline, by \ + \interleaving requests for additional transaction identifiers with \ + \requests for transactions, which requires these requests not block. \ + \\n\ + \The request gives the maximum number of transaction identifiers that \ + \can be accepted in the response. This must be greater than zero in the \ + \'TokBlocking' case. In the 'TokNonBlocking' case either the numbers \ + \acknowledged or the number requested must be non-zero. In either case, \ + \the number requested must not put the total outstanding over the fixed \ + \protocol limit. \ + \\n\ + \The request also gives the number of outstanding transaction \ + \identifiers that can now be acknowledged. The actual transactions \ + \to acknowledge are known to the peer based on the FIFO order in which \ + \they were provided. \ + \\n\ + \There is no choice about when to use the blocking case versus the \ + \non-blocking case, it depends on whether there are any remaining \ + \unacknowledged transactions (after taking into account the ones \ + \acknowledged in this message): \ + \\n\ + \* The blocking case must be used when there are zero remaining \ + \ unacknowledged transactions. \ + \\n\ + \* The non-blocking case must be used when there are non-zero remaining \ + \ unacknowledged transactions." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (MsgTalk (TXS.MsgReplyTxIds anyProto))))) + [] + "Reply with a list of transaction identifiers for available\ + \transactions, along with the size of each transaction.\ + \\n\ + \The list must not be longer than the maximum number requested.\ + \\n\ + \In the 'StTxIds' 'StBlocking' state the list must be non-empty while\ + \in the 'StTxIds' 'StNonBlocking' state the list may be empty.\ + \\n\ + \These transactions are added to the notional FIFO of outstanding\ + \transaction identifiers for the protocol.\ + \\n\ + \The order in which these transaction identifiers are returned must be\ + \the order in which they are submitted to the mempool, to preserve\ + \dependent transactions." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (MsgTalk (TXS.MsgRequestTxs [anyProto]))))) + [] + "Request one or more transactions corresponding to the given \ + \transaction identifiers. \ + \\n\ + \While it is the responsibility of the replying peer to keep within\ + \pipelining in-flight limits, the sender must also cooperate by keeping\ + \the total requested across all in-flight requests within the limits.\ + \\n\ + \It is an error to ask for transaction identifiers that were not\ + \previously announced (via 'MsgReplyTxIds').\ + \\n\ + \It is an error to ask for transaction identifiers that are not\ + \outstanding or that were already asked for." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (MsgTalk (TXS.MsgReplyTxs [anyProto]))))) + [] + "Reply with the requested transactions, or implicitly discard.\ + \\n\ + \Transactions can become invalid between the time the transaction\ + \identifier was sent and the transaction being requested. Invalid\ + \(including committed) transactions do not need to be sent.\ + \\n\ + \Any transaction identifiers requested but not provided in this reply\ + \should be considered as if this peer had never announced them. (Note\ + \that this is no guarantee that the transaction is invalid, it may still\ + \be valid and available from another peer)." + , DocMsg + (BlockFetch.TraceLabelPeer anyProto + (TraceSendMsg + (AnyMessageAndAgency anyProto + (MsgTalk TXS.MsgDone)))) + [] + "Termination message, initiated by the client when the server is\ + \making a blocking call for more transaction identifiers." + --TODO: Can't use 'MsgKThxBye' because NodeToNodeV_2 is not introduced yet. + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/NonP2P.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/NonP2P.hs new file mode 100644 index 00000000000..8e9d4e1a6ee --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/NonP2P.hs @@ -0,0 +1,561 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.NonP2P + ( + severityIPSubscription + , namesForIPSubscription + , docIPSubscription + + , severityDNSSubscription + , namesForDNSSubscription + , docDNSSubscription + + , severityDNSResolver + , namesForDNSResolver + , docDNSResolver + + , severityErrorPolicy + , namesForErrorPolicy + , docErrorPolicy + + , severityLocalErrorPolicy + , namesForLocalErrorPolicy + , docLocalErrorPolicy + + , severityAcceptPolicy + , namesForAcceptPolicy + , docAcceptPolicy + +) where + +import Cardano.Logging +import Cardano.Prelude hiding (Show, show) +import Data.Aeson (Value (String), (.=)) +import qualified Data.IP as IP +import Data.Text (pack) +import qualified Network.Socket as Socket +import Text.Show + +import qualified Ouroboros.Network.NodeToClient as NtC +import Ouroboros.Network.NodeToNode (ErrorPolicyTrace (..), WithAddr (..)) +import qualified Ouroboros.Network.NodeToNode as NtN +import Ouroboros.Network.Snocket (LocalAddress (..)) +import Ouroboros.Network.Subscription.Dns (DnsTrace (..), WithDomainName (..)) +import Ouroboros.Network.Subscription.Ip (SubscriptionTrace, WithIPList (..)) +import Ouroboros.Network.Subscription.Worker (ConnectResult (..), SubscriberError, + SubscriptionTrace (..)) + + +instance LogFormatting NtN.RemoteAddress where + forMachine _dtal (Socket.SockAddrInet port addr) = + let ip = IP.fromHostAddress addr in + mkObject [ "addr" .= show ip + , "port" .= show port + ] + forMachine _dtal (Socket.SockAddrInet6 port _ addr _) = + let ip = IP.fromHostAddress6 addr in + mkObject [ "addr" .= show ip + , "port" .= show port + ] + forMachine _dtal (Socket.SockAddrUnix path) = + mkObject [ "path" .= show path ] + + +instance LogFormatting NtN.RemoteConnectionId where + forMachine dtal (NtN.ConnectionId l r) = + mkObject [ "local" .= forMachine dtal l + , "remote" .= forMachine dtal r + ] + +instance LogFormatting LocalAddress where + forMachine _dtal (LocalAddress path) = + mkObject ["path" .= path] + +instance LogFormatting NtC.LocalConnectionId where + forMachine dtal (NtC.ConnectionId l r) = + mkObject [ "local" .= forMachine dtal l + , "remote" .= forMachine dtal r + ] + +-------------------------------------------------------------------------------- +-- IPSubscription Tracer +-------------------------------------------------------------------------------- + +severityIPSubscription :: + WithIPList (SubscriptionTrace Socket.SockAddr) + -> SeverityS +severityIPSubscription WithIPList {..} = case wilEvent of + SubscriptionTraceConnectStart _ -> Info + SubscriptionTraceConnectEnd _ connectResult -> case connectResult of + ConnectSuccess -> Info + ConnectSuccessLast -> Notice + ConnectValencyExceeded -> Warning + SubscriptionTraceConnectException _ e -> + case fromException $ SomeException e of + Just (_::SubscriberError) -> Debug + _ -> Error + SubscriptionTraceSocketAllocationException {} -> Error + SubscriptionTraceTryConnectToPeer {} -> Info + SubscriptionTraceSkippingPeer {} -> Info + SubscriptionTraceSubscriptionRunning -> Debug + SubscriptionTraceSubscriptionWaiting {} -> Debug + SubscriptionTraceSubscriptionFailed -> Error + SubscriptionTraceSubscriptionWaitingNewConnection {} -> Notice + SubscriptionTraceStart {} -> Debug + SubscriptionTraceRestart {} -> Info + SubscriptionTraceConnectionExist {} -> Notice + SubscriptionTraceUnsupportedRemoteAddr {} -> Error + SubscriptionTraceMissingLocalAddress -> Warning + SubscriptionTraceApplicationException _ e -> + case fromException $ SomeException e of + Just (_::SubscriberError) -> Debug + _ -> Error + SubscriptionTraceAllocateSocket {} -> Debug + SubscriptionTraceCloseSocket {} -> Info + +namesForSubscription :: + SubscriptionTrace Socket.SockAddr + -> [Text] +namesForSubscription SubscriptionTraceConnectStart {} = ["ConnectStart"] +namesForSubscription SubscriptionTraceConnectEnd {} = ["ConnectEnd"] +namesForSubscription SubscriptionTraceConnectException {} = ["ConnectException"] +namesForSubscription SubscriptionTraceSocketAllocationException {} = ["SocketAllocationException"] +namesForSubscription SubscriptionTraceTryConnectToPeer {} = ["TryConnectToPeer"] +namesForSubscription SubscriptionTraceSkippingPeer {} = ["SkippingPeer"] +namesForSubscription SubscriptionTraceSubscriptionRunning = ["SubscriptionRunning"] +namesForSubscription SubscriptionTraceSubscriptionWaiting {} = ["SubscriptionWaiting"] +namesForSubscription SubscriptionTraceSubscriptionFailed = ["SubscriptionFailed"] +namesForSubscription SubscriptionTraceSubscriptionWaitingNewConnection {} = ["SubscriptionWaitingNewConnection"] +namesForSubscription SubscriptionTraceStart {} = ["Start"] +namesForSubscription SubscriptionTraceRestart {} = ["Restart"] +namesForSubscription SubscriptionTraceConnectionExist {} = ["ConnectionExist"] +namesForSubscription SubscriptionTraceUnsupportedRemoteAddr {} = ["UnsupportedRemoteAddr"] +namesForSubscription SubscriptionTraceMissingLocalAddress = ["MissingLocalAddress"] +namesForSubscription SubscriptionTraceApplicationException {} = ["ApplicationException"] +namesForSubscription SubscriptionTraceAllocateSocket {} = ["AllocateSocket"] +namesForSubscription SubscriptionTraceCloseSocket {} = ["CloseSocket"] + +namesForIPSubscription :: + WithIPList (SubscriptionTrace Socket.SockAddr) + -> [Text] +namesForIPSubscription(WithIPList _ _ e) = "IP" : namesForSubscription e + +instance LogFormatting (WithIPList (SubscriptionTrace Socket.SockAddr)) where + forMachine _dtal (WithIPList localAddresses dests ev) = + mkObject [ "kind" .= String "IP SubscriptionTrace" + , "localAddresses" .= String (pack $ show localAddresses) + , "dests" .= String (pack $ show dests) + , "event" .= String (pack $ show ev)] + forHuman (WithIPList localAddresses dests ev) = + pack (show ev) + <> ". Local addresses are " + <> pack (show localAddresses) + <> ". Destinations are " + <> pack (show dests) + <> "." + +docIPSubscription :: Documented (WithIPList (SubscriptionTrace Socket.SockAddr)) +docIPSubscription = Documented $ map withIPList (undoc docSubscription) + where + withIPList (DocMsg v nl comment) = + DocMsg (WithIPList anyProto [] v) nl ("IP Subscription: " <> comment) + +-------------------------------------------------------------------------------- +-- DNSSubscription Tracer +-------------------------------------------------------------------------------- + +namesForDNSSubscription :: + NtN.WithDomainName (SubscriptionTrace Socket.SockAddr) + -> [Text] +namesForDNSSubscription(NtN.WithDomainName _ e) = "DNS" : namesForSubscription e + +severityDNSSubscription :: + NtN.WithDomainName (SubscriptionTrace Socket.SockAddr) + -> SeverityS +severityDNSSubscription NtN.WithDomainName {..} = case wdnEvent of + SubscriptionTraceConnectStart {} -> Notice + SubscriptionTraceConnectEnd {} -> Notice + SubscriptionTraceConnectException _ e -> + case fromException $ SomeException e of + Just (_::SubscriberError) -> Debug + _ -> Error + SubscriptionTraceSocketAllocationException {} -> Error + SubscriptionTraceTryConnectToPeer {} -> Info + SubscriptionTraceSkippingPeer {} -> Info + SubscriptionTraceSubscriptionRunning -> Debug + SubscriptionTraceSubscriptionWaiting {} -> Debug + SubscriptionTraceSubscriptionFailed -> Warning + SubscriptionTraceSubscriptionWaitingNewConnection {} -> Debug + SubscriptionTraceStart {} -> Debug + SubscriptionTraceRestart {} -> Debug + SubscriptionTraceConnectionExist {} -> Info + SubscriptionTraceUnsupportedRemoteAddr {} -> Warning + SubscriptionTraceMissingLocalAddress -> Warning + SubscriptionTraceApplicationException _ e -> + case fromException $ SomeException e of + Just (_::SubscriberError) -> Debug + _ -> Error + SubscriptionTraceAllocateSocket {} -> Debug + SubscriptionTraceCloseSocket {} -> Debug + + +instance LogFormatting (WithDomainName (SubscriptionTrace Socket.SockAddr)) where + forMachine _dtal (WithDomainName dom ev) = + mkObject [ "kind" .= String "DNS SubscriptionTrace" + , "domain" .= String (pack $ show dom) + , "event" .= String (pack $ show ev)] + forHuman (WithDomainName dom ev) = + pack (show ev) + <> ". Domain is " + <> pack (show dom) + <> "." + +docDNSSubscription :: Documented (WithDomainName (SubscriptionTrace Socket.SockAddr)) +docDNSSubscription = Documented $ map withDomainName (undoc docSubscription) + where + withDomainName (DocMsg v nl comment) = + DocMsg (WithDomainName anyProto v) nl ("DNS Subscription: " <> comment) + + +docSubscription :: Documented (SubscriptionTrace Socket.SockAddr) +docSubscription = Documented [ + DocMsg + (SubscriptionTraceConnectStart anyProto) + [] + "Connection Attempt Start with destination." + , DocMsg + (SubscriptionTraceConnectEnd anyProto ConnectSuccess) + [] + "Connection Attempt end with destination and outcome." + , DocMsg + (SubscriptionTraceSocketAllocationException anyProto (anyProto :: SomeException)) + [] + "Socket Allocation Exception with destination and the exception." + , DocMsg + (SubscriptionTraceConnectException anyProto (anyProto :: SomeException)) + [] + "Connection Attempt Exception with destination and exception." + , DocMsg + (SubscriptionTraceTryConnectToPeer anyProto) + [] + "Trying to connect to peer with address." + , DocMsg + (SubscriptionTraceSkippingPeer anyProto) + [] + "Skipping peer with address." + , DocMsg + SubscriptionTraceSubscriptionRunning + [] + "Required subscriptions started." + , DocMsg + (SubscriptionTraceSubscriptionWaiting 1) + [] + "Waiting on address with active connections." + , DocMsg + SubscriptionTraceSubscriptionFailed + [] + "Failed to start all required subscriptions." + , DocMsg + (SubscriptionTraceSubscriptionWaitingNewConnection anyProto) + [] + "Waiting delay time before attempting a new connection." + , DocMsg + (SubscriptionTraceStart 1) + [] + "Starting Subscription Worker with a valency." + , DocMsg + (SubscriptionTraceRestart anyProto 1 2) + [] + "Restarting Subscription after duration with desired valency and\ + \ current valency." + , DocMsg + (SubscriptionTraceConnectionExist anyProto) + [] + "Connection exists to destination." + , DocMsg + (SubscriptionTraceUnsupportedRemoteAddr anyProto) + [] + "Unsupported remote target address." + , DocMsg + SubscriptionTraceMissingLocalAddress + [] + "Missing local address." + , DocMsg + (SubscriptionTraceApplicationException anyProto (anyProto :: SomeException)) + [] + "Application Exception occured." + , DocMsg + (SubscriptionTraceAllocateSocket anyProto) + [] + "Allocate socket to address." + , DocMsg + (SubscriptionTraceCloseSocket anyProto) + [] + "Closed socket to address." + ] + +-------------------------------------------------------------------------------- +-- DNSResolver Tracer +-------------------------------------------------------------------------------- + +severityDNSResolver :: NtN.WithDomainName DnsTrace -> SeverityS +severityDNSResolver (NtN.WithDomainName _ ev) = case ev of + DnsTraceLookupException {} -> Error + DnsTraceLookupAError {} -> Error + DnsTraceLookupAAAAError {} -> Error + DnsTraceLookupIPv6First -> Debug + DnsTraceLookupIPv4First -> Debug + DnsTraceLookupAResult {} -> Debug + DnsTraceLookupAAAAResult {} -> Debug + +namesForDNSResolver :: NtN.WithDomainName DnsTrace -> [Text] +namesForDNSResolver (NtN.WithDomainName _ ev) = case ev of + DnsTraceLookupException {} -> ["LookupException"] + DnsTraceLookupAError {} -> ["LookupAError"] + DnsTraceLookupAAAAError {} -> ["LookupAAAAError"] + DnsTraceLookupIPv6First -> ["LookupIPv6First"] + DnsTraceLookupIPv4First -> ["LookupIPv4First"] + DnsTraceLookupAResult {} -> ["LookupAResult"] + DnsTraceLookupAAAAResult {} -> ["LookupAAAAResult"] + +instance LogFormatting (WithDomainName DnsTrace) where + forMachine _dtal (WithDomainName dom ev) = + mkObject [ "kind" .= String "DnsTrace" + , "domain" .= String (pack $ show dom) + , "event" .= String (pack $ show ev)] + forHuman (WithDomainName dom ev) = + pack (show ev) + <> ". Domain is " + <> pack (show dom) + <> "." + +docDNSResolver :: Documented (WithDomainName DnsTrace) +docDNSResolver = Documented [ + DocMsg + (WithDomainName anyProto + (DnsTraceLookupException anyProto)) + [] + "A DNS lookup exception occured." + , DocMsg + (WithDomainName anyProto + (DnsTraceLookupAError anyProto)) + [] + "A lookup failed with an error." + , DocMsg + (WithDomainName anyProto + (DnsTraceLookupAAAAError anyProto)) + [] + "AAAA lookup failed with an error." + , DocMsg + (WithDomainName anyProto + DnsTraceLookupIPv4First) + [] + "Returning IPv4 address first." + , DocMsg + (WithDomainName anyProto + DnsTraceLookupIPv6First) + [] + "Returning IPv6 address first." + , DocMsg + (WithDomainName anyProto + DnsTraceLookupIPv6First) + [] + "Returning IPv6 address first." + , DocMsg + (WithDomainName anyProto + (DnsTraceLookupAResult [anyProto])) + [] + "Lookup A result." + , DocMsg + (WithDomainName anyProto + (DnsTraceLookupAAAAResult [anyProto])) + [] + "Lookup AAAA result." + ] + +-------------------------------------------------------------------------------- +-- ErrorPolicy Tracer +-------------------------------------------------------------------------------- + +severityErrorPolicy :: WithAddr Socket.SockAddr ErrorPolicyTrace -> SeverityS +severityErrorPolicy (WithAddr _ ev) = case ev of + ErrorPolicySuspendPeer {} -> Warning -- peer misbehaved + ErrorPolicySuspendConsumer {} -> Notice -- peer temporarily not useful + ErrorPolicyLocalNodeError {} -> Error + ErrorPolicyResumePeer {} -> Debug + ErrorPolicyKeepSuspended {} -> Debug + ErrorPolicyResumeConsumer {} -> Debug + ErrorPolicyResumeProducer {} -> Debug + ErrorPolicyUnhandledApplicationException {} -> Error + ErrorPolicyUnhandledConnectionException {} -> Error + ErrorPolicyAcceptException {} -> Error + +namesForErrorPolicy :: WithAddr Socket.SockAddr ErrorPolicyTrace -> [Text] +namesForErrorPolicy (WithAddr _ ev) = case ev of + ErrorPolicySuspendPeer {} -> ["SuspendPeer"] + ErrorPolicySuspendConsumer {} -> ["SuspendConsumer"] + ErrorPolicyLocalNodeError {} -> ["LocalNodeError"] + ErrorPolicyResumePeer {} -> ["ResumePeer"] + ErrorPolicyKeepSuspended {} -> ["KeepSuspended"] + ErrorPolicyResumeConsumer {} -> ["ResumeConsumer"] + ErrorPolicyResumeProducer {} -> ["ResumeProducer"] + ErrorPolicyUnhandledApplicationException {} -> ["UnhandledApplicationException"] + ErrorPolicyUnhandledConnectionException {} -> ["UnhandledConnectionException"] + ErrorPolicyAcceptException {} -> ["AcceptException"] + +instance Show addr => LogFormatting (NtN.WithAddr addr NtN.ErrorPolicyTrace) where + forMachine _dtal (NtN.WithAddr addr ev) = + mkObject [ "kind" .= String "ErrorPolicyTrace" + , "address" .= show addr + , "event" .= show ev ] + forHuman (NtN.WithAddr addr ev) = "With address " <> showT addr <> ". " <> showT ev + +-- WithDomainName has strict constructors +docErrorPolicy :: Documented (WithAddr Socket.SockAddr ErrorPolicyTrace) +docErrorPolicy = docErrorPolicy' anyProto + +-------------------------------------------------------------------------------- +-- LocalErrorPolicy Tracer +-------------------------------------------------------------------------------- + +severityLocalErrorPolicy :: WithAddr NtC.LocalAddress ErrorPolicyTrace -> SeverityS +severityLocalErrorPolicy (WithAddr _ ev) = case ev of + ErrorPolicySuspendPeer {} -> Warning -- peer misbehaved + ErrorPolicySuspendConsumer {} -> Notice -- peer temporarily not useful + ErrorPolicyLocalNodeError {} -> Error + ErrorPolicyResumePeer {} -> Debug + ErrorPolicyKeepSuspended {} -> Debug + ErrorPolicyResumeConsumer {} -> Debug + ErrorPolicyResumeProducer {} -> Debug + ErrorPolicyUnhandledApplicationException {} -> Error + ErrorPolicyUnhandledConnectionException {} -> Error + ErrorPolicyAcceptException {} -> Error + +namesForLocalErrorPolicy :: WithAddr NtC.LocalAddress ErrorPolicyTrace -> [Text] +namesForLocalErrorPolicy (WithAddr _ ev) = case ev of + ErrorPolicySuspendPeer {} -> ["SuspendPeer"] + ErrorPolicySuspendConsumer {} -> ["SuspendConsumer"] + ErrorPolicyLocalNodeError {} -> ["LocalNodeError"] + ErrorPolicyResumePeer {} -> ["ResumePeer"] + ErrorPolicyKeepSuspended {} -> ["KeepSuspended"] + ErrorPolicyResumeConsumer {} -> ["ResumeConsumer"] + ErrorPolicyResumeProducer {} -> ["ResumeProducer"] + ErrorPolicyUnhandledApplicationException {} -> ["UnhandledApplicationException"] + ErrorPolicyUnhandledConnectionException {} -> ["UnhandledConnectionException"] + ErrorPolicyAcceptException {} -> ["AcceptException"] + + +docLocalErrorPolicy :: Documented (WithAddr LocalAddress ErrorPolicyTrace) +docLocalErrorPolicy = docErrorPolicy' anyProto + +-- WithAddr has strict constructors + +docErrorPolicy' :: adr -> Documented (WithAddr adr ErrorPolicyTrace) +docErrorPolicy' adr = Documented [ + DocMsg + (WithAddr adr + (ErrorPolicySuspendPeer anyProto anyProto anyProto)) + [] + "Suspending peer with a given exception." + , DocMsg + (WithAddr adr + (ErrorPolicySuspendConsumer anyProto anyProto)) + [] + "Suspending consumer." + , DocMsg + (WithAddr adr + (ErrorPolicyLocalNodeError anyProto)) + [] + "caught a local exception." + , DocMsg + (WithAddr adr + ErrorPolicyResumePeer) + [] + "Resume a peer (both consumer and producer)." + , DocMsg + (WithAddr adr + ErrorPolicyKeepSuspended) + [] + "Consumer was suspended until producer will resume." + , DocMsg + (WithAddr adr + ErrorPolicyResumeConsumer) + [] + "Resume consumer." + , DocMsg + (WithAddr adr + ErrorPolicyResumeProducer) + [] + "Resume producer." + , DocMsg + (WithAddr adr + (ErrorPolicyUnhandledApplicationException anyProto)) + [] + "An application throwed an exception, which was not handled." + , DocMsg + (WithAddr adr + (ErrorPolicyUnhandledConnectionException anyProto)) + [] + "'connect' throwed an exception, which was not handled by any\ + \ 'ErrorPolicy'." + , DocMsg + (WithAddr adr + (ErrorPolicyAcceptException anyProto)) + [] + "'accept' throwed an exception." + ] + +-------------------------------------------------------------------------------- +-- AcceptPolicy Tracer +-------------------------------------------------------------------------------- + +severityAcceptPolicy :: NtN.AcceptConnectionsPolicyTrace -> SeverityS +severityAcceptPolicy NtN.ServerTraceAcceptConnectionRateLimiting {} = Info +severityAcceptPolicy NtN.ServerTraceAcceptConnectionHardLimit {} = Warning +severityAcceptPolicy NtN.ServerTraceAcceptConnectionResume {} = Info + + +namesForAcceptPolicy :: NtN.AcceptConnectionsPolicyTrace -> [Text] +namesForAcceptPolicy NtN.ServerTraceAcceptConnectionRateLimiting {} = + ["ConectionRateLimiting"] +namesForAcceptPolicy NtN.ServerTraceAcceptConnectionHardLimit {} = + ["ConnectionHardLimit"] +namesForAcceptPolicy NtN.ServerTraceAcceptConnectionResume {} = + ["ConnectionLimitResume"] + +instance LogFormatting NtN.AcceptConnectionsPolicyTrace where + forMachine _dtal (NtN.ServerTraceAcceptConnectionRateLimiting delay numOfConnections) = + mkObject [ "kind" .= String "ServerTraceAcceptConnectionRateLimiting" + , "delay" .= show delay + , "numberOfConnection" .= show numOfConnections + ] + forMachine _dtal (NtN.ServerTraceAcceptConnectionHardLimit softLimit) = + mkObject [ "kind" .= String "ServerTraceAcceptConnectionHardLimit" + , "softLimit" .= show softLimit + ] + forMachine _dtal (NtN.ServerTraceAcceptConnectionResume numOfConnections) = + mkObject [ "kind" .= String "ServerTraceAcceptConnectionResume" + , "numberOfConnection" .= show numOfConnections + ] + forHuman = showT + +docAcceptPolicy :: Documented NtN.AcceptConnectionsPolicyTrace +docAcceptPolicy = Documented [ + DocMsg + (NtN.ServerTraceAcceptConnectionRateLimiting anyProto 2) + [] + "Rate limiting accepting connections,\ + \ delaying next accept for given time, currently serving n connections." + , DocMsg + (NtN.ServerTraceAcceptConnectionHardLimit 2) + [] + "Hard rate limit reached,\ + \ waiting until the number of connections drops below n." + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/P2P.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/P2P.hs new file mode 100644 index 00000000000..b4490bb57da --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/P2P.hs @@ -0,0 +1,1375 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE PolyKinds #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.P2P + ( + namesForLocalRootPeers + , severityLocalRootPeers + , docLocalRootPeers + + , namesForPublicRootPeers + , severityPublicRootPeers + , docPublicRootPeers + + , namesForPeerSelection + , severityPeerSelection + , docPeerSelection + + , namesForDebugPeerSelection + , severityDebugPeerSelection + , docDebugPeerSelection + + , namesForPeerSelectionCounters + , severityPeerSelectionCounters + , docPeerSelectionCounters + + , namesForPeerSelectionActions + , severityPeerSelectionActions + , docPeerSelectionActions + + , namesForConnectionManager + , severityConnectionManager + , docConnectionManager + + , namesForServer + , severityServer + , docServer + + , namesForInboundGovernor + , severityInboundGovernor + , docInboundGovernorLocal + , docInboundGovernorRemote + + ) where + +import Cardano.Logging +import Cardano.Prelude hiding (group, show) +import Data.Aeson (ToJSON, ToJSONKey, Value (..), object, toJSON, toJSONList, (.=)) +import Data.Aeson.Types (listValue) +import qualified Data.Map.Strict as Map +import qualified Data.Set as Set +import Data.Text (pack) +import Network.Socket (SockAddr (..)) +import Prelude (id, show) + +import Cardano.Node.Configuration.TopologyP2P () +import Cardano.Tracing.OrphanInstances.Network () + +import Cardano.Node.Tracing.Tracers.NodeToNode () +import Cardano.Node.Tracing.Tracers.NonP2P () + +import Network.Mux (MiniProtocolNum (..)) +import Ouroboros.Network.ConnectionHandler (ConnectionHandlerTrace (..)) +import Ouroboros.Network.ConnectionId (ConnectionId (..)) +import Ouroboros.Network.ConnectionManager.Types (AbstractState (..), + ConnectionManagerCounters (..), ConnectionManagerTrace (..), + DemotedToColdRemoteTr (..), OperationResult (..)) +import qualified Ouroboros.Network.ConnectionManager.Types as ConnectionManager +import Ouroboros.Network.InboundGovernor (InboundGovernorTrace (..)) +import qualified Ouroboros.Network.InboundGovernor as InboundGovernor +import Ouroboros.Network.InboundGovernor.State (InboundGovernorCounters (..)) +import qualified Ouroboros.Network.PeerSelection.EstablishedPeers as EstablishedPeers +import Ouroboros.Network.PeerSelection.Governor (DebugPeerSelection (..), + PeerSelectionCounters (..), PeerSelectionState (..), PeerSelectionTargets (..), + TracePeerSelection (..)) +import qualified Ouroboros.Network.PeerSelection.KnownPeers as KnownPeers +import Ouroboros.Network.PeerSelection.PeerStateActions (PeerSelectionActionsTrace (..)) +import Ouroboros.Network.PeerSelection.RelayAccessPoint (RelayAccessPoint) +import Ouroboros.Network.PeerSelection.RootPeersDNS (TraceLocalRootPeers (..), + TracePublicRootPeers (..)) +import Ouroboros.Network.PeerSelection.Types () +import Ouroboros.Network.RethrowPolicy (ErrorCommand (..)) +import Ouroboros.Network.Server2 (ServerTrace (..)) +import Ouroboros.Network.Snocket (LocalAddress (..)) + +-------------------------------------------------------------------------------- +-- LocalRootPeers Tracer +-------------------------------------------------------------------------------- + +namesForLocalRootPeers :: TraceLocalRootPeers ntnAddr resolverError -> [Text] +namesForLocalRootPeers TraceLocalRootDomains {} = ["LocalRootDomains"] +namesForLocalRootPeers TraceLocalRootWaiting {} = ["LocalRootWaiting"] +namesForLocalRootPeers TraceLocalRootResult {} = ["LocalRootResult"] +namesForLocalRootPeers TraceLocalRootGroups {} = ["LocalRootGroups"] +namesForLocalRootPeers TraceLocalRootFailure {} = ["LocalRootFailure"] +namesForLocalRootPeers TraceLocalRootError {} = ["LocalRootError"] + +severityLocalRootPeers :: TraceLocalRootPeers ntnAddr resolverError -> SeverityS +severityLocalRootPeers _ = Info + +instance (ToJSONKey ntnAddr, ToJSONKey RelayAccessPoint, Show ntnAddr, Show exception) => + LogFormatting (TraceLocalRootPeers ntnAddr exception) where + forMachine _dtal (TraceLocalRootDomains groups) = + mkObject [ "kind" .= String "LocalRootDomains" + , "localRootDomains" .= toJSON groups + ] + forMachine _dtal (TraceLocalRootWaiting d dt) = + mkObject [ "kind" .= String "LocalRootWaiting" + , "domainAddress" .= toJSON d + , "diffTime" .= show dt + ] + forMachine _dtal (TraceLocalRootResult d res) = + mkObject [ "kind" .= String "LocalRootResult" + , "domainAddress" .= toJSON d + , "result" .= toJSONList res + ] + forMachine _dtal (TraceLocalRootGroups groups) = + mkObject [ "kind" .= String "LocalRootGroups" + , "localRootGroups" .= toJSON groups + ] + forMachine _dtal (TraceLocalRootFailure d exception) = + mkObject [ "kind" .= String "LocalRootFailure" + , "domainAddress" .= toJSON d + , "reason" .= show exception + ] + forMachine _dtal (TraceLocalRootError d exception) = + mkObject [ "kind" .= String "LocalRootError" + , "domainAddress" .= toJSON d + , "reason" .= show exception + ] + forHuman = pack . show + +docLocalRootPeers :: Documented (TraceLocalRootPeers ntnAddr resolverError) +docLocalRootPeers = Documented [ + DocMsg + (TraceLocalRootDomains anyProto) + [] + "" + , DocMsg + (TraceLocalRootWaiting anyProto anyProto) + [] + "" + , DocMsg + (TraceLocalRootResult anyProto anyProto) + [] + "" + , DocMsg + (TraceLocalRootGroups anyProto) + [] + "" + , DocMsg + (TraceLocalRootFailure anyProto anyProto) + [] + "" + , DocMsg + (TraceLocalRootError anyProto anyProto) + [] + "" + ] + +-------------------------------------------------------------------------------- +-- PublicRootPeers Tracer +-------------------------------------------------------------------------------- + +namesForPublicRootPeers :: TracePublicRootPeers -> [Text] +namesForPublicRootPeers TracePublicRootRelayAccessPoint {} = ["PublicRootRelayAccessPoint"] +namesForPublicRootPeers TracePublicRootDomains {} = ["PublicRootDomains"] +namesForPublicRootPeers TracePublicRootResult {} = ["PublicRootResult"] +namesForPublicRootPeers TracePublicRootFailure {} = ["PublicRootFailure"] + +severityPublicRootPeers :: TracePublicRootPeers -> SeverityS +severityPublicRootPeers _ = Info + +instance LogFormatting TracePublicRootPeers where + forMachine _dtal (TracePublicRootRelayAccessPoint relays) = + mkObject [ "kind" .= String "PublicRootRelayAddresses" + , "relayAddresses" .= toJSONList relays + ] + forMachine _dtal (TracePublicRootDomains domains) = + mkObject [ "kind" .= String "PublicRootDomains" + , "domainAddresses" .= toJSONList domains + ] + forMachine _dtal (TracePublicRootResult b res) = + mkObject [ "kind" .= String "PublicRootResult" + , "domain" .= show b + , "result" .= toJSONList res + ] + forMachine _dtal (TracePublicRootFailure b d) = + mkObject [ "kind" .= String "PublicRootFailure" + , "domain" .= show b + , "reason" .= show d + ] + forHuman = pack . show + +docPublicRootPeers :: Documented TracePublicRootPeers +docPublicRootPeers = Documented [ + DocMsg + (TracePublicRootRelayAccessPoint anyProto) + [] + "" + , DocMsg + (TracePublicRootDomains anyProto) + [] + "" + , DocMsg + (TracePublicRootResult anyProto anyProto) + [] + "" + , DocMsg + (TracePublicRootFailure anyProto anyProto) + [] + "" + ] + +-------------------------------------------------------------------------------- +-- PeerSelection Tracer +-------------------------------------------------------------------------------- + +namesForPeerSelection :: TracePeerSelection peeraddr -> [Text] +namesForPeerSelection TraceLocalRootPeersChanged {} = ["LocalRootPeersChanged"] +namesForPeerSelection TraceTargetsChanged {} = ["TargetsChanged"] +namesForPeerSelection TracePublicRootsRequest {} = ["ublicRootsRequest"] +namesForPeerSelection TracePublicRootsResults {} = ["PublicRootsResults"] +namesForPeerSelection TracePublicRootsFailure {} = ["PublicRootsFailure"] +namesForPeerSelection TraceGossipRequests {} = ["GossipRequests"] +namesForPeerSelection TraceGossipResults {} = ["GossipResults"] +namesForPeerSelection TraceForgetColdPeers {} = ["ForgetColdPeers"] +namesForPeerSelection TracePromoteColdPeers {} = ["PromoteColdPeers"] +namesForPeerSelection TracePromoteColdLocalPeers {} = ["PromoteColdLocalPeers"] +namesForPeerSelection TracePromoteColdFailed {} = ["PromoteColdFailed"] +namesForPeerSelection TracePromoteColdDone {} = ["PromoteColdDone"] +namesForPeerSelection TracePromoteWarmPeers {} = ["PromoteWarmPeers"] +namesForPeerSelection TracePromoteWarmLocalPeers {} = ["PromoteWarmLocalPeers"] +namesForPeerSelection TracePromoteWarmFailed {} = ["PromoteWarmFailed"] +namesForPeerSelection TracePromoteWarmDone {} = ["PromoteWarmDone"] +namesForPeerSelection TraceDemoteWarmPeers {} = ["DemoteWarmPeers"] +namesForPeerSelection TraceDemoteWarmFailed {} = ["DemoteWarmFailed"] +namesForPeerSelection TraceDemoteWarmDone {} = ["DemoteWarmDone"] +namesForPeerSelection TraceDemoteHotPeers {} = ["DemoteHotPeers"] +namesForPeerSelection TraceDemoteLocalHotPeers {} = ["DemoteLocalHotPeers"] +namesForPeerSelection TraceDemoteHotFailed {} = ["DemoteHotFailed"] +namesForPeerSelection TraceDemoteHotDone {} = ["DemoteHotDone"] +namesForPeerSelection TraceDemoteAsynchronous {} = ["DemoteAsynchronous"] +namesForPeerSelection TraceGovernorWakeup {} = ["GovernorWakeup"] +namesForPeerSelection TraceChurnWait {} = ["ChurnWait"] +namesForPeerSelection TraceChurnMode {} = ["ChurnMode"] + + +severityPeerSelection :: TracePeerSelection peeraddr -> SeverityS +severityPeerSelection TraceLocalRootPeersChanged {} = Notice +severityPeerSelection TraceTargetsChanged {} = Notice +severityPeerSelection TracePublicRootsRequest {} = Info +severityPeerSelection TracePublicRootsResults {} = Info +severityPeerSelection TracePublicRootsFailure {} = Error +severityPeerSelection TraceGossipRequests {} = Debug +severityPeerSelection TraceGossipResults {} = Debug +severityPeerSelection TraceForgetColdPeers {} = Info +severityPeerSelection TracePromoteColdPeers {} = Info +severityPeerSelection TracePromoteColdLocalPeers {} = Info +severityPeerSelection TracePromoteColdFailed {} = Info +severityPeerSelection TracePromoteColdDone {} = Info +severityPeerSelection TracePromoteWarmPeers {} = Info +severityPeerSelection TracePromoteWarmLocalPeers {} = Info +severityPeerSelection TracePromoteWarmFailed {} = Info +severityPeerSelection TracePromoteWarmDone {} = Info +severityPeerSelection TraceDemoteWarmPeers {} = Info +severityPeerSelection TraceDemoteWarmFailed {} = Info +severityPeerSelection TraceDemoteWarmDone {} = Info +severityPeerSelection TraceDemoteHotPeers {} = Info +severityPeerSelection TraceDemoteLocalHotPeers {} = Info +severityPeerSelection TraceDemoteHotFailed {} = Info +severityPeerSelection TraceDemoteHotDone {} = Info +severityPeerSelection TraceDemoteAsynchronous {} = Info +severityPeerSelection TraceGovernorWakeup {} = Info +severityPeerSelection TraceChurnWait {} = Info +severityPeerSelection TraceChurnMode {} = Info + +instance LogFormatting (TracePeerSelection SockAddr) where + forMachine _dtal (TraceLocalRootPeersChanged lrp lrp') = + mkObject [ "kind" .= String "LocalRootPeersChanged" + , "previous" .= toJSON lrp + , "current" .= toJSON lrp' + ] + forMachine _dtal (TraceTargetsChanged pst pst') = + mkObject [ "kind" .= String "TargetsChanged" + , "previous" .= toJSON pst + , "current" .= toJSON pst' + ] + forMachine _dtal (TracePublicRootsRequest tRootPeers nRootPeers) = + mkObject [ "kind" .= String "PublicRootsRequest" + , "targetNumberOfRootPeers" .= tRootPeers + , "numberOfRootPeers" .= nRootPeers + ] + forMachine _dtal (TracePublicRootsResults res group dt) = + mkObject [ "kind" .= String "PublicRootsResults" + , "result" .= toJSONList (toList res) + , "group" .= group + , "diffTime" .= dt + ] + forMachine _dtal (TracePublicRootsFailure err group dt) = + mkObject [ "kind" .= String "PublicRootsFailure" + , "reason" .= show err + , "group" .= group + , "diffTime" .= dt + ] + forMachine _dtal (TraceGossipRequests targetKnown actualKnown aps sps) = + mkObject [ "kind" .= String "GossipRequests" + , "targetKnown" .= targetKnown + , "actualKnown" .= actualKnown + , "availablePeers" .= toJSONList (toList aps) + , "selectedPeers" .= toJSONList (toList sps) + ] + forMachine _dtal (TraceGossipResults res) = + mkObject [ "kind" .= String "GossipResults" + , "result" .= toJSONList (map ( bimap show id <$> ) res) + ] + forMachine _dtal (TraceForgetColdPeers targetKnown actualKnown sp) = + mkObject [ "kind" .= String "ForgeColdPeers" + , "targetKnown" .= targetKnown + , "actualKnown" .= actualKnown + , "selectedPeers" .= toJSONList (toList sp) + ] + forMachine _dtal (TracePromoteColdPeers targetKnown actualKnown sp) = + mkObject [ "kind" .= String "PromoteColdPeers" + , "targetEstablished" .= targetKnown + , "actualEstablished" .= actualKnown + , "selectedPeers" .= toJSONList (toList sp) + ] + forMachine _dtal (TracePromoteColdLocalPeers tLocalEst aLocalEst sp) = + mkObject [ "kind" .= String "PromoteColdLocalPeers" + , "targetLocalEstablished" .= tLocalEst + , "actualLocalEstablished" .= aLocalEst + , "selectedPeers" .= toJSONList (toList sp) + ] + forMachine _dtal (TracePromoteColdFailed tEst aEst p d err) = + mkObject [ "kind" .= String "PromoteColdFailed" + , "targetEstablished" .= tEst + , "actualEstablished" .= aEst + , "peer" .= toJSON p + , "delay" .= toJSON d + , "reason" .= show err + ] + forMachine _dtal (TracePromoteColdDone tEst aEst p) = + mkObject [ "kind" .= String "PromoteColdDone" + , "targetEstablished" .= tEst + , "actualEstablished" .= aEst + , "peer" .= toJSON p + ] + forMachine _dtal (TracePromoteWarmPeers tActive aActive sp) = + mkObject [ "kind" .= String "PromoteWarmPeers" + , "targetActive" .= tActive + , "actualActive" .= aActive + , "selectedPeers" .= toJSONList (toList sp) + ] + forMachine _dtal (TracePromoteWarmLocalPeers taa sp) = + mkObject [ "kind" .= String "PromoteWarmLocalPeers" + , "targetActualActive" .= toJSONList taa + , "selectedPeers" .= toJSONList (toList sp) + ] + forMachine _dtal (TracePromoteWarmFailed tActive aActive p err) = + mkObject [ "kind" .= String "PromoteWarmFailed" + , "targetActive" .= tActive + , "actualActive" .= aActive + , "peer" .= toJSON p + , "reason" .= show err + ] + forMachine _dtal (TracePromoteWarmDone tActive aActive p) = + mkObject [ "kind" .= String "PromoteWarmDone" + , "targetActive" .= tActive + , "actualActive" .= aActive + , "peer" .= toJSON p + ] + forMachine _dtal (TraceDemoteWarmPeers tEst aEst sp) = + mkObject [ "kind" .= String "DemoteWarmPeers" + , "targetEstablished" .= tEst + , "actualEstablished" .= aEst + , "selectedPeers" .= toJSONList (toList sp) + ] + forMachine _dtal (TraceDemoteWarmFailed tEst aEst p err) = + mkObject [ "kind" .= String "DemoteWarmFailed" + , "targetEstablished" .= tEst + , "actualEstablished" .= aEst + , "peer" .= toJSON p + , "reason" .= show err + ] + forMachine _dtal (TraceDemoteWarmDone tEst aEst p) = + mkObject [ "kind" .= String "DemoteWarmDone" + , "targetEstablished" .= tEst + , "actualEstablished" .= aEst + , "peer" .= toJSON p + ] + forMachine _dtal (TraceDemoteHotPeers tActive aActive sp) = + mkObject [ "kind" .= String "DemoteHotPeers" + , "targetActive" .= tActive + , "actualActive" .= aActive + , "selectedPeers" .= toJSONList (toList sp) + ] + forMachine _dtal (TraceDemoteLocalHotPeers taa sp) = + mkObject [ "kind" .= String "DemoteLocalHotPeers" + , "targetActualActive" .= toJSONList taa + , "selectedPeers" .= toJSONList (toList sp) + ] + forMachine _dtal (TraceDemoteHotFailed tActive aActive p err) = + mkObject [ "kind" .= String "DemoteHotFailed" + , "targetActive" .= tActive + , "actualActive" .= aActive + , "peer" .= toJSON p + , "reason" .= show err + ] + forMachine _dtal (TraceDemoteHotDone tActive aActive p) = + mkObject [ "kind" .= String "DemoteHotDone" + , "targetActive" .= tActive + , "actualActive" .= aActive + , "peer" .= toJSON p + ] + forMachine _dtal (TraceDemoteAsynchronous msp) = + mkObject [ "kind" .= String "DemoteAsynchronous" + , "state" .= toJSON msp + ] + forMachine _dtal TraceGovernorWakeup = + mkObject [ "kind" .= String "GovernorWakeup" + ] + forMachine _dtal (TraceChurnWait dt) = + mkObject [ "kind" .= String "ChurnWait" + , "diffTime" .= toJSON dt + ] + forMachine _dtal (TraceChurnMode c) = + mkObject [ "kind" .= String "ChurnMode" + , "event" .= show c ] + forHuman = pack . show + +docPeerSelection :: Documented (TracePeerSelection SockAddr) +docPeerSelection = Documented [ + DocMsg + (TraceLocalRootPeersChanged anyProto anyProto) + [] + "" + , DocMsg + (TraceTargetsChanged anyProto anyProto) + [] + "" + , DocMsg + (TracePublicRootsRequest 1 1) + [] + "" + , DocMsg + (TracePublicRootsResults anyProto 1 anyProto) + [] + "" + , DocMsg + (TracePublicRootsResults anyProto 1 anyProto) + [] + "" + , DocMsg + (TraceGossipRequests 1 1 anyProto anyProto) + [] + "target known peers, actual known peers, peers available for gossip,\ + \ peers selected for gossip" + , DocMsg + (TraceGossipResults []) + [] + "" + , DocMsg + (TraceForgetColdPeers 1 1 anyProto) + [] + "target known peers, actual known peers, selected peers" + , DocMsg + (TracePromoteColdPeers 1 1 anyProto) + [] + "target established, actual established, selected peers" + , DocMsg + (TracePromoteColdLocalPeers 1 1 anyProto) + [] + "target local established, actual local established, selected peers" + , DocMsg + (TracePromoteColdFailed 1 1 anyProto anyProto anyProto) + [] + "target established, actual established, peer, delay until next\ + \ promotion, reason" + , DocMsg + (TracePromoteColdDone 1 1 anyProto) + [] + "target active, actual active, selected peers" + , DocMsg + (TracePromoteWarmPeers 1 1 anyProto) + [] + "target active, actual active, selected peers" + , DocMsg + (TracePromoteWarmLocalPeers [] anyProto) + [] + "local per-group (target active, actual active), selected peers" + , DocMsg + (TracePromoteWarmFailed 1 1 anyProto anyProto) + [] + "target active, actual active, peer, reason" + , DocMsg + (TracePromoteWarmDone 1 1 anyProto) + [] + "target active, actual active, peer" + , DocMsg + (TraceDemoteWarmPeers 1 1 anyProto) + [] + "target established, actual established, selected peers" + , DocMsg + (TraceDemoteWarmFailed 1 1 anyProto anyProto) + [] + "target established, actual established, peer, reason" + , DocMsg + (TraceDemoteWarmDone 1 1 anyProto) + [] + "target established, actual established, peer" + , DocMsg + (TraceDemoteHotPeers 1 1 anyProto) + [] + "target active, actual active, selected peers" + , DocMsg + (TraceDemoteLocalHotPeers [] anyProto) + [] + "local per-group (target active, actual active), selected peers" + , DocMsg + (TraceDemoteHotFailed 1 1 anyProto anyProto) + [] + "target active, actual active, peer, reason" + , DocMsg + (TraceDemoteHotFailed 1 1 anyProto anyProto) + [] + "target active, actual active, peer, reason" + , DocMsg + (TraceDemoteHotDone 1 1 anyProto ) + [] + "target active, actual active, peer" + , DocMsg + (TraceDemoteAsynchronous anyProto ) + [] + "" + , DocMsg + TraceGovernorWakeup + [] + "" + , DocMsg + (TraceChurnWait anyProto) + [] + "" + , DocMsg + (TraceChurnMode anyProto) + [] + "" + ] + +peerSelectionTargetsToObject :: PeerSelectionTargets -> Value +peerSelectionTargetsToObject + PeerSelectionTargets { targetNumberOfRootPeers, + targetNumberOfKnownPeers, + targetNumberOfEstablishedPeers, + targetNumberOfActivePeers } = + Object $ + mkObject [ "roots" .= targetNumberOfRootPeers + , "knownPeers" .= targetNumberOfKnownPeers + , "established" .= targetNumberOfEstablishedPeers + , "active" .= targetNumberOfActivePeers + ] + +-------------------------------------------------------------------------------- +-- DebugPeerSelection Tracer +-------------------------------------------------------------------------------- + +namesForDebugPeerSelection :: DebugPeerSelection SockAddr peerConn -> [Text] +namesForDebugPeerSelection _ = ["GovernorState"] + +severityDebugPeerSelection :: DebugPeerSelection SockAddr peerConn -> SeverityS +severityDebugPeerSelection _ = Debug + +instance Show peerConn => LogFormatting (DebugPeerSelection SockAddr peerConn) where + forMachine DNormal (TraceGovernorState blockedAt wakeupAfter + PeerSelectionState { targets, knownPeers, establishedPeers, activePeers }) = + mkObject [ "kind" .= String "DebugPeerSelection" + , "blockedAt" .= String (pack $ show blockedAt) + , "wakeupAfter" .= String (pack $ show wakeupAfter) + , "targets" .= peerSelectionTargetsToObject targets + , "numberOfPeers" .= + Object (mkObject [ "known" .= KnownPeers.size knownPeers + , "established" .= EstablishedPeers.size establishedPeers + , "active" .= Set.size activePeers + ]) + ] + forMachine _ (TraceGovernorState blockedAt wakeupAfter ev) = + mkObject [ "kind" .= String "DebugPeerSelection" + , "blockedAt" .= String (pack $ show blockedAt) + , "wakeupAfter" .= String (pack $ show wakeupAfter) + , "peerSelectionState" .= String (pack $ show ev) + ] + forHuman = pack . show + +docDebugPeerSelection :: Documented (DebugPeerSelection SockAddr peerConn) +docDebugPeerSelection = Documented + [ DocMsg + (TraceGovernorState anyProto anyProto anyProto) + [] + "" + ] + +namesForPeerSelectionCounters :: PeerSelectionCounters -> [Text] +namesForPeerSelectionCounters _ = [] + +severityPeerSelectionCounters :: PeerSelectionCounters -> SeverityS +severityPeerSelectionCounters _ = Info + +instance LogFormatting PeerSelectionCounters where + forMachine _dtal ev = + mkObject [ "kind" .= String "PeerSelectionCounters" + , "coldPeers" .= coldPeers ev + , "warmPeers" .= warmPeers ev + , "hotPeers" .= hotPeers ev + ] + forHuman = pack . show + asMetrics PeerSelectionCounters {..} = + [ IntM + "cardano.node.peerSelection.cold" + (fromIntegral coldPeers) + , IntM + "cardano.node.peerSelection.warm" + (fromIntegral warmPeers) + , IntM + "cardano.node.peerSelection.hot" + (fromIntegral hotPeers) + ] + +docPeerSelectionCounters :: Documented PeerSelectionCounters +docPeerSelectionCounters = Documented + [ DocMsg + (PeerSelectionCounters 1 1 1) + [ ("cardano.node.peerSelection.cold", "Number of cold peers") + , ("cardano.node.peerSelection.warm", "Number of warm peers") + , ("cardano.node.peerSelection.hot", "Number of hot peers") ] + "Counters for cold, warm and hot peers" + ] + +-------------------------------------------------------------------------------- +-- PeerSelectionActions Tracer +-------------------------------------------------------------------------------- + +namesForPeerSelectionActions :: PeerSelectionActionsTrace ntnAddr -> [Text] +namesForPeerSelectionActions PeerStatusChanged {} = ["StatusChanged"] +namesForPeerSelectionActions PeerStatusChangeFailure {} = ["StatusChangeFailure"] +namesForPeerSelectionActions PeerMonitoringError {} = ["MonitoringError"] +namesForPeerSelectionActions PeerMonitoringResult {} = ["MonitoringResult"] + +severityPeerSelectionActions :: PeerSelectionActionsTrace ntnAddr -> SeverityS +severityPeerSelectionActions PeerStatusChanged {} = Info +severityPeerSelectionActions PeerStatusChangeFailure {} = Error +severityPeerSelectionActions PeerMonitoringError {} = Error +severityPeerSelectionActions PeerMonitoringResult {} = Debug + +-- TODO: Write PeerStatusChangeType ToJSON at ouroboros-network +-- For that an export is needed at ouroboros-network +instance LogFormatting (PeerSelectionActionsTrace SockAddr) where + forMachine _dtal (PeerStatusChanged ps) = + mkObject [ "kind" .= String "PeerStatusChanged" + , "peerStatusChangeType" .= show ps + ] + forMachine _dtal (PeerStatusChangeFailure ps f) = + mkObject [ "kind" .= String "PeerStatusChangeFailure" + , "peerStatusChangeType" .= show ps + , "reason" .= show f + ] + forMachine _dtal (PeerMonitoringError connId s) = + mkObject [ "kind" .= String "PeerMonitoridngError" + , "connectionId" .= toJSON connId + , "reason" .= show s + ] + forMachine _dtal (PeerMonitoringResult connId wf) = + mkObject [ "kind" .= String "PeerMonitoringResult" + , "connectionId" .= toJSON connId + , "withProtocolTemp" .= show wf + ] + forHuman = pack . show + +docPeerSelectionActions :: Documented (PeerSelectionActionsTrace ntnAddr) +docPeerSelectionActions = Documented + [ DocMsg + (PeerStatusChanged anyProto) + [] + "" + , DocMsg + (PeerStatusChangeFailure anyProto anyProto) + [] + "" + , DocMsg + (PeerMonitoringError anyProto anyProto) + [] + "" + , DocMsg + (PeerMonitoringResult anyProto anyProto) + [] + "" + ] + +-------------------------------------------------------------------------------- +-- Connection Manager Tracer +-------------------------------------------------------------------------------- + +namesForConnectionManager :: ConnectionManagerTrace ntnAddr cht -> [Text] +namesForConnectionManager TrIncludeConnection {} = ["IncludeConnection"] +namesForConnectionManager TrUnregisterConnection {} = ["UnregisterConnection"] +namesForConnectionManager TrConnect {} = ["Connect"] +namesForConnectionManager TrConnectError {} = ["ConnectError"] +namesForConnectionManager TrTerminatingConnection {} = ["TerminatingConnection"] +namesForConnectionManager TrTerminatedConnection {} = ["TerminatedConnection"] +namesForConnectionManager TrConnectionHandler {} = ["ConnectionHandler"] +namesForConnectionManager TrShutdown {} = ["Shutdown"] +namesForConnectionManager TrConnectionExists {} = ["ConnectionExists"] +namesForConnectionManager TrForbiddenConnection {} = ["ForbiddenConnection"] +namesForConnectionManager TrImpossibleConnection {} = ["ImpossibleConnection"] +namesForConnectionManager TrConnectionFailure {} = ["ConnectionFailure"] +namesForConnectionManager TrConnectionNotFound {} = ["ConnectionNotFound"] +namesForConnectionManager TrForbiddenOperation {} = ["ForbiddenOperation"] +namesForConnectionManager TrPruneConnections {} = ["PruneConnections"] +namesForConnectionManager TrConnectionCleanup {} = ["ConnectionCleanup"] +namesForConnectionManager TrConnectionTimeWait {} = ["ConnectionTimeWait"] +namesForConnectionManager TrConnectionTimeWaitDone {} = ["ConnectionTimeWaitDone"] +namesForConnectionManager TrConnectionManagerCounters {} = ["ConnectionManagerCounters"] +namesForConnectionManager TrState {} = ["State"] +namesForConnectionManager ConnectionManager.TrUnexpectedlyFalseAssertion {} = + ["UnexpectedlyFalseAssertion"] + +severityConnectionManager :: + ConnectionManagerTrace addr + (ConnectionHandlerTrace versionNumber agreedOptions) -> SeverityS +severityConnectionManager TrIncludeConnection {} = Debug +severityConnectionManager TrUnregisterConnection {} = Debug +severityConnectionManager TrConnect {} = Debug +severityConnectionManager TrConnectError {} = Info +severityConnectionManager TrTerminatingConnection {} = Debug +severityConnectionManager TrTerminatedConnection {} = Debug +severityConnectionManager (TrConnectionHandler _ ev') = + case ev' of + TrHandshakeSuccess {} -> Info + TrHandshakeClientError {} -> Notice + TrHandshakeServerError {} -> Info + TrError _ _ ShutdownNode -> Critical + TrError _ _ ShutdownPeer -> Info + +severityConnectionManager TrShutdown = Info +severityConnectionManager TrConnectionExists {} = Info +severityConnectionManager TrForbiddenConnection {} = Info +severityConnectionManager TrImpossibleConnection {} = Info +severityConnectionManager TrConnectionFailure {} = Info +severityConnectionManager TrConnectionNotFound {} = Debug +severityConnectionManager TrForbiddenOperation {} = Info + +severityConnectionManager TrPruneConnections {} = Notice +severityConnectionManager TrConnectionCleanup {} = Debug +severityConnectionManager TrConnectionTimeWait {} = Debug +severityConnectionManager TrConnectionTimeWaitDone {} = Debug +severityConnectionManager TrConnectionManagerCounters {} = Info +severityConnectionManager TrState {} = Info +severityConnectionManager ConnectionManager.TrUnexpectedlyFalseAssertion {} = + Error + +instance (Show addr, Show versionNumber, Show agreedOptions, LogFormatting addr, + ToJSON addr, ToJSON versionNumber, ToJSON agreedOptions) + => LogFormatting (ConnectionManagerTrace addr (ConnectionHandlerTrace versionNumber agreedOptions)) where + forMachine dtal (TrIncludeConnection prov peerAddr) = + mkObject $ reverse + [ "kind" .= String "IncludeConnection" + , "remoteAddress" .= forMachine dtal peerAddr + , "provenance" .= String (pack . show $ prov) + ] + forMachine dtal (TrUnregisterConnection prov peerAddr) = + mkObject $ reverse + [ "kind" .= String "UnregisterConnection" + , "remoteAddress" .= forMachine dtal peerAddr + , "provenance" .= String (pack . show $ prov) + ] + forMachine _dtal (TrConnect (Just localAddress) remoteAddress) = + mkObject + [ "kind" .= String "ConnectTo" + , "connectionId" .= toJSON ConnectionId { localAddress, remoteAddress } + ] + forMachine dtal (TrConnect Nothing remoteAddress) = + mkObject + [ "kind" .= String "ConnectTo" + , "remoteAddress" .= forMachine dtal remoteAddress + ] + forMachine _dtal (TrConnectError (Just localAddress) remoteAddress err) = + mkObject + [ "kind" .= String "ConnectError" + , "connectionId" .= toJSON ConnectionId { localAddress, remoteAddress } + , "reason" .= String (pack . show $ err) + ] + forMachine dtal (TrConnectError Nothing remoteAddress err) = + mkObject + [ "kind" .= String "ConnectError" + , "remoteAddress" .= forMachine dtal remoteAddress + , "reason" .= String (pack . show $ err) + ] + forMachine _dtal (TrTerminatingConnection prov connId) = + mkObject + [ "kind" .= String "TerminatingConnection" + , "provenance" .= String (pack . show $ prov) + , "connectionId" .= toJSON connId + ] + forMachine dtal (TrTerminatedConnection prov remoteAddress) = + mkObject + [ "kind" .= String "TerminatedConnection" + , "provenance" .= String (pack . show $ prov) + , "remoteAddress" .= forMachine dtal remoteAddress + ] + forMachine dtal (TrConnectionHandler connId a) = + mkObject + [ "kind" .= String "ConnectionHandler" + , "connectionId" .= toJSON connId + , "connectionHandler" .= forMachine dtal a + ] + forMachine _dtal TrShutdown = + mkObject + [ "kind" .= String "Shutdown" + ] + forMachine dtal (TrConnectionExists prov remoteAddress inState) = + mkObject + [ "kind" .= String "ConnectionExists" + , "provenance" .= String (pack . show $ prov) + , "remoteAddress" .= forMachine dtal remoteAddress + , "state" .= toJSON inState + ] + forMachine _dtal (TrForbiddenConnection connId) = + mkObject + [ "kind" .= String "ForbiddenConnection" + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrImpossibleConnection connId) = + mkObject + [ "kind" .= String "ImpossibleConnection" + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrConnectionFailure connId) = + mkObject + [ "kind" .= String "ConnectionFailure" + , "connectionId" .= toJSON connId + ] + forMachine dtal (TrConnectionNotFound prov remoteAddress) = + mkObject + [ "kind" .= String "ConnectionNotFound" + , "remoteAddress" .= forMachine dtal remoteAddress + , "provenance" .= String (pack . show $ prov) + ] + forMachine dtal (TrForbiddenOperation remoteAddress connState) = + mkObject + [ "kind" .= String "ForbiddenOperation" + , "remoteAddress" .= forMachine dtal remoteAddress + , "connectionState" .= toJSON connState + ] + forMachine dtal (TrPruneConnections pruningSet numberPruned chosenPeers) = + mkObject + [ "kind" .= String "PruneConnections" + , "prunedPeers" .= toJSON pruningSet + , "numberPrunedPeers" .= toJSON numberPruned + , "choiceSet" .= toJSON (forMachine dtal `Set.map` chosenPeers) + ] + forMachine _dtal (TrConnectionCleanup connId) = + mkObject + [ "kind" .= String "ConnectionCleanup" + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrConnectionTimeWait connId) = + mkObject + [ "kind" .= String "ConnectionTimeWait" + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrConnectionTimeWaitDone connId) = + mkObject + [ "kind" .= String "ConnectionTimeWaitDone" + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrConnectionManagerCounters cmCounters) = + mkObject + [ "kind" .= String "ConnectionManagerCounters" + , "state" .= toJSON cmCounters + ] + forMachine _dtal (TrState cmState) = + mkObject + [ "kind" .= String "ConnectionManagerState" + , "state" .= listValue (\(addr, connState) -> + object + [ "remoteAddress" .= toJSON addr + , "connectionState" .= toJSON connState + ]) + (Map.toList cmState) + ] + forMachine _dtal (ConnectionManager.TrUnexpectedlyFalseAssertion info) = + mkObject + [ "kind" .= String "UnexpectedlyFalseAssertion" + , "info" .= String (pack . show $ info) + ] + forHuman = pack . show + asMetrics (TrConnectionManagerCounters ConnectionManagerCounters {..}) = + [ IntM + "cardano.node.connectionManager.fullDuplexConns" + (fromIntegral fullDuplexConns) + , IntM + "cardano.node.connectionManager.duplexConns" + (fromIntegral duplexConns) + , IntM + "cardano.node.connectionManager.unidirectionalConns" + (fromIntegral unidirectionalConns) + , IntM + "cardano.node.connectionManager.inboundConns" + (fromIntegral inboundConns) + , IntM + "cardano.node.connectionManager.outboundConns" + (fromIntegral outboundConns) + ] + asMetrics _ = [] + +instance (Show versionNumber, ToJSON versionNumber, ToJSON agreedOptions) + => LogFormatting (ConnectionHandlerTrace versionNumber agreedOptions) where + forMachine _dtal (TrHandshakeSuccess versionNumber agreedOptions) = + mkObject + [ "kind" .= String "HandshakeSuccess" + , "versionNumber" .= toJSON versionNumber + , "agreedOptions" .= toJSON agreedOptions + ] + forMachine _dtal (TrHandshakeClientError err) = + mkObject + [ "kind" .= String "HandshakeClientError" + , "reason" .= toJSON err + ] + forMachine _dtal (TrHandshakeServerError err) = + mkObject + [ "kind" .= String "HandshakeServerError" + , "reason" .= toJSON err + ] + forMachine _dtal (TrError e err cerr) = + mkObject + [ "kind" .= String "Error" + , "context" .= show e + , "reason" .= show err + , "command" .= show cerr + ] + +protoConnectionHandlerTrace :: ConnectionHandlerTrace + ntnVersion + ntnVersionData +protoConnectionHandlerTrace = TrHandshakeSuccess anyProto anyProto + +docConnectionManager :: Documented + (ConnectionManagerTrace + ntnAddr + (ConnectionHandlerTrace + ntnVersion + ntnVersionData)) +docConnectionManager = Documented + [ DocMsg + (TrIncludeConnection anyProto anyProto) + [] + "" + , DocMsg + (TrUnregisterConnection anyProto anyProto) + [] + "" + , DocMsg + (TrConnect Nothing anyProto) + [] + "" + , DocMsg + (TrConnectError Nothing anyProto protoSomeException) + [] + "" + , DocMsg + (TrTerminatingConnection anyProto anyProto) + [] + "" + , DocMsg + (TrTerminatedConnection anyProto anyProto) + [] + "" + , DocMsg + (TrConnectionHandler anyProto protoConnectionHandlerTrace) + [] + "" + , DocMsg + TrShutdown + [] + "" + , DocMsg + (TrConnectionExists anyProto anyProto anyProto) + [] + "" + , DocMsg + (TrForbiddenConnection anyProto) + [] + "" + , DocMsg + (TrImpossibleConnection anyProto) + [] + "" + , DocMsg + (TrConnectionFailure anyProto) + [] + "" + , DocMsg + (TrConnectionNotFound anyProto anyProto) + [] + "" + , DocMsg + (TrForbiddenOperation anyProto anyProto) + [] + "" + , DocMsg + (TrPruneConnections anyProto anyProto anyProto) + [] + "" + , DocMsg + (TrConnectionCleanup anyProto) + [] + "" + , DocMsg + (TrConnectionTimeWait anyProto) + [] + "" + , DocMsg + (TrConnectionTimeWaitDone anyProto) + [] + "" + , DocMsg + (TrConnectionManagerCounters anyProto) + [("cardano.node.connectionManager.fullDuplexConns","") + ,("cardano.node.connectionManager.duplexConns","") + ,("cardano.node.connectionManager.unidirectionalConns","") + ,("cardano.node.connectionManager.inboundConns","") + ,("cardano.node.connectionManager.outboundConns","") + ] + "" + , DocMsg + (TrState anyProto) + [] + "" + , DocMsg + (ConnectionManager.TrUnexpectedlyFalseAssertion anyProto) + [] + "" + ] + +-------------------------------------------------------------------------------- +-- Server Tracer +-------------------------------------------------------------------------------- + +namesForServer :: ServerTrace ntnAddr -> [Text] +namesForServer TrAcceptConnection {} = ["AcceptConnection"] +namesForServer TrAcceptError {} = ["AcceptError"] +namesForServer TrAcceptPolicyTrace {} = ["AcceptPolicy"] +namesForServer TrServerStarted {} = ["Started"] +namesForServer TrServerStopped {} = ["Stopped"] +namesForServer TrServerError {} = ["Error"] + +severityServer :: ServerTrace ntnAddr -> SeverityS +severityServer TrAcceptConnection {} = Debug +severityServer TrAcceptError {} = Error +severityServer TrAcceptPolicyTrace {} = Notice +severityServer TrServerStarted {} = Notice +severityServer TrServerStopped {} = Notice +severityServer TrServerError {} = Critical + +instance (Show addr, LogFormatting addr, ToJSON addr) + => LogFormatting (ServerTrace addr) where + forMachine dtal (TrAcceptConnection peerAddr) = + mkObject [ "kind" .= String "AcceptConnection" + , "address" .= forMachine dtal peerAddr + ] + forMachine _dtal (TrAcceptError exception) = + mkObject [ "kind" .= String "AcceptErroor" + , "reason" .= show exception + ] + forMachine dtal (TrAcceptPolicyTrace policyTrace) = + mkObject [ "kind" .= String "AcceptPolicyTrace" + , "policy" .= forMachine dtal policyTrace + ] + forMachine dtal (TrServerStarted peerAddrs) = + mkObject [ "kind" .= String "AcceptPolicyTrace" + , "addresses" .= toJSON (forMachine dtal `map` peerAddrs) + ] + forMachine _dtal TrServerStopped = + mkObject [ "kind" .= String "ServerStopped" + ] + forMachine _dtal (TrServerError exception) = + mkObject [ "kind" .= String "ServerError" + , "reason" .= show exception + ] + forHuman = pack . show + +docServer :: Documented (ServerTrace ntnAddr) +docServer = Documented + [ DocMsg + (TrAcceptConnection anyProto) + [] + "" + , DocMsg + (TrAcceptError anyProto) + [] + "" + , DocMsg + (TrAcceptPolicyTrace anyProto) + [] + "" + , DocMsg + (TrServerStarted anyProto) + [] + "" + , DocMsg + TrServerStopped + [] + "" + , DocMsg + (TrServerError anyProto) + [] + "" + ] + +-------------------------------------------------------------------------------- +-- InboundGovernor Tracer +-------------------------------------------------------------------------------- + +namesForInboundGovernor :: InboundGovernorTrace peerAddr -> [Text] +namesForInboundGovernor TrNewConnection {} = ["NewConnection"] +namesForInboundGovernor TrResponderRestarted {} = ["ResponderRestarted"] +namesForInboundGovernor TrResponderStartFailure {} = ["ResponderStartFailure"] +namesForInboundGovernor TrResponderErrored {} = ["ResponderErrored"] +namesForInboundGovernor TrResponderStarted {} = ["ResponderStarted"] +namesForInboundGovernor TrResponderTerminated {} = ["ResponderTerminated"] +namesForInboundGovernor TrPromotedToWarmRemote {} = ["PromotedToWarmRemote"] +namesForInboundGovernor TrPromotedToHotRemote {} = ["PromotedToHotRemote"] +namesForInboundGovernor TrDemotedToColdRemote {} = ["DemotedToColdRemote"] +namesForInboundGovernor TrDemotedToWarmRemote {} = ["DemotedToWarmRemote"] +namesForInboundGovernor TrWaitIdleRemote {} = ["WaitIdleRemote"] +namesForInboundGovernor TrMuxCleanExit {} = ["MuxCleanExit"] +namesForInboundGovernor TrMuxErrored {} = ["MuxErrored"] +namesForInboundGovernor TrInboundGovernorCounters {} = ["InboundGovernorCounters"] +namesForInboundGovernor TrRemoteState {} = ["RemoteState"] +namesForInboundGovernor InboundGovernor.TrUnexpectedlyFalseAssertion {} = + ["UnexpectedlyFalseAssertion"] + +severityInboundGovernor :: InboundGovernorTrace peerAddr -> SeverityS +severityInboundGovernor TrNewConnection {} = Debug +severityInboundGovernor TrResponderRestarted {} = Debug +severityInboundGovernor TrResponderStartFailure {} = Error +severityInboundGovernor TrResponderErrored {} = Info +severityInboundGovernor TrResponderStarted {} = Debug +severityInboundGovernor TrResponderTerminated {} = Debug +severityInboundGovernor TrPromotedToWarmRemote {} = Info +severityInboundGovernor TrPromotedToHotRemote {} = Info +severityInboundGovernor TrDemotedToColdRemote {} = Info +severityInboundGovernor TrDemotedToWarmRemote {} = Info +severityInboundGovernor TrWaitIdleRemote {} = Debug +severityInboundGovernor TrMuxCleanExit {} = Debug +severityInboundGovernor TrMuxErrored {} = Info +severityInboundGovernor TrInboundGovernorCounters {} = Info +severityInboundGovernor TrRemoteState {} = Debug +severityInboundGovernor InboundGovernor.TrUnexpectedlyFalseAssertion {} = Error + +instance (ToJSON addr, Show addr) + => LogFormatting (InboundGovernorTrace addr) where + forMachine _dtal (TrNewConnection p connId) = + mkObject [ "kind" .= String "NewConnection" + , "provenance" .= show p + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrResponderRestarted connId m) = + mkObject [ "kind" .= String "ResponderStarted" + , "connectionId" .= toJSON connId + , "miniProtocolNum" .= toJSON m + ] + forMachine _dtal (TrResponderStartFailure connId m s) = + mkObject [ "kind" .= String "ResponderStartFailure" + , "connectionId" .= toJSON connId + , "miniProtocolNum" .= toJSON m + , "reason" .= show s + ] + forMachine _dtal (TrResponderErrored connId m s) = + mkObject [ "kind" .= String "ResponderErrored" + , "connectionId" .= toJSON connId + , "miniProtocolNum" .= toJSON m + , "reason" .= show s + ] + forMachine _dtal (TrResponderStarted connId m) = + mkObject [ "kind" .= String "ResponderStarted" + , "connectionId" .= toJSON connId + , "miniProtocolNum" .= toJSON m + ] + forMachine _dtal (TrResponderTerminated connId m) = + mkObject [ "kind" .= String "ResponderTerminated" + , "connectionId" .= toJSON connId + , "miniProtocolNum" .= toJSON m + ] + forMachine _dtal (TrPromotedToWarmRemote connId opRes) = + mkObject [ "kind" .= String "PromotedToWarmRemote" + , "connectionId" .= toJSON connId + , "result" .= toJSON opRes + ] + forMachine _dtal (TrPromotedToHotRemote connId) = + mkObject [ "kind" .= String "PromotedToHotRemote" + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrDemotedToColdRemote connId od) = + mkObject [ "kind" .= String "DemotedToColdRemote" + , "connectionId" .= toJSON connId + , "result" .= show od + ] + forMachine _dtal (TrDemotedToWarmRemote connId) = + mkObject [ "kind" .= String "DemotedToWarmRemote" + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrWaitIdleRemote connId opRes) = + mkObject [ "kind" .= String "WaitIdleRemote" + , "connectionId" .= toJSON connId + , "result" .= toJSON opRes + ] + forMachine _dtal (TrMuxCleanExit connId) = + mkObject [ "kind" .= String "MuxCleanExit" + , "connectionId" .= toJSON connId + ] + forMachine _dtal (TrMuxErrored connId s) = + mkObject [ "kind" .= String "MuxErrored" + , "connectionId" .= toJSON connId + , "reason" .= show s + ] + forMachine _dtal (TrInboundGovernorCounters counters) = + mkObject [ "kind" .= String "InboundGovernorCounters" + , "idlePeers" .= idlePeersRemote counters + , "coldPeers" .= coldPeersRemote counters + , "warmPeers" .= warmPeersRemote counters + , "hotPeers" .= hotPeersRemote counters + ] + forMachine _dtal (TrRemoteState st) = + mkObject [ "kind" .= String "RemoteState" + , "remoteSt" .= toJSON st + ] + forMachine _dtal (InboundGovernor.TrUnexpectedlyFalseAssertion info) = + mkObject [ "kind" .= String "UnexpectedlyFalseAssertion" + , "remoteSt" .= String (pack . show $ info) + ] + forHuman = pack . show + asMetrics (TrInboundGovernorCounters InboundGovernorCounters {..}) = + [ IntM + "cardano.node.inbound-governor.warm" + (fromIntegral warmPeersRemote) + , IntM + "cardano.node.inbound-governor.hot" + (fromIntegral hotPeersRemote) + ] + asMetrics _ = [] + +protoProvenance :: ConnectionManager.Provenance +protoProvenance = ConnectionManager.Inbound + +protoConnectionId :: peerAddr -> ConnectionId peerAddr +protoConnectionId pa = ConnectionId pa pa + +protoMiniProtocolNum :: MiniProtocolNum +protoMiniProtocolNum = MiniProtocolNum 1 + +protoSomeException :: SomeException +protoSomeException = SomeException (AssertionFailed "just fooled") + +protoAbstractState :: AbstractState +protoAbstractState = UnknownConnectionSt + +protoOperationResult :: a -> OperationResult a +protoOperationResult = OperationSuccess + +protoDemotedToColdRemoteTr :: DemotedToColdRemoteTr +protoDemotedToColdRemoteTr = CommitTr + +protoInboundGovernorCounters :: InboundGovernorCounters +protoInboundGovernorCounters = InboundGovernorCounters 1 1 1 1 + +protoRemoteAddr :: SockAddr +protoRemoteAddr = SockAddrUnix "loopback" + +protoLocalAddress :: LocalAddress +protoLocalAddress = LocalAddress "loopback" + + +-- Not possible to prvide such prototype, +-- as type and constructor are not exported +-- protoIGAssertionLocation :: IGAssertionLocation peerAddr +-- protoIGAssertionLocation = InboundGovernorLoop Nothing protoAbstractState + +docInboundGovernorLocal :: + Documented (InboundGovernorTrace LocalAddress) +docInboundGovernorLocal = docInboundGovernor protoLocalAddress + +docInboundGovernorRemote :: + Documented (InboundGovernorTrace SockAddr) +docInboundGovernorRemote = docInboundGovernor protoRemoteAddr + +docInboundGovernor :: peerAddr -> Documented (InboundGovernorTrace peerAddr) +docInboundGovernor peerAddr = Documented + [ DocMsg + (TrNewConnection protoProvenance (protoConnectionId peerAddr)) + [] + "" + , DocMsg + (TrResponderRestarted (protoConnectionId peerAddr) protoMiniProtocolNum) + [] + "" + , DocMsg + (TrResponderStartFailure (protoConnectionId peerAddr) protoMiniProtocolNum + protoSomeException) + [] + "" + , DocMsg + (TrResponderErrored (protoConnectionId peerAddr) protoMiniProtocolNum + protoSomeException) + [] + "" + , DocMsg + (TrResponderStarted (protoConnectionId peerAddr) protoMiniProtocolNum) + [] + "" + , DocMsg + (TrResponderTerminated (protoConnectionId peerAddr) protoMiniProtocolNum) + [] + "" + , DocMsg + (TrPromotedToWarmRemote (protoConnectionId peerAddr) + (protoOperationResult protoAbstractState)) + [] + "" + , DocMsg + (TrPromotedToHotRemote (protoConnectionId peerAddr)) + [] + "" + , DocMsg + (TrDemotedToColdRemote (protoConnectionId peerAddr) + (protoOperationResult protoDemotedToColdRemoteTr)) + [] + "All mini-protocols terminated. The boolean is true if this connection\ + \ was not used by p2p-governor, and thus the connection will be terminated." + , DocMsg + (TrDemotedToWarmRemote (protoConnectionId peerAddr)) + [] + "All mini-protocols terminated. The boolean is true if this connection\ + \ was not used by p2p-governor, and thus the connection will be terminated." + , DocMsg + (TrWaitIdleRemote (protoConnectionId peerAddr) + (protoOperationResult protoAbstractState)) + [] + "" + , DocMsg + (TrMuxCleanExit (protoConnectionId peerAddr)) + [] + "" + , DocMsg + (TrMuxErrored (protoConnectionId peerAddr) protoSomeException) + [] + "" + , DocMsg + (TrInboundGovernorCounters protoInboundGovernorCounters) + [] + "" + , DocMsg + (TrRemoteState Map.empty) + [] + "" + -- , DocMsg + -- (InboundGovernor.TrUnexpectedlyFalseAssertion protoIGAssertionLocation) + -- [] + -- "" + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Peer.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Peer.hs new file mode 100644 index 00000000000..d1639b24100 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/Peer.hs @@ -0,0 +1,154 @@ +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PackageImports #-} + +module Cardano.Node.Tracing.Tracers.Peer + ( PeerT (..) + , startPeerTracer + , namesForPeers + , severityPeers + , docPeers + , ppPeer + ) where + +import Cardano.Prelude hiding (atomically) +import Prelude (String) + +import qualified Control.Monad.Class.MonadSTM.Strict as STM +import "contra-tracer" Control.Tracer + +import Data.Aeson (ToJSON (..), Value (..), toJSON, (.=)) +import qualified Data.Map.Strict as Map +import qualified Data.Set as Set +import qualified Data.Text as Text +import Text.Printf (printf) + +import Ouroboros.Consensus.Block (Header) +import Ouroboros.Consensus.Util.Orphans () +import Ouroboros.Network.ConnectionId (remoteAddress) + +import qualified Ouroboros.Network.AnchoredFragment as Net +import Ouroboros.Network.Block (unSlotNo) +import qualified Ouroboros.Network.Block as Net +import qualified Ouroboros.Network.BlockFetch.ClientRegistry as Net +import Ouroboros.Network.BlockFetch.ClientState (PeerFetchInFlight (..), + PeerFetchStatus (..), readFetchClientState) + +import Cardano.Logging hiding (traceWith) +import Cardano.Node.Queries + +startPeerTracer + :: Tracer IO [PeerT blk] + -> NodeKernelData blk + -> Int + -> IO () +startPeerTracer tr nodeKern delayMilliseconds = do + as <- async peersThread + link as + where + peersThread :: IO () + peersThread = forever $ do + peers <- getCurrentPeers nodeKern + traceWith tr peers + threadDelay (delayMilliseconds * 1000) + +data PeerT blk = PeerT + RemoteConnectionId + (Net.AnchoredFragment (Header blk)) + (PeerFetchStatus (Header blk)) + (PeerFetchInFlight (Header blk)) + + +ppPeer :: PeerT blk -> Text +ppPeer (PeerT cid _af status inflight) = + Text.pack $ printf "%-15s %-8s %s" (ppCid cid) (ppStatus status) (ppInFlight inflight) + +ppCid :: RemoteConnectionId -> String +ppCid = takeWhile (/= ':') . show . remoteAddress + +ppInFlight :: PeerFetchInFlight header -> String +ppInFlight f = printf + "%5s %3d %5d %6d" + (ppMaxSlotNo $ peerFetchMaxSlotNo f) + (peerFetchReqsInFlight f) + (Set.size $ peerFetchBlocksInFlight f) + (peerFetchBytesInFlight f) + +ppMaxSlotNo :: Net.MaxSlotNo -> String +ppMaxSlotNo Net.NoMaxSlotNo = "???" +ppMaxSlotNo (Net.MaxSlotNo x) = show (unSlotNo x) + +ppStatus :: PeerFetchStatus header -> String +ppStatus PeerFetchStatusShutdown = "shutdown" +ppStatus PeerFetchStatusAberrant = "aberrant" +ppStatus PeerFetchStatusBusy = "fetching" +ppStatus PeerFetchStatusReady {} = "ready" + +getCurrentPeers + :: NodeKernelData blk + -> IO [PeerT blk] +getCurrentPeers nkd = mapNodeKernelDataIO extractPeers nkd + <&> fromSMaybe mempty + where + tuple3pop :: (a, b, c) -> (a, b) + tuple3pop (a, b, _) = (a, b) + + getCandidates + :: STM.StrictTVar IO (Map peer (STM.StrictTVar IO (Net.AnchoredFragment (Header blk)))) + -> STM.STM IO (Map peer (Net.AnchoredFragment (Header blk))) + getCandidates var = STM.readTVar var >>= traverse STM.readTVar + + extractPeers :: NodeKernel IO RemoteConnectionId LocalConnectionId blk + -> IO [PeerT blk] + extractPeers kernel = do + peerStates <- fmap tuple3pop <$> ( STM.atomically + . (>>= traverse readFetchClientState) + . Net.readFetchClientsStateVars + . getFetchClientRegistry $ kernel + ) + candidates <- STM.atomically . getCandidates . getNodeCandidates $ kernel + + let peers = flip Map.mapMaybeWithKey candidates $ \cid af -> + maybe Nothing + (\(status, inflight) -> Just $ PeerT cid af status inflight) + $ Map.lookup cid peerStates + pure . Map.elems $ peers + +-------------------------------------------------------------------------------- +-- Peers Tracer +-------------------------------------------------------------------------------- + +namesForPeers :: [PeerT blk] -> [Text] +namesForPeers _ = [] + +severityPeers :: [PeerT blk] -> SeverityS +severityPeers _ = Notice + +instance LogFormatting [PeerT blk] where + forMachine DMinimal _ = mkObject [ "kind" .= String "NodeKernelPeers"] + forMachine _ [] = mkObject [ "kind" .= String "NodeKernelPeers"] + forMachine dtal xs = mkObject + [ "kind" .= String "NodeKernelPeers" + , "peers" .= toJSON (foldl' (\acc x -> forMachine dtal x : acc) [] xs) + ] + forHuman peers = Text.concat $ intersperse ", " (map ppPeer peers) + asMetrics peers = [IntM "peersFromNodeKernel" (fromIntegral (length peers))] + +instance LogFormatting (PeerT blk) where + forMachine _dtal (PeerT cid _af status inflight) = + mkObject [ "peerAddress" .= String (Text.pack . show . remoteAddress $ cid) + , "peerStatus" .= String (Text.pack . ppStatus $ status) + , "peerSlotNo" .= String (Text.pack . ppMaxSlotNo . peerFetchMaxSlotNo $ inflight) + , "peerReqsInF" .= String (show . peerFetchReqsInFlight $ inflight) + , "peerBlocksInF" .= String (show . Set.size . peerFetchBlocksInFlight $ inflight) + , "peerBytesInF" .= String (show . peerFetchBytesInFlight $ inflight) + ] + +docPeers :: Documented [PeerT blk] +docPeers = Documented [ + DocMsg + [] + [("peersFromNodeKernel","TODO Doc")] + "TODO Doc" + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Resources.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Resources.hs new file mode 100644 index 00000000000..847acecbffe --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/Resources.hs @@ -0,0 +1,39 @@ +{-# LANGUAGE PackageImports #-} + +module Cardano.Node.Tracing.Tracers.Resources + ( startResourceTracer + , namesForResources + , severityResources + ) where + +import "contra-tracer" Control.Tracer + +import Cardano.Logging (SeverityS (..)) +import Cardano.Logging.Resources +import Cardano.Prelude hiding (trace) + +startResourceTracer + :: Tracer IO ResourceStats + -> Int + -> IO () +startResourceTracer tr delayMilliseconds = do + as <- async resourceThread + link as + where + resourceThread :: IO () + resourceThread = forever $ do + mbrs <- readResourceStats + case mbrs of + Just rs -> traceWith tr rs + Nothing -> pure () + threadDelay (delayMilliseconds * 1000) + +-------------------------------------------------------------------------------- +-- ResourceStats Tracer +-------------------------------------------------------------------------------- + +namesForResources :: ResourceStats -> [Text] +namesForResources _ = [] + +severityResources :: ResourceStats -> SeverityS +severityResources _ = Info diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Shutdown.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Shutdown.hs new file mode 100644 index 00000000000..54ced73ac09 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/Shutdown.hs @@ -0,0 +1,91 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-name-shadowing -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.Shutdown + ( namesForShutdown + , severityShutdown + , ppShutdownTrace + , docShutdown + ) where + +import Cardano.Logging +import Cardano.Node.Handlers.Shutdown +import Data.Aeson (ToJSON (..), Value (..), (.=)) +import Data.Monoid ((<>)) +import Data.Text (Text, pack) +import Prelude (show) + +-------------------------------------------------------------------------------- +-- ShutdownTrace Tracer +-------------------------------------------------------------------------------- + +namesForShutdown :: ShutdownTrace -> [Text] +namesForShutdown = \case + ShutdownRequested{} -> ["ShutdownRequested"] + AbnormalShutdown{} -> ["AbnormalShutdown"] + ShutdownUnexpectedInput{} -> ["ShutdownUnexpectedInput"] + RequestingShutdown{} -> ["RequestingShutdown"] + ShutdownArmedAtSlot{} -> ["ShutdownArmedAtSlot"] + +severityShutdown :: ShutdownTrace -> SeverityS +severityShutdown = \case + ShutdownRequested{} -> Warning + AbnormalShutdown{} -> Error + ShutdownUnexpectedInput{} -> Error + RequestingShutdown{} -> Warning + ShutdownArmedAtSlot{} -> Warning + +ppShutdownTrace :: ShutdownTrace -> Text +ppShutdownTrace = \case + ShutdownRequested -> "Received shutdown request" + AbnormalShutdown -> "non-isEOFerror shutdown request" + ShutdownUnexpectedInput text -> + "Received shutdown request but found unexpected input in --shutdown-ipc FD: " <> text + RequestingShutdown reason -> "Ringing the node shutdown doorbell: " <> reason + ShutdownArmedAtSlot slot -> "Will terminate upon reaching " <> pack (show slot) + +instance LogFormatting ShutdownTrace where + forHuman = ppShutdownTrace + + forMachine _ = \case + ShutdownRequested -> + mkObject [ "kind" .= String "ShutdownRequested" ] + AbnormalShutdown -> + mkObject [ "kind" .= String "AbnormalShutdown" ] + ShutdownUnexpectedInput text -> + mkObject [ "kind" .= String "AbnormalShutdown" + , "unexpected" .= String text ] + RequestingShutdown reason -> + mkObject [ "kind" .= String "RequestingShutdown" + , "reason" .= String reason ] + ShutdownArmedAtSlot slot -> + mkObject [ "kind" .= String "ShutdownArmedAtSlot" + , "slot" .= toJSON slot ] + +docShutdown :: Documented ShutdownTrace +docShutdown = Documented + [ DocMsg + ShutdownRequested + [] + "Node shutdown was requested." + , DocMsg + AbnormalShutdown + [] + "non-isEOFerror shutdown request" + , DocMsg + (ShutdownUnexpectedInput anyProto) + [] + "Received shutdown request but found unexpected input in --shutdown-ipc FD: " + , DocMsg + (RequestingShutdown anyProto) + [] + "Ringing the node shutdown doorbell" + , DocMsg + (ShutdownArmedAtSlot anyProto) + [] + "Setting up node shutdown at given slot." + ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/StartLeadershipCheck.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/StartLeadershipCheck.hs new file mode 100644 index 00000000000..9b8d2ef69ba --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/StartLeadershipCheck.hs @@ -0,0 +1,128 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE PackageImports #-} + +module Cardano.Node.Tracing.Tracers.StartLeadershipCheck + ( TraceStartLeadershipCheckPlus (..) + , ForgeTracerType + , forgeTracerTransform + ) where + + +import Cardano.Logging +import Cardano.Prelude +import qualified "trace-dispatcher" Control.Tracer as T +import Data.IORef (readIORef) + +import qualified Ouroboros.Network.AnchoredFragment as AF +import Ouroboros.Network.Block (BlockNo (..), blockNo, unBlockNo) +import Ouroboros.Network.NodeToClient (LocalConnectionId) +import Ouroboros.Network.NodeToNode (RemoteConnectionId) + +import Ouroboros.Consensus.Block (SlotNo (..)) +import Ouroboros.Consensus.HardFork.Combinator +import Ouroboros.Consensus.Ledger.Abstract (IsLedger) +import Ouroboros.Consensus.Ledger.Extended (ExtLedgerState, ledgerState) +import Ouroboros.Consensus.Node (NodeKernel (..)) +import Ouroboros.Consensus.Node.Tracers +import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB + +import Cardano.Node.Queries (LedgerQueries (..), NodeKernelData (..)) +import Cardano.Slotting.Slot (fromWithOrigin) + +import Cardano.Ledger.BaseTypes (StrictMaybe (..), fromSMaybe) + + +type ForgeTracerType blk = Either (TraceLabelCreds (TraceForgeEvent blk)) + (TraceLabelCreds TraceStartLeadershipCheckPlus) + +data TraceStartLeadershipCheckPlus = + TraceStartLeadershipCheckPlus { + tsSlotNo :: SlotNo + , tsUtxoSize :: Int + , tsDelegMapSize :: Int + , tsChainDensity :: Double + } + +forgeTracerTransform :: + ( IsLedger (LedgerState blk) + , LedgerQueries blk + , AF.HasHeader (Header blk)) + => NodeKernelData blk + -> Trace IO (ForgeTracerType blk) + -> IO (Trace IO (ForgeTracerType blk)) +forgeTracerTransform nodeKern (Trace tr) = pure $ Trace $ T.arrow $ T.emit $ + \case + (lc, Nothing, Left (TraceLabelCreds creds + (TraceStartLeadershipCheck slotNo))) -> do + query <- mapNodeKernelDataIO + (\nk -> + (,,) + <$> nkQueryLedger (ledgerUtxoSize . ledgerState) nk + <*> nkQueryLedger (ledgerDelegMapSize . ledgerState) nk + <*> nkQueryChain fragmentChainDensity nk) + nodeKern + fromSMaybe (pure ()) + (query <&> + \(utxoSize, delegMapSize, chainDensity) -> + let msg = TraceStartLeadershipCheckPlus + slotNo + utxoSize + delegMapSize + (fromRational chainDensity) + in T.traceWith tr (lc, Nothing, Right (TraceLabelCreds creds msg))) + (lc, Nothing, a) -> + T.traceWith tr (lc, Nothing, a) + (lc, Just control, a) -> + T.traceWith tr (lc, Just control, a) + +nkQueryLedger :: + IsLedger (LedgerState blk) + => (ExtLedgerState blk -> a) + -> NodeKernel IO RemoteConnectionId LocalConnectionId blk + -> IO a +nkQueryLedger f NodeKernel{getChainDB} = + f <$> atomically (ChainDB.getCurrentLedger getChainDB) + +fragmentChainDensity :: + AF.HasHeader (Header blk) + => AF.AnchoredFragment (Header blk) -> Rational +fragmentChainDensity frag = calcDensity blockD slotD + where + calcDensity :: Word64 -> Word64 -> Rational + calcDensity bl sl + | sl > 0 = toRational bl / toRational sl + | otherwise = 0 + slotN = unSlotNo $ fromWithOrigin 0 (AF.headSlot frag) + -- Slot of the tip - slot @k@ blocks back. Use 0 as the slot for genesis + -- includes EBBs + slotD = slotN + - unSlotNo (fromWithOrigin 0 (AF.lastSlot frag)) + -- Block numbers start at 1. We ignore the genesis EBB, which has block number 0. + blockD = blockN - firstBlock + blockN = unBlockNo $ fromWithOrigin (BlockNo 1) (AF.headBlockNo frag) + firstBlock = case unBlockNo . blockNo <$> AF.last frag of + -- Empty fragment, no blocks. We have that @blocks = 1 - 1 = 0@ + Left _ -> 1 + -- The oldest block is the genesis EBB with block number 0, + -- don't let it contribute to the number of blocks + Right 0 -> 1 + Right b -> b + +nkQueryChain :: + (AF.AnchoredFragment (Header blk) -> a) + -> NodeKernel IO RemoteConnectionId LocalConnectionId blk + -> IO a +nkQueryChain f NodeKernel{getChainDB} = + f <$> atomically (ChainDB.getCurrentChain getChainDB) + + +mapNodeKernelDataIO :: + (NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO a) + -> NodeKernelData blk + -> IO (StrictMaybe a) +mapNodeKernelDataIO f (NodeKernelData ref) = + readIORef ref >>= traverse f diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Startup.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Startup.hs new file mode 100644 index 00000000000..40ee9da1e17 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/Startup.hs @@ -0,0 +1,416 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE UndecidableInstances #-} + +{-# OPTIONS_GHC -Wno-name-shadowing -Wno-orphans #-} + +module Cardano.Node.Tracing.Tracers.Startup + ( getStartupInfo + , namesStartupInfo + , docStartupInfo + , ppStartupInfoTrace + ) where + +import Prelude + +import Data.Aeson (ToJSON (..), Value (..), (.=)) +import Data.List (intercalate) +import qualified Data.Map as Map +import Data.Text (Text, pack) +import Data.Time (getCurrentTime) +import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds) +import Data.Version (showVersion) +import Network.Socket (SockAddr) +import Paths_cardano_node (version) + +import qualified Cardano.Chain.Genesis as Gen +import Cardano.Slotting.Slot (EpochSize (..)) + +import Cardano.Ledger.Shelley.API as SL + +import Ouroboros.Network.NodeToClient (LocalAddress (..), LocalSocket (..)) +import Ouroboros.Network.NodeToNode (DiffusionMode (..)) +import Ouroboros.Network.PeerSelection.LedgerPeers (UseLedgerAfter (..)) + +import qualified Ouroboros.Consensus.BlockchainTime.WallClock.Types as WCT +import Ouroboros.Consensus.Byron.Ledger.Conversions (fromByronEpochSlots, + fromByronSlotLength, genesisSlotLength) +import Ouroboros.Consensus.Cardano.Block (HardForkLedgerConfig (..)) +import Ouroboros.Consensus.Cardano.CanHardFork (ByronPartialLedgerConfig (..), + ShelleyPartialLedgerConfig (..)) +import qualified Ouroboros.Consensus.Config as Consensus +import Ouroboros.Consensus.Config.SupportsNode (ConfigSupportsNode (..)) +import Ouroboros.Consensus.HardFork.Combinator.Degenerate (HardForkLedgerConfig (..)) +import Ouroboros.Consensus.Node.NetworkProtocolVersion +import Ouroboros.Consensus.Node.ProtocolInfo (ProtocolInfo (..)) +import Ouroboros.Consensus.Shelley.Ledger.Ledger (shelleyLedgerGenesis) + +import Cardano.Logging + +import Cardano.Api (NetworkMagic (..), SlotNo (..)) +import Cardano.Api.Protocol.Types (BlockType (..), protocolInfo) + +import Cardano.Config.Git.Rev (gitRev) + +import Cardano.Node.Configuration.POM (NodeConfiguration, ncProtocol) +import Cardano.Node.Configuration.Socket +import Cardano.Node.Configuration.TopologyP2P +import Cardano.Node.Protocol (SomeConsensusProtocol (..)) +import Cardano.Node.Startup + + +getStartupInfo + :: NodeConfiguration + -> SomeConsensusProtocol + -> FilePath + -> IO [StartupTrace blk] +getStartupInfo nc (SomeConsensusProtocol whichP pForInfo) fp = do + nodeStartTime <- getCurrentTime + let cfg = pInfoConfig $ protocolInfo pForInfo + basicInfoCommon = BICommon $ BasicInfoCommon { + biProtocol = pack . show $ ncProtocol nc + , biVersion = pack . showVersion $ version + , biCommit = gitRev + , biNodeStartTime = nodeStartTime + , biConfigPath = fp + , biNetworkMagic = getNetworkMagic $ Consensus.configBlock cfg + } + protocolDependentItems = + case whichP of + ByronBlockType -> + let DegenLedgerConfig cfgByron = Consensus.configLedger cfg + in [getGenesisValuesByron cfg cfgByron] + ShelleyBlockType -> + let DegenLedgerConfig cfgShelley = Consensus.configLedger cfg + in [getGenesisValues "Shelley" cfgShelley] + CardanoBlockType -> + let CardanoLedgerConfig cfgByron cfgShelley cfgAllegra cfgMary cfgAlonzo = Consensus.configLedger cfg + in getGenesisValuesByron cfg cfgByron + : getGenesisValues "Shelley" cfgShelley + : getGenesisValues "Allegra" cfgAllegra + : getGenesisValues "Mary" cfgMary + : [getGenesisValues "Alonzo" cfgAlonzo] + pure (basicInfoCommon : protocolDependentItems) + where + getGenesisValues era config = + let genesis = shelleyLedgerGenesis $ shelleyLedgerConfig config + in BIShelley $ BasicInfoShelleyBased { + bisEra = era + , bisSystemStartTime = SL.sgSystemStart genesis + , bisSlotLength = WCT.getSlotLength . WCT.mkSlotLength + $ SL.sgSlotLength genesis + , bisEpochLength = unEpochSize . SL.sgEpochLength $ genesis + , bisSlotsPerKESPeriod = SL.sgSlotsPerKESPeriod genesis + } + getGenesisValuesByron cfg config = + let genesis = byronLedgerConfig config + in BIByron $ BasicInfoByron { + bibSystemStartTime = WCT.getSystemStart . getSystemStart + $ Consensus.configBlock cfg + , bibSlotLength = WCT.getSlotLength . fromByronSlotLength + $ genesisSlotLength genesis + , bibEpochLength = unEpochSize . fromByronEpochSlots + $ Gen.configEpochSlots genesis + } + +-------------------------------------------------------------------------------- +-- StartupInfo Tracer +-------------------------------------------------------------------------------- + +namesStartupInfo :: StartupTrace blk -> [Text] +namesStartupInfo = \case + StartupInfo {} -> ["StartupInfo"] + StartupP2PInfo {} -> ["StartupP2PInfo"] + StartupTime {} -> ["StartupTime"] + StartupNetworkMagic {} -> ["StartupNetworkMagic"] + StartupSocketConfigError {} -> ["StartupSocketConfigError"] + StartupDBValidation {} -> ["StartupDBValidation"] + NetworkConfigUpdate {} -> ["NetworkConfigUpdate"] + NetworkConfigUpdateError {} -> ["NetworkConfigUpdateError"] + NetworkConfig {} -> ["NetworkConfig"] + P2PWarning {} -> ["P2PWarning"] + P2PWarningDevelopementNetworkProtocols {} -> ["P2PWarningDevelopementNetworkProtocols"] + WarningDevelopmentNetworkProtocols {} -> ["WarningDevelopmentNetworkProtocols"] + BICommon {} -> ["Common"] + BIShelley {} -> ["ShelleyBased"] + BIByron {} -> ["Byron"] + BINetwork {} -> ["Network"] + +instance ( Show (BlockNodeToNodeVersion blk) + , Show (BlockNodeToClientVersion blk) + ) + => LogFormatting (StartupTrace blk) where + forHuman = ppStartupInfoTrace + + forMachine dtal (StartupInfo addresses + localSocket + supportedNodeToNodeVersions + supportedNodeToClientVersions) + = mkObject ( + [ "kind" .= String "StartupInfo" + , "nodeAddresses" .= toJSON (map ppN2NSocketInfo addresses) + , "localSocket" .= case localSocket of + Nothing -> Null + Just a -> String (pack . ppN2CSocketInfo $ a) + ] + ++ + case dtal of + DMaximum -> + [ "nodeToNodeVersions" .= + toJSON (map show . Map.assocs $ supportedNodeToNodeVersions) + , "nodeToClientVersions" .= + toJSON (map show . Map.assocs $ supportedNodeToClientVersions) + ] + _ -> + [ "maxNodeToNodeVersion" .= + case Map.maxViewWithKey supportedNodeToNodeVersions of + Nothing -> String "no-supported-version" + Just (v, _) -> String (pack . show $ v) + , "maxNodeToClientVersion" .= + case Map.maxViewWithKey supportedNodeToClientVersions of + Nothing -> String "no-supported-version" + Just (v, _) -> String (pack . show $ v) + ]) + forMachine _dtal (StartupP2PInfo diffusionMode) = + mkObject [ "kind" .= String "StartupP2PInfo" + , "diffusionMode" .= String (showT diffusionMode) ] + forMachine _dtal (StartupTime time) = + mkObject [ "kind" .= String "StartupTime" + , "startupTime" .= String ( showT + . (ceiling :: POSIXTime -> Int) + . utcTimeToPOSIXSeconds + $ time + ) + ] + forMachine _dtal (StartupNetworkMagic networkMagic) = + mkObject [ "kind" .= String "StartupNetworkMagic" + , "networkMagic" .= String (showT . unNetworkMagic + $ networkMagic) ] + forMachine _dtal (StartupSocketConfigError err) = + mkObject [ "kind" .= String "StartupSocketConfigError" + , "error" .= String (showT err) ] + forMachine _dtal StartupDBValidation = + mkObject [ "kind" .= String "StartupDBValidation" + , "message" .= String "start db validation" ] + forMachine _dtal NetworkConfigUpdate = + mkObject [ "kind" .= String "NetworkConfigUpdate" + , "message" .= String "ntework configuration update" ] + forMachine _dtal (NetworkConfigUpdateError err) = + mkObject [ "kind" .= String "NetworkConfigUpdateError" + , "error" .= String err ] + forMachine _dtal (NetworkConfig localRoots publicRoots useLedgerAfter) = + mkObject [ "kind" .= String "NetworkConfig" + , "localRoots" .= toJSON localRoots + , "publicRoots" .= toJSON publicRoots + , "useLedgerAfter" .= UseLedger useLedgerAfter + ] + forMachine _dtal P2PWarning = + mkObject [ "kind" .= String "P2PWarning" + , "message" .= String p2pWarningMessage ] + forMachine _dtal P2PWarningDevelopementNetworkProtocols = + mkObject [ "kind" .= String "P2PWarningDevelopementNetworkProtocols" + , "message" .= String p2pWarningDevelopmentNetworkProtocolsMessage ] + forMachine _ver (WarningDevelopmentNetworkProtocols ntnVersions ntcVersions) = + mkObject [ "kind" .= String "WarningDevelopmentNetworkProtocols" + , "message" .= String "enabled development network protocols" + , "nodeToNodeDevelopmentVersions" .= String (showT ntnVersions) + , "nodeToClientDevelopmentVersions" .= String (showT ntcVersions) + ] + forMachine _dtal (BINetwork BasicInfoNetwork {..}) = + mkObject [ "kind" .= String "BasicInfoNetwork" + , "addresses" .= String (showT niAddresses) + , "diffusionMode" .= String (showT niDiffusionMode) + , "dnsProducers" .= String (showT niDnsProducers) + , "ipProducers" .= String (showT niIpProducers) + ] + forMachine _dtal (BIByron BasicInfoByron {..}) = + mkObject [ "kind" .= String "BasicInfoByron" + , "systemStartTime" .= String (showT bibSystemStartTime) + , "slotLength" .= String (showT bibSlotLength) + , "epochLength" .= String (showT bibEpochLength) + ] + forMachine _dtal (BIShelley BasicInfoShelleyBased {..}) = + mkObject [ "kind" .= String "BasicInfoShelleyBased" + , "era" .= String bisEra + , "systemStartTime" .= String (showT bisSystemStartTime) + , "slotLength" .= String (showT bisSlotLength) + , "epochLength" .= String (showT bisEpochLength) + , "slotsPerKESPeriod" .= String (showT bisSlotsPerKESPeriod) + ] + forMachine _dtal (BICommon BasicInfoCommon {..}) = + mkObject [ "kind" .= String "BasicInfoCommon" + , "configPath" .= String (pack biConfigPath) + , "networkMagic" .= String (showT biNetworkMagic) + , "protocol" .= String biProtocol + , "version" .= String biVersion + , "commit" .= String biCommit + , "nodeStartTime" .= biNodeStartTime + ] + +-- | Pretty print 'StartupInfoTrace' +-- +ppStartupInfoTrace :: ( Show (BlockNodeToNodeVersion blk) + , Show (BlockNodeToClientVersion blk) + ) + => StartupTrace blk + -> Text +ppStartupInfoTrace (StartupInfo addresses + localSocket + supportedNodeToNodeVersions + supportedNodeToClientVersions) + = pack + $ "\n" ++ intercalate "\n" + [ "node addresses: " ++ intercalate ", " (map ppN2NSocketInfo addresses) + , "local socket: " ++ maybe "NONE" ppN2CSocketInfo localSocket + , "node-to-node versions:\n" + ++ intercalate "\n" + (map (\(v, bv) -> show v ++ "\t" ++ show bv) + . Map.assocs + $ supportedNodeToNodeVersions) + , "node-to-client versions:\n" + ++ intercalate "\n" + (map (\(v, bv) -> show v ++ "\t" ++ show bv) + . Map.assocs + $ supportedNodeToClientVersions) + ] + +ppStartupInfoTrace (StartupP2PInfo diffusionMode) = + case diffusionMode of + InitiatorAndResponderDiffusionMode -> "initiator and responder diffusion mode" + InitiatorOnlyDiffusionMode -> "initaitor only diffusion mode" + +ppStartupInfoTrace (StartupTime time) = + "startup time: " + <> ( showT + . (ceiling :: POSIXTime -> Int) + . utcTimeToPOSIXSeconds + $ time + ) +ppStartupInfoTrace (StartupNetworkMagic networkMagic) = + "network magic: " <> showT (unNetworkMagic networkMagic) + +ppStartupInfoTrace (StartupSocketConfigError err) = + pack $ renderSocketConfigError err + +ppStartupInfoTrace StartupDBValidation = "Performing DB validation" + +ppStartupInfoTrace NetworkConfigUpdate = "Performing topology configuration update" +ppStartupInfoTrace (NetworkConfigUpdateError err) = err +ppStartupInfoTrace (NetworkConfig localRoots publicRoots useLedgerAfter) = + pack + $ intercalate "\n" + [ "\nLocal Root Groups:" + , " " ++ intercalate "\n " (map (\(x,y) -> show (x, Map.assocs y)) + localRoots) + , "Public Roots:" + , " " ++ intercalate "\n " (map show publicRoots) + , case useLedgerAfter of + UseLedgerAfter slotNo -> "Get root peers from the ledger after slot " + ++ show (unSlotNo slotNo) + DontUseLedger -> "Don't use ledger to get root peers." + ] + +ppStartupInfoTrace P2PWarning = p2pWarningMessage + +ppStartupInfoTrace P2PWarningDevelopementNetworkProtocols = + p2pWarningDevelopmentNetworkProtocolsMessage + +ppStartupInfoTrace (WarningDevelopmentNetworkProtocols ntnVersions ntcVersions) = + "enabled development network protocols: " + <> showT ntnVersions + <> " " + <> showT ntcVersions + +ppStartupInfoTrace (BINetwork BasicInfoNetwork {..}) = + "Addresses " <> showT niAddresses + <> ", DiffusionMode " <> showT niDiffusionMode + <> ", DnsProducers " <> showT niDnsProducers + <> ", IpProducers " <> showT niIpProducers + +ppStartupInfoTrace (BIByron BasicInfoByron {..}) = + "Era Byron" + <> ", Slot length " <> showT bibSlotLength + <> ", Epoch length " <> showT bibEpochLength + +ppStartupInfoTrace (BIShelley BasicInfoShelleyBased {..}) = + "Era " <> bisEra + <> ", Slot length " <> showT bisSlotLength + <> ", Epoch length " <> showT bisEpochLength + <> ", Slots per KESPeriod " <> showT bisSlotsPerKESPeriod + +ppStartupInfoTrace (BICommon BasicInfoCommon {..}) = + "Config path " <> pack biConfigPath + <> ", Network magic " <> showT biNetworkMagic + <> ", Protocol " <> showT biProtocol + <> ", Version " <> showT biVersion + <> ", Commit " <> showT biCommit + <> ", Node start time " <> showT biNodeStartTime + +p2pWarningMessage :: Text +p2pWarningMessage = + "unsupported and unverified version of " + <> "`cardano-node` with peer-to-peer networking capabilities" + +p2pWarningDevelopmentNetworkProtocolsMessage :: Text +p2pWarningDevelopmentNetworkProtocolsMessage = + "peer-to-peer requires TestEnableDevelopmentNetworkProtocols to be set to True" + + +docStartupInfo :: Documented (StartupTrace blk) +docStartupInfo = Documented [ + DocMsg + (BICommon anyProto) + [] + "_biConfigPath_: is the path to the config in use. \ + \\n_biProtocol_: is the name of the protocol, e.g. \"Byron\", \"Shelley\" \ + \or \"Byron; Shelley\". \ + \\n_biVersion_: is the version of the node software running. \ + \\n_biCommit_: is the commit revision of the software running. \ + \\n_biNodeStartTime_: gives the time this node was started." + , DocMsg + (BIShelley anyProto) + [] + "bisEra is the current era, e.g. \"Shelley\", \"Allegra\", \"Mary\" \ + \or \"Alonzo\". \ + \\n_bisSystemStartTime_: TODO JNF \ + \\n_bisSlotLength_: gives the length of a slot as time interval. \ + \\n_bisEpochLength_: gives the number of slots which forms an epoch. \ + \\n_bisSlotsPerKESPeriod_: gives the slots per KES period." + , DocMsg + (BIByron anyProto) + [] + "_bibSystemStartTime_: TODO JNF \ + \\n_bibSlotLength_: gives the length of a slot as time interval. \ + \\n_bibEpochLength_: gives the number of slots which forms an epoch." + , DocMsg + (BINetwork anyProto) + [] + "_niAddresses_: IPv4 or IPv6 socket ready to accept connections\ + \or diffusion addresses. \ + \\n_niDiffusionMode_: shows if the node runs only initiator or both\ + \initiator or responder node. \ + \\n_niDnsProducers_: shows the list of domain names to subscribe to. \ + \\n_niIpProducers_: shows the list of ip subscription addresses." + ] + +-- +-- Utils +-- + +-- | Pretty print 'SocketOrSocketInfo'. +-- +ppSocketInfo :: Show sock + => (info -> String) + -> SocketOrSocketInfo sock info -> String +ppSocketInfo ppInfo (SocketInfo addr) = ppInfo addr +ppSocketInfo _ppInfo (ActualSocket sock) = show sock + +ppN2CSocketInfo :: SocketOrSocketInfo LocalSocket LocalAddress + -> String +ppN2CSocketInfo = ppSocketInfo getFilePath + +ppN2NSocketInfo :: SocketOrSocketInfo SockAddr SockAddr + -> String +ppN2NSocketInfo = ppSocketInfo show diff --git a/cardano-node/src/Cardano/Node/Types.hs b/cardano-node/src/Cardano/Node/Types.hs index 018cf214796..cbf91b44933 100644 --- a/cardano-node/src/Cardano/Node/Types.hs +++ b/cardano-node/src/Cardano/Node/Types.hs @@ -1,7 +1,7 @@ -{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralisedNewtypeDeriving #-} +{-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} @@ -16,26 +16,7 @@ module Cardano.Node.Types , GenesisHash(..) , MaxConcurrencyBulkSync(..) , MaxConcurrencyDeadline(..) - -- * Node addresses - , NodeAddress'(..) - , NodeIPAddress - , nodeAddressToSockAddr - , NodeIPv4Address - , NodeIPv6Address - , NodeDnsAddress - , nodeIPv4ToIPAddress - , nodeIPv6ToIPAddress - , nodeDnsAddressToDomainAddress - , NodeHostIPAddress (..) - , nodeHostIPAddressToSockAddr - , NodeHostIPv4Address (..) - , NodeHostIPv6Address (..) - , nodeHostIPv4AddressToIPAddress - , nodeHostIPv6AddressToIPAddress - , NodeHostDnsAddress (..) - , nodeHostDnsAddressToDomain - , PortNumber - , SocketPath(..) + -- * Networking , TopologyFile(..) , NodeDiffusionMode (..) -- * Consensus protocol configuration @@ -45,34 +26,30 @@ module Cardano.Node.Types , NodeShelleyProtocolConfiguration(..) , NodeAlonzoProtocolConfiguration(..) , VRFPrivateKeyFilePermissionError(..) - , protocolName , renderVRFPrivateKeyFilePermissionError ) where import Cardano.Prelude -import Prelude (String, fail) +import Prelude (fail) import Data.Aeson -import Data.IP (IP (..), IPv4, IPv6) -import qualified Data.IP as IP import qualified Data.Text as Text -import qualified Data.Text.Encoding as Text -import qualified Network.DNS as DNS (Domain) -import Network.Socket (PortNumber, SockAddr (..)) import Cardano.Api import qualified Cardano.Chain.Update as Byron import Cardano.Crypto (RequiresNetworkMagic (..)) import qualified Cardano.Crypto.Hash as Crypto -import Cardano.Node.Protocol.Types (Protocol (..)) -import Ouroboros.Network.PeerSelection.RootPeersDNS (DomainAccessPoint (..)) +import Cardano.Node.Configuration.NodeAddress +import Cardano.Node.Configuration.Socket (SocketConfig (..)) --TODO: things will probably be clearer if we don't use these newtype wrappers and instead -- use records with named fields in the CLI code. import Ouroboros.Network.NodeToNode (DiffusionMode (..)) -- | Errors for the cardano-config module. -newtype ConfigError = ConfigErrorFileNotFound FilePath +data ConfigError = + ConfigErrorFileNotFound FilePath + | ConfigErrorNoEKG deriving Show -- | Filepath of the configuration yaml file. This file determines @@ -107,123 +84,6 @@ newtype MaxConcurrencyDeadline = MaxConcurrencyDeadline deriving newtype (FromJSON, Show) --- | IPv4 or IPv6 address with a port number. -data NodeAddress' addr = NodeAddress - { naHostAddress :: !addr - , naPort :: !PortNumber - } deriving (Eq, Ord, Show, Functor) - -type NodeIPAddress = NodeAddress' NodeHostIPAddress -type NodeIPv4Address = NodeAddress' NodeHostIPv4Address -type NodeIPv6Address = NodeAddress' NodeHostIPv6Address -type NodeDnsAddress = NodeAddress' NodeHostDnsAddress - - -instance FromJSON addr => FromJSON (NodeAddress' addr) where - parseJSON = withObject "NodeAddress" $ \v -> do - NodeAddress - <$> v .: "addr" - <*> ((fromIntegral :: Int -> PortNumber) <$> v .: "port") - -instance ToJSON addr => ToJSON (NodeAddress' addr) where - toJSON na = - object - [ "addr" .= toJSON (naHostAddress na) - , "port" .= (fromIntegral (naPort na) :: Int) - ] - - -nodeIPv4ToIPAddress :: NodeIPv4Address -> NodeIPAddress -nodeIPv4ToIPAddress = fmap nodeHostIPv4AddressToIPAddress - -nodeIPv6ToIPAddress :: NodeIPv6Address -> NodeIPAddress -nodeIPv6ToIPAddress = fmap nodeHostIPv6AddressToIPAddress - -nodeDnsAddressToDomainAddress :: NodeDnsAddress -> DomainAccessPoint -nodeDnsAddressToDomainAddress NodeAddress { naHostAddress = NodeHostDnsAddress dns, naPort } - = DomainAccessPoint (Text.encodeUtf8 dns) naPort - -nodeAddressToSockAddr :: NodeIPAddress -> SockAddr -nodeAddressToSockAddr (NodeAddress addr port) = - case unNodeHostIPAddress addr of - IP.IPv4 ipv4 -> SockAddrInet port (IP.toHostAddress ipv4) - IP.IPv6 ipv6 -> SockAddrInet6 port 0 (IP.toHostAddress6 ipv6) 0 - -nodeHostIPAddressToSockAddr :: NodeIPAddress -> SockAddr -nodeHostIPAddressToSockAddr NodeAddress { naHostAddress = NodeHostIPAddress ip, naPort } = - case ip of - IPv4 ipv4 -> SockAddrInet (fromIntegral naPort) (IP.toHostAddress ipv4) - IPv6 ipv6 -> SockAddrInet6 (fromIntegral naPort) 0 (IP.toHostAddress6 ipv6) 0 - - -newtype NodeHostIPv4Address - = NodeHostIPv4Address { unNodeHostIPv4Address :: IPv4 } - deriving newtype Show - deriving (Eq, Ord) - -instance FromJSON NodeHostIPv4Address where - parseJSON (String ipStr) = - case readMaybe $ Text.unpack ipStr of - Just ip -> pure $ NodeHostIPv4Address ip - Nothing -> fail $ "Parsing of IPv4 failed: " <> Text.unpack ipStr - parseJSON invalid = fail $ "Parsing of IPv4 failed due to type mismatch. " - <> "Encountered: " <> show invalid <> "\n" - -instance ToJSON NodeHostIPv4Address where - toJSON (NodeHostIPv4Address ip) = String (Text.pack $ show ip) - - -newtype NodeHostIPv6Address - = NodeHostIPv6Address { unNodeHostIPv6Address :: IPv6 } - deriving newtype Show - deriving (Eq, Ord) - -instance FromJSON NodeHostIPv6Address where - parseJSON (String ipStr) = - case readMaybe $ Text.unpack ipStr of - Just ip -> pure $ NodeHostIPv6Address ip - Nothing -> fail $ "Parsing of IPv6 failed: " <> Text.unpack ipStr - parseJSON invalid = fail $ "Parsing of IPv6 failed due to type mismatch. " - <> "Encountered: " <> show invalid <> "\n" -instance ToJSON NodeHostIPv6Address where - toJSON (NodeHostIPv6Address ip) = String (Text.pack $ show ip) - - -newtype NodeHostIPAddress - = NodeHostIPAddress { unNodeHostIPAddress :: IP } - deriving newtype Show - deriving (Eq, Ord) - -instance FromJSON NodeHostIPAddress where - parseJSON (String ipStr) = - case readMaybe $ Text.unpack ipStr of - Just ip -> pure $ NodeHostIPAddress ip - Nothing -> fail $ "Parsing of IP failed: " <> Text.unpack ipStr - parseJSON invalid = fail $ "Parsing of IP failed due to type mismatch. " - <> "Encountered: " <> show invalid <> "\n" - -instance ToJSON NodeHostIPAddress where - toJSON (NodeHostIPAddress ip) = String (Text.pack $ show ip) - - -nodeHostIPv6AddressToIPAddress :: NodeHostIPv6Address -> NodeHostIPAddress -nodeHostIPv6AddressToIPAddress (NodeHostIPv6Address ip) = NodeHostIPAddress (IPv6 ip) - -nodeHostIPv4AddressToIPAddress :: NodeHostIPv4Address -> NodeHostIPAddress -nodeHostIPv4AddressToIPAddress (NodeHostIPv4Address ip) = NodeHostIPAddress (IPv4 ip) - - --- | Domain name. --- -newtype NodeHostDnsAddress - = NodeHostDnsAddress { unNodeHostDnsAddress :: Text } - deriving newtype Show - deriving (Eq, Ord) - -nodeHostDnsAddressToDomain :: NodeHostDnsAddress -> DNS.Domain -nodeHostDnsAddressToDomain = Text.encodeUtf8 . unNodeHostDnsAddress - - -- | Newtype wrapper which provides 'FromJSON' instance for 'DiffusionMode'. -- newtype NodeDiffusionMode @@ -282,17 +142,17 @@ data NodeAlonzoProtocolConfiguration = data NodeByronProtocolConfiguration = NodeByronProtocolConfiguration { - npcByronGenesisFile :: !GenesisFile - , npcByronGenesisFileHash :: !(Maybe GenesisHash) - , npcByronReqNetworkMagic :: !RequiresNetworkMagic - , npcByronPbftSignatureThresh :: !(Maybe Double) + npcByronGenesisFile :: !GenesisFile + , npcByronGenesisFileHash :: !(Maybe GenesisHash) + , npcByronReqNetworkMagic :: !RequiresNetworkMagic + , npcByronPbftSignatureThresh :: !(Maybe Double) --TODO: eliminate these two: it can be hard-coded -- | Update application name. - , npcByronApplicationName :: !Byron.ApplicationName + , npcByronApplicationName :: !Byron.ApplicationName -- | Application (ie software) version. - , npcByronApplicationVersion :: !Byron.NumSoftwareVersion + , npcByronApplicationVersion :: !Byron.NumSoftwareVersion --TODO: eliminate these: it can be done automatically in consensus -- | These declare the version of the protocol that the node is prepared @@ -336,7 +196,7 @@ data NodeHardForkProtocolConfiguration = -- Obviously if this is used, all the nodes in the test cluster must be -- configured the same, or they will disagree. -- - , npcTestShelleyHardForkAtEpoch :: Maybe EpochNo + , npcTestShelleyHardForkAtEpoch :: Maybe EpochNo -- | For testing purposes we support specifying that the hard fork -- happens at a given major protocol version. For example this can be @@ -347,7 +207,7 @@ data NodeHardForkProtocolConfiguration = -- Obviously if this is used, all the nodes in the test cluster must be -- configured the same, or they will disagree. -- - , npcTestShelleyHardForkAtVersion :: Maybe Word + , npcTestShelleyHardForkAtVersion :: Maybe Word -- | For testing purposes we support specifying that the hard fork -- happens at an exact epoch number (ie the first epoch of the new era). @@ -355,7 +215,7 @@ data NodeHardForkProtocolConfiguration = -- Obviously if this is used, all the nodes in the test cluster must be -- configured the same, or they will disagree. -- - , npcTestAllegraHardForkAtEpoch :: Maybe EpochNo + , npcTestAllegraHardForkAtEpoch :: Maybe EpochNo -- | For testing purposes we support specifying that the hard fork -- happens at a given major protocol version. @@ -363,7 +223,7 @@ data NodeHardForkProtocolConfiguration = -- Obviously if this is used, all the nodes in the test cluster must be -- configured the same, or they will disagree. -- - , npcTestAllegraHardForkAtVersion :: Maybe Word + , npcTestAllegraHardForkAtVersion :: Maybe Word -- | For testing purposes we support specifying that the hard fork -- happens at an exact epoch number (ie the first epoch of the new era). @@ -371,7 +231,7 @@ data NodeHardForkProtocolConfiguration = -- Obviously if this is used, all the nodes in the test cluster must be -- configured the same, or they will disagree. -- - , npcTestMaryHardForkAtEpoch :: Maybe EpochNo + , npcTestMaryHardForkAtEpoch :: Maybe EpochNo -- | For testing purposes we support specifying that the hard fork -- happens at a given major protocol version. @@ -380,7 +240,7 @@ data NodeHardForkProtocolConfiguration = -- configured the same, or they will disagree. -- -- - , npcTestMaryHardForkAtVersion :: Maybe Word + , npcTestMaryHardForkAtVersion :: Maybe Word -- | For testing purposes we support specifying that the hard fork -- happens at an exact epoch number (ie the first epoch of the new era). @@ -388,7 +248,7 @@ data NodeHardForkProtocolConfiguration = -- Obviously if this is used, all the nodes in the test cluster must be -- configured the same, or they will disagree. -- - , npcTestAlonzoHardForkAtEpoch :: Maybe EpochNo + , npcTestAlonzoHardForkAtEpoch :: Maybe EpochNo -- | For testing purposes we support specifying that the hard fork -- happens at a given major protocol version. @@ -396,15 +256,10 @@ data NodeHardForkProtocolConfiguration = -- Obviously if this is used, all the nodes in the test cluster must be -- configured the same, or they will disagree. -- - , npcTestAlonzoHardForkAtVersion :: Maybe Word + , npcTestAlonzoHardForkAtVersion :: Maybe Word } deriving (Eq, Show) -newtype SocketPath = SocketPath - { unSocketPath :: FilePath } - deriving stock (Eq, Ord) - deriving newtype (FromJSON, IsString, Show) - newtype TopologyFile = TopologyFile { unTopology :: FilePath } deriving newtype (Show, Eq) @@ -441,6 +296,10 @@ instance AdjustFilePaths NodeAlonzoProtocolConfiguration where } = x { npcAlonzoGenesisFile = adjustFilePaths f npcAlonzoGenesisFile } +instance AdjustFilePaths SocketConfig where + adjustFilePaths f x@SocketConfig{ncSocketPath} = + x { ncSocketPath = adjustFilePaths f ncSocketPath } + instance AdjustFilePaths SocketPath where adjustFilePaths f (SocketPath p) = SocketPath (f p) @@ -450,25 +309,8 @@ instance AdjustFilePaths GenesisFile where instance AdjustFilePaths a => AdjustFilePaths (Maybe a) where adjustFilePaths f = fmap (adjustFilePaths f) - -instance AdjustFilePaths (Last NodeProtocolConfiguration) where - - adjustFilePaths f (Last (Just npc)) = - Last . Just $ adjustFilePaths f npc - - adjustFilePaths _ (Last Nothing) = Last Nothing - -instance AdjustFilePaths (Last SocketPath) where - adjustFilePaths f (Last (Just (SocketPath p))) = Last . Just $ SocketPath (f p) - adjustFilePaths _ (Last Nothing) = Last Nothing - --- | A human readable name for the protocol --- -protocolName :: Protocol -> String -protocolName ByronProtocol = "Byron" -protocolName ShelleyProtocol = "Shelley" -protocolName CardanoProtocol = "Byron; Shelley" - +instance AdjustFilePaths a => AdjustFilePaths (Last a) where + adjustFilePaths f = fmap (adjustFilePaths f) data VRFPrivateKeyFilePermissionError = OtherPermissionsExist FilePath diff --git a/cardano-node/src/Cardano/Tracing/Config.hs b/cardano-node/src/Cardano/Tracing/Config.hs index 2f1afae32e0..dcf6a113e2e 100644 --- a/cardano-node/src/Cardano/Tracing/Config.hs +++ b/cardano-node/src/Cardano/Tracing/Config.hs @@ -4,7 +4,6 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} - module Cardano.Tracing.Config ( TraceOptions (..) , TraceSelection (..) @@ -24,13 +23,13 @@ import Data.Aeson.Types (Parser) import Data.Text (pack) import Cardano.BM.Tracing (TracingVerbosity (..)) - import Cardano.Node.Orphans () data TraceOptions = TracingOff - | TracingOn TraceSelection + | TracingOnLegacy TraceSelection + | TraceDispatcher TraceSelection deriving (Eq, Show) type TraceAcceptPolicy = ("TraceAcceptPolicy" :: Symbol) @@ -151,9 +150,8 @@ data TraceSelection } deriving (Eq, Show) -traceConfigParser :: Object -> Parser TraceOptions -traceConfigParser v = - -- TODO: By using 'TypeApplication' we can cut half of the lines below! +traceConfigParser :: Object -> (TraceSelection -> TraceOptions) -> Parser TraceOptions +traceConfigParser v ctor = let acceptPolicy :: OnOff TraceAcceptPolicy acceptPolicy = OnOff False blockFetchClient :: OnOff TraceBlockFetchClient @@ -255,7 +253,7 @@ traceConfigParser v = txSubmission2Protocol :: OnOff TraceTxSubmission2Protocol txSubmission2Protocol = OnOff False in - TracingOn <$> (TraceSelection + ctor <$> (TraceSelection <$> v .:? "TracingVerbosity" .!= NormalVerbosity -- Per-trace toggles, alpha-sorted. <*> v .:? getName acceptPolicy .!= acceptPolicy diff --git a/cardano-node/src/Cardano/Tracing/Kernel.hs b/cardano-node/src/Cardano/Tracing/Kernel.hs deleted file mode 100644 index ed0be8bc2aa..00000000000 --- a/cardano-node/src/Cardano/Tracing/Kernel.hs +++ /dev/null @@ -1,70 +0,0 @@ -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE NamedFieldPuns #-} -module Cardano.Tracing.Kernel - ( NodeKernelData (..) - , mkNodeKernelData - , setNodeKernel - , mapNodeKernelDataIO - , nkQueryLedger - , nkQueryChain - -- * Re-exports - , NodeKernel (..) - , LocalConnectionId - , RemoteConnectionId - , StrictMaybe(..) - , fromSMaybe - ) where - -import Cardano.Prelude - -import Cardano.Ledger.BaseTypes (StrictMaybe (..), fromSMaybe) - -import Data.IORef (IORef, newIORef, readIORef, writeIORef) - -import Ouroboros.Consensus.Block (Header) -import Ouroboros.Consensus.Ledger.Abstract (IsLedger, LedgerState) -import Ouroboros.Consensus.Ledger.Extended (ExtLedgerState) -import Ouroboros.Consensus.Node (NodeKernel (..)) -import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB -import Ouroboros.Consensus.Util.Orphans () - -import qualified Ouroboros.Network.AnchoredFragment as AF -import Ouroboros.Network.NodeToClient (LocalConnectionId) -import Ouroboros.Network.NodeToNode (RemoteConnectionId) - - -newtype NodeKernelData blk = - NodeKernelData - { unNodeKernelData :: IORef (StrictMaybe (NodeKernel IO RemoteConnectionId LocalConnectionId blk)) - } - -mkNodeKernelData :: IO (NodeKernelData blk) -mkNodeKernelData = NodeKernelData <$> newIORef SNothing - -setNodeKernel :: NodeKernelData blk - -> NodeKernel IO RemoteConnectionId LocalConnectionId blk - -> IO () -setNodeKernel (NodeKernelData ref) nodeKern = - writeIORef ref $ SJust nodeKern - -mapNodeKernelDataIO :: - (NodeKernel IO RemoteConnectionId LocalConnectionId blk -> IO a) - -> NodeKernelData blk - -> IO (StrictMaybe a) -mapNodeKernelDataIO f (NodeKernelData ref) = - readIORef ref >>= traverse f - -nkQueryLedger :: - IsLedger (LedgerState blk) - => (ExtLedgerState blk -> a) - -> NodeKernel IO RemoteConnectionId LocalConnectionId blk - -> IO a -nkQueryLedger f NodeKernel{getChainDB} = - f <$> atomically (ChainDB.getCurrentLedger getChainDB) - -nkQueryChain :: - (AF.AnchoredFragment (Header blk) -> a) - -> NodeKernel IO RemoteConnectionId LocalConnectionId blk - -> IO a -nkQueryChain f NodeKernel{getChainDB} = - f <$> atomically (ChainDB.getCurrentChain getChainDB) diff --git a/cardano-node/src/Cardano/Tracing/OrphanInstances/Common.hs b/cardano-node/src/Cardano/Tracing/OrphanInstances/Common.hs index c4a3f40cede..6165c3bdc29 100644 --- a/cardano-node/src/Cardano/Tracing/OrphanInstances/Common.hs +++ b/cardano-node/src/Cardano/Tracing/OrphanInstances/Common.hs @@ -58,7 +58,6 @@ import Cardano.BM.Stats import Cardano.BM.Tracing (HasPrivacyAnnotation (..), HasSeverityAnnotation (..), Severity (..), ToObject (..), Tracer (..), TracingVerbosity (..), Transformable (..)) -import qualified Cardano.Chain.Update as Update import Cardano.Slotting.Block (BlockNo (..)) import Ouroboros.Consensus.Byron.Ledger.Block (ByronHash (..)) import Ouroboros.Consensus.HardFork.Combinator (OneEraHash (..)) @@ -89,12 +88,6 @@ instance FromJSON PortNumber where parseJSON invalid = fail $ "Parsing of port number failed due to type mismatch. " <> "Encountered: " <> show invalid -instance FromJSON Update.ApplicationName where - parseJSON (String x) = pure $ Update.ApplicationName x - parseJSON invalid = - fail $ "Parsing of application name failed due to type mismatch. " - <> "Encountered: " <> show invalid - instance ToJSON (HeaderHash blk) => ToJSON (Tip blk) where toJSON TipGenesis = object [ "genesis" .= True ] toJSON (Tip slotNo headerHash blockNo) = @@ -122,4 +115,3 @@ instance ToObject ResourceStats where case toJSON stats of Object x -> x _ -> mempty - diff --git a/cardano-node/src/Cardano/Tracing/Peer.hs b/cardano-node/src/Cardano/Tracing/Peer.hs index 7d2ed54ae6c..0b1adad7704 100644 --- a/cardano-node/src/Cardano/Tracing/Peer.hs +++ b/cardano-node/src/Cardano/Tracing/Peer.hs @@ -37,7 +37,7 @@ import qualified Ouroboros.Network.BlockFetch.ClientRegistry as Net import Ouroboros.Network.BlockFetch.ClientState (PeerFetchInFlight (..), PeerFetchStatus (..), readFetchClientState) -import Cardano.Tracing.Kernel +import Cardano.Node.Queries data Peer blk = Peer diff --git a/cardano-node/src/Cardano/Tracing/Shutdown.hs b/cardano-node/src/Cardano/Tracing/Shutdown.hs new file mode 100644 index 00000000000..99dafdf8373 --- /dev/null +++ b/cardano-node/src/Cardano/Tracing/Shutdown.hs @@ -0,0 +1,31 @@ +{-# LANGUAGE MultiParamTypeClasses #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.Tracing.Shutdown where + +import Prelude (IO) +import Data.Text (Text) + +import Cardano.Logging (LogFormatting (..)) +import Cardano.Node.Handlers.Shutdown +import Cardano.Node.Tracing.Compat +import Cardano.Node.Tracing.Tracers.Shutdown +import Cardano.BM.Tracing (HasPrivacyAnnotation (..), + HasSeverityAnnotation (..), Severity (..), ToObject (..), + Transformable (..)) +import Cardano.BM.Data.Tracer (HasTextFormatter (..), + trStructuredText) + +instance HasPrivacyAnnotation ShutdownTrace +instance HasSeverityAnnotation ShutdownTrace where + getSeverityAnnotation _ = Warning + +instance Transformable Text IO ShutdownTrace where + trTransformer = trStructuredText + +instance HasTextFormatter ShutdownTrace where + formatText a _ = ppShutdownTrace a + +instance ToObject ShutdownTrace where + toObject verb = forMachine (toDetailLevel verb) diff --git a/cardano-node/src/Cardano/Tracing/Startup.hs b/cardano-node/src/Cardano/Tracing/Startup.hs index 6bb0a0fc0a7..cfdd8b7bbc3 100644 --- a/cardano-node/src/Cardano/Tracing/Startup.hs +++ b/cardano-node/src/Cardano/Tracing/Startup.hs @@ -1,98 +1,28 @@ -{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} +{-# OPTIONS_GHC -Wno-orphans #-} + module Cardano.Tracing.Startup where import Prelude - -import Data.Aeson (Value (..), (.=)) -import qualified Data.Aeson as Aeson -import Data.List (intercalate) -import Data.Map (Map) -import qualified Data.Map as Map import Data.Text (Text) -import qualified Data.Text as Text -import Data.Time.Clock (UTCTime) -import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds) -import Cardano.Slotting.Slot (SlotNo (..)) -import Cardano.Node.Configuration.TopologyP2P (UseLedger (..)) -import Cardano.Node.Configuration.Socket +import Cardano.Logging (LogFormatting (..)) +import Cardano.Node.Startup +import Cardano.Node.Tracing.Compat +import Cardano.Node.Tracing.Tracers.Startup import Cardano.Tracing.OrphanInstances.Network () import Cardano.BM.Tracing (HasPrivacyAnnotation (..), HasSeverityAnnotation (..), Severity (..), ToObject (..), - TracingVerbosity (..), Transformable (..)) -import Cardano.BM.Data.Tracer (HasTextFormatter (..), mkObject, + Transformable (..)) +import Cardano.BM.Data.Tracer (HasTextFormatter (..), trStructuredText) import Ouroboros.Consensus.Node.NetworkProtocolVersion (BlockNodeToClientVersion, BlockNodeToNodeVersion) -import Ouroboros.Network.Magic (NetworkMagic (..)) -import Ouroboros.Network.NodeToClient (LocalAddress (..), - LocalSocket, NodeToClientVersion) -import Ouroboros.Network.NodeToNode (DiffusionMode (..), - NodeToNodeVersion) -import Ouroboros.Network.PeerSelection.LedgerPeers (UseLedgerAfter (..)) -import Ouroboros.Network.PeerSelection.Types (PeerAdvertise) -import Ouroboros.Network.PeerSelection.RelayAccessPoint (RelayAccessPoint) - -import qualified Network.Socket as Socket - - -data StartupTrace blk = - -- | Log startup information. - -- - StartupInfo - [SocketOrSocketInfo Socket.SockAddr Socket.SockAddr] - -- ^ node-to-node addresses - (Maybe (SocketOrSocketInfo LocalSocket LocalAddress)) - -- ^ node-to-client socket path - (Map NodeToNodeVersion (BlockNodeToNodeVersion blk)) - -- ^ supported node-to-node versions - (Map NodeToClientVersion (BlockNodeToClientVersion blk)) - -- ^ supported node-to-client versions - - -- | Log peer-to-peer diffusion mode - | StartupP2PInfo DiffusionMode - - | StartupTime UTCTime - - | StartupNetworkMagic NetworkMagic - - | StartupSocketConfigError SocketConfigError - - | StartupDBValidation - - -- | Log that the network configuration is being updated. - -- - | NetworkConfigUpdate - - -- | Log network configuration update error. - -- - | NetworkConfigUpdateError Text - - -- | Log peer-to-peer network configuration, either on startup or when its - -- updated. - -- - | NetworkConfig [(Int, Map RelayAccessPoint PeerAdvertise)] - [RelayAccessPoint] - UseLedgerAfter - - -- | Warn when 'EnableP2P' is set. - | P2PWarning - - -- | Warn that peer-to-peer requires - -- 'TestEnableDevelopmentNetworkProtocols' to be set. - -- - | P2PWarningDevelopementNetworkProtocols - - -- | Warn when 'TestEnableDevelopmentNetworkProtocols' is set. - -- - | WarningDevelopmentNetworkProtocols [NodeToNodeVersion] [NodeToClientVersion] - instance HasSeverityAnnotation (StartupTrace blk) where getSeverityAnnotation (StartupSocketConfigError _) = Error @@ -101,187 +31,23 @@ instance HasSeverityAnnotation (StartupTrace blk) where getSeverityAnnotation P2PWarningDevelopementNetworkProtocols = Warning getSeverityAnnotation WarningDevelopmentNetworkProtocols {} = Warning getSeverityAnnotation _ = Info -instance HasPrivacyAnnotation (StartupTrace blk) where + +instance HasPrivacyAnnotation (StartupTrace blk) + instance ( Show (BlockNodeToNodeVersion blk) , Show (BlockNodeToClientVersion blk) ) - => Transformable Text IO (StartupTrace blk) where - trTransformer = trStructuredText + => Transformable Text IO (StartupTrace blk) where + trTransformer = trStructuredText + instance ( Show (BlockNodeToNodeVersion blk) , Show (BlockNodeToClientVersion blk) ) => HasTextFormatter (StartupTrace blk) where - formatText a _ = ppStartupInfoTrace a + formatText a _ = ppStartupInfoTrace a + instance ( Show (BlockNodeToNodeVersion blk) , Show (BlockNodeToClientVersion blk) ) => ToObject (StartupTrace blk) where - toObject verb (StartupInfo addresses - localSocket - supportedNodeToNodeVersions - supportedNodeToClientVersions) - = mkObject $ - [ "nodeAddresses" .= Aeson.toJSON (map ppN2NSocketInfo addresses) - , "localSocket" .= case localSocket of - Nothing -> Aeson.Null - Just a -> String (Text.pack . ppN2CSocketInfo $ a) - ] - ++ - case verb of - MaximalVerbosity -> - [ "nodeToNodeVersions" .= - Aeson.toJSON (map show . Map.assocs $ supportedNodeToNodeVersions) - , "nodeToClientVersions" .= - Aeson.toJSON (map show . Map.assocs $ supportedNodeToClientVersions) - ] - _ -> - [ "maxNodeToNodeVersion" .= - case Map.maxViewWithKey supportedNodeToNodeVersions of - Nothing -> String "no-supported-version" - Just (v, _) -> String (Text.pack . show $ v) - , "maxNodeToClientVersion" .= - case Map.maxViewWithKey supportedNodeToClientVersions of - Nothing -> String "no-supported-version" - Just (v, _) -> String (Text.pack . show $ v) - ] - toObject _verb (StartupP2PInfo diffusionMode) - = mkObject [ "diffusionMode" .= String (Text.pack . show $ diffusionMode) ] - toObject _verb (StartupTime time) = - mkObject [ "startupTime" .= String ( Text.pack - . show - . (ceiling :: POSIXTime -> Int) - . utcTimeToPOSIXSeconds - $ time - ) - ] - toObject _verb (StartupNetworkMagic networkMagic) = - mkObject [ "networkMagic" .= String ( Text.pack . show . unNetworkMagic - $ networkMagic) ] - toObject _verb (StartupSocketConfigError err) = - mkObject [ "error" .= String (Text.pack . show $ err) ] - toObject _verb StartupDBValidation = - mkObject [ "message" .= String "start db validation" ] - toObject _verb NetworkConfigUpdate = - mkObject [ "message" .= String "ntework configuration update" ] - toObject _verb (NetworkConfigUpdateError err) = - mkObject [ "error" .= String err ] - toObject _verb (NetworkConfig localRoots publicRoots useLedgerAfter) = - mkObject [ "localRoots" .= Aeson.toJSON localRoots - , "publicRoots" .= Aeson.toJSON publicRoots - , "useLedgerAfter" .= UseLedger useLedgerAfter - ] - toObject _verb P2PWarning = - mkObject [ "message" .= String p2pWarningMessage ] - toObject _verb P2PWarningDevelopementNetworkProtocols = - mkObject [ "message" .= String p2pWarningDevelopmentNetworkProtocolsMessage ] - toObject _ver (WarningDevelopmentNetworkProtocols ntnVersions ntcVersions) = - mkObject [ "message" .= String "enabled development network protocols" - , "nodeToNodeDevelopmentVersions" .= String (Text.pack . show $ ntnVersions) - , "nodeToClientDevelopmentVersions" .= String (Text.pack . show $ ntcVersions) - ] - - - --- | Pretty print 'StartupInfoTrace' --- -ppStartupInfoTrace :: ( Show (BlockNodeToNodeVersion blk) - , Show (BlockNodeToClientVersion blk) - ) - => StartupTrace blk - -> Text -ppStartupInfoTrace (StartupInfo addresses - localSocket - supportedNodeToNodeVersions - supportedNodeToClientVersions) - = Text.pack - $ "\n" ++ intercalate "\n" - [ "node addresses: " ++ intercalate ", " (map ppN2NSocketInfo addresses) - , "local socket: " ++ maybe "NONE" ppN2CSocketInfo localSocket - , "node-to-node versions:\n" - ++ intercalate "\n" - (map (\(v, bv) -> show v ++ "\t" ++ show bv) - . Map.assocs - $ supportedNodeToNodeVersions) - , "node-to-client versions:\n" - ++ intercalate "\n" - (map (\(v, bv) -> show v ++ "\t" ++ show bv) - . Map.assocs - $ supportedNodeToClientVersions) - ] - -ppStartupInfoTrace (StartupP2PInfo diffusionMode) = - case diffusionMode of - InitiatorAndResponderDiffusionMode -> "initiator and responder diffusion mode" - InitiatorOnlyDiffusionMode -> "initaitor only diffusion mode" - -ppStartupInfoTrace (StartupTime time) = - Text.pack $ "startup time: " - ++ ( show - . (ceiling :: POSIXTime -> Int) - . utcTimeToPOSIXSeconds - $ time - ) -ppStartupInfoTrace (StartupNetworkMagic networkMagic) = - "network magic: " <> Text.pack (show $ unNetworkMagic networkMagic) - -ppStartupInfoTrace (StartupSocketConfigError err) = - Text.pack $ renderSocketConfigError err - -ppStartupInfoTrace StartupDBValidation = "Performing DB validation" - -ppStartupInfoTrace NetworkConfigUpdate = "Performing topology configuration update" -ppStartupInfoTrace (NetworkConfigUpdateError err) = err -ppStartupInfoTrace (NetworkConfig localRoots publicRoots useLedgerAfter) = - Text.pack - $ intercalate "\n" - [ "\nLocal Root Groups:" - , " " ++ intercalate "\n " (map (\(x,y) -> show (x, Map.assocs y)) - localRoots) - , "Public Roots:" - , " " ++ intercalate "\n " (map show publicRoots) - , case useLedgerAfter of - UseLedgerAfter slotNo -> "Get root peers from the ledger after slot " - ++ show (unSlotNo slotNo) - DontUseLedger -> "Don't use ledger to get root peers." - ] - -ppStartupInfoTrace P2PWarning = p2pWarningMessage - -ppStartupInfoTrace P2PWarningDevelopementNetworkProtocols = - p2pWarningDevelopmentNetworkProtocolsMessage - -ppStartupInfoTrace (WarningDevelopmentNetworkProtocols ntnVersions ntcVersions) = - "enabled development network protocols: " - <> (Text.pack . show $ ntnVersions) - <> " " - <> (Text.pack . show $ ntcVersions) - - -p2pWarningMessage :: Text -p2pWarningMessage = - "unsupported and unverified version of " - <> "`cardano-node` with peer-to-peer networking capabilities" - -p2pWarningDevelopmentNetworkProtocolsMessage :: Text -p2pWarningDevelopmentNetworkProtocolsMessage = - "peer-to-peer requires TestEnableDevelopmentNetworkProtocols to be set to True" - --- --- Utils --- - --- | Pretty print 'SocketOrSocketInfo'. --- -ppSocketInfo :: Show sock - => (info -> String) - -> SocketOrSocketInfo sock info -> String -ppSocketInfo ppInfo (SocketInfo addr) = ppInfo addr -ppSocketInfo _ppInfo (ActualSocket sock) = show sock - -ppN2CSocketInfo :: SocketOrSocketInfo LocalSocket LocalAddress - -> String -ppN2CSocketInfo = ppSocketInfo getFilePath - -ppN2NSocketInfo :: SocketOrSocketInfo Socket.SockAddr Socket.SockAddr - -> String -ppN2NSocketInfo = ppSocketInfo show + toObject verb = forMachine (toDetailLevel verb) diff --git a/cardano-node/src/Cardano/Tracing/Tracers.hs b/cardano-node/src/Cardano/Tracing/Tracers.hs index 6fa88e5640a..d110dd5f947 100644 --- a/cardano-node/src/Cardano/Tracing/Tracers.hs +++ b/cardano-node/src/Cardano/Tracing/Tracers.hs @@ -9,6 +9,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PackageImports #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} @@ -44,7 +45,7 @@ import qualified System.Metrics.Gauge as Gauge import qualified System.Metrics.Label as Label import qualified System.Remote.Monitoring as EKG -import Control.Tracer +import "contra-tracer" Control.Tracer import Control.Tracer.Transformers import Cardano.Slotting.Slot (EpochNo (..), SlotNo (..), WithOrigin (..)) @@ -95,20 +96,22 @@ import Ouroboros.Network.ConnectionManager.Types (ConnectionManagerCou import qualified Ouroboros.Network.Diffusion as Diffusion import qualified Ouroboros.Network.Diffusion.NonP2P as NonP2P import qualified Ouroboros.Network.Diffusion.P2P as P2P -import Ouroboros.Network.NodeToClient (LocalAddress, NodeToClientVersion) -import Ouroboros.Network.NodeToNode (NodeToNodeVersion, RemoteAddress) +import Ouroboros.Network.NodeToClient (LocalAddress) +import Ouroboros.Network.NodeToNode (RemoteAddress) import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB import qualified Ouroboros.Consensus.Storage.LedgerDB.OnDisk as LedgerDB import qualified Ouroboros.Consensus.Storage.LedgerDB.Types as LedgerDB import Cardano.Tracing.Config -import Cardano.Tracing.Constraints (TraceConstraints) -import Cardano.Tracing.Kernel import Cardano.Tracing.Metrics -import Cardano.Tracing.Startup +import Cardano.Tracing.Startup () +import Cardano.Tracing.Shutdown () import Cardano.Node.Configuration.Logging +import Cardano.Node.TraceConstraints +import Cardano.Node.Tracing + -- For tracing instances import Cardano.Node.Protocol.Byron () import Cardano.Node.Protocol.Shelley () @@ -125,24 +128,6 @@ import Cardano.Protocol.TPraos.OCert (KESPeriod (..)) {- HLINT ignore "Redundant bracket" -} {- HLINT ignore "Use record patterns" -} -data Tracers peer localPeer blk p2p = Tracers - { -- | Trace the ChainDB - chainDBTracer :: Tracer IO (ChainDB.TraceEvent blk) - -- | Consensus-specific tracers. - , consensusTracers :: Consensus.Tracers IO peer localPeer blk - -- | Tracers for the node-to-node protocols. - , nodeToNodeTracers :: NodeToNode.Tracers IO peer blk DeserialiseFailure - --, serialisedBlockTracer :: NodeToNode.SerialisedTracer IO peer blk (SerialisedBlockTrace) - -- | Tracers for the node-to-client protocols - , nodeToClientTracers :: NodeToClient.Tracers IO localPeer blk DeserialiseFailure - -- | Diffusion tracers - , diffusionTracers :: Diffusion.Tracers RemoteAddress NodeToNodeVersion - LocalAddress NodeToClientVersion - IO - , diffusionTracersExtra :: Diffusion.ExtraTracers p2p - , startupTracer :: Tracer IO (StartupTrace blk) - } - data ForgeTracers = ForgeTracers { ftForged :: Trace IO Text , ftForgeAboutToLead :: Trace IO Text @@ -167,6 +152,10 @@ nullTracersP2P = Tracers , diffusionTracers = Diffusion.nullTracers , diffusionTracersExtra = Diffusion.P2PTracers P2P.nullTracers , startupTracer = nullTracer + , shutdownTracer = nullTracer + , nodeInfoTracer = nullTracer + , resourcesTracer = nullTracer + , peersTracer = nullTracer } nullTracersNonP2P :: Tracers peer localPeer blk Diffusion.NonP2P @@ -178,6 +167,10 @@ nullTracersNonP2P = Tracers , diffusionTracers = Diffusion.nullTracers , diffusionTracersExtra = Diffusion.NonP2PTracers NonP2P.nullTracers , startupTracer = nullTracer + , shutdownTracer = nullTracer + , nodeInfoTracer = nullTracer + , resourcesTracer = nullTracer + , peersTracer = nullTracer } indexGCType :: ChainDB.TraceGCEvent a -> Int @@ -297,8 +290,6 @@ instance (StandardHash header, Eq peer) => ElidingTracer mkTracers :: forall blk p2p. ( Consensus.RunNode blk - , HasKESMetricsData blk - , HasKESInfo blk , TraceConstraints blk ) => BlockConfig blk @@ -308,7 +299,7 @@ mkTracers -> Maybe EKGDirect -> NetworkP2PMode p2p -> IO (Tracers (ConnectionId RemoteAddress) (ConnectionId LocalAddress) blk p2p) -mkTracers blockConfig tOpts@(TracingOn trSel) tr nodeKern ekgDirect enableP2P = do +mkTracers blockConfig tOpts@(TracingOnLegacy trSel) tr nodeKern ekgDirect enableP2P = do fStats <- mkForgingStats consensusTracers <- mkConsensusTracers ekgDirect trSel verb tr nodeKern fStats elidedChainDB <- newstate -- for eliding messages in ChainDB tracer @@ -331,7 +322,12 @@ mkTracers blockConfig tOpts@(TracingOn trSel) tr nodeKern ekgDirect enableP2P = , diffusionTracersExtra = diffusionTracersExtra' enableP2P -- TODO: startupTracer should ignore severity level (i.e. it should always -- be printed)! - , startupTracer = toLogObject' verb $ appendName "nodeconfig" tr + , startupTracer = toLogObject' verb $ appendName "startup" tr + , shutdownTracer = toLogObject' verb $ appendName "shutdown" tr + -- The remaining tracers are completely unused by the legacy tracing: + , nodeInfoTracer = nullTracer + , resourcesTracer = nullTracer + , peersTracer = nullTracer } where diffusionTracers = Diffusion.Tracers @@ -427,7 +423,7 @@ mkTracers blockConfig tOpts@(TracingOn trSel) tr nodeKern ekgDirect enableP2P = tracerOnOff (traceDiffusionInitialization trSel) verb "DiffusionInitializationTracer" tr -mkTracers _ TracingOff _ _ _ enableP2P = +mkTracers _ _ _ _ _ enableP2P = pure Tracers { chainDBTracer = nullTracer , consensusTracers = Consensus.Tracers @@ -465,6 +461,10 @@ mkTracers _ TracingOff _ _ _ enableP2P = EnabledP2PMode -> Diffusion.P2PTracers P2P.nullTracers DisabledP2PMode -> Diffusion.NonP2PTracers NonP2P.nullTracers , startupTracer = nullTracer + , shutdownTracer = nullTracer + , nodeInfoTracer = nullTracer + , resourcesTracer = nullTracer + , peersTracer = nullTracer } -------------------------------------------------------------------------------- @@ -488,7 +488,8 @@ teeTraceChainTip -> Trace IO Text -> Tracer IO (WithSeverity (ChainDB.TraceEvent blk)) teeTraceChainTip _ _ TracingOff _ _ _ _ _ = nullTracer -teeTraceChainTip blockConfig fStats (TracingOn trSel) elided ekgDirect tFork trTrc trMet = +teeTraceChainTip _ _ TraceDispatcher{} _ _ _ _ _ = nullTracer +teeTraceChainTip blockConfig fStats (TracingOnLegacy trSel) elided ekgDirect tFork trTrc trMet = Tracer $ \ev -> do traceWith (teeTraceChainTipElide (traceVerbosity trSel) elided trTrc) ev traceWith (ignoringSeverity (traceChainMetrics ekgDirect tFork blockConfig fStats trMet)) ev diff --git a/cardano-node/test/Test/Cardano/Node/Gen.hs b/cardano-node/test/Test/Cardano/Node/Gen.hs index 3622cadddb2..2a7c2f1025e 100644 --- a/cardano-node/test/Test/Cardano/Node/Gen.hs +++ b/cardano-node/test/Test/Cardano/Node/Gen.hs @@ -21,7 +21,7 @@ import Cardano.Prelude import Cardano.Node.Configuration.TopologyP2P (NetworkTopology (..), PublicRootPeers (..), LocalRootPeersGroups (..), LocalRootPeersGroup (..), RootConfig (..), NodeSetup (..), PeerAdvertise (..), UseLedger (..)) -import Cardano.Node.Types (NodeAddress' (..), NodeHostIPAddress (..), +import Cardano.Node.Configuration.NodeAddress (NodeAddress' (..), NodeHostIPAddress (..), NodeHostIPv4Address (..), NodeHostIPv6Address (..), NodeIPAddress, NodeIPv4Address, NodeIPv6Address) import Cardano.Slotting.Slot (SlotNo (..)) @@ -54,7 +54,7 @@ genNodeAddress' genAddr = genNodeHostIPv4Address :: Gen NodeHostIPv4Address genNodeHostIPv4Address = - NodeHostIPv4Address . IP.toIPv4w <$> Gen.enumBounded + NodeHostIPv4Address . IP.toIPv4w <$> Gen.enumBounded genNodeHostIPv6Address :: Gen NodeHostIPv6Address genNodeHostIPv6Address = diff --git a/cardano-node/test/Test/Cardano/Node/POM.hs b/cardano-node/test/Test/Cardano/Node/POM.hs index b268b7e381c..6cf74354b4d 100644 --- a/cardano-node/test/Test/Cardano/Node/POM.hs +++ b/cardano-node/test/Test/Cardano/Node/POM.hs @@ -10,6 +10,8 @@ import Cardano.Prelude import Data.Time.Clock (secondsToDiffTime) import Cardano.Node.Configuration.POM +import Cardano.Node.Configuration.Socket +import Cardano.Node.Handlers.Shutdown import Cardano.Node.Types import Cardano.Tracing.Config (TraceOptions (..)) import qualified Ouroboros.Consensus.Node as Consensus (NetworkP2PMode (..)) @@ -48,7 +50,8 @@ testPartialYamlConfig = . NodeProtocolConfigurationShelley $ NodeShelleyProtocolConfiguration (GenesisFile "dummmy-genesis-file") Nothing - , pncSocketPath = Last Nothing + , pncSocketConfig = Last . Just $ SocketConfig (Last Nothing) mempty mempty mempty + , pncShutdownConfig = Last Nothing , pncDiffusionMode = Last Nothing , pncSnapshotInterval = mempty , pncTestEnableDevelopmentNetworkProtocols = Last Nothing @@ -57,16 +60,11 @@ testPartialYamlConfig = , pncLoggingSwitch = Last $ Just True , pncLogMetrics = Last $ Just True , pncTraceConfig = Last $ Just TracingOff - , pncNodeIPv4Addr = mempty - , pncNodeIPv6Addr = mempty - , pncNodePortNumber = mempty , pncConfigFile = mempty , pncTopologyFile = mempty , pncDatabaseFile = mempty , pncProtocolFiles = mempty , pncValidateDB = mempty - , pncShutdownIPC = mempty - , pncShutdownOnSlotSynced = mempty , pncMaybeMempoolCapacityOverride = mempty , pncProtocolIdleTimeout = mempty , pncTimeWaitTimeout = mempty @@ -83,20 +81,16 @@ testPartialYamlConfig = testPartialCliConfig :: PartialNodeConfiguration testPartialCliConfig = PartialNodeConfiguration - { pncNodeIPv4Addr = mempty - , pncNodeIPv6Addr = mempty - , pncNodePortNumber = mempty + { pncSocketConfig = Last . Just $ SocketConfig mempty mempty mempty mempty + , pncShutdownConfig = Last . Just $ ShutdownConfig Nothing (Just . MaxSlotNo $ SlotNo 42) , pncConfigFile = mempty , pncTopologyFile = mempty , pncDatabaseFile = mempty - , pncSocketPath = mempty , pncDiffusionMode = mempty , pncSnapshotInterval = Last . Just . RequestedSnapshotInterval $ secondsToDiffTime 100 , pncTestEnableDevelopmentNetworkProtocols = Last $ Just True , pncProtocolFiles = Last . Just $ ProtocolFilepaths Nothing Nothing Nothing Nothing Nothing Nothing , pncValidateDB = Last $ Just True - , pncShutdownIPC = Last Nothing - , pncShutdownOnSlotSynced = Last . Just . MaxSlotNo $ SlotNo 42 , pncProtocolConfig = mempty , pncMaxConcurrencyBulkSync = mempty , pncMaxConcurrencyDeadline = mempty @@ -118,20 +112,16 @@ testPartialCliConfig = expectedConfig :: NodeConfiguration expectedConfig = NodeConfiguration - { ncNodeIPv4Addr = Nothing - , ncNodeIPv6Addr = Nothing - , ncNodePortNumber = Nothing + { ncSocketConfig = SocketConfig mempty mempty mempty mempty + , ncShutdownConfig = ShutdownConfig Nothing (Just . MaxSlotNo $ SlotNo 42) , ncConfigFile = ConfigYamlFilePath "configuration/cardano/mainnet-config.json" , ncTopologyFile = TopologyFile "configuration/cardano/mainnet-topology.json" , ncDatabaseFile = DbFile "mainnet/db/" , ncProtocolFiles = ProtocolFilepaths Nothing Nothing Nothing Nothing Nothing Nothing , ncValidateDB = True - , ncShutdownIPC = Nothing - , ncShutdownOnSlotSynced = MaxSlotNo $ SlotNo 42 , ncProtocolConfig = NodeProtocolConfigurationShelley $ NodeShelleyProtocolConfiguration (GenesisFile "dummmy-genesis-file") Nothing - , ncSocketPath = Nothing , ncDiffusionMode = InitiatorAndResponderDiffusionMode , ncSnapshotInterval = RequestedSnapshotInterval $ secondsToDiffTime 100 , ncTestEnableDevelopmentNetworkProtocols = True diff --git a/configuration/cardano/mainnet-config-new-tracing.yaml b/configuration/cardano/mainnet-config-new-tracing.yaml new file mode 100644 index 00000000000..22c831ae9db --- /dev/null +++ b/configuration/cardano/mainnet-config-new-tracing.yaml @@ -0,0 +1,141 @@ +################################################################################ +# Mainnet Cardano Node Configuration + +##### Locations ##### + +AlonzoGenesisFile: mainnet-alonzo-genesis.json +AlonzoGenesisHash: 7e94a15f55d1e82d10f09203fa1d40f8eede58fd8066542cf6566008068ed874 +ByronGenesisFile: mainnet-byron-genesis.json +ByronGenesisHash: 5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb +ShelleyGenesisFile: mainnet-shelley-genesis.json +ShelleyGenesisHash: 1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81 + +##### Core protocol parameters ##### + +Protocol: Cardano + +# The mainnet does not include the network magic into addresses. Testnets do. +RequiresNetworkMagic: RequiresNoMagic + +##### Update system parameters ##### + +# This protocol version number gets used by block producing nodes as part +# of the system for agreeing on and synchronising protocol updates. +# +# See https://github.com/input-output-hk/cardano-node/blob/master/cardano-node/src/Cardano/Node/Protocol/Cardano.hs#L199 +LastKnownBlockVersion-Major: 3 +LastKnownBlockVersion-Minor: 0 +LastKnownBlockVersion-Alt: 0 +MaxKnownMajorProtocolVersion: 2 + +# In the Byron era some software versions are also published on the chain. +# We do this only for Byron compatibility now. +ApplicationName: cardano-sl +ApplicationVersion: 1 + +##### Logging configuration ##### + +# Enable or disable logging overall +TurnOnLogging: True + +##### New logging model ##### +# Options for new tracing + +# Use old tracing as standard for now +UseTraceDispatcher: True + + +TraceOptionSeverity: + # Show messages of Severity Notice or higher as default + - ns: "" + severity: Notice + + # But modify severity for the following namespaces + - ns: Node.ChainDB + severity: Info + + - ns: Node.AcceptPolicy + severity: Info + + - ns: Node.DNSResolver + severity: Info + + - ns: Node.DNSSubscription + severity: Info + + - ns: Node.DiffusionInit + severity: Info + + - ns: Node.ErrorPolicy + severity: Info + + - ns: Node.Forge + severity: Info + + - ns: Node.IpSubscription + severity: Info + + - ns: Node.LocalErrorPolicy + severity: Info + + - ns: Node.Mempool + severity: Info + + - ns: Node.Resources + severity: Info + +TraceOptionDetail: + # All messages are shown with normal detail level + - ns: "" + detail: DNormal + +TraceOptionBackend: + # Use these backends + - ns: "" + backends: + - Stdout MachineFormat + - EKGBackend + # - Forwarder + +# Limit the frequency of the following messages +TraceOptionLimiter: + - ns: Node.ChainDB.AddBlockEvent.AddedBlockToQueue + limiterName: AddedBlockToQueueLimiter + limiterFrequency: 2.0 + + - ns: Node.ChainDB.AddBlockEvent.AddedBlockToVolatileDB + limiterName: AddedBlockToVolatileDBLimiter + limiterFrequency: 2.0 + + - ns: Node.ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB + limiterName: CopiedBlockToImmutableDBLimiter + limiterFrequency: 2.0 + + - ns: Node.ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate + limiterName: ValidCandidateLimiter + limiterFrequency: 2.0 + + - ns: Node.BlockFetchClient.CompletedBlockFetch + limiterName: CompletedBlockFetchLimiter + limiterFrequency: 2.0 + +# Options for the trace forwarder +TraceOptionForwarder: + address: + filePath: /tmp/forwarder.sock + mode: Initiator + +TraceOptionPeerFreqency: 2000 + +TraceOptionResourceFreqency: 5000 + + +##### Stubs for legacy logging config ##### + +TurnOnLogMetrics: False +minSeverity: Critical +setupScribes: [] +setupBackends: [] +defaultScribes: [] +defaultBackends: [] +options: {} diff --git a/doc/New Tracing Quickstart.md b/doc/New Tracing Quickstart.md new file mode 100644 index 00000000000..5ec663dde98 --- /dev/null +++ b/doc/New Tracing Quickstart.md @@ -0,0 +1,148 @@ +# New Tracing Quickstart + +From now on old-tracing (based on iohk-monitoring-framework) exists +together with new-tracing (based on trace-dispatcher and cardano-tracer) for a while. + +In this transition time new-tracing can be tested and improved. Since we have several hundred trace messages +it is expected that you will find regressions and bugs in the port, please help to find +and fix them. + +In this transition time new tracing will for technical reason have a restricted functionality, +as e.g. the reconfiguration of a running node is not available. + +To switch to new tracing set the value `UseTraceDispatcher` to true. If you do this, the +config file needs to contain several values for the configuration of new-tracing, as we +describe next. + +### Configuration of new tracing + +1. Specify a filter for the severity of the messages you want to see, e.g.: + + ~~~yaml + TraceOptionSeverity: + # Show messages of Severity Notice or higher as default + - ns: "" + severity: Notice + + # But show ChainDB messages starting from Info + - ns: Node.ChainDB + severity: Info + ~~~ + + + So the namespaces are used for configuration values, which works + down to individual messages, and the more specialized value overwrites the more general. + + If you don't want to see any messages from tracers the new severity `Silence` + exists, which suppresses all messages. + + +2. Specify in which detail level, the messages get shown. + + ~~~yaml + TraceOptionDetail: + # All messages are shown with normal detail level + - ns: "" + detail: DNormal + ~~~ + + Other options would be DMinimal, DDetailed and DMaximum. This has only an effect on messages which support the representation in different ways. + +3. Specify limiters for the frequency of messages + + Eliding tracers are not supported in new-tracing, instead you can limit the + frequency in which messages get shown. + + ~~~yaml + TraceOptionLimiter: + # Only show a maximum of 2 of these messages per second + - ns: Node.ChainDB.AddBlockEvent.AddedBlockToQueue + limiterName: AddedBlockToQueueLimiter + limiterFrequency: 2.0 + ~~~ + + The activity of limiters will be written in the traces as well. + +4. Specify the backends the messages are routed to. + + ~~~yaml + TraceOptionBackend: + # Use these backends + - ns: "" + backends: + - Stdout MachineFormat + - EKGBackend + - Forwarder + ~~~ + + These are all the backends currently supported. With Stdout you have the + options MachineFormat or HumanFormat. If messages don't support representation + in HumanFormat they are shown in MachineFormat anyway. + + Forwarder means that messages are send to cardano-tracer + +Configuration can be written in JSON and YAML, we have shown the examples in YAML. + +### Configuration and use of cardano-tracer + +`cardano-tracer` is a part of the new tracing infrastructure. It is a separate service that accepts different messages from the node and handles them. +So it is assumed that if you want to use the new tracing infrastructure - you will use `cardano-tracer`. Please read its [documentation](https://github.com/input-output-hk/cardano-node/blob/master/cardano-tracer/docs/cardano-tracer.md) for more details. + +This example describes the simplest case, when the node and `cardano-tracer` on the same machine. + +First of all, add `TraceOptionForwarder` section in the node's configuration, this section specifies how the node should work with `cardano-tracer`: + +~~~yaml +TraceOptionForwarder: + address: + filePath: /tmp/forwarder.sock + mode: Initiator +~~~ + +Then build and run `cardano-tracer`: + +~~~shell +$ cabal build cardano-tracer && cabal install cardano-tracer --installdir=PATH_TO_DIR --overwrite-policy=always +$ cd PATH_TO_DIR +$ ./cardano-tracer --config PATH_TO_CONFIG +~~~ + +where `PATH_TO_CONFIG` is a path to tracer's configuration file. This is an example of such a configuration: + +~~~yaml +--- +network: + tag: AcceptAt + contents: "/tmp/forwarder.sock" +logging: +- logRoot: "/tmp/cardano-tracer-logs" + logMode: FileMode + logFormat: ForMachine +~~~ + +That's it. After you run the node, it will establish the connection with `cardano-tracer` and will start to forward messages to it. +As a result, you will find log files, in JSON format, in `/tmp/cardano-tracer-logs` directory. + +### Development during transition-time + +For developing tracers in the transition time we suggest: + +1. Don't use strictness annotations for trace types. Trace messages are either +discarded immediately (which happens frequently) or instantly converted to another format +but never stored. So strictness annotations make the code less efficient without any benefit. +As well it doesn't play well together with the required prototypes of messages in the +new framework. + +2. If you develop new tracers we suggest that you develop the new tracers first, +and then map to old tracers, as the new tracers will survive. You will find plenty of +examples in cardano-node under Cardano.Node.Tracing.Tracers. + +3. Contact the benchmarking team or node-logging channel for any questions and reviews. + +### Documentation of trace messages and further documentation + +[Trace messages with default config](https://github.com/input-output-hk/cardano-node/blob/master/doc/new-tracing/tracers_doc_generated.md) + +[Trace-dispatcher documentation](https://github.com/input-output-hk/cardano-node/blob/master/trace-dispatcher/doc/trace-dispatcher.md) + +[cardano-tracer documentation](https://github.com/input-output-hk/cardano-node/blob/master/cardano-tracer/docs/cardano-tracer.md) diff --git a/doc/new-tracing/tracers_doc_generated.md b/doc/new-tracing/tracers_doc_generated.md new file mode 100644 index 00000000000..6274c5b3254 --- /dev/null +++ b/doc/new-tracing/tracers_doc_generated.md @@ -0,0 +1,10168 @@ +# Cardano Trace Documentation# Table Of Contents +1.[Trace Messages] (#trace-messages) +1.1 [Cardano.Node.AcceptPolicy.ConectionRateLimiting] (#cardanonodeacceptpolicyconectionratelimiting) +1.2 [Cardano.Node.AcceptPolicy.ConnectionHardLimit] (#cardanonodeacceptpolicyconnectionhardlimit) +1.3 [Cardano.Node.BlockFetch.NodeToNode.Send.BatchDone] (#cardanonodeblockfetchnodetonodesendbatchdone) +1.4 [Cardano.Node.BlockFetch.NodeToNode.Send.Block] (#cardanonodeblockfetchnodetonodesendblock) +1.5 [Cardano.Node.BlockFetch.NodeToNode.Send.ClientDone] (#cardanonodeblockfetchnodetonodesendclientdone) +1.6 [Cardano.Node.BlockFetch.NodeToNode.Send.NoBlocks] (#cardanonodeblockfetchnodetonodesendnoblocks) +1.7 [Cardano.Node.BlockFetch.NodeToNode.Send.RequestRange] (#cardanonodeblockfetchnodetonodesendrequestrange) +1.8 [Cardano.Node.BlockFetch.NodeToNode.Send.StartBatch] (#cardanonodeblockfetchnodetonodesendstartbatch) +1.9 [Cardano.Node.BlockFetchClient.AcknowledgedFetchRequest] (#cardanonodeblockfetchclientacknowledgedfetchrequest) +1.10 [Cardano.Node.BlockFetchClient.AddedFetchRequest] (#cardanonodeblockfetchclientaddedfetchrequest) +1.11 [Cardano.Node.BlockFetchClient.ClientTerminating] (#cardanonodeblockfetchclientclientterminating) +1.12 [Cardano.Node.BlockFetchClient.CompletedFetchBatch] (#cardanonodeblockfetchclientcompletedfetchbatch) +1.13 [Cardano.Node.BlockFetchClient.RejectedFetchBatch] (#cardanonodeblockfetchclientrejectedfetchbatch) +1.14 [Cardano.Node.BlockFetchClient.StartedFetchBatch] (#cardanonodeblockfetchclientstartedfetchbatch) +1.15 [Cardano.Node.BlockFetchDecision] (#cardanonodeblockfetchdecision) +1.16 [Cardano.Node.BlockFetchSerialised.NodeToNode.Send.BatchDone] (#cardanonodeblockfetchserialisednodetonodesendbatchdone) +1.17 [Cardano.Node.BlockFetchSerialised.NodeToNode.Send.Block] (#cardanonodeblockfetchserialisednodetonodesendblock) +1.18 [Cardano.Node.BlockFetchSerialised.NodeToNode.Send.ClientDone] (#cardanonodeblockfetchserialisednodetonodesendclientdone) +1.19 [Cardano.Node.BlockFetchSerialised.NodeToNode.Send.NoBlocks] (#cardanonodeblockfetchserialisednodetonodesendnoblocks) +1.20 [Cardano.Node.BlockFetchSerialised.NodeToNode.Send.RequestRange] (#cardanonodeblockfetchserialisednodetonodesendrequestrange) +1.21 [Cardano.Node.BlockFetchSerialised.NodeToNode.Send.StartBatch] (#cardanonodeblockfetchserialisednodetonodesendstartbatch) +1.22 [Cardano.Node.BlockFetchServer.SendBlock] (#cardanonodeblockfetchserversendblock) +1.23 [Cardano.Node.BlockchainTime.CurrentSlotUnknown] (#cardanonodeblockchaintimecurrentslotunknown) +1.24 [Cardano.Node.BlockchainTime.StartTimeInTheFuture] (#cardanonodeblockchaintimestarttimeinthefuture) +1.25 [Cardano.Node.BlockchainTime.SystemClockMovedBack] (#cardanonodeblockchaintimesystemclockmovedback) +1.26 [Cardano.Node.ChainDB.AddBlockEvent.AddBlockValidation.CandidateContainsFutureBlocks] (#cardanonodechaindbaddblockeventaddblockvalidationcandidatecontainsfutureblocks) +1.27 [Cardano.Node.ChainDB.AddBlockEvent.AddBlockValidation.CandidateContainsFutureBlocksExceedingClockSkew] (#cardanonodechaindbaddblockeventaddblockvalidationcandidatecontainsfutureblocksexceedingclockskew) +1.28 [Cardano.Node.ChainDB.AddBlockEvent.AddBlockValidation.InvalidBlock] (#cardanonodechaindbaddblockeventaddblockvalidationinvalidblock) +1.29 [Cardano.Node.ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate] (#cardanonodechaindbaddblockeventaddblockvalidationvalidcandidate) +1.30 [Cardano.Node.ChainDB.AddBlockEvent.AddedBlockToQueue] (#cardanonodechaindbaddblockeventaddedblocktoqueue) +1.31 [Cardano.Node.ChainDB.AddBlockEvent.AddedBlockToVolatileDB] (#cardanonodechaindbaddblockeventaddedblocktovolatiledb) +1.32 [Cardano.Node.ChainDB.AddBlockEvent.AddedToCurrentChain] (#cardanonodechaindbaddblockeventaddedtocurrentchain) +1.33 [Cardano.Node.ChainDB.AddBlockEvent.BlockInTheFuture] (#cardanonodechaindbaddblockeventblockinthefuture) +1.34 [Cardano.Node.ChainDB.AddBlockEvent.ChainSelectionForFutureBlock] (#cardanonodechaindbaddblockeventchainselectionforfutureblock) +1.35 [Cardano.Node.ChainDB.AddBlockEvent.IgnoreBlockAlreadyInVolatileDB] (#cardanonodechaindbaddblockeventignoreblockalreadyinvolatiledb) +1.36 [Cardano.Node.ChainDB.AddBlockEvent.IgnoreBlockAlreadyInVolatileDB] (#cardanonodechaindbaddblockeventignoreblockalreadyinvolatiledb) +1.37 [Cardano.Node.ChainDB.AddBlockEvent.IgnoreBlockOlderThanK] (#cardanonodechaindbaddblockeventignoreblockolderthank) +1.38 [Cardano.Node.ChainDB.AddBlockEvent.StoreButDontChange] (#cardanonodechaindbaddblockeventstorebutdontchange) +1.39 [Cardano.Node.ChainDB.AddBlockEvent.SwitchedToAFork] (#cardanonodechaindbaddblockeventswitchedtoafork) +1.40 [Cardano.Node.ChainDB.AddBlockEvent.TryAddToCurrentChain] (#cardanonodechaindbaddblockeventtryaddtocurrentchain) +1.41 [Cardano.Node.ChainDB.AddBlockEvent.TrySwitchToAFork] (#cardanonodechaindbaddblockeventtryswitchtoafork) +1.42 [Cardano.Node.ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB] (#cardanonodechaindbcopytoimmutabledbeventcopiedblocktoimmutabledb) +1.43 [Cardano.Node.ChainDB.CopyToImmutableDBEvent.NoBlocksToCopyToImmutableDB] (#cardanonodechaindbcopytoimmutabledbeventnoblockstocopytoimmutabledb) +1.44 [Cardano.Node.ChainDB.FollowerEvent.FollowerNewImmIterator] (#cardanonodechaindbfollowereventfollowernewimmiterator) +1.45 [Cardano.Node.ChainDB.FollowerEvent.FollowerNoLongerInMem] (#cardanonodechaindbfollowereventfollowernolongerinmem) +1.46 [Cardano.Node.ChainDB.FollowerEvent.FollowerSwitchToMem] (#cardanonodechaindbfollowereventfollowerswitchtomem) +1.47 [Cardano.Node.ChainDB.FollowerEvent.NewFollower] (#cardanonodechaindbfollowereventnewfollower) +1.48 [Cardano.Node.ChainDB.GCEvent.PerformedGC] (#cardanonodechaindbgceventperformedgc) +1.49 [Cardano.Node.ChainDB.GCEvent.ScheduledGC] (#cardanonodechaindbgceventscheduledgc) +1.50 [Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.CurrentChunkHit] (#cardanonodechaindbimmdbeventcacheeventcurrentchunkhit) +1.51 [Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.PastChunkEvict] (#cardanonodechaindbimmdbeventcacheeventpastchunkevict) +1.52 [Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.PastChunkExpired] (#cardanonodechaindbimmdbeventcacheeventpastchunkexpired) +1.53 [Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.PastChunkHit] (#cardanonodechaindbimmdbeventcacheeventpastchunkhit) +1.54 [Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.PastChunkMiss] (#cardanonodechaindbimmdbeventcacheeventpastchunkmiss) +1.55 [Cardano.Node.ChainDB.ImmDbEvent.ChunkFileDoesntFit] (#cardanonodechaindbimmdbeventchunkfiledoesntfit) +1.56 [Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.InvalidChunkFile] (#cardanonodechaindbimmdbeventchunkvalidationinvalidchunkfile) +1.57 [Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.InvalidPrimaryIndex] (#cardanonodechaindbimmdbeventchunkvalidationinvalidprimaryindex) +1.58 [Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.InvalidSecondaryIndex] (#cardanonodechaindbimmdbeventchunkvalidationinvalidsecondaryindex) +1.59 [Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.MissingChunkFile] (#cardanonodechaindbimmdbeventchunkvalidationmissingchunkfile) +1.60 [Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.MissingPrimaryIndex] (#cardanonodechaindbimmdbeventchunkvalidationmissingprimaryindex) +1.61 [Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.MissingSecondaryIndex] (#cardanonodechaindbimmdbeventchunkvalidationmissingsecondaryindex) +1.62 [Cardano.Node.ChainDB.ImmDbEvent.DBAlreadyClosed] (#cardanonodechaindbimmdbeventdbalreadyclosed) +1.63 [Cardano.Node.ChainDB.ImmDbEvent.DBClosed] (#cardanonodechaindbimmdbeventdbclosed) +1.64 [Cardano.Node.ChainDB.ImmDbEvent.DeletingAfter] (#cardanonodechaindbimmdbeventdeletingafter) +1.65 [Cardano.Node.ChainDB.ImmDbEvent.Migrating] (#cardanonodechaindbimmdbeventmigrating) +1.66 [Cardano.Node.ChainDB.ImmDbEvent.NoValidLastLocation] (#cardanonodechaindbimmdbeventnovalidlastlocation) +1.67 [Cardano.Node.ChainDB.ImmDbEvent.ValidatedLastLocation] (#cardanonodechaindbimmdbeventvalidatedlastlocation) +1.68 [Cardano.Node.ChainDB.InitChainSelEvent.CandidateContainsFutureBlocks] (#cardanonodechaindbinitchainseleventcandidatecontainsfutureblocks) +1.69 [Cardano.Node.ChainDB.InitChainSelEvent.CandidateContainsFutureBlocksExceedingClockSkew] (#cardanonodechaindbinitchainseleventcandidatecontainsfutureblocksexceedingclockskew) +1.70 [Cardano.Node.ChainDB.InitChainSelEvent.InvalidBlock] (#cardanonodechaindbinitchainseleventinvalidblock) +1.71 [Cardano.Node.ChainDB.InitChainSelEvent.ValidCandidate] (#cardanonodechaindbinitchainseleventvalidcandidate) +1.72 [Cardano.Node.ChainDB.IteratorEvent.BlockGCedFromVolatileDB] (#cardanonodechaindbiteratoreventblockgcedfromvolatiledb) +1.73 [Cardano.Node.ChainDB.IteratorEvent.BlockMissingFromVolatileDB] (#cardanonodechaindbiteratoreventblockmissingfromvolatiledb) +1.74 [Cardano.Node.ChainDB.IteratorEvent.BlockWasCopiedToImmutableDB] (#cardanonodechaindbiteratoreventblockwascopiedtoimmutabledb) +1.75 [Cardano.Node.ChainDB.IteratorEvent.StreamFromBoth] (#cardanonodechaindbiteratoreventstreamfromboth) +1.76 [Cardano.Node.ChainDB.IteratorEvent.StreamFromImmutableDB] (#cardanonodechaindbiteratoreventstreamfromimmutabledb) +1.77 [Cardano.Node.ChainDB.IteratorEvent.StreamFromVolatileDB] (#cardanonodechaindbiteratoreventstreamfromvolatiledb) +1.78 [Cardano.Node.ChainDB.IteratorEvent.SwitchBackToVolatileDB] (#cardanonodechaindbiteratoreventswitchbacktovolatiledb) +1.79 [Cardano.Node.ChainDB.IteratorEvent.UnknownRangeRequested] (#cardanonodechaindbiteratoreventunknownrangerequested) +1.80 [Cardano.Node.ChainDB.LedgerEvent.DeletedSnapshot] (#cardanonodechaindbledgereventdeletedsnapshot) +1.81 [Cardano.Node.ChainDB.LedgerEvent.InvalidSnapshot] (#cardanonodechaindbledgereventinvalidsnapshot) +1.82 [Cardano.Node.ChainDB.LedgerEvent.ReplayFromGenesis] (#cardanonodechaindbledgereventreplayfromgenesis) +1.83 [Cardano.Node.ChainDB.LedgerEvent.ReplayFromSnapshot] (#cardanonodechaindbledgereventreplayfromsnapshot) +1.84 [Cardano.Node.ChainDB.LedgerEvent.ReplayedBlock] (#cardanonodechaindbledgereventreplayedblock) +1.85 [Cardano.Node.ChainDB.LedgerEvent.TookSnapshot] (#cardanonodechaindbledgereventtooksnapshot) +1.86 [Cardano.Node.ChainDB.OpenEvent.ClosedDB] (#cardanonodechaindbopeneventcloseddb) +1.87 [Cardano.Node.ChainDB.OpenEvent.OpenedDB] (#cardanonodechaindbopeneventopeneddb) +1.88 [Cardano.Node.ChainDB.OpenEvent.OpenedImmutableDB] (#cardanonodechaindbopeneventopenedimmutabledb) +1.89 [Cardano.Node.ChainDB.OpenEvent.OpenedLgrDB] (#cardanonodechaindbopeneventopenedlgrdb) +1.90 [Cardano.Node.ChainDB.OpenEvent.OpenedVolatileDB] (#cardanonodechaindbopeneventopenedvolatiledb) +1.91 [Cardano.Node.ChainDB.VolatileDbEvent.BlockAlreadyHere] (#cardanonodechaindbvolatiledbeventblockalreadyhere) +1.92 [Cardano.Node.ChainDB.VolatileDbEvent.DBAlreadyClosed] (#cardanonodechaindbvolatiledbeventdbalreadyclosed) +1.93 [Cardano.Node.ChainDB.VolatileDbEvent.InvalidFileNames] (#cardanonodechaindbvolatiledbeventinvalidfilenames) +1.94 [Cardano.Node.ChainDB.VolatileDbEvent.Truncate] (#cardanonodechaindbvolatiledbeventtruncate) +1.95 [Cardano.Node.ChainSyncClient.ChainSyncClientEvent.DownloadedHeader] (#cardanonodechainsyncclientchainsyncclientevent.downloadedheader) +1.96 [Cardano.Node.ChainSyncClient.ChainSyncClientEvent.Exception] (#cardanonodechainsyncclientchainsyncclientevent.exception) +1.97 [Cardano.Node.ChainSyncClient.ChainSyncClientEvent.FoundIntersection] (#cardanonodechainsyncclientchainsyncclientevent.foundintersection) +1.98 [Cardano.Node.ChainSyncClient.ChainSyncClientEvent.RolledBack] (#cardanonodechainsyncclientchainsyncclientevent.rolledback) +1.99 [Cardano.Node.ChainSyncClient.ChainSyncClientEvent.Termination] (#cardanonodechainsyncclientchainsyncclientevent.termination) +1.100 [Cardano.Node.ChainSyncClient.NodeToClient.Send.AwaitReply] (#cardanonodechainsyncclientnodetoclientsendawaitreply) +1.101 [Cardano.Node.ChainSyncClient.NodeToClient.Send.AwaitReply] (#cardanonodechainsyncclientnodetoclientsendawaitreply) +1.102 [Cardano.Node.ChainSyncClient.NodeToClient.Send.Done] (#cardanonodechainsyncclientnodetoclientsenddone) +1.103 [Cardano.Node.ChainSyncClient.NodeToClient.Send.FindIntersect] (#cardanonodechainsyncclientnodetoclientsendfindintersect) +1.104 [Cardano.Node.ChainSyncClient.NodeToClient.Send.IntersectFound] (#cardanonodechainsyncclientnodetoclientsendintersectfound) +1.105 [Cardano.Node.ChainSyncClient.NodeToClient.Send.IntersectNotFound] (#cardanonodechainsyncclientnodetoclientsendintersectnotfound) +1.106 [Cardano.Node.ChainSyncClient.NodeToClient.Send.RequestNext] (#cardanonodechainsyncclientnodetoclientsendrequestnext) +1.107 [Cardano.Node.ChainSyncClient.NodeToClient.Send.RollBackward] (#cardanonodechainsyncclientnodetoclientsendrollbackward) +1.108 [Cardano.Node.ChainSyncClient.NodeToClient.Send.RollForward] (#cardanonodechainsyncclientnodetoclientsendrollforward) +1.109 [Cardano.Node.ChainSyncNode.NodeToNode.Send.AwaitReply] (#cardanonodechainsyncnodenodetonodesendawaitreply) +1.110 [Cardano.Node.ChainSyncNode.NodeToNode.Send.AwaitReply] (#cardanonodechainsyncnodenodetonodesendawaitreply) +1.111 [Cardano.Node.ChainSyncNode.NodeToNode.Send.Done] (#cardanonodechainsyncnodenodetonodesenddone) +1.112 [Cardano.Node.ChainSyncNode.NodeToNode.Send.FindIntersect] (#cardanonodechainsyncnodenodetonodesendfindintersect) +1.113 [Cardano.Node.ChainSyncNode.NodeToNode.Send.IntersectFound] (#cardanonodechainsyncnodenodetonodesendintersectfound) +1.114 [Cardano.Node.ChainSyncNode.NodeToNode.Send.IntersectNotFound] (#cardanonodechainsyncnodenodetonodesendintersectnotfound) +1.115 [Cardano.Node.ChainSyncNode.NodeToNode.Send.RequestNext] (#cardanonodechainsyncnodenodetonodesendrequestnext) +1.116 [Cardano.Node.ChainSyncNode.NodeToNode.Send.RollBackward] (#cardanonodechainsyncnodenodetonodesendrollbackward) +1.117 [Cardano.Node.ChainSyncNode.NodeToNode.Send.RollForward] (#cardanonodechainsyncnodenodetonodesendrollforward) +1.118 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.AwaitReply] (#cardanonodechainsyncserialisednodetonodesendawaitreply) +1.119 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.AwaitReply] (#cardanonodechainsyncserialisednodetonodesendawaitreply) +1.120 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.Done] (#cardanonodechainsyncserialisednodetonodesenddone) +1.121 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.FindIntersect] (#cardanonodechainsyncserialisednodetonodesendfindintersect) +1.122 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.IntersectFound] (#cardanonodechainsyncserialisednodetonodesendintersectfound) +1.123 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.IntersectNotFound] (#cardanonodechainsyncserialisednodetonodesendintersectnotfound) +1.124 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.RequestNext] (#cardanonodechainsyncserialisednodetonodesendrequestnext) +1.125 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.RollBackward] (#cardanonodechainsyncserialisednodetonodesendrollbackward) +1.126 [Cardano.Node.ChainSyncSerialised.NodeToNode.Send.RollForward] (#cardanonodechainsyncserialisednodetonodesendrollforward) +1.127 [Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.RollBackward] (#cardanonodechainsyncserverblockchainsyncserverevent.rollbackward) +1.128 [Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.RollForward] (#cardanonodechainsyncserverblockchainsyncserverevent.rollforward) +1.129 [Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.ServerRead] (#cardanonodechainsyncserverblockchainsyncserverevent.serverread) +1.130 [Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.ServerReadBlocked] (#cardanonodechainsyncserverblockchainsyncserverevent.serverreadblocked) +1.131 [Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.RollBackward] (#cardanonodechainsyncserverheaderchainsyncserverevent.rollbackward) +1.132 [Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.RollForward] (#cardanonodechainsyncserverheaderchainsyncserverevent.rollforward) +1.133 [Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.ServerRead] (#cardanonodechainsyncserverheaderchainsyncserverevent.serverread) +1.134 [Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.ServerReadBlocked] (#cardanonodechainsyncserverheaderchainsyncserverevent.serverreadblocked) +1.135 [Cardano.Node.ConnectionManager.Connect] (#cardanonodeconnectionmanagerconnect) +1.136 [Cardano.Node.ConnectionManager.ConnectError] (#cardanonodeconnectionmanagerconnecterror) +1.137 [Cardano.Node.ConnectionManager.ConnectionCleanup] (#cardanonodeconnectionmanagerconnectioncleanup) +1.138 [Cardano.Node.ConnectionManager.ConnectionExists] (#cardanonodeconnectionmanagerconnectionexists) +1.139 [Cardano.Node.ConnectionManager.ConnectionFailure] (#cardanonodeconnectionmanagerconnectionfailure) +1.140 [Cardano.Node.ConnectionManager.ConnectionHandler] (#cardanonodeconnectionmanagerconnectionhandler) +1.141 [Cardano.Node.ConnectionManager.ConnectionManagerCounters] (#cardanonodeconnectionmanagerconnectionmanagercounters) +1.142 [Cardano.Node.ConnectionManager.ConnectionNotFound] (#cardanonodeconnectionmanagerconnectionnotfound) +1.143 [Cardano.Node.ConnectionManager.ConnectionTimeWait] (#cardanonodeconnectionmanagerconnectiontimewait) +1.144 [Cardano.Node.ConnectionManager.ConnectionTimeWaitDone] (#cardanonodeconnectionmanagerconnectiontimewaitdone) +1.145 [Cardano.Node.ConnectionManager.ForbiddenConnection] (#cardanonodeconnectionmanagerforbiddenconnection) +1.146 [Cardano.Node.ConnectionManager.ForbiddenOperation] (#cardanonodeconnectionmanagerforbiddenoperation) +1.147 [Cardano.Node.ConnectionManager.ImpossibleConnection] (#cardanonodeconnectionmanagerimpossibleconnection) +1.148 [Cardano.Node.ConnectionManager.IncludeConnection] (#cardanonodeconnectionmanagerincludeconnection) +1.149 [Cardano.Node.ConnectionManager.PruneConnections] (#cardanonodeconnectionmanagerpruneconnections) +1.150 [Cardano.Node.ConnectionManager.Shutdown] (#cardanonodeconnectionmanagershutdown) +1.151 [Cardano.Node.ConnectionManager.State] (#cardanonodeconnectionmanagerstate) +1.152 [Cardano.Node.ConnectionManager.TerminatedConnection] (#cardanonodeconnectionmanagerterminatedconnection) +1.153 [Cardano.Node.ConnectionManager.TerminatingConnection] (#cardanonodeconnectionmanagerterminatingconnection) +1.154 [Cardano.Node.ConnectionManager.UnexpectedlyFalseAssertion] (#cardanonodeconnectionmanagerunexpectedlyfalseassertion) +1.155 [Cardano.Node.ConnectionManager.UnregisterConnection] (#cardanonodeconnectionmanagerunregisterconnection) +1.156 [Cardano.Node.DNSResolver.LookupAAAAError] (#cardanonodednsresolverlookupaaaaerror) +1.157 [Cardano.Node.DNSResolver.LookupAAAAResult] (#cardanonodednsresolverlookupaaaaresult) +1.158 [Cardano.Node.DNSResolver.LookupAError] (#cardanonodednsresolverlookupaerror) +1.159 [Cardano.Node.DNSResolver.LookupAResult] (#cardanonodednsresolverlookuparesult) +1.160 [Cardano.Node.DNSResolver.LookupException] (#cardanonodednsresolverlookupexception) +1.161 [Cardano.Node.DNSResolver.LookupIPv4First] (#cardanonodednsresolverlookupipv4first) +1.162 [Cardano.Node.DNSResolver.LookupIPv6First] (#cardanonodednsresolverlookupipv6first) +1.163 [Cardano.Node.DNSResolver.LookupIPv6First] (#cardanonodednsresolverlookupipv6first) +1.164 [Cardano.Node.DNSSubscription.DNS.AllocateSocket] (#cardanonodednssubscriptiondnsallocatesocket) +1.165 [Cardano.Node.DNSSubscription.DNS.ApplicationException] (#cardanonodednssubscriptiondnsapplicationexception) +1.166 [Cardano.Node.DNSSubscription.DNS.CloseSocket] (#cardanonodednssubscriptiondnsclosesocket) +1.167 [Cardano.Node.DNSSubscription.DNS.ConnectEnd] (#cardanonodednssubscriptiondnsconnectend) +1.168 [Cardano.Node.DNSSubscription.DNS.ConnectException] (#cardanonodednssubscriptiondnsconnectexception) +1.169 [Cardano.Node.DNSSubscription.DNS.ConnectStart] (#cardanonodednssubscriptiondnsconnectstart) +1.170 [Cardano.Node.DNSSubscription.DNS.ConnectionExist] (#cardanonodednssubscriptiondnsconnectionexist) +1.171 [Cardano.Node.DNSSubscription.DNS.MissingLocalAddress] (#cardanonodednssubscriptiondnsmissinglocaladdress) +1.172 [Cardano.Node.DNSSubscription.DNS.Restart] (#cardanonodednssubscriptiondnsrestart) +1.173 [Cardano.Node.DNSSubscription.DNS.SkippingPeer] (#cardanonodednssubscriptiondnsskippingpeer) +1.174 [Cardano.Node.DNSSubscription.DNS.SocketAllocationException] (#cardanonodednssubscriptiondnssocketallocationexception) +1.175 [Cardano.Node.DNSSubscription.DNS.Start] (#cardanonodednssubscriptiondnsstart) +1.176 [Cardano.Node.DNSSubscription.DNS.SubscriptionFailed] (#cardanonodednssubscriptiondnssubscriptionfailed) +1.177 [Cardano.Node.DNSSubscription.DNS.SubscriptionRunning] (#cardanonodednssubscriptiondnssubscriptionrunning) +1.178 [Cardano.Node.DNSSubscription.DNS.SubscriptionWaiting] (#cardanonodednssubscriptiondnssubscriptionwaiting) +1.179 [Cardano.Node.DNSSubscription.DNS.SubscriptionWaitingNewConnection] (#cardanonodednssubscriptiondnssubscriptionwaitingnewconnection) +1.180 [Cardano.Node.DNSSubscription.DNS.TryConnectToPeer] (#cardanonodednssubscriptiondnstryconnecttopeer) +1.181 [Cardano.Node.DNSSubscription.DNS.UnsupportedRemoteAddr] (#cardanonodednssubscriptiondnsunsupportedremoteaddr) +1.182 [Cardano.Node.DebugPeerSelection.GovernorState] (#cardanonodedebugpeerselectiongovernorstate) +1.183 [Cardano.Node.DebugPeerSelectionResponder.GovernorState] (#cardanonodedebugpeerselectionrespondergovernorstate) +1.184 [Cardano.Node.DiffusionInit.ConfiguringLocalSocket] (#cardanonodediffusioninitconfiguringlocalsocket) +1.185 [Cardano.Node.DiffusionInit.ConfiguringServerSocket] (#cardanonodediffusioninitconfiguringserversocket) +1.186 [Cardano.Node.DiffusionInit.CreateSystemdSocketForSnocketPath] (#cardanonodediffusioninitcreatesystemdsocketforsnocketpath) +1.187 [Cardano.Node.DiffusionInit.CreatedLocalSocket] (#cardanonodediffusioninitcreatedlocalsocket) +1.188 [Cardano.Node.DiffusionInit.CreatingServerSocket] (#cardanonodediffusioninitcreatingserversocket) +1.189 [Cardano.Node.DiffusionInit.DiffusionErrored] (#cardanonodediffusioninitdiffusionerrored) +1.190 [Cardano.Node.DiffusionInit.ListeningLocalSocket] (#cardanonodediffusioninitlisteninglocalsocket) +1.191 [Cardano.Node.DiffusionInit.ListeningServerSocket] (#cardanonodediffusioninitlisteningserversocket) +1.192 [Cardano.Node.DiffusionInit.LocalSocketUp] (#cardanonodediffusioninitlocalsocketup) +1.193 [Cardano.Node.DiffusionInit.RunLocalServer] (#cardanonodediffusioninitrunlocalserver) +1.194 [Cardano.Node.DiffusionInit.RunServer] (#cardanonodediffusioninitrunserver) +1.195 [Cardano.Node.DiffusionInit.ServerSocketUp] (#cardanonodediffusioninitserversocketup) +1.196 [Cardano.Node.DiffusionInit.UnsupportedLocalSystemdSocket] (#cardanonodediffusioninitunsupportedlocalsystemdsocket) +1.197 [Cardano.Node.DiffusionInit.UnsupportedReadySocketCase] (#cardanonodediffusioninitunsupportedreadysocketcase) +1.198 [Cardano.Node.DiffusionInit.UsingSystemdSocket] (#cardanonodediffusioninitusingsystemdsocket) +1.199 [Cardano.Node.ErrorPolicy.AcceptException] (#cardanonodeerrorpolicyacceptexception) +1.200 [Cardano.Node.ErrorPolicy.KeepSuspended] (#cardanonodeerrorpolicykeepsuspended) +1.201 [Cardano.Node.ErrorPolicy.LocalNodeError] (#cardanonodeerrorpolicylocalnodeerror) +1.202 [Cardano.Node.ErrorPolicy.ResumeConsumer] (#cardanonodeerrorpolicyresumeconsumer) +1.203 [Cardano.Node.ErrorPolicy.ResumePeer] (#cardanonodeerrorpolicyresumepeer) +1.204 [Cardano.Node.ErrorPolicy.ResumeProducer] (#cardanonodeerrorpolicyresumeproducer) +1.205 [Cardano.Node.ErrorPolicy.SuspendConsumer] (#cardanonodeerrorpolicysuspendconsumer) +1.206 [Cardano.Node.ErrorPolicy.SuspendPeer] (#cardanonodeerrorpolicysuspendpeer) +1.207 [Cardano.Node.ErrorPolicy.UnhandledApplicationException] (#cardanonodeerrorpolicyunhandledapplicationexception) +1.208 [Cardano.Node.ErrorPolicy.UnhandledConnectionException] (#cardanonodeerrorpolicyunhandledconnectionexception) +1.209 [Cardano.Node.Forge.AdoptedBlock] (#cardanonodeforgeadoptedblock) +1.210 [Cardano.Node.Forge.BlockContext] (#cardanonodeforgeblockcontext) +1.211 [Cardano.Node.Forge.BlockFromFuture] (#cardanonodeforgeblockfromfuture) +1.212 [Cardano.Node.Forge.DidntAdoptBlock] (#cardanonodeforgedidntadoptblock) +1.213 [Cardano.Node.Forge.ForgeStateUpdateError] (#cardanonodeforgeforgestateupdateerror) +1.214 [Cardano.Node.Forge.ForgedBlock] (#cardanonodeforgeforgedblock) +1.215 [Cardano.Node.Forge.ForgedInvalidBlock] (#cardanonodeforgeforgedinvalidblock) +1.216 [Cardano.Node.Forge.LedgerState] (#cardanonodeforgeledgerstate) +1.217 [Cardano.Node.Forge.LedgerView] (#cardanonodeforgeledgerview) +1.218 [Cardano.Node.Forge.NoLedgerState] (#cardanonodeforgenoledgerstate) +1.219 [Cardano.Node.Forge.NoLedgerView] (#cardanonodeforgenoledgerview) +1.220 [Cardano.Node.Forge.NodeCannotForge] (#cardanonodeforgenodecannotforge) +1.221 [Cardano.Node.Forge.NodeIsLeader] (#cardanonodeforgenodeisleader) +1.222 [Cardano.Node.Forge.NodeNotLeader] (#cardanonodeforgenodenotleader) +1.223 [Cardano.Node.Forge.SlotIsImmutable] (#cardanonodeforgeslotisimmutable) +1.224 [Cardano.Node.Forge.StartLeadershipCheck] (#cardanonodeforgestartleadershipcheck) +1.225 [Cardano.Node.Forge.StartLeadershipCheckPlus] (#cardanonodeforgestartleadershipcheckplus) +1.226 [Cardano.Node.ForgeStateInfo] (#cardanonodeforgestateinfo) +1.227 [Cardano.Node.Handshake.AcceptVersion] (#cardanonodehandshakeacceptversion) +1.228 [Cardano.Node.Handshake.ProposeVersions] (#cardanonodehandshakeproposeversions) +1.229 [Cardano.Node.Handshake.Refuse] (#cardanonodehandshakerefuse) +1.230 [Cardano.Node.InboundGovernor.DemotedToColdRemote] (#cardanonodeinboundgovernordemotedtocoldremote) +1.231 [Cardano.Node.InboundGovernor.DemotedToWarmRemote] (#cardanonodeinboundgovernordemotedtowarmremote) +1.232 [Cardano.Node.InboundGovernor.InboundGovernorCounters] (#cardanonodeinboundgovernorinboundgovernorcounters) +1.233 [Cardano.Node.InboundGovernor.MuxCleanExit] (#cardanonodeinboundgovernormuxcleanexit) +1.234 [Cardano.Node.InboundGovernor.MuxErrored] (#cardanonodeinboundgovernormuxerrored) +1.235 [Cardano.Node.InboundGovernor.NewConnection] (#cardanonodeinboundgovernornewconnection) +1.236 [Cardano.Node.InboundGovernor.PromotedToHotRemote] (#cardanonodeinboundgovernorpromotedtohotremote) +1.237 [Cardano.Node.InboundGovernor.PromotedToWarmRemote] (#cardanonodeinboundgovernorpromotedtowarmremote) +1.238 [Cardano.Node.InboundGovernor.RemoteState] (#cardanonodeinboundgovernorremotestate) +1.239 [Cardano.Node.InboundGovernor.ResponderErrored] (#cardanonodeinboundgovernorrespondererrored) +1.240 [Cardano.Node.InboundGovernor.ResponderRestarted] (#cardanonodeinboundgovernorresponderrestarted) +1.241 [Cardano.Node.InboundGovernor.ResponderStartFailure] (#cardanonodeinboundgovernorresponderstartfailure) +1.242 [Cardano.Node.InboundGovernor.ResponderStarted] (#cardanonodeinboundgovernorresponderstarted) +1.243 [Cardano.Node.InboundGovernor.ResponderTerminated] (#cardanonodeinboundgovernorresponderterminated) +1.244 [Cardano.Node.InboundGovernor.WaitIdleRemote] (#cardanonodeinboundgovernorwaitidleremote) +1.245 [Cardano.Node.IpSubscription.IP.AllocateSocket] (#cardanonodeipsubscriptionipallocatesocket) +1.246 [Cardano.Node.IpSubscription.IP.ApplicationException] (#cardanonodeipsubscriptionipapplicationexception) +1.247 [Cardano.Node.IpSubscription.IP.CloseSocket] (#cardanonodeipsubscriptionipclosesocket) +1.248 [Cardano.Node.IpSubscription.IP.ConnectEnd] (#cardanonodeipsubscriptionipconnectend) +1.249 [Cardano.Node.IpSubscription.IP.ConnectException] (#cardanonodeipsubscriptionipconnectexception) +1.250 [Cardano.Node.IpSubscription.IP.ConnectStart] (#cardanonodeipsubscriptionipconnectstart) +1.251 [Cardano.Node.IpSubscription.IP.ConnectionExist] (#cardanonodeipsubscriptionipconnectionexist) +1.252 [Cardano.Node.IpSubscription.IP.MissingLocalAddress] (#cardanonodeipsubscriptionipmissinglocaladdress) +1.253 [Cardano.Node.IpSubscription.IP.Restart] (#cardanonodeipsubscriptioniprestart) +1.254 [Cardano.Node.IpSubscription.IP.SkippingPeer] (#cardanonodeipsubscriptionipskippingpeer) +1.255 [Cardano.Node.IpSubscription.IP.SocketAllocationException] (#cardanonodeipsubscriptionipsocketallocationexception) +1.256 [Cardano.Node.IpSubscription.IP.Start] (#cardanonodeipsubscriptionipstart) +1.257 [Cardano.Node.IpSubscription.IP.SubscriptionFailed] (#cardanonodeipsubscriptionipsubscriptionfailed) +1.258 [Cardano.Node.IpSubscription.IP.SubscriptionRunning] (#cardanonodeipsubscriptionipsubscriptionrunning) +1.259 [Cardano.Node.IpSubscription.IP.SubscriptionWaiting] (#cardanonodeipsubscriptionipsubscriptionwaiting) +1.260 [Cardano.Node.IpSubscription.IP.SubscriptionWaitingNewConnection] (#cardanonodeipsubscriptionipsubscriptionwaitingnewconnection) +1.261 [Cardano.Node.IpSubscription.IP.TryConnectToPeer] (#cardanonodeipsubscriptioniptryconnecttopeer) +1.262 [Cardano.Node.IpSubscription.IP.UnsupportedRemoteAddr] (#cardanonodeipsubscriptionipunsupportedremoteaddr) +1.263 [Cardano.Node.KeepAliveClient.KeepAliveClient] (#cardanonodekeepaliveclientkeepaliveclient) +1.264 [Cardano.Node.LedgerPeers.DisabledLedgerPeers] (#cardanonodeledgerpeersdisabledledgerpeers) +1.265 [Cardano.Node.LedgerPeers.DisabledLedgerPeers] (#cardanonodeledgerpeersdisabledledgerpeers) +1.266 [Cardano.Node.LedgerPeers.FallingBackToBootstrapPeers] (#cardanonodeledgerpeersfallingbacktobootstrappeers) +1.267 [Cardano.Node.LedgerPeers.FetchingNewLedgerState] (#cardanonodeledgerpeersfetchingnewledgerstate) +1.268 [Cardano.Node.LedgerPeers.PickedPeer] (#cardanonodeledgerpeerspickedpeer) +1.269 [Cardano.Node.LedgerPeers.PickedPeers] (#cardanonodeledgerpeerspickedpeers) +1.270 [Cardano.Node.LedgerPeers.ReusingLedgerState] (#cardanonodeledgerpeersreusingledgerstate) +1.271 [Cardano.Node.LedgerPeers.TraceUseLedgerAfter] (#cardanonodeledgerpeerstraceuseledgerafter) +1.272 [Cardano.Node.LedgerPeers.WaitingOnRequest] (#cardanonodeledgerpeerswaitingonrequest) +1.273 [Cardano.Node.LedgerPeers.WaitingOnRequest] (#cardanonodeledgerpeerswaitingonrequest) +1.274 [Cardano.Node.LocalConnectionManager.Connect] (#cardanonodelocalconnectionmanagerconnect) +1.275 [Cardano.Node.LocalConnectionManager.ConnectError] (#cardanonodelocalconnectionmanagerconnecterror) +1.276 [Cardano.Node.LocalConnectionManager.ConnectionCleanup] (#cardanonodelocalconnectionmanagerconnectioncleanup) +1.277 [Cardano.Node.LocalConnectionManager.ConnectionExists] (#cardanonodelocalconnectionmanagerconnectionexists) +1.278 [Cardano.Node.LocalConnectionManager.ConnectionFailure] (#cardanonodelocalconnectionmanagerconnectionfailure) +1.279 [Cardano.Node.LocalConnectionManager.ConnectionHandler] (#cardanonodelocalconnectionmanagerconnectionhandler) +1.280 [Cardano.Node.LocalConnectionManager.ConnectionManagerCounters] (#cardanonodelocalconnectionmanagerconnectionmanagercounters) +1.281 [Cardano.Node.LocalConnectionManager.ConnectionNotFound] (#cardanonodelocalconnectionmanagerconnectionnotfound) +1.282 [Cardano.Node.LocalConnectionManager.ConnectionTimeWait] (#cardanonodelocalconnectionmanagerconnectiontimewait) +1.283 [Cardano.Node.LocalConnectionManager.ConnectionTimeWaitDone] (#cardanonodelocalconnectionmanagerconnectiontimewaitdone) +1.284 [Cardano.Node.LocalConnectionManager.ForbiddenConnection] (#cardanonodelocalconnectionmanagerforbiddenconnection) +1.285 [Cardano.Node.LocalConnectionManager.ForbiddenOperation] (#cardanonodelocalconnectionmanagerforbiddenoperation) +1.286 [Cardano.Node.LocalConnectionManager.ImpossibleConnection] (#cardanonodelocalconnectionmanagerimpossibleconnection) +1.287 [Cardano.Node.LocalConnectionManager.IncludeConnection] (#cardanonodelocalconnectionmanagerincludeconnection) +1.288 [Cardano.Node.LocalConnectionManager.PruneConnections] (#cardanonodelocalconnectionmanagerpruneconnections) +1.289 [Cardano.Node.LocalConnectionManager.Shutdown] (#cardanonodelocalconnectionmanagershutdown) +1.290 [Cardano.Node.LocalConnectionManager.State] (#cardanonodelocalconnectionmanagerstate) +1.291 [Cardano.Node.LocalConnectionManager.TerminatedConnection] (#cardanonodelocalconnectionmanagerterminatedconnection) +1.292 [Cardano.Node.LocalConnectionManager.TerminatingConnection] (#cardanonodelocalconnectionmanagerterminatingconnection) +1.293 [Cardano.Node.LocalConnectionManager.UnexpectedlyFalseAssertion] (#cardanonodelocalconnectionmanagerunexpectedlyfalseassertion) +1.294 [Cardano.Node.LocalConnectionManager.UnregisterConnection] (#cardanonodelocalconnectionmanagerunregisterconnection) +1.295 [Cardano.Node.LocalErrorPolicy.AcceptException] (#cardanonodelocalerrorpolicyacceptexception) +1.296 [Cardano.Node.LocalErrorPolicy.KeepSuspended] (#cardanonodelocalerrorpolicykeepsuspended) +1.297 [Cardano.Node.LocalErrorPolicy.LocalNodeError] (#cardanonodelocalerrorpolicylocalnodeerror) +1.298 [Cardano.Node.LocalErrorPolicy.ResumeConsumer] (#cardanonodelocalerrorpolicyresumeconsumer) +1.299 [Cardano.Node.LocalErrorPolicy.ResumePeer] (#cardanonodelocalerrorpolicyresumepeer) +1.300 [Cardano.Node.LocalErrorPolicy.ResumeProducer] (#cardanonodelocalerrorpolicyresumeproducer) +1.301 [Cardano.Node.LocalErrorPolicy.SuspendConsumer] (#cardanonodelocalerrorpolicysuspendconsumer) +1.302 [Cardano.Node.LocalErrorPolicy.SuspendPeer] (#cardanonodelocalerrorpolicysuspendpeer) +1.303 [Cardano.Node.LocalErrorPolicy.UnhandledApplicationException] (#cardanonodelocalerrorpolicyunhandledapplicationexception) +1.304 [Cardano.Node.LocalErrorPolicy.UnhandledConnectionException] (#cardanonodelocalerrorpolicyunhandledconnectionexception) +1.305 [Cardano.Node.LocalHandshake.AcceptVersion] (#cardanonodelocalhandshakeacceptversion) +1.306 [Cardano.Node.LocalHandshake.ProposeVersions] (#cardanonodelocalhandshakeproposeversions) +1.307 [Cardano.Node.LocalHandshake.Refuse] (#cardanonodelocalhandshakerefuse) +1.308 [Cardano.Node.LocalInboundGovernor.DemotedToColdRemote] (#cardanonodelocalinboundgovernordemotedtocoldremote) +1.309 [Cardano.Node.LocalInboundGovernor.DemotedToWarmRemote] (#cardanonodelocalinboundgovernordemotedtowarmremote) +1.310 [Cardano.Node.LocalInboundGovernor.InboundGovernorCounters] (#cardanonodelocalinboundgovernorinboundgovernorcounters) +1.311 [Cardano.Node.LocalInboundGovernor.MuxCleanExit] (#cardanonodelocalinboundgovernormuxcleanexit) +1.312 [Cardano.Node.LocalInboundGovernor.MuxErrored] (#cardanonodelocalinboundgovernormuxerrored) +1.313 [Cardano.Node.LocalInboundGovernor.NewConnection] (#cardanonodelocalinboundgovernornewconnection) +1.314 [Cardano.Node.LocalInboundGovernor.PromotedToHotRemote] (#cardanonodelocalinboundgovernorpromotedtohotremote) +1.315 [Cardano.Node.LocalInboundGovernor.PromotedToWarmRemote] (#cardanonodelocalinboundgovernorpromotedtowarmremote) +1.316 [Cardano.Node.LocalInboundGovernor.RemoteState] (#cardanonodelocalinboundgovernorremotestate) +1.317 [Cardano.Node.LocalInboundGovernor.ResponderErrored] (#cardanonodelocalinboundgovernorrespondererrored) +1.318 [Cardano.Node.LocalInboundGovernor.ResponderRestarted] (#cardanonodelocalinboundgovernorresponderrestarted) +1.319 [Cardano.Node.LocalInboundGovernor.ResponderStartFailure] (#cardanonodelocalinboundgovernorresponderstartfailure) +1.320 [Cardano.Node.LocalInboundGovernor.ResponderStarted] (#cardanonodelocalinboundgovernorresponderstarted) +1.321 [Cardano.Node.LocalInboundGovernor.ResponderTerminated] (#cardanonodelocalinboundgovernorresponderterminated) +1.322 [Cardano.Node.LocalInboundGovernor.WaitIdleRemote] (#cardanonodelocalinboundgovernorwaitidleremote) +1.323 [Cardano.Node.LocalRootPeers.LocalRootDomains] (#cardanonodelocalrootpeerslocalrootdomains) +1.324 [Cardano.Node.LocalRootPeers.LocalRootError] (#cardanonodelocalrootpeerslocalrooterror) +1.325 [Cardano.Node.LocalRootPeers.LocalRootFailure] (#cardanonodelocalrootpeerslocalrootfailure) +1.326 [Cardano.Node.LocalRootPeers.LocalRootGroups] (#cardanonodelocalrootpeerslocalrootgroups) +1.327 [Cardano.Node.LocalRootPeers.LocalRootResult] (#cardanonodelocalrootpeerslocalrootresult) +1.328 [Cardano.Node.LocalRootPeers.LocalRootWaiting] (#cardanonodelocalrootpeerslocalrootwaiting) +1.329 [Cardano.Node.LocalServer.AcceptConnection] (#cardanonodelocalserveracceptconnection) +1.330 [Cardano.Node.LocalServer.AcceptError] (#cardanonodelocalserveraccepterror) +1.331 [Cardano.Node.LocalServer.AcceptPolicy] (#cardanonodelocalserveracceptpolicy) +1.332 [Cardano.Node.LocalServer.Error] (#cardanonodelocalservererror) +1.333 [Cardano.Node.LocalServer.Started] (#cardanonodelocalserverstarted) +1.334 [Cardano.Node.LocalServer.Stopped] (#cardanonodelocalserverstopped) +1.335 [Cardano.Node.LocalTxSubmissionServer.ReceivedTx] (#cardanonodelocaltxsubmissionserverreceivedtx) +1.336 [Cardano.Node.Mempool.AddedTx] (#cardanonodemempooladdedtx) +1.337 [Cardano.Node.Mempool.ManuallyRemovedTxs] (#cardanonodemempoolmanuallyremovedtxs) +1.338 [Cardano.Node.Mempool.RejectedTx] (#cardanonodemempoolrejectedtx) +1.339 [Cardano.Node.Mempool.RemoveTxs] (#cardanonodemempoolremovetxs) +1.340 [Cardano.Node.Mux.ChannelRecvEnd] (#cardanonodemuxchannelrecvend) +1.341 [Cardano.Node.Mux.ChannelRecvStart] (#cardanonodemuxchannelrecvstart) +1.342 [Cardano.Node.Mux.ChannelSendEnd] (#cardanonodemuxchannelsendend) +1.343 [Cardano.Node.Mux.ChannelSendStart] (#cardanonodemuxchannelsendstart) +1.344 [Cardano.Node.Mux.CleanExit] (#cardanonodemuxcleanexit) +1.345 [Cardano.Node.Mux.ExceptionExit] (#cardanonodemuxexceptionexit) +1.346 [Cardano.Node.Mux.HandshakeClientEnd] (#cardanonodemuxhandshakeclientend) +1.347 [Cardano.Node.Mux.HandshakeClientError] (#cardanonodemuxhandshakeclienterror) +1.348 [Cardano.Node.Mux.HandshakeServerError] (#cardanonodemuxhandshakeservererror) +1.349 [Cardano.Node.Mux.HandshakeStart ] (#cardanonodemuxhandshakestart ) +1.350 [Cardano.Node.Mux.RecvDeltaQObservation] (#cardanonodemuxrecvdeltaqobservation) +1.351 [Cardano.Node.Mux.RecvDeltaQSample] (#cardanonodemuxrecvdeltaqsample) +1.352 [Cardano.Node.Mux.RecvEnd] (#cardanonodemuxrecvend) +1.353 [Cardano.Node.Mux.RecvHeaderEnd] (#cardanonodemuxrecvheaderend) +1.354 [Cardano.Node.Mux.RecvHeaderStart] (#cardanonodemuxrecvheaderstart) +1.355 [Cardano.Node.Mux.RecvStart] (#cardanonodemuxrecvstart) +1.356 [Cardano.Node.Mux.SDUReadTimeoutException] (#cardanonodemuxsdureadtimeoutexception) +1.357 [Cardano.Node.Mux.SDUWriteTimeoutException] (#cardanonodemuxsduwritetimeoutexception) +1.358 [Cardano.Node.Mux.SendEnd] (#cardanonodemuxsendend) +1.359 [Cardano.Node.Mux.SendStart] (#cardanonodemuxsendstart) +1.360 [Cardano.Node.Mux.Shutdown] (#cardanonodemuxshutdown) +1.361 [Cardano.Node.Mux.StartEagerly] (#cardanonodemuxstarteagerly) +1.362 [Cardano.Node.Mux.StartOnDemand] (#cardanonodemuxstartondemand) +1.363 [Cardano.Node.Mux.StartedOnDemand] (#cardanonodemuxstartedondemand) +1.364 [Cardano.Node.Mux.State] (#cardanonodemuxstate) +1.365 [Cardano.Node.Mux.Terminating] (#cardanonodemuxterminating) +1.366 [Cardano.Node.MuxLocal.ChannelRecvEnd] (#cardanonodemuxlocalchannelrecvend) +1.367 [Cardano.Node.MuxLocal.ChannelRecvStart] (#cardanonodemuxlocalchannelrecvstart) +1.368 [Cardano.Node.MuxLocal.ChannelSendEnd] (#cardanonodemuxlocalchannelsendend) +1.369 [Cardano.Node.MuxLocal.ChannelSendStart] (#cardanonodemuxlocalchannelsendstart) +1.370 [Cardano.Node.MuxLocal.CleanExit] (#cardanonodemuxlocalcleanexit) +1.371 [Cardano.Node.MuxLocal.ExceptionExit] (#cardanonodemuxlocalexceptionexit) +1.372 [Cardano.Node.MuxLocal.HandshakeClientEnd] (#cardanonodemuxlocalhandshakeclientend) +1.373 [Cardano.Node.MuxLocal.HandshakeClientError] (#cardanonodemuxlocalhandshakeclienterror) +1.374 [Cardano.Node.MuxLocal.HandshakeServerError] (#cardanonodemuxlocalhandshakeservererror) +1.375 [Cardano.Node.MuxLocal.HandshakeStart ] (#cardanonodemuxlocalhandshakestart ) +1.376 [Cardano.Node.MuxLocal.RecvDeltaQObservation] (#cardanonodemuxlocalrecvdeltaqobservation) +1.377 [Cardano.Node.MuxLocal.RecvDeltaQSample] (#cardanonodemuxlocalrecvdeltaqsample) +1.378 [Cardano.Node.MuxLocal.RecvEnd] (#cardanonodemuxlocalrecvend) +1.379 [Cardano.Node.MuxLocal.RecvHeaderEnd] (#cardanonodemuxlocalrecvheaderend) +1.380 [Cardano.Node.MuxLocal.RecvHeaderStart] (#cardanonodemuxlocalrecvheaderstart) +1.381 [Cardano.Node.MuxLocal.RecvStart] (#cardanonodemuxlocalrecvstart) +1.382 [Cardano.Node.MuxLocal.SDUReadTimeoutException] (#cardanonodemuxlocalsdureadtimeoutexception) +1.383 [Cardano.Node.MuxLocal.SDUWriteTimeoutException] (#cardanonodemuxlocalsduwritetimeoutexception) +1.384 [Cardano.Node.MuxLocal.SendEnd] (#cardanonodemuxlocalsendend) +1.385 [Cardano.Node.MuxLocal.SendStart] (#cardanonodemuxlocalsendstart) +1.386 [Cardano.Node.MuxLocal.Shutdown] (#cardanonodemuxlocalshutdown) +1.387 [Cardano.Node.MuxLocal.StartEagerly] (#cardanonodemuxlocalstarteagerly) +1.388 [Cardano.Node.MuxLocal.StartOnDemand] (#cardanonodemuxlocalstartondemand) +1.389 [Cardano.Node.MuxLocal.StartedOnDemand] (#cardanonodemuxlocalstartedondemand) +1.390 [Cardano.Node.MuxLocal.State] (#cardanonodemuxlocalstate) +1.391 [Cardano.Node.MuxLocal.Terminating] (#cardanonodemuxlocalterminating) +1.392 [Cardano.Node.PeerSelection.ChurnMode] (#cardanonodepeerselectionchurnmode) +1.393 [Cardano.Node.PeerSelection.ChurnWait] (#cardanonodepeerselectionchurnwait) +1.394 [Cardano.Node.PeerSelection.DemoteAsynchronous] (#cardanonodepeerselectiondemoteasynchronous) +1.395 [Cardano.Node.PeerSelection.DemoteHotDone] (#cardanonodepeerselectiondemotehotdone) +1.396 [Cardano.Node.PeerSelection.DemoteHotFailed] (#cardanonodepeerselectiondemotehotfailed) +1.397 [Cardano.Node.PeerSelection.DemoteHotFailed] (#cardanonodepeerselectiondemotehotfailed) +1.398 [Cardano.Node.PeerSelection.DemoteHotPeers] (#cardanonodepeerselectiondemotehotpeers) +1.399 [Cardano.Node.PeerSelection.DemoteLocalHotPeers] (#cardanonodepeerselectiondemotelocalhotpeers) +1.400 [Cardano.Node.PeerSelection.DemoteWarmDone] (#cardanonodepeerselectiondemotewarmdone) +1.401 [Cardano.Node.PeerSelection.DemoteWarmFailed] (#cardanonodepeerselectiondemotewarmfailed) +1.402 [Cardano.Node.PeerSelection.DemoteWarmPeers] (#cardanonodepeerselectiondemotewarmpeers) +1.403 [Cardano.Node.PeerSelection.ForgetColdPeers] (#cardanonodepeerselectionforgetcoldpeers) +1.404 [Cardano.Node.PeerSelection.GossipRequests] (#cardanonodepeerselectiongossiprequests) +1.405 [Cardano.Node.PeerSelection.GossipResults] (#cardanonodepeerselectiongossipresults) +1.406 [Cardano.Node.PeerSelection.GovernorWakeup] (#cardanonodepeerselectiongovernorwakeup) +1.407 [Cardano.Node.PeerSelection.LocalRootPeersChanged] (#cardanonodepeerselectionlocalrootpeerschanged) +1.408 [Cardano.Node.PeerSelection.PromoteColdDone] (#cardanonodepeerselectionpromotecolddone) +1.409 [Cardano.Node.PeerSelection.PromoteColdFailed] (#cardanonodepeerselectionpromotecoldfailed) +1.410 [Cardano.Node.PeerSelection.PromoteColdLocalPeers] (#cardanonodepeerselectionpromotecoldlocalpeers) +1.411 [Cardano.Node.PeerSelection.PromoteColdPeers] (#cardanonodepeerselectionpromotecoldpeers) +1.412 [Cardano.Node.PeerSelection.PromoteWarmDone] (#cardanonodepeerselectionpromotewarmdone) +1.413 [Cardano.Node.PeerSelection.PromoteWarmFailed] (#cardanonodepeerselectionpromotewarmfailed) +1.414 [Cardano.Node.PeerSelection.PromoteWarmLocalPeers] (#cardanonodepeerselectionpromotewarmlocalpeers) +1.415 [Cardano.Node.PeerSelection.PromoteWarmPeers] (#cardanonodepeerselectionpromotewarmpeers) +1.416 [Cardano.Node.PeerSelection.PublicRootsResults] (#cardanonodepeerselectionpublicrootsresults) +1.417 [Cardano.Node.PeerSelection.PublicRootsResults] (#cardanonodepeerselectionpublicrootsresults) +1.418 [Cardano.Node.PeerSelection.TargetsChanged] (#cardanonodepeerselectiontargetschanged) +1.419 [Cardano.Node.PeerSelection.ublicRootsRequest] (#cardanonodepeerselectionublicrootsrequest) +1.420 [Cardano.Node.PeerSelectionActions.MonitoringError] (#cardanonodepeerselectionactionsmonitoringerror) +1.421 [Cardano.Node.PeerSelectionActions.MonitoringResult] (#cardanonodepeerselectionactionsmonitoringresult) +1.422 [Cardano.Node.PeerSelectionActions.StatusChangeFailure] (#cardanonodepeerselectionactionsstatuschangefailure) +1.423 [Cardano.Node.PeerSelectionActions.StatusChanged] (#cardanonodepeerselectionactionsstatuschanged) +1.424 [Cardano.Node.PeerSelectionCounters] (#cardanonodepeerselectioncounters) +1.425 [Cardano.Node.Peers] (#cardanonodepeers) +1.426 [Cardano.Node.PublicRootPeers.PublicRootDomains] (#cardanonodepublicrootpeerspublicrootdomains) +1.427 [Cardano.Node.PublicRootPeers.PublicRootFailure] (#cardanonodepublicrootpeerspublicrootfailure) +1.428 [Cardano.Node.PublicRootPeers.PublicRootRelayAccessPoint] (#cardanonodepublicrootpeerspublicrootrelayaccesspoint) +1.429 [Cardano.Node.PublicRootPeers.PublicRootResult] (#cardanonodepublicrootpeerspublicrootresult) +1.430 [Cardano.Node.ReplayBlock.LedgerReplay] (#cardanonodereplayblockledgerreplay) +1.431 [Cardano.Node.Resources] (#cardanonoderesources) +1.432 [Cardano.Node.Server.AcceptConnection] (#cardanonodeserveracceptconnection) +1.433 [Cardano.Node.Server.AcceptError] (#cardanonodeserveraccepterror) +1.434 [Cardano.Node.Server.AcceptPolicy] (#cardanonodeserveracceptpolicy) +1.435 [Cardano.Node.Server.Error] (#cardanonodeservererror) +1.436 [Cardano.Node.Server.Started] (#cardanonodeserverstarted) +1.437 [Cardano.Node.Server.Stopped] (#cardanonodeserverstopped) +1.438 [Cardano.Node.Shutdown.AbnormalShutdown] (#cardanonodeshutdownabnormalshutdown) +1.439 [Cardano.Node.Shutdown.RequestingShutdown] (#cardanonodeshutdownrequestingshutdown) +1.440 [Cardano.Node.Shutdown.ShutdownArmedAtSlot] (#cardanonodeshutdownshutdownarmedatslot) +1.441 [Cardano.Node.Shutdown.ShutdownRequested] (#cardanonodeshutdownshutdownrequested) +1.442 [Cardano.Node.Shutdown.ShutdownUnexpectedInput] (#cardanonodeshutdownshutdownunexpectedinput) +1.443 [Cardano.Node.Startup.Byron] (#cardanonodestartupbyron) +1.444 [Cardano.Node.Startup.Common] (#cardanonodestartupcommon) +1.445 [Cardano.Node.Startup.Network] (#cardanonodestartupnetwork) +1.446 [Cardano.Node.Startup.ShelleyBased] (#cardanonodestartupshelleybased) +1.447 [Cardano.Node.StateQueryClient.Acquire] (#cardanonodestatequeryclientacquire) +1.448 [Cardano.Node.StateQueryClient.Acquired] (#cardanonodestatequeryclientacquired) +1.449 [Cardano.Node.StateQueryClient.Acquired] (#cardanonodestatequeryclientacquired) +1.450 [Cardano.Node.StateQueryClient.Done] (#cardanonodestatequeryclientdone) +1.451 [Cardano.Node.StateQueryClient.Query] (#cardanonodestatequeryclientquery) +1.452 [Cardano.Node.StateQueryClient.ReAcquire] (#cardanonodestatequeryclientreacquire) +1.453 [Cardano.Node.StateQueryClient.Release] (#cardanonodestatequeryclientrelease) +1.454 [Cardano.Node.StateQueryClient.Result] (#cardanonodestatequeryclientresult) +1.455 [Cardano.Node.TxInbound.TxInboundCanRequestMoreTxs] (#cardanonodetxinboundtxinboundcanrequestmoretxs) +1.456 [Cardano.Node.TxInbound.TxInboundCannotRequestMoreTxs] (#cardanonodetxinboundtxinboundcannotrequestmoretxs) +1.457 [Cardano.Node.TxInbound.TxInboundTerminated] (#cardanonodetxinboundtxinboundterminated) +1.458 [Cardano.Node.TxInbound.TxSubmissionCollected] (#cardanonodetxinboundtxsubmissioncollected) +1.459 [Cardano.Node.TxInbound.TxSubmissionProcessed] (#cardanonodetxinboundtxsubmissionprocessed) +1.460 [Cardano.Node.TxOutbound.ControlMessage] (#cardanonodetxoutboundcontrolmessage) +1.461 [Cardano.Node.TxOutbound.TxSubmissionOutboundRecvMsgRequest] (#cardanonodetxoutboundtxsubmissionoutboundrecvmsgrequest) +1.462 [Cardano.Node.TxOutbound.TxSubmissionOutboundSendMsgReply] (#cardanonodetxoutboundtxsubmissionoutboundsendmsgreply) +1.463 [Cardano.Node.TxSubmission.NodeToNode.Send.Done] (#cardanonodetxsubmissionnodetonodesenddone) +1.464 [Cardano.Node.TxSubmission.NodeToNode.Send.ReplyTxIds] (#cardanonodetxsubmissionnodetonodesendreplytxids) +1.465 [Cardano.Node.TxSubmission.NodeToNode.Send.ReplyTxs] (#cardanonodetxsubmissionnodetonodesendreplytxs) +1.466 [Cardano.Node.TxSubmission.NodeToNode.Send.RequestTxIds] (#cardanonodetxsubmissionnodetonodesendrequesttxids) +1.467 [Cardano.Node.TxSubmission.NodeToNode.Send.RequestTxs] (#cardanonodetxsubmissionnodetonodesendrequesttxs) +1.468 [Cardano.Node.TxSubmission2.NodeToNode.Send.Done] (#cardanonodetxsubmission2nodetonodesenddone) +1.469 [Cardano.Node.TxSubmission2.NodeToNode.Send.MsgHello] (#cardanonodetxsubmission2nodetonodesendmsghello) +1.470 [Cardano.Node.TxSubmission2.NodeToNode.Send.ReplyTxIds] (#cardanonodetxsubmission2nodetonodesendreplytxids) +1.471 [Cardano.Node.TxSubmission2.NodeToNode.Send.ReplyTxs] (#cardanonodetxsubmission2nodetonodesendreplytxs) +1.472 [Cardano.Node.TxSubmission2.NodeToNode.Send.RequestTxIds] (#cardanonodetxsubmission2nodetonodesendrequesttxids) +1.473 [Cardano.Node.TxSubmission2.NodeToNode.Send.RequestTxs] (#cardanonodetxsubmission2nodetonodesendrequesttxs) +1.474 [Cardano.Node.TxSubmissionClient.Send.AcceptTx] (#cardanonodetxsubmissionclientsendaccepttx) +1.475 [Cardano.Node.TxSubmissionClient.Send.Done] (#cardanonodetxsubmissionclientsenddone) +1.476 [Cardano.Node.TxSubmissionClient.Send.RejectTx] (#cardanonodetxsubmissionclientsendrejecttx) +1.477 [Cardano.Node.TxSubmissionClient.Send.SubmitTx] (#cardanonodetxsubmissionclientsendsubmittx) +2.[Metrics] (#metrics) +2.1 [Block replay progress (%)] (#block replay progress (%)) +2.2 [cardano.node.aboutToLeadSlotLast] (#cardanonodeabouttoleadslotlast) +2.3 [cardano.node.aboutToLeadSlotLast] (#cardanonodeabouttoleadslotlast) +2.4 [cardano.node.adoptedSlotLast] (#cardanonodeadoptedslotlast) +2.5 [cardano.node.blockContext] (#cardanonodeblockcontext) +2.6 [cardano.node.blockFromFuture] (#cardanonodeblockfromfuture) +2.7 [cardano.node.blocks] (#cardanonodeblocks) +2.8 [cardano.node.blocks] (#cardanonodeblocks) +2.9 [cardano.node.chainSync.rollForward] (#cardanonodechainsyncrollforward) +2.10 [cardano.node.chainSync.rollForward] (#cardanonodechainsyncrollforward) +2.11 [cardano.node.connectedPeers] (#cardanonodeconnectedpeers) +2.12 [cardano.node.connectionManager.duplexConns] (#cardanonodeconnectionmanagerduplexconns) +2.13 [cardano.node.connectionManager.duplexConns] (#cardanonodeconnectionmanagerduplexconns) +2.14 [cardano.node.connectionManager.fullDuplexConns] (#cardanonodeconnectionmanagerfullduplexconns) +2.15 [cardano.node.connectionManager.fullDuplexConns] (#cardanonodeconnectionmanagerfullduplexconns) +2.16 [cardano.node.connectionManager.inboundConns] (#cardanonodeconnectionmanagerinboundconns) +2.17 [cardano.node.connectionManager.inboundConns] (#cardanonodeconnectionmanagerinboundconns) +2.18 [cardano.node.connectionManager.outboundConns] (#cardanonodeconnectionmanageroutboundconns) +2.19 [cardano.node.connectionManager.outboundConns] (#cardanonodeconnectionmanageroutboundconns) +2.20 [cardano.node.connectionManager.unidirectionalConns] (#cardanonodeconnectionmanagerunidirectionalconns) +2.21 [cardano.node.connectionManager.unidirectionalConns] (#cardanonodeconnectionmanagerunidirectionalconns) +2.22 [cardano.node.couldNotForgeSlotLast] (#cardanonodecouldnotforgeslotlast) +2.23 [cardano.node.couldNotForgeSlotLast] (#cardanonodecouldnotforgeslotlast) +2.24 [cardano.node.currentKESPeriod] (#cardanonodecurrentkesperiod) +2.25 [cardano.node.delegMapSize] (#cardanonodedelegmapsize) +2.26 [cardano.node.density] (#cardanonodedensity) +2.27 [cardano.node.density] (#cardanonodedensity) +2.28 [cardano.node.epoch] (#cardanonodeepoch) +2.29 [cardano.node.epoch] (#cardanonodeepoch) +2.30 [cardano.node.forgedInvalidSlotLast] (#cardanonodeforgedinvalidslotlast) +2.31 [cardano.node.forgedSlotLast] (#cardanonodeforgedslotlast) +2.32 [cardano.node.ledgerState] (#cardanonodeledgerstate) +2.33 [cardano.node.ledgerView] (#cardanonodeledgerview) +2.34 [cardano.node.mempoolBytes] (#cardanonodemempoolbytes) +2.35 [cardano.node.mempoolBytes] (#cardanonodemempoolbytes) +2.36 [cardano.node.mempoolBytes] (#cardanonodemempoolbytes) +2.37 [cardano.node.mempoolBytes] (#cardanonodemempoolbytes) +2.38 [cardano.node.nodeCannotForge] (#cardanonodenodecannotforge) +2.39 [cardano.node.nodeIsLeader] (#cardanonodenodeisleader) +2.40 [cardano.node.nodeNotLeader] (#cardanonodenodenotleader) +2.41 [cardano.node.notAdoptedSlotLast] (#cardanonodenotadoptedslotlast) +2.42 [cardano.node.operationalCertificateExpiryKESPeriod] (#cardanonodeoperationalcertificateexpirykesperiod) +2.43 [cardano.node.operationalCertificateStartKESPeriod] (#cardanonodeoperationalcertificatestartkesperiod) +2.44 [cardano.node.peerSelection.cold] (#cardanonodepeerselectioncold) +2.45 [cardano.node.peerSelection.hot] (#cardanonodepeerselectionhot) +2.46 [cardano.node.peerSelection.warm] (#cardanonodepeerselectionwarm) +2.47 [cardano.node.remainingKESPeriods] (#cardanonoderemainingkesperiods) +2.48 [cardano.node.served.block] (#cardanonodeservedblock) +2.49 [cardano.node.slotInEpoch] (#cardanonodeslotinepoch) +2.50 [cardano.node.slotInEpoch] (#cardanonodeslotinepoch) +2.51 [cardano.node.slotIsImmutable] (#cardanonodeslotisimmutable) +2.52 [cardano.node.slots] (#cardanonodeslots) +2.53 [cardano.node.slots] (#cardanonodeslots) +2.54 [cardano.node.submissions.accepted] (#cardanonodesubmissionsaccepted) +2.55 [cardano.node.submissions.rejected] (#cardanonodesubmissionsrejected) +2.56 [cardano.node.submissions.submitted] (#cardanonodesubmissionssubmitted) +2.57 [cardano.node.txsInMempool] (#cardanonodetxsinmempool) +2.58 [cardano.node.txsInMempool] (#cardanonodetxsinmempool) +2.59 [cardano.node.txsInMempool] (#cardanonodetxsinmempool) +2.60 [cardano.node.txsInMempool] (#cardanonodetxsinmempool) +2.61 [cardano.node.txsProcessedNum] (#cardanonodetxsprocessednum) +2.62 [cardano.node.utxoSize] (#cardanonodeutxosize) +2.63 [mem.resident] (#memresident) +2.64 [peersFromNodeKernel] (#peersfromnodekernel) +2.65 [rts.gcLiveBytes] (#rtsgclivebytes) +2.66 [rts.gcMajorNum] (#rtsgcmajornum) +2.67 [rts.gcMinorNum] (#rtsgcminornum) +2.68 [rts.gcticks] (#rtsgcticks) +2.69 [rts.mutticks] (#rtsmutticks) +2.70 [rts.threads] (#rtsthreads) +2.71 [stat.cputicks] (#statcputicks) +3.[Datapoints] (#datapoints) +1.1 [NodeInfo] (#nodeinfo) + +## Trace Messages +### Cardano.Node.AcceptPolicy.ConectionRateLimiting + + +*** +Rate limiting accepting connections, delaying next accept for given time, currently serving n connections. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.AcceptPolicy.ConnectionHardLimit + + +*** +Hard rate limit reached, waiting until the number of connections drops below n. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.BlockFetch.NodeToNode.Send.BatchDone + + +*** +End of block streaming. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetch.NodeToNode.Send.Block + + +*** +Stream a single block. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetch.NodeToNode.Send.ClientDone + + +*** +Client termination message. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetch.NodeToNode.Send.NoBlocks + + +*** +Respond that there are no blocks. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetch.NodeToNode.Send.RequestRange + + +*** +Request range of blocks. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetch.NodeToNode.Send.StartBatch + + +*** +Start block streaming. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchClient.AcknowledgedFetchRequest + + +*** +Mark the point when the fetch client picks up the request added by the block fetch decision thread. Note that this event can happen fewer times than the 'AddedFetchRequest' due to fetch request merging. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchClient.AddedFetchRequest + + +*** +The block fetch decision thread has added a new fetch instruction consisting of one or more individual request ranges. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchClient.ClientTerminating + + +*** +The client is terminating. Log the number of outstanding requests. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchClient.CompletedFetchBatch + + +*** +Mark the successful end of receiving a streaming batch of blocks. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchClient.RejectedFetchBatch + + +*** +If the other peer rejects our request then we have this event instead of 'StartedFetchBatch' and 'CompletedFetchBatch'. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchClient.StartedFetchBatch + + +*** +Mark the start of receiving a streaming batch of blocks. This will be followed by one or more 'CompletedBlockFetch' and a final 'CompletedFetchBatch' +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchDecision + + +*** +Throughout the decision making process we accumulate reasons to decline to fetch any blocks. This message carries the intermediate and final results. +*** + + +> Severity: `Info` +Privacy: `Confidential` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchSerialised.NodeToNode.Send.BatchDone + + +*** +End of block streaming. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchSerialised.NodeToNode.Send.Block + + +*** +Stream a single block. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchSerialised.NodeToNode.Send.ClientDone + + +*** +Client termination message. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchSerialised.NodeToNode.Send.NoBlocks + + +*** +Respond that there are no blocks. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchSerialised.NodeToNode.Send.RequestRange + + +*** +Request range of blocks. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchSerialised.NodeToNode.Send.StartBatch + + +*** +Start block streaming. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockFetchServer.SendBlock + + +*** +The server sent a block to the peer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.BlockchainTime.CurrentSlotUnknown + + +*** +Current slot is not yet known + This happens when the tip of our current chain is so far in the past that we cannot translate the current wallclock to a slot number, typically during syncing. Until the current slot number is known, we cannot produce blocks. Seeing this message during syncing therefore is normal and to be expected. + We record the current time (the time we tried to translate to a 'SlotNo') as well as the 'PastHorizonException', which provides detail on the bounds between which we /can/ do conversions. The distance between the current time and the upper bound should rapidly decrease with consecutive 'CurrentSlotUnknown' messages during syncing. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.BlockchainTime.StartTimeInTheFuture + + +*** +The start time of the blockchain time is in the future + We have to block (for 'NominalDiffTime') until that time comes. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.BlockchainTime.SystemClockMovedBack + + +*** +The system clock moved back an acceptable time span, e.g., because of an NTP sync. + The system clock moved back such that the new current slot would be smaller than the previous one. If this is within the configured limit, we trace this warning but *do not change the current slot*. The current slot never decreases, but the current slot may stay the same longer than expected. + When the system clock moved back more than the configured limit, we shut down with a fatal exception. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.ChainDB.AddBlockEvent.AddBlockValidation.CandidateContainsFutureBlocks + + +*** +An event traced during validating performed while adding a block. Candidate contains headers from the future which do no exceed the clock skew. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.AddBlockValidation.CandidateContainsFutureBlocksExceedingClockSkew + + +*** +An event traced during validating performed while adding a block. Candidate contains headers from the future which exceed the clock skew. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.AddBlockValidation.InvalidBlock + + +*** +An event traced during validating performed while adding a block. A point was found to be invalid. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate + + +*** +An event traced during validating performed while adding a block. A candidate chain was valid. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` +Limiters: Limiter `ValidCandidateLimiter` with frequency `2.0` + +### Cardano.Node.ChainDB.AddBlockEvent.AddedBlockToQueue + + +*** +The block was added to the queue and will be added to the ChainDB by the background thread. The size of the queue is included.. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` +Limiters: Limiter `AddedBlockToQueueLimiter` with frequency `2.0` + +### Cardano.Node.ChainDB.AddBlockEvent.AddedBlockToVolatileDB + + +*** +A block was added to the Volatile DB +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` +Limiters: Limiter `AddedBlockToVolatileDBLimiter` with frequency `2.0` + +### Cardano.Node.ChainDB.AddBlockEvent.AddedToCurrentChain + + +*** +The new block fits onto the current chain (first fragment) and we have successfully used it to extend our (new) current chain (second fragment). +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.BlockInTheFuture + + +*** +The block is from the future, i.e., its slot number is greater than the current slot (the second argument). +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.ChainSelectionForFutureBlock + + +*** +Run chain selection for a block that was previously from the future. This is done for all blocks from the future each time a new block is added. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.IgnoreBlockAlreadyInVolatileDB + + +*** +A block that is already in the Volatile DB was ignored. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.IgnoreBlockAlreadyInVolatileDB + + +*** +A block that is already in the Volatile DB was ignored. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.IgnoreBlockOlderThanK + + +*** +A block with a 'BlockNo' more than @k@ back than the current tip was ignored. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.StoreButDontChange + + +*** +The block fits onto some fork, we'll try to switch to that fork (if it is preferable to our chain). +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.SwitchedToAFork + + +*** +The new block fits onto some fork and we have switched to that fork (second fragment), as it is preferable to our (previous) current chain (first fragment). +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.TryAddToCurrentChain + + +*** +The block fits onto the current chain, we'll try to use it to extend our chain. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.AddBlockEvent.TrySwitchToAFork + + +*** +The block fits onto some fork, we'll try to switch to that fork (if it is preferable to our chain) +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB + + +*** +A block was successfully copied to the ImmDB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` +Limiters: Limiter `CopiedBlockToImmutableDBLimiter` with frequency `2.0` + +### Cardano.Node.ChainDB.CopyToImmutableDBEvent.NoBlocksToCopyToImmutableDB + + +*** +There are no block to copy to the ImmDB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.FollowerEvent.FollowerNewImmIterator + + +*** +The follower is in the 'FollowerInImmutableDB' state but the iterator is exhausted while the ImmDB has grown, so we open a new iterator to stream these blocks too. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.FollowerEvent.FollowerNoLongerInMem + + +*** +The follower was in the 'FollowerInImmutableDB' state and is switched to the 'FollowerInMem' state. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.FollowerEvent.FollowerSwitchToMem + + +*** +The follower was in the 'FollowerInImmutableDB' state and is switched to the 'FollowerInMem' state. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.FollowerEvent.NewFollower + + +*** +A new follower was created. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.GCEvent.PerformedGC + + +*** +There are no block to copy to the ImmDB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.GCEvent.ScheduledGC + + +*** +There are no block to copy to the ImmDB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.CurrentChunkHit + + +*** +Current chunk found in the cache. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.PastChunkEvict + + +*** +The least recently used past chunk was evicted because the cache was full. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.PastChunkExpired + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.PastChunkHit + + +*** +Past chunk found in the cache +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.CacheEvent.PastChunkMiss + + +*** +Past chunk was not found in the cache +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.ChunkFileDoesntFit + + +*** +The hash of the last block in the previous epoch doesn't match the previous hash of the first block in the current epoch +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.InvalidChunkFile + + +*** +Chunk file is invalid +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.InvalidPrimaryIndex + + +*** +The primary index is invalid. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.InvalidSecondaryIndex + + +*** + +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.MissingChunkFile + + +*** +Chunk file is missing +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.MissingPrimaryIndex + + +*** +The primary index is missing. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.ChunkValidation.MissingSecondaryIndex + + +*** +The secondary index is missing. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.DBAlreadyClosed + + +*** +The immutable DB is already closed +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.DBClosed + + +*** +Closing the immutable DB +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.DeletingAfter + + +*** +Delete after +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.Migrating + + +*** +Performing a migration of the on-disk files. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.NoValidLastLocation + + +*** +No valid last location was found +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.ImmDbEvent.ValidatedLastLocation + + +*** +The last location was validatet +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.InitChainSelEvent.CandidateContainsFutureBlocks + + +*** +Candidate contains headers from the future which do not exceed the clock skew. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.InitChainSelEvent.CandidateContainsFutureBlocksExceedingClockSkew + + +*** +Candidate contains headers from the future which exceed the clock skew, making them invalid. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.InitChainSelEvent.InvalidBlock + + +*** +A point was found to be invalid. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.InitChainSelEvent.ValidCandidate + + +*** +A candidate chain was valid. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.IteratorEvent.BlockGCedFromVolatileDB + + +*** +A block is no longer in the VolatileDB and isn't in the ImmDB either; it wasn't part of the current chain. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.IteratorEvent.BlockMissingFromVolatileDB + + +*** +A block is no longer in the VolatileDB because it has been garbage collected. It might now be in the ImmDB if it was part of the current chain. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.IteratorEvent.BlockWasCopiedToImmutableDB + + +*** +A block that has been garbage collected from the VolatileDB is now found and streamed from the ImmDB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.IteratorEvent.StreamFromBoth + + +*** +Stream from both the VolatileDB and the ImmDB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.IteratorEvent.StreamFromImmutableDB + + +*** +Stream only from the ImmDB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.IteratorEvent.StreamFromVolatileDB + + +*** +Stream only from the VolatileDB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.IteratorEvent.SwitchBackToVolatileDB + + +*** +We have streamed one or more blocks from the ImmDB that were part of the VolatileDB when initialising the iterator. Now, we have to look back in the VolatileDB again because the ImmDB doesn't have the next block we're looking for. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.IteratorEvent.UnknownRangeRequested + + +*** +An unknown range was requested, see 'UnknownRange'. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.LedgerEvent.DeletedSnapshot + + +*** +An old or invalid on-disk snapshot was deleted. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.LedgerEvent.InvalidSnapshot + + +*** +An on disk snapshot was skipped because it was invalid. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.LedgerEvent.ReplayFromGenesis + + +*** +There were no LedgerDB snapshots on disk, so we're replaying all blocks starting from Genesis against the initial ledger. The @replayTo@ parameter corresponds to the block at the tip of the ImmDB, i.e., the last block to replay. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.LedgerEvent.ReplayFromSnapshot + + +*** +There was a LedgerDB snapshot on disk corresponding to the given tip. We're replaying more recent blocks against it. The @replayTo@ parameter corresponds to the block at the tip of the ImmDB, i.e., the last block to replay. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.LedgerEvent.ReplayedBlock + + +*** +We replayed the given block (reference) on the genesis snapshot during the initialisation of the LedgerDB. + The @blockInfo@ parameter corresponds replayed block and the @replayTo@ parameter corresponds to the block at the tip of the ImmDB, i.e., the last block to replay. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.LedgerEvent.TookSnapshot + + +*** +A snapshot was written to disk. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.OpenEvent.ClosedDB + + +*** +The ChainDB was closed. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.OpenEvent.OpenedDB + + +*** +The ChainDB was opened. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.OpenEvent.OpenedImmutableDB + + +*** +The ImmDB was opened. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.OpenEvent.OpenedLgrDB + + +*** +The LedgerDB was opened. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.OpenEvent.OpenedVolatileDB + + +*** +The VolatileDB was opened. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ChainDB.VolatileDbEvent.BlockAlreadyHere + + +*** +A block was found to be already in the DB. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.VolatileDbEvent.DBAlreadyClosed + + +*** +When closing the DB it was found itis closed already. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.VolatileDbEvent.InvalidFileNames + + +*** +Reports a list of invalid file paths. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainDB.VolatileDbEvent.Truncate + + +*** +Truncates a file up to offset because of the error. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ChainSyncClient.ChainSyncClientEvent.DownloadedHeader + + +*** +While following a candidate chain, we rolled forward by downloading a header. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.ChainSyncClientEvent.Exception + + +*** +An exception was thrown by the Chain Sync Client. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.ChainSyncClientEvent.FoundIntersection + + +*** +We found an intersection between our chain fragment and the candidate's chain. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.ChainSyncClientEvent.RolledBack + + +*** +While following a candidate chain, we rolled back to the given point. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.ChainSyncClientEvent.Termination + + +*** +The client has terminated. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.AwaitReply + + +*** +Acknowledge the request but require the consumer to wait for the nextupdate. This means that the consumer is synced with the producer, andthe producer is waiting for its own chain state to change. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.AwaitReply + + +*** +Tell the consumer to extend their chain with the given header. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.Done + + +*** +We have to explain to the framework what our states mean, in terms ofwhich party has agency in each state. +Idle states are where it is for the client to send a message,busy states are where the server is expected to send a reply. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.FindIntersect + + +*** +Ask the producer to try to find an improved intersection point betweenthe consumer and producer's chains. The consumer sends a sequence ofpoints and it is up to the producer to find the first intersection pointon its chain and send it back to the consumer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.IntersectFound + + +*** +The reply to the consumer about an intersection found.The consumer can decide weather to send more points. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.IntersectNotFound + + +*** +The reply to the consumer that no intersection was found: none of thepoints the consumer supplied are on the producer chain. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.RequestNext + + +*** +Request the next update from the producer. The response can be a rollforward, a roll back or wait. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.RollBackward + + +*** +Tell the consumer to roll back to a given point on their chain. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncClient.NodeToClient.Send.RollForward + + +*** +Tell the consumer to extend their chain with the given header. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.AwaitReply + + +*** +Acknowledge the request but require the consumer to wait for the nextupdate. This means that the consumer is synced with the producer, andthe producer is waiting for its own chain state to change. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.AwaitReply + + +*** +Tell the consumer to extend their chain with the given header. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.Done + + +*** +We have to explain to the framework what our states mean, in terms ofwhich party has agency in each state. +Idle states are where it is for the client to send a message,busy states are where the server is expected to send a reply. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.FindIntersect + + +*** +Ask the producer to try to find an improved intersection point betweenthe consumer and producer's chains. The consumer sends a sequence ofpoints and it is up to the producer to find the first intersection pointon its chain and send it back to the consumer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.IntersectFound + + +*** +The reply to the consumer about an intersection found.The consumer can decide weather to send more points. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.IntersectNotFound + + +*** +The reply to the consumer that no intersection was found: none of thepoints the consumer supplied are on the producer chain. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.RequestNext + + +*** +Request the next update from the producer. The response can be a rollforward, a roll back or wait. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.RollBackward + + +*** +Tell the consumer to roll back to a given point on their chain. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncNode.NodeToNode.Send.RollForward + + +*** +Tell the consumer to extend their chain with the given header. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.AwaitReply + + +*** +Acknowledge the request but require the consumer to wait for the nextupdate. This means that the consumer is synced with the producer, andthe producer is waiting for its own chain state to change. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.AwaitReply + + +*** +Tell the consumer to extend their chain with the given header. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.Done + + +*** +We have to explain to the framework what our states mean, in terms ofwhich party has agency in each state. +Idle states are where it is for the client to send a message,busy states are where the server is expected to send a reply. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.FindIntersect + + +*** +Ask the producer to try to find an improved intersection point betweenthe consumer and producer's chains. The consumer sends a sequence ofpoints and it is up to the producer to find the first intersection pointon its chain and send it back to the consumer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.IntersectFound + + +*** +The reply to the consumer about an intersection found.The consumer can decide weather to send more points. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.IntersectNotFound + + +*** +The reply to the consumer that no intersection was found: none of thepoints the consumer supplied are on the producer chain. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.RequestNext + + +*** +Request the next update from the producer. The response can be a rollforward, a roll back or wait. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.RollBackward + + +*** +Tell the consumer to roll back to a given point on their chain. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncSerialised.NodeToNode.Send.RollForward + + +*** +Tell the consumer to extend their chain with the given header. +The message also tells the consumer about the head point of the producer. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.RollBackward + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.RollForward + + +*** +Roll forward to the given point. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.ServerRead + + +*** +A server read has occured, either for an add block or a rollback +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.ServerReadBlocked + + +*** +A server read has blocked, either for an add block or a rollback +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.RollBackward + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.RollForward + + +*** +Roll forward to the given point. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.ServerRead + + +*** +A server read has occured, either for an add block or a rollback +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.ServerReadBlocked + + +*** +A server read has blocked, either for an add block or a rollback +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.Connect + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectError + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectionCleanup + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectionExists + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectionFailure + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectionHandler + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectionManagerCounters + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectionNotFound + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectionTimeWait + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ConnectionTimeWaitDone + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ForbiddenConnection + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ForbiddenOperation + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.ImpossibleConnection + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.IncludeConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.PruneConnections + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.Shutdown + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.State + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.TerminatedConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.TerminatingConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.UnexpectedlyFalseAssertion + + +*** + +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.ConnectionManager.UnregisterConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.DNSResolver.LookupAAAAError + + +*** +AAAA lookup failed with an error. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSResolver.LookupAAAAResult + + +*** +Lookup AAAA result. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSResolver.LookupAError + + +*** +A lookup failed with an error. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSResolver.LookupAResult + + +*** +Lookup A result. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSResolver.LookupException + + +*** +A DNS lookup exception occured. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSResolver.LookupIPv4First + + +*** +Returning IPv4 address first. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSResolver.LookupIPv6First + + +*** +Returning IPv6 address first. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSResolver.LookupIPv6First + + +*** +Returning IPv6 address first. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.AllocateSocket + + +*** +DNS Subscription: Allocate socket to address. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.ApplicationException + + +*** +DNS Subscription: Application Exception occured. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.CloseSocket + + +*** +DNS Subscription: Closed socket to address. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.ConnectEnd + + +*** +DNS Subscription: Connection Attempt end with destination and outcome. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.ConnectException + + +*** +DNS Subscription: Connection Attempt Exception with destination and exception. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.ConnectStart + + +*** +DNS Subscription: Connection Attempt Start with destination. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.ConnectionExist + + +*** +DNS Subscription: Connection exists to destination. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.MissingLocalAddress + + +*** +DNS Subscription: Missing local address. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.Restart + + +*** +DNS Subscription: Restarting Subscription after duration with desired valency and current valency. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.SkippingPeer + + +*** +DNS Subscription: Skipping peer with address. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.SocketAllocationException + + +*** +DNS Subscription: Socket Allocation Exception with destination and the exception. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.Start + + +*** +DNS Subscription: Starting Subscription Worker with a valency. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.SubscriptionFailed + + +*** +DNS Subscription: Failed to start all required subscriptions. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.SubscriptionRunning + + +*** +DNS Subscription: Required subscriptions started. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.SubscriptionWaiting + + +*** +DNS Subscription: Waiting on address with active connections. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.SubscriptionWaitingNewConnection + + +*** +DNS Subscription: Waiting delay time before attempting a new connection. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.TryConnectToPeer + + +*** +DNS Subscription: Trying to connect to peer with address. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DNSSubscription.DNS.UnsupportedRemoteAddr + + +*** +DNS Subscription: Unsupported remote target address. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DebugPeerSelection.GovernorState + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.DebugPeerSelectionResponder.GovernorState + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.DiffusionInit.ConfiguringLocalSocket + + +*** +ConfiguringLocalSocket +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.ConfiguringServerSocket + + +*** +ConfiguringServerSocket +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.CreateSystemdSocketForSnocketPath + + +*** +CreateSystemdSocketForSnocketPath +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.CreatedLocalSocket + + +*** +CreatedLocalSocket +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.CreatingServerSocket + + +*** +CreatingServerSocket +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.DiffusionErrored + + +*** +DiffusionErrored +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.ListeningLocalSocket + + +*** +ListeningLocalSocket +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.ListeningServerSocket + + +*** +ListeningServerSocket +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.LocalSocketUp + + +*** +LocalSocketUp +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.RunLocalServer + + +*** +RunLocalServer +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.RunServer + + +*** +RunServer +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.ServerSocketUp + + +*** +ServerSocketUp +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.UnsupportedLocalSystemdSocket + + +*** +UnsupportedLocalSystemdSocket +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.UnsupportedReadySocketCase + + +*** +UnsupportedReadySocketCase +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.DiffusionInit.UsingSystemdSocket + + +*** +UsingSystemdSocket +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.AcceptException + + +*** +'accept' throwed an exception. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.KeepSuspended + + +*** +Consumer was suspended until producer will resume. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.LocalNodeError + + +*** +caught a local exception. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.ResumeConsumer + + +*** +Resume consumer. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.ResumePeer + + +*** +Resume a peer (both consumer and producer). +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.ResumeProducer + + +*** +Resume producer. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.SuspendConsumer + + +*** +Suspending consumer. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.SuspendPeer + + +*** +Suspending peer with a given exception. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.UnhandledApplicationException + + +*** +An application throwed an exception, which was not handled. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ErrorPolicy.UnhandledConnectionException + + +*** +'connect' throwed an exception, which was not handled by any 'ErrorPolicy'. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.AdoptedBlock + + +*** +We adopted the block we produced, we also trace the transactions that were adopted. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.BlockContext + + +*** +We found out to which block we are going to connect the block we are about to forge. We record the current slot number, the block number of the block to connect to and its point. Note that block number of the block we will try to forge is one more than the recorded block number. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.Forge.BlockFromFuture + + +*** +Leadership check failed: the current chain contains a block from a slot /after/ the current slot This can only happen if the system is under heavy load. We record both the current slot number as well as the slot number of the block at the tip of the chain. See also +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.DidntAdoptBlock + + +*** +We did not adopt the block we produced, but the block was valid. We must have adopted a block that another leader of the same slot produced before we got the chance of adopting our own block. This is very rare, this warrants a warning. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.ForgeStateUpdateError + + +*** +Updating the forge state failed. For example, the KES key could not be evolved anymore. We record the error returned by 'updateForgeState'. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.ForgedBlock + + +*** +We forged a block. + We record the current slot number, the point of the predecessor, the block itself, and the total size of the mempool snapshot at the time we produced the block (which may be significantly larger than the block, due to maximum block size) + This will be followed by one of three messages: + * AdoptedBlock (normally) + * DidntAdoptBlock (rarely) + * ForgedInvalidBlock (hopefully never -- this would indicate a bug) +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.ForgedInvalidBlock + + +*** +We forged a block that is invalid according to the ledger in the ChainDB. This means there is an inconsistency between the mempool validation and the ledger validation. This is a serious error! +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.LedgerState + + +*** +We obtained a ledger state for the point of the block we want to connect to We record both the current slot number as well as the point of the block we attempt to connect the new block to (that we requested the ledger state for). +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.Forge.LedgerView + + +*** +We obtained a ledger view for the current slot number We record the current slot number. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.Forge.NoLedgerState + + +*** +Leadership check failed: we were unable to get the ledger state for the point of the block we want to connect to This can happen if after choosing which block to connect to the node switched to a different fork. We expect this to happen only rather rarely, so this certainly merits a warning; if it happens a lot, that merits an investigation. We record both the current slot number as well as the point of the block we attempt to connect the new block to (that we requested the ledger state for). +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.NoLedgerView + + +*** +Leadership check failed: we were unable to get the ledger view for the current slot number This will only happen if there are many missing blocks between the tip of our chain and the current slot. We record also the failure returned by 'forecastFor'. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.NodeCannotForge + + +*** +We did the leadership check and concluded that we should lead and forge a block, but cannot. This should only happen rarely and should be logged with warning severity. Records why we cannot forge a block. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.NodeIsLeader + + +*** +We did the leadership check and concluded we /are/ the leader + The node will soon forge; it is about to read its transactions from the Mempool. This will be followed by ForgedBlock. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.NodeNotLeader + + +*** +We did the leadership check and concluded we are not the leader We record the current slot number +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.SlotIsImmutable + + +*** +Leadership check failed: the tip of the ImmutableDB inhabits the current slot This might happen in two cases. 1. the clock moved backwards, on restart we ignored everything from the VolatileDB since it's all in the future, and now the tip of the ImmutableDB points to a block produced in the same slot we're trying to produce a block in 2. k = 0 and we already adopted a block from another leader of the same slot. We record both the current slot number as well as the tip of the ImmutableDB. See also +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.StartLeadershipCheck + + +*** +Start of the leadership check. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Forge.StartLeadershipCheckPlus + + +*** +We adopted the block we produced, we also trace the transactions that were adopted. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.ForgeStateInfo + + +*** +kesStartPeriod +kesEndPeriod is kesStartPeriod + tpraosMaxKESEvo +kesEvolution is the current evolution or /relative period/. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Handshake.AcceptVersion + + +*** +The remote end decides which version to use and sends chosen version.The server is allowed to modify version parameters. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Handshake.ProposeVersions + + +*** +Propose versions together with version parameters. It must be encoded to a sorted list.. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Handshake.Refuse + + +*** +It refuses to run any version. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.DemotedToColdRemote + + +*** +All mini-protocols terminated. The boolean is true if this connection was not used by p2p-governor, and thus the connection will be terminated. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.DemotedToWarmRemote + + +*** +All mini-protocols terminated. The boolean is true if this connection was not used by p2p-governor, and thus the connection will be terminated. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.InboundGovernorCounters + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.MuxCleanExit + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.MuxErrored + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.NewConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.PromotedToHotRemote + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.PromotedToWarmRemote + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.RemoteState + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.ResponderErrored + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.ResponderRestarted + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.ResponderStartFailure + + +*** + +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.ResponderStarted + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.ResponderTerminated + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.InboundGovernor.WaitIdleRemote + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.IpSubscription.IP.AllocateSocket + + +*** +IP Subscription: Allocate socket to address. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.ApplicationException + + +*** +IP Subscription: Application Exception occured. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.CloseSocket + + +*** +IP Subscription: Closed socket to address. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.ConnectEnd + + +*** +IP Subscription: Connection Attempt end with destination and outcome. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.ConnectException + + +*** +IP Subscription: Connection Attempt Exception with destination and exception. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.ConnectStart + + +*** +IP Subscription: Connection Attempt Start with destination. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.ConnectionExist + + +*** +IP Subscription: Connection exists to destination. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.MissingLocalAddress + + +*** +IP Subscription: Missing local address. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.Restart + + +*** +IP Subscription: Restarting Subscription after duration with desired valency and current valency. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.SkippingPeer + + +*** +IP Subscription: Skipping peer with address. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.SocketAllocationException + + +*** +IP Subscription: Socket Allocation Exception with destination and the exception. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.Start + + +*** +IP Subscription: Starting Subscription Worker with a valency. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.SubscriptionFailed + + +*** +IP Subscription: Failed to start all required subscriptions. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.SubscriptionRunning + + +*** +IP Subscription: Required subscriptions started. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.SubscriptionWaiting + + +*** +IP Subscription: Waiting on address with active connections. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.SubscriptionWaitingNewConnection + + +*** +IP Subscription: Waiting delay time before attempting a new connection. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.TryConnectToPeer + + +*** +IP Subscription: Trying to connect to peer with address. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.IpSubscription.IP.UnsupportedRemoteAddr + + +*** +IP Subscription: Unsupported remote target address. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.KeepAliveClient.KeepAliveClient + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.DisabledLedgerPeers + + +*** +Trace for when getting peers from the ledger is disabled, that is DontUseLedger. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.DisabledLedgerPeers + + +*** +Trace for when getting peers from the ledger is disabled, that is DontUseLedger. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.FallingBackToBootstrapPeers + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.FetchingNewLedgerState + + +*** +Trace for fetching a new list of peers from the ledger. Int is the number of peers returned. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.PickedPeer + + +*** +Trace for a peer picked with accumulated and relative stake of its pool. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.PickedPeers + + +*** +Trace for the number of peers we wanted to pick and the list of peers picked. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.ReusingLedgerState + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.TraceUseLedgerAfter + + +*** +Trace UseLedgerAfter value. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.WaitingOnRequest + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LedgerPeers.WaitingOnRequest + + +*** +RequestForPeers (NumberOfPeers 1) +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.Connect + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectError + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectionCleanup + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectionExists + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectionFailure + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectionHandler + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectionManagerCounters + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectionNotFound + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectionTimeWait + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ConnectionTimeWaitDone + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ForbiddenConnection + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ForbiddenOperation + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.ImpossibleConnection + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.IncludeConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.PruneConnections + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.Shutdown + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.State + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.TerminatedConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.TerminatingConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.UnexpectedlyFalseAssertion + + +*** + +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.LocalConnectionManager.UnregisterConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalErrorPolicy.AcceptException + + +*** +'accept' throwed an exception. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.KeepSuspended + + +*** +Consumer was suspended until producer will resume. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.LocalNodeError + + +*** +caught a local exception. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.ResumeConsumer + + +*** +Resume consumer. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.ResumePeer + + +*** +Resume a peer (both consumer and producer). +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.ResumeProducer + + +*** +Resume producer. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.SuspendConsumer + + +*** +Suspending consumer. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.SuspendPeer + + +*** +Suspending peer with a given exception. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.UnhandledApplicationException + + +*** +An application throwed an exception, which was not handled. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.LocalErrorPolicy.UnhandledConnectionException + + +*** +'connect' throwed an exception, which was not handled by any 'ErrorPolicy'. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.LocalHandshake.AcceptVersion + + +*** +The remote end decides which version to use and sends chosen version.The server is allowed to modify version parameters. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalHandshake.ProposeVersions + + +*** +Propose versions together with version parameters. It must be encoded to a sorted list.. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalHandshake.Refuse + + +*** +It refuses to run any version. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.DemotedToColdRemote + + +*** +All mini-protocols terminated. The boolean is true if this connection was not used by p2p-governor, and thus the connection will be terminated. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.DemotedToWarmRemote + + +*** +All mini-protocols terminated. The boolean is true if this connection was not used by p2p-governor, and thus the connection will be terminated. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.InboundGovernorCounters + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.MuxCleanExit + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.MuxErrored + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.NewConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.PromotedToHotRemote + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.PromotedToWarmRemote + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.RemoteState + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.ResponderErrored + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.ResponderRestarted + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.ResponderStartFailure + + +*** + +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.ResponderStarted + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.ResponderTerminated + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalInboundGovernor.WaitIdleRemote + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalRootPeers.LocalRootDomains + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalRootPeers.LocalRootError + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalRootPeers.LocalRootFailure + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalRootPeers.LocalRootGroups + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalRootPeers.LocalRootResult + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalRootPeers.LocalRootWaiting + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalServer.AcceptConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.LocalServer.AcceptError + + +*** + +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.LocalServer.AcceptPolicy + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.LocalServer.Error + + +*** + +*** + + +> Severity: `Critical` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.LocalServer.Started + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.LocalServer.Stopped + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.LocalTxSubmissionServer.ReceivedTx + + +*** +A transaction was received. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mempool.AddedTx + + +*** +New, valid transaction that was added to the Mempool. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Mempool.ManuallyRemovedTxs + + +*** +Transactions that have been manually removed from the Mempool. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Mempool.RejectedTx + + +*** +New, invalid transaction thas was rejected and thus not added to the Mempool. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Mempool.RemoveTxs + + +*** +Previously valid transactions that are no longer valid because of changes in the ledger state. These transactions have been removed from the Mempool. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Mux.ChannelRecvEnd + + +*** +Channel receive end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.ChannelRecvStart + + +*** +Channel receive start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.ChannelSendEnd + + +*** +Channel send end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.ChannelSendStart + + +*** +Channel send start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.CleanExit + + +*** +Miniprotocol terminated cleanly. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Mux.ExceptionExit + + +*** +Miniprotocol terminated with exception. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Mux.HandshakeClientEnd + + +*** +Handshake client end. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.HandshakeClientError + + +*** +Handshake client error. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Mux.HandshakeServerError + + +*** +Handshake server error. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Mux.HandshakeStart + + +*** +Handshake start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.RecvDeltaQObservation + + +*** +Bearer DeltaQ observation. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.RecvDeltaQSample + + +*** +Bearer DeltaQ sample. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.RecvEnd + + +*** +Bearer receive end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.RecvHeaderEnd + + +*** +Bearer receive header end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.RecvHeaderStart + + +*** +Bearer receive header start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.RecvStart + + +*** +Bearer receive start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.SDUReadTimeoutException + + +*** +Timed out reading SDU. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Mux.SDUWriteTimeoutException + + +*** +Timed out writing SDU. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Mux.SendEnd + + +*** +Bearer send end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.SendStart + + +*** +Bearer send start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.Shutdown + + +*** +Mux shutdown. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.StartEagerly + + +*** +Eagerly started. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.StartOnDemand + + +*** +Preparing to start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.StartedOnDemand + + +*** +Started on demand. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.State + + +*** +State. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Mux.Terminating + + +*** +Terminating. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.ChannelRecvEnd + + +*** +Channel receive end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.ChannelRecvStart + + +*** +Channel receive start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.ChannelSendEnd + + +*** +Channel send end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.ChannelSendStart + + +*** +Channel send start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.CleanExit + + +*** +Miniprotocol terminated cleanly. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.ExceptionExit + + +*** +Miniprotocol terminated with exception. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.HandshakeClientEnd + + +*** +Handshake client end. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.HandshakeClientError + + +*** +Handshake client error. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.HandshakeServerError + + +*** +Handshake server error. +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.HandshakeStart + + +*** +Handshake start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.RecvDeltaQObservation + + +*** +Bearer DeltaQ observation. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.RecvDeltaQSample + + +*** +Bearer DeltaQ sample. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.RecvEnd + + +*** +Bearer receive end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.RecvHeaderEnd + + +*** +Bearer receive header end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.RecvHeaderStart + + +*** +Bearer receive header start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.RecvStart + + +*** +Bearer receive start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.SDUReadTimeoutException + + +*** +Timed out reading SDU. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.SDUWriteTimeoutException + + +*** +Timed out writing SDU. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.SendEnd + + +*** +Bearer send end. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.SendStart + + +*** +Bearer send start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.Shutdown + + +*** +Mux shutdown. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.StartEagerly + + +*** +Eagerly started. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.StartOnDemand + + +*** +Preparing to start. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.StartedOnDemand + + +*** +Started on demand. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.State + + +*** +State. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.MuxLocal.Terminating + + +*** +Terminating. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.ChurnMode + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.ChurnWait + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteAsynchronous + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteHotDone + + +*** +target active, actual active, peer +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteHotFailed + + +*** +target active, actual active, peer, reason +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteHotFailed + + +*** +target active, actual active, peer, reason +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteHotPeers + + +*** +target active, actual active, selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteLocalHotPeers + + +*** +local per-group (target active, actual active), selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteWarmDone + + +*** +target established, actual established, peer +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteWarmFailed + + +*** +target established, actual established, peer, reason +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.DemoteWarmPeers + + +*** +target established, actual established, selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.ForgetColdPeers + + +*** +target known peers, actual known peers, selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.GossipRequests + + +*** +target known peers, actual known peers, peers available for gossip, peers selected for gossip +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.GossipResults + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.GovernorWakeup + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.LocalRootPeersChanged + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PromoteColdDone + + +*** +target active, actual active, selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PromoteColdFailed + + +*** +target established, actual established, peer, delay until next promotion, reason +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PromoteColdLocalPeers + + +*** +target local established, actual local established, selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PromoteColdPeers + + +*** +target established, actual established, selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PromoteWarmDone + + +*** +target active, actual active, peer +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PromoteWarmFailed + + +*** +target active, actual active, peer, reason +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PromoteWarmLocalPeers + + +*** +local per-group (target active, actual active), selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PromoteWarmPeers + + +*** +target active, actual active, selected peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PublicRootsResults + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.PublicRootsResults + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.TargetsChanged + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.PeerSelection.ublicRootsRequest + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelectionActions.MonitoringError + + +*** + +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.PeerSelectionActions.MonitoringResult + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelectionActions.StatusChangeFailure + + +*** + +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.PeerSelectionActions.StatusChanged + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PeerSelectionCounters + + +*** +Counters for cold, warm and hot peers +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Peers + + +*** +TODO Doc +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.PublicRootPeers.PublicRootDomains + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PublicRootPeers.PublicRootFailure + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PublicRootPeers.PublicRootRelayAccessPoint + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.PublicRootPeers.PublicRootResult + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.ReplayBlock.LedgerReplay + + +*** +Counts up the percent of a block replay. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Resources + + +*** +TODO JNF +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Info` + +### Cardano.Node.Server.AcceptConnection + + +*** + +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.Server.AcceptError + + +*** + +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Server.AcceptPolicy + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Server.Error + + +*** + +*** + + +> Severity: `Critical` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Server.Started + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Server.Stopped + + +*** + +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Shutdown.AbnormalShutdown + + +*** +non-isEOFerror shutdown request +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Shutdown.RequestingShutdown + + +*** +Ringing the node shutdown doorbell +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Shutdown.ShutdownArmedAtSlot + + +*** +Setting up node shutdown at given slot. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Shutdown.ShutdownRequested + + +*** +Node shutdown was requested. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Shutdown.ShutdownUnexpectedInput + + +*** +Received shutdown request but found unexpected input in --shutdown-ipc FD: +*** + + +> Severity: `Error` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Startup.Byron + + +*** +_bibSystemStartTime_: TODO JNF +_bibSlotLength_: gives the length of a slot as time interval. +_bibEpochLength_: gives the number of slots which forms an epoch. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Startup.Common + + +*** +_biConfigPath_: is the path to the config in use. +_biProtocol_: is the name of the protocol, e.g. "Byron", "Shelley" or "Byron; Shelley". +_biVersion_: is the version of the node software running. +_biCommit_: is the commit revision of the software running. +_biNodeStartTime_: gives the time this node was started. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Startup.Network + + +*** +_niAddresses_: IPv4 or IPv6 socket ready to accept connectionsor diffusion addresses. +_niDiffusionMode_: shows if the node runs only initiator or bothinitiator or responder node. +_niDnsProducers_: shows the list of domain names to subscribe to. +_niIpProducers_: shows the list of ip subscription addresses. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.Startup.ShelleyBased + + +*** +bisEra is the current era, e.g. "Shelley", "Allegra", "Mary" or "Alonzo". +_bisSystemStartTime_: TODO JNF +_bisSlotLength_: gives the length of a slot as time interval. +_bisEpochLength_: gives the number of slots which forms an epoch. +_bisSlotsPerKESPeriod_: gives the slots per KES period. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.StateQueryClient.Acquire + + +*** +The client requests that the state as of a particular recent point onthe server's chain (within K of the tip) be made available to query,and waits for confirmation or failure. +From 'NodeToClient_V8' onwards if the point is not specified, current tipwill be acquired. For previous versions of the protocol 'point' must begiven. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.StateQueryClient.Acquired + + +*** +The server can confirm that it has the state at the requested point. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.StateQueryClient.Acquired + + +*** +The server can report that it cannot obtain the state for therequested point. +*** + + +> Severity: `Warning` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.StateQueryClient.Done + + +*** +The client can terminate the protocol. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.StateQueryClient.Query + + +*** +The client can perform queries on the current acquired state. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.StateQueryClient.ReAcquire + + +*** +This is like 'MsgAcquire' but for when the client already has astate. By moveing to another state directly without a 'MsgRelease' itenables optimisations on the server side (e.g. moving to the state forthe immediate next block). +Note that failure to re-acquire is equivalent to 'MsgRelease',rather than keeping the exiting acquired state. +From 'NodeToClient_V8' onwards if the point is not specified, current tipwill be acquired. For previous versions of the protocol 'point' must begiven. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.StateQueryClient.Release + + +*** +The client can instruct the server to release the state. This letsthe server free resources. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.StateQueryClient.Result + + +*** +The server must reply with the queries. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxInbound.TxInboundCanRequestMoreTxs + + +*** +There are no replies in flight, but we do know some more txs we can ask for, so lets ask for them and more txids. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxInbound.TxInboundCannotRequestMoreTxs + + +*** +There's no replies in flight, and we have no more txs we can ask for so the only remaining thing to do is to ask for more txids. Since this is the only thing to do now, we make this a blocking call. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxInbound.TxInboundTerminated + + +*** +Server received 'MsgDone'. +*** + + +> Severity: `Notice` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Visible` because the filter level is `Notice` + +### Cardano.Node.TxInbound.TxSubmissionCollected + + +*** +Number of transactions just about to be inserted. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxInbound.TxSubmissionProcessed + + +*** +Just processed transaction pass/fail breakdown. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxOutbound.ControlMessage + + +*** + +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxOutbound.TxSubmissionOutboundRecvMsgRequest + + +*** +The IDs of the transactions requested. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxOutbound.TxSubmissionOutboundSendMsgReply + + +*** +The transactions to be sent in the response. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission.NodeToNode.Send.Done + + +*** +Termination message, initiated by the client when the server is making a blocking call for more transaction identifiers. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission.NodeToNode.Send.ReplyTxIds + + +*** +Reply with a list of transaction identifiers for availabletransactions, along with the size of each transaction. +The list must not be longer than the maximum number requested. +In the 'StTxIds' 'StBlocking' state the list must be non-empty whilein the 'StTxIds' 'StNonBlocking' state the list may be empty. +These transactions are added to the notional FIFO of outstandingtransaction identifiers for the protocol. +The order in which these transaction identifiers are returned must bethe order in which they are submitted to the mempool, to preservedependent transactions. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission.NodeToNode.Send.ReplyTxs + + +*** +Reply with the requested transactions, or implicitly discard. +Transactions can become invalid between the time the transaction identifier was sent and the transaction being requested. Invalid (including committed) transactions do not need to be sent. +Any transaction identifiers requested but not provided in this reply should be considered as if this peer had never announced them. (Note that this is no guarantee that the transaction is invalid, it may still be valid and available from another peer). +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission.NodeToNode.Send.RequestTxIds + + +*** +Request a non-empty list of transaction identifiers from the client,and confirm a number of outstanding transaction identifiers. +With 'TokBlocking' this is a a blocking operation: the response willalways have at least one transaction identifier, and it does not expecta prompt response: there is no timeout. This covers the case when thereis nothing else to do but wait. For example this covers leaf nodes thatrarely, if ever, create and submit a transaction. +With 'TokNonBlocking' this is a non-blocking operation: the responsemay be an empty list and this does expect a prompt response. Thiscovers high throughput use cases where we wish to pipeline, byinterleaving requests for additional transaction identifiers withrequests for transactions, which requires these requests not block. +The request gives the maximum number of transaction identifiers thatcan be accepted in the response. This must be greater than zero in the'TokBlocking' case. In the 'TokNonBlocking' case either the numbersacknowledged or the number requested must be non-zero. In either case,the number requested must not put the total outstanding over the fixedprotocol limit. +The request also gives the number of outstanding transactionidentifiers that can now be acknowledged. The actual transactionsto acknowledge are known to the peer based on the FIFO order in whichthey were provided. +There is no choice about when to use the blocking case versus thenon-blocking case, it depends on whether there are any remainingunacknowledged transactions (after taking into account the onesacknowledged in this message): +* The blocking case must be used when there are zero remaining unacknowledged transactions. +* The non-blocking case must be used when there are non-zero remaining unacknowledged transactions. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission.NodeToNode.Send.RequestTxs + + +*** +Request one or more transactions corresponding to the given transaction identifiers. +While it is the responsibility of the replying peer to keep within pipelining in-flight limits, the sender must also cooperate by keeping the total requested across all in-flight requests within the limits. +It is an error to ask for transaction identifiers that were not previously announced (via 'MsgReplyTxIds'). +It is an error to ask for transaction identifiers that are not outstanding or that were already asked for. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission2.NodeToNode.Send.Done + + +*** +Termination message, initiated by the client when the server ismaking a blocking call for more transaction identifiers. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission2.NodeToNode.Send.MsgHello + + +*** +Client side hello message. +*** + + +> Severity: `Debug` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission2.NodeToNode.Send.ReplyTxIds + + +*** +Reply with a list of transaction identifiers for availabletransactions, along with the size of each transaction. +The list must not be longer than the maximum number requested. +In the 'StTxIds' 'StBlocking' state the list must be non-empty whilein the 'StTxIds' 'StNonBlocking' state the list may be empty. +These transactions are added to the notional FIFO of outstandingtransaction identifiers for the protocol. +The order in which these transaction identifiers are returned must bethe order in which they are submitted to the mempool, to preservedependent transactions. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission2.NodeToNode.Send.ReplyTxs + + +*** +Reply with the requested transactions, or implicitly discard. +Transactions can become invalid between the time the transactionidentifier was sent and the transaction being requested. Invalid(including committed) transactions do not need to be sent. +Any transaction identifiers requested but not provided in this replyshould be considered as if this peer had never announced them. (Notethat this is no guarantee that the transaction is invalid, it may stillbe valid and available from another peer). +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission2.NodeToNode.Send.RequestTxIds + + +*** +Request a non-empty list of transaction identifiers from the client, and confirm a number of outstanding transaction identifiers. +With 'TokBlocking' this is a a blocking operation: the response will always have at least one transaction identifier, and it does not expect a prompt response: there is no timeout. This covers the case when there is nothing else to do but wait. For example this covers leaf nodes that rarely, if ever, create and submit a transaction. +With 'TokNonBlocking' this is a non-blocking operation: the response may be an empty list and this does expect a prompt response. This covers high throughput use cases where we wish to pipeline, by interleaving requests for additional transaction identifiers with requests for transactions, which requires these requests not block. +The request gives the maximum number of transaction identifiers that can be accepted in the response. This must be greater than zero in the 'TokBlocking' case. In the 'TokNonBlocking' case either the numbers acknowledged or the number requested must be non-zero. In either case, the number requested must not put the total outstanding over the fixed protocol limit. +The request also gives the number of outstanding transaction identifiers that can now be acknowledged. The actual transactions to acknowledge are known to the peer based on the FIFO order in which they were provided. +There is no choice about when to use the blocking case versus the non-blocking case, it depends on whether there are any remaining unacknowledged transactions (after taking into account the ones acknowledged in this message): +* The blocking case must be used when there are zero remaining unacknowledged transactions. +* The non-blocking case must be used when there are non-zero remaining unacknowledged transactions. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmission2.NodeToNode.Send.RequestTxs + + +*** +Request one or more transactions corresponding to the given transaction identifiers. +While it is the responsibility of the replying peer to keep withinpipelining in-flight limits, the sender must also cooperate by keepingthe total requested across all in-flight requests within the limits. +It is an error to ask for transaction identifiers that were notpreviously announced (via 'MsgReplyTxIds'). +It is an error to ask for transaction identifiers that are notoutstanding or that were already asked for. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmissionClient.Send.AcceptTx + + +*** +The server can reply to inform the client that it has accepted thetransaction. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmissionClient.Send.Done + + +*** +The client can terminate the protocol. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmissionClient.Send.RejectTx + + +*** +The server can reply to inform the client that it has rejected thetransaction. A reason for the rejection is included. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +### Cardano.Node.TxSubmissionClient.Send.SubmitTx + + +*** +The client submits a single transaction and waits a reply. +*** + + +> Severity: `Info` +Privacy: `Public` + +From current configuration: +Details: `DNormal` +Backends: + `Stdout MachineFormat`, + `EKGBackend` +Filtered: `Invisible` because the filter level is `Notice` + +## Metrics +### Block replay progress (%) + +*** +Progress in percent +*** + + +Dispatched by: +Cardano.Node.ReplayBlock.LedgerReplay + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.aboutToLeadSlotLast + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.StartLeadershipCheck + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.aboutToLeadSlotLast + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.StartLeadershipCheckPlus + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.adoptedSlotLast + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.AdoptedBlock + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.blockContext + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.BlockContext + +From current configuration: +Filtered: `Invisible` because the filter level is `Info` + +### cardano.node.blockFromFuture + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.BlockFromFuture + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.blocks + +*** +Number of blocks in this chain fragment. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.AddedToCurrentChain + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.blocks + +*** +Number of blocks in this chain fragment. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.SwitchedToAFork + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.chainSync.rollForward + +*** + +*** + + +Dispatched by: +Cardano.Node.ChainSyncServerHeader.ChainSyncServerEvent.RollForward + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.chainSync.rollForward + +*** + +*** + + +Dispatched by: +Cardano.Node.ChainSyncServerBlock.ChainSyncServerEvent.RollForward + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectedPeers + +*** +Number of connected peers +*** + + +Dispatched by: +Cardano.Node.BlockFetchDecision + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.duplexConns + +*** + +*** + + +Dispatched by: +Cardano.Node.ConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.duplexConns + +*** + +*** + + +Dispatched by: +Cardano.Node.LocalConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.fullDuplexConns + +*** + +*** + + +Dispatched by: +Cardano.Node.ConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.fullDuplexConns + +*** + +*** + + +Dispatched by: +Cardano.Node.LocalConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.inboundConns + +*** + +*** + + +Dispatched by: +Cardano.Node.ConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.inboundConns + +*** + +*** + + +Dispatched by: +Cardano.Node.LocalConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.outboundConns + +*** + +*** + + +Dispatched by: +Cardano.Node.ConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.outboundConns + +*** + +*** + + +Dispatched by: +Cardano.Node.LocalConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.unidirectionalConns + +*** + +*** + + +Dispatched by: +Cardano.Node.ConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.connectionManager.unidirectionalConns + +*** + +*** + + +Dispatched by: +Cardano.Node.LocalConnectionManager.ConnectionManagerCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.couldNotForgeSlotLast + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.NoLedgerState + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.couldNotForgeSlotLast + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.NoLedgerView + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.currentKESPeriod + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.ForgeStateUpdateError + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.delegMapSize + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.StartLeadershipCheckPlus + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.density + +*** +The actual number of blocks created over the maximum expected number of blocks that could be created over the span of the last @k@ blocks. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.AddedToCurrentChain + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.density + +*** +The actual number of blocks created over the maximum expected number of blocks that could be created over the span of the last @k@ blocks. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.SwitchedToAFork + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.epoch + +*** +In which epoch is the tip of the current chain. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.AddedToCurrentChain + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.epoch + +*** +In which epoch is the tip of the current chain. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.SwitchedToAFork + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.forgedInvalidSlotLast + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.ForgedInvalidBlock + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.forgedSlotLast + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.ForgedBlock + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.ledgerState + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.LedgerState + +From current configuration: +Filtered: `Invisible` because the filter level is `Info` + +### cardano.node.ledgerView + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.LedgerView + +From current configuration: +Filtered: `Invisible` because the filter level is `Info` + +### cardano.node.mempoolBytes + +*** +Byte size of the mempool +*** + + +Dispatched by: +Cardano.Node.Mempool.AddedTx + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.mempoolBytes + +*** +Byte size of the mempool +*** + + +Dispatched by: +Cardano.Node.Mempool.ManuallyRemovedTxs + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.mempoolBytes + +*** +Byte size of the mempool +*** + + +Dispatched by: +Cardano.Node.Mempool.RejectedTx + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.mempoolBytes + +*** +Byte size of the mempool +*** + + +Dispatched by: +Cardano.Node.Mempool.RemoveTxs + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.nodeCannotForge + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.NodeCannotForge + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.nodeIsLeader + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.NodeIsLeader + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.nodeNotLeader + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.NodeNotLeader + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.notAdoptedSlotLast + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.DidntAdoptBlock + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.operationalCertificateExpiryKESPeriod + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.ForgeStateUpdateError + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.operationalCertificateStartKESPeriod + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.ForgeStateUpdateError + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.peerSelection.cold + +*** +Number of cold peers +*** + + +Dispatched by: +Cardano.Node.PeerSelectionCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.peerSelection.hot + +*** +Number of hot peers +*** + + +Dispatched by: +Cardano.Node.PeerSelectionCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.peerSelection.warm + +*** +Number of warm peers +*** + + +Dispatched by: +Cardano.Node.PeerSelectionCounters + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.remainingKESPeriods + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.ForgeStateUpdateError + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.served.block + +*** + +*** + + +Dispatched by: +Cardano.Node.BlockFetchServer.SendBlock + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.slotInEpoch + +*** +Relative slot number of the tip of the current chain within theepoch.. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.AddedToCurrentChain + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.slotInEpoch + +*** +Relative slot number of the tip of the current chain within theepoch.. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.SwitchedToAFork + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.slotIsImmutable + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.SlotIsImmutable + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.slots + +*** +Number of slots in this chain fragment. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.AddedToCurrentChain + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.slots + +*** +Number of slots in this chain fragment. +*** + + +Dispatched by: +Cardano.Node.ChainDB.AddBlockEvent.SwitchedToAFork + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.submissions.accepted + +*** + +*** + + +Dispatched by: +Cardano.Node.TxInbound.TxSubmissionProcessed + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.submissions.rejected + +*** + +*** + + +Dispatched by: +Cardano.Node.TxInbound.TxSubmissionProcessed + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.submissions.submitted + +*** + +*** + + +Dispatched by: +Cardano.Node.TxInbound.TxSubmissionCollected + +From current configuration: +Filtered: `Invisible` because the filter level is `Notice` + +### cardano.node.txsInMempool + +*** +Transactions in mempool +*** + + +Dispatched by: +Cardano.Node.Mempool.AddedTx + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.txsInMempool + +*** +Transactions in mempool +*** + + +Dispatched by: +Cardano.Node.Mempool.ManuallyRemovedTxs + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.txsInMempool + +*** +Transactions in mempool +*** + + +Dispatched by: +Cardano.Node.Mempool.RejectedTx + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.txsInMempool + +*** +Transactions in mempool +*** + + +Dispatched by: +Cardano.Node.Mempool.RemoveTxs + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.txsProcessedNum + +*** + +*** + + +Dispatched by: +Cardano.Node.Mempool.ManuallyRemovedTxs + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### cardano.node.utxoSize + +*** + +*** + + +Dispatched by: +Cardano.Node.Forge.StartLeadershipCheckPlus + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### mem.resident + +*** +TODO JNF +*** + + +Dispatched by: +Cardano.Node.Resources + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### peersFromNodeKernel + +*** +TODO Doc +*** + + +Dispatched by: +Cardano.Node.Peers + +From current configuration: +Filtered: `Visible` because the filter level is `Notice` + +### rts.gcLiveBytes + +*** +TODO JNF +*** + + +Dispatched by: +Cardano.Node.Resources + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### rts.gcMajorNum + +*** +TODO JNF +*** + + +Dispatched by: +Cardano.Node.Resources + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### rts.gcMinorNum + +*** +TODO JNF +*** + + +Dispatched by: +Cardano.Node.Resources + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### rts.gcticks + +*** +TODO JNF +*** + + +Dispatched by: +Cardano.Node.Resources + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### rts.mutticks + +*** +TODO JNF +*** + + +Dispatched by: +Cardano.Node.Resources + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### rts.threads + +*** +TODO JNF +*** + + +Dispatched by: +Cardano.Node.Resources + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +### stat.cputicks + +*** +Reports the CPU ticks, sice the process was started +*** + + +Dispatched by: +Cardano.Node.Resources + +From current configuration: +Filtered: `Visible` because the filter level is `Info` + +## Datapoints +### NodeInfo + + +*** +Basic information about this node collected at startup + + _niName_: Name of the node. + _niProtocol_: Protocol which this nodes uses. + _niVersion_: Software version which this node is using. + _niStartTime_: Start time of this node. + _niSystemStartTime_: How long did the start of the node took. +*** + + +Configuration: TraceConfig {tcOptions = fromList [([],[ConfBackend [Stdout MachineFormat,EKGBackend],ConfDetail DNormal,ConfSeverity Notice]),(["Node","AcceptPolicy"],[ConfSeverity Info]),(["Node","BlockFetchClient","CompletedBlockFetch"],[ConfLimiter "CompletedBlockFetchLimiter" 2.0]),(["Node","ChainDB"],[ConfSeverity Info]),(["Node","ChainDB","AddBlockEvent","AddBlockValidation","ValidCandidate"],[ConfLimiter "ValidCandidateLimiter" 2.0]),(["Node","ChainDB","AddBlockEvent","AddedBlockToQueue"],[ConfLimiter "AddedBlockToQueueLimiter" 2.0]),(["Node","ChainDB","AddBlockEvent","AddedBlockToVolatileDB"],[ConfLimiter "AddedBlockToVolatileDBLimiter" 2.0]),(["Node","ChainDB","CopyToImmutableDBEvent","CopiedBlockToImmutableDB"],[ConfLimiter "CopiedBlockToImmutableDBLimiter" 2.0]),(["Node","DNSResolver"],[ConfSeverity Info]),(["Node","DNSSubscription"],[ConfSeverity Info]),(["Node","DiffusionInit"],[ConfSeverity Info]),(["Node","ErrorPolicy"],[ConfSeverity Info]),(["Node","Forge"],[ConfSeverity Info]),(["Node","IpSubscription"],[ConfSeverity Info]),(["Node","LocalErrorPolicy"],[ConfSeverity Info]),(["Node","Mempool"],[ConfSeverity Info]),(["Node","Resources"],[ConfSeverity Info])], tcForwarder = TraceOptionForwarder {tofAddress = LocalSocket "/tmp/forwarder.sock", tofMode = Responder, tofConnQueueSize = 2000, tofDisconnQueueSize = 200000}, tcNodeName = Nothing, tcPeerFreqency = Just 2000, tcResourceFreqency = Just 5000} + +549 log messages. +Generated at 2022-01-12 11:04:35.660916858 CET. \ No newline at end of file diff --git a/nix/haskell.nix b/nix/haskell.nix index 08c53520b60..f2de420f1b9 100644 --- a/nix/haskell.nix +++ b/nix/haskell.nix @@ -83,7 +83,7 @@ let packages.cardano-cli.components.tests.cardano-cli-golden.build-tools = lib.mkForce (with pkgs.buildPackages; [jq coreutils shellcheck]); packages.cardano-testnet.components.tests.cardano-testnet-tests.build-tools = - lib.mkForce (with pkgs.buildPackages; [jq coreutils shellcheck]); + lib.mkForce (with pkgs.buildPackages; [jq coreutils shellcheck lsof]); }) ({ pkgs, ...}: { # Use the VRF fork of libsodium @@ -129,13 +129,6 @@ let # This is similar to jailbreakCabal, however it # does not require any messing with cabal files. packages.katip.doExactConfig = true; - # we need the following shared libraries for the musl build to succeed - # musl on x86_64, can load dynamic libraries, and we need it to use the - # shared loader, as the one in GHC is not very stable. - packages.cardano-api.components.library.enableShared = true; - packages.cardano-config.components.library.enableShared = true; - packages.cardano-node.components.library.enableShared = true; - packages.cardano-cli.components.library.enableShared = true; # split data output for ekg to reduce closure size packages.ekg.components.library.enableSeparateDataOutput = true; # cardano-cli-test depends on cardano-cli @@ -145,6 +138,7 @@ let "; packages.cardano-node-chairman.components.tests.chairman-tests.build-tools = lib.mkForce [ + pkgs.lsof config.hsPkgs.cardano-node.components.exes.cardano-node config.hsPkgs.cardano-cli.components.exes.cardano-cli config.hsPkgs.cardano-node-chairman.components.exes.cardano-node-chairman]; @@ -203,7 +197,7 @@ let }; in { - packages = lib.genAttrs projectPackages (name: fullyStaticOptions); + # packages = lib.genAttrs projectPackages (name: fullyStaticOptions); # Haddock not working and not needed for cross builds doHaddock = false; } diff --git a/nix/workbench/profiles/node-services.nix b/nix/workbench/profiles/node-services.nix index 48b2ad63398..99775c25453 100644 --- a/nix/workbench/profiles/node-services.nix +++ b/nix/workbench/profiles/node-services.nix @@ -51,24 +51,45 @@ let Protocol = "Cardano"; RequiresNetworkMagic = "RequiresMagic"; - TracingVerbosity = "NormalVerbosity"; - minSeverity = "Debug"; + UseTraceDispatcher = true; + + TraceOptionSeverity = [ + { ns = ""; severity = "Debug"; } + { ns = "Node.Resources"; severity = "Debug"; } + { ns = "Node.ChainDB"; severity = "Debug"; } + # { ns = "Node.Mempool"; severity = "Debug"; } + # { ns = "Node.ChainDB.ImmutableDBEvent"; severity = "Warning"; } + ]; - TraceMempool = true; - TraceTxInbound = true; + TraceOptionDetail = [ + { ns = ""; detail = "DNormal"; } + { ns = "Node.BlockFetchClient"; detail = "DMinimal"; } + ]; - defaultScribes = [ - [ "StdoutSK" "stdout" ] + TraceOptionBackend = [ + { ns = ""; + backends = [ + "Stdout MachineFormat" + "EKGBackend" + "Forwarder" + ]; + } + # { ns = "Node.ChainDB"; + # backends = ["Stdout HumanFormatColoured"]; + # } ]; - setupScribes = - [{ - scKind = "StdoutSK"; - scName = "stdout"; - scFormat = "ScJson"; - }]; - options = { - mapBackends = { - "cardano.node.resources" = [ "KatipBK" ]; + + TraceOptionLimiter = [ + { ns = "Node.ChainDB.OpenEvent"; + limiterName = "ChainDB open limiter"; + limiterFrequency = 0.1; + } + ]; + + TraceOptionForwarder = { + mode = "Initiator"; + address = { + filePath = "/tmp/forwarder-${toString i}.sock"; }; }; diff --git a/release.nix b/release.nix index f6172da2f30..4de6f74a8b7 100644 --- a/release.nix +++ b/release.nix @@ -121,12 +121,13 @@ let # Paths or prefixes of paths of derivations to build only on the default system (ie. linux on hydra): onlyBuildOnDefaultSystem = [ ["checks" "hlint"] ["dockerImage"] ["submitApiDockerImage"] ["clusterTests"] ["nixosTests"] - [ "haskellPackages" "cardano-node-chairman" "checks" ] - [ "haskellPackages" "cardano-node-chairman" "coverageReport" ] + [ "haskellPackages" "cardano-node-chairman" ] [ "cardano-node-profiled" ] [ "cardano-node-eventlogged" ] [ "checks" "tests" "cardano-node-chairman" ] [ "workbench" ] [ "profiles" ] + [ "exes" "tx-generator" ] [ "tx-generator" "components" "exes" ] + [ "tx-generator" ] [ "tx-generator-profiled" ] [ "locli-profiled" ] ]; @@ -135,6 +136,7 @@ let ["shell"] ["devShell"] ["devopsShell"] ["cardano-ping"] ["roots"] [ "haskellPackages" "cardano-testnet" ] [ "checks" "tests" "cardano-testnet" ] + [ "tests" "cardano-node-chairman" ] [ "tests" "cardano-testnet" ] [ "plutus-scripts" ] [ "exes" "plutus-example" ] [ "haskellPackages" "plutus-example" ] [ "tests" "plutus-example" ] [ "checks" "tests" "plutus-example"] diff --git a/scripts/lite/configuration/shelley-1.yaml b/scripts/lite/configuration/shelley-1.yaml index 00514723bde..9a8329edd7c 100644 --- a/scripts/lite/configuration/shelley-1.yaml +++ b/scripts/lite/configuration/shelley-1.yaml @@ -255,3 +255,37 @@ options: mapSeverity: cardano.node.ChainDB: Notice cardano.node.DnsSubscription: Debug + +##### New logging model ##### + +UseTraceDispatcher: False + +TraceOptionSeverity: + - ns: '' + severity: Info + - ns: Node.AcceptPolicy + severity: Silence + - ns: Node.ChainDB + severity: Debug +TraceOptionDetail: + - ns: '' + detail: DNormal + - ns: Node.BlockFetchClient + detail: DMinimal +TraceOptionBackend: + - ns: '' + backends: + - Stdout HumanFormatColoured + - Forwarder + - EKGBackend + - ns: Node.ChainDB + backends: + - Forwarder +TraceOptionLimiter: + - ns: Node.Resources + limiterName: ResourceLimiter + limiterFrequency: 1.0 +TraceOptionForwarder: + address: + filePath: /tmp/forwarder-1.sock + mode: Initiator diff --git a/scripts/lite/configuration/shelley-2.yaml b/scripts/lite/configuration/shelley-2.yaml index 00514723bde..e683412f561 100644 --- a/scripts/lite/configuration/shelley-2.yaml +++ b/scripts/lite/configuration/shelley-2.yaml @@ -255,3 +255,37 @@ options: mapSeverity: cardano.node.ChainDB: Notice cardano.node.DnsSubscription: Debug + +##### New logging model ##### + +UseTraceDispatcher: False + +TraceOptionSeverity: + - ns: '' + severity: Info + - ns: Node.AcceptPolicy + severity: Silence + - ns: Node.ChainDB + severity: Debug +TraceOptionDetail: + - ns: '' + detail: DNormal + - ns: Node.BlockFetchClient + detail: DMinimal +TraceOptionBackend: + - ns: '' + backends: + - Stdout HumanFormatColoured + - Forwarder + - EKGBackend + - ns: Node.ChainDB + backends: + - Forwarder +TraceOptionLimiter: + - ns: Node.Resources + limiterName: ResourceLimiter + limiterFrequency: 1.0 +TraceOptionForwarder: + address: + filePath: /tmp/forwarder-2.sock + mode: Initiator diff --git a/scripts/lite/configuration/shelley-3.yaml b/scripts/lite/configuration/shelley-3.yaml index 00514723bde..237abf810c3 100644 --- a/scripts/lite/configuration/shelley-3.yaml +++ b/scripts/lite/configuration/shelley-3.yaml @@ -255,3 +255,37 @@ options: mapSeverity: cardano.node.ChainDB: Notice cardano.node.DnsSubscription: Debug + +##### New logging model ##### + +UseTraceDispatcher: False + +TraceOptionSeverity: + - ns: '' + severity: Info + - ns: Node.AcceptPolicy + severity: Silence + - ns: Node.ChainDB + severity: Debug +TraceOptionDetail: + - ns: '' + detail: DNormal + - ns: Node.BlockFetchClient + detail: DMinimal +TraceOptionBackend: + - ns: '' + backends: + - Stdout HumanFormatColoured + - Forwarder + - EKGBackend + - ns: Node.ChainDB + backends: + - Forwarder +TraceOptionLimiter: + - ns: Node.Resources + limiterName: ResourceLimiter + limiterFrequency: 1.0 +TraceOptionForwarder: + address: + filePath: /tmp/forwarder-3.sock + mode: Initiator diff --git a/scripts/lite/mainnet-new-tracing.sh b/scripts/lite/mainnet-new-tracing.sh new file mode 100755 index 00000000000..8773e139bb2 --- /dev/null +++ b/scripts/lite/mainnet-new-tracing.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# This script connects a node to mainnet + +ROOT="$(realpath "$(dirname "$0")/../..")" +configuration="${ROOT}/configuration/cardano" + +data_dir=mainnetsingle +mkdir -p "${data_dir}" +db_dir="${data_dir}/db/node" +mkdir -p "${db_dir}" +socket_dir="${data_dir}/socket" +mkdir -p "${socket_dir}" + +# Launch a node +cabal run exe:cardano-node -- run \ + --config "${configuration}/mainnet-config-new-tracing.yaml" \ + --topology "${configuration}/mainnet-topology.json" \ + --database-path "${db_dir}" \ + --socket-path "${socket_dir}/node-1-socket" \ + --host-addr "127.0.0.1" \ + --port "3001" + + + +function cleanup() +{ + for child in $(jobs -p); do + echo kill "$child" && kill "$child" + done +} + +trap cleanup EXIT diff --git a/trace-dispatcher/bench/trace-dispatcher-bench.hs b/trace-dispatcher/bench/trace-dispatcher-bench.hs new file mode 100644 index 00000000000..a44f51b235f --- /dev/null +++ b/trace-dispatcher/bench/trace-dispatcher-bench.hs @@ -0,0 +1,141 @@ +import Criterion.Main +import Data.IORef + +import Cardano.Logging +import Cardano.Logging.Test.Config +import Cardano.Logging.Test.Messages +import Cardano.Logging.Test.Oracles +import Cardano.Logging.Test.Script +import Cardano.Logging.Test.Tracer +import Cardano.Logging.Test.Types +import System.Remote.Monitoring (forkServer) + +import Debug.Trace + +-- Can be run with: +-- cabal bench trace-dispatcher-bench --benchmark-option='-o benchmark-trace.html' + +main :: IO () +main = do + stdioTr <- standardTracer + tr <- stdoutTracers stdioTr + filtr <- filterTracers stdioTr + imtr <- inMemoryTracers + tlTr <- timeLimitedTracers stdioTr + ekgTr <- ekgTracers + defaultMain [ + bgroup "tracer" [ + bench "sendMessageStdout1" $ whnfIO (sendMessage 1 tr) + , bench "sendMessageStdout10" $ whnfIO (sendMessage 10 tr) + , bench "sendMessageStdout100" $ whnfIO (sendMessage 100 tr) + , bench "sendMessageStdout1000" $ whnfIO (sendMessage 1000 tr) + + , bench "sendMessageInMemory1" $ whnfIO (sendMessage 1 imtr) + , bench "sendMessageInMemory10" $ whnfIO (sendMessage 10 imtr) + , bench "sendMessageInMemory100" $ whnfIO (sendMessage 100 imtr) + , bench "sendMessageInMemory1000" $ whnfIO (sendMessage 1000 imtr) + + , bench "sendMessageFiltered1" $ whnfIO (sendMessage 1 filtr) + , bench "sendMessageFiltered10" $ whnfIO (sendMessage 10 filtr) + , bench "sendMessageFiltered100" $ whnfIO (sendMessage 100 filtr) + , bench "sendMessageFiltered1000" $ whnfIO (sendMessage 1000 filtr) + + , bench "sendMessageTimeLimited1000_100" $ whnfIO (sendMessage 1000 tlTr) + , bench "sendMessageTimeLimited10000_100" $ whnfIO (sendMessage 10000 tlTr) + + , bench "sendEKG 5/1" $ whnfIO (sendMessage 1 ekgTr) + , bench "sendEKG 5/10" $ whnfIO (sendMessage 10 ekgTr) + , bench "sendEKG 5/100" $ whnfIO (sendMessage 100 ekgTr) + , bench "sendEKG 5/1000" $ whnfIO (sendMessage 1000 ekgTr) + ] + ] + +stdoutTracers :: Trace IO FormattedMessage -> IO (Trace IO Message) +stdoutTracers stdoutTracer = do + forwardTrRef <- newIORef [] + forwardTracer' <- testTracer forwardTrRef + tr <- mkCardanoTracer + stdoutTracer + forwardTracer' + Nothing + "Test" + namesForMessage + severityForMessage + privacyForMessage + configureTracers config1 docMessage [tr] + pure tr + +filterTracers :: Trace IO FormattedMessage -> IO (Trace IO Message) +filterTracers stdoutTracer = do + forwardTrRef <- newIORef [] + forwardTracer' <- testTracer forwardTrRef + tr <- mkCardanoTracer + stdoutTracer + forwardTracer' + Nothing + "Test" + namesForMessage + severityForMessage + privacyForMessage + configureTracers config2 docMessage [tr] + pure tr + +inMemoryTracers :: IO (Trace IO Message) +inMemoryTracers = do + stdoutTrRef <- newIORef [] + stdoutTracer' <- testTracer stdoutTrRef + forwardTrRef <- newIORef [] + forwardTracer' <- testTracer forwardTrRef + tr <- mkCardanoTracer + stdoutTracer' + forwardTracer' + Nothing + "Test" + namesForMessage + severityForMessage + privacyForMessage + configureTracers config1 docMessage [tr] + pure tr + +timeLimitedTracers :: Trace IO FormattedMessage -> IO (Trace IO Message) +timeLimitedTracers stdoutTracer = do + forwardTrRef <- newIORef [] + forwardTracer' <- testTracer forwardTrRef + tr <- mkCardanoTracer + stdoutTracer + forwardTracer' + Nothing + "Test" + namesForMessage + severityForMessage + privacyForMessage + configureTracers config3 docMessage [tr] + pure tr + +ekgTracers :: IO (Trace IO Message) +ekgTracers = do + stdoutTrRef <- newIORef [] + stdoutTracer' <- testTracer stdoutTrRef + forwardTrRef <- newIORef [] + forwardTracer' <- testTracer forwardTrRef + ekgServer <- forkServer "localhost" 8000 + ekgTracer <- ekgTracer (Right ekgServer) + tr <- mkCardanoTracer + stdoutTracer' + forwardTracer' + Nothing + "Test" + namesForMessage + severityForMessage + privacyForMessage + configureTracers config4 docMessage [tr] + pure tr + +timesRepeat :: Int -> IO () -> IO () +timesRepeat 0 _ = pure () +timesRepeat n action = do + action + timesRepeat (n - 1) action + +sendMessage n tr = + timesRepeat n (traceWith tr (Message1 1 1)) diff --git a/trace-dispatcher/doc/trace-dispatcher.md b/trace-dispatcher/doc/trace-dispatcher.md index 8f977737f57..4114fe3a7aa 100644 --- a/trace-dispatcher/doc/trace-dispatcher.md +++ b/trace-dispatcher/doc/trace-dispatcher.md @@ -232,7 +232,7 @@ In addition, the __severity context__ of a particular trace can be further overr `Info` is the default __severity__, in the absence of trace context or configured severity overrides. -NOTE: as en extension to the filtering severity type (`SeverityF`), a `SilenceF` constructor is defined, which encodes unconditional silencing of a particular trace -- and therefore serves as a semantic expression of the `nullTracer` functionality. +NOTE: as en extension to the filtering severity type (`SeverityF`), a `Silence` constructor is defined, which encodes unconditional silencing of a particular trace -- and therefore serves as a semantic expression of the `nullTracer` functionality. ### Privacy @@ -384,7 +384,7 @@ foldTraceM :: MonadIO m -> m (Trace m a) foldMTraceM :: forall a acc m . MonadIO m - => (acc -> LoggingContext -> Maybe TraceControl -> a -> acc) + => (acc -> LoggingContext -> Maybe TraceControl -> a -> m acc) -> acc -> Trace m (Folding a acc) -> m (Trace m a) @@ -477,7 +477,7 @@ These are the options that can be configured based on a namespace: ```haskell data ConfigOption = - -- | Severity level for filtering (default is WarningF) + -- | Severity level for filtering (default is Warning) ConfSeverity SeverityF -- | Detail level of message representation (Default is DNormal) | ConfDetail DetailLevel @@ -508,7 +508,7 @@ all messages with Info or higher Priority are shown: ```yaml TraceOptionSeverity: - ns: '' - severity: InfoF + severity: Info ``` But if you want to see Debug messages of the ChainDB tracer, then add: @@ -516,9 +516,9 @@ But if you want to see Debug messages of the ChainDB tracer, then add: ```yaml TraceOptionSeverity: - ns: '' - severity: InfoF + severity: Info - ns: Node.ChainDB - severity: DebugF + severity: Debug ``` And if you never want to see any message of the AcceptPolicy tracer, then add: @@ -526,9 +526,9 @@ And if you never want to see any message of the AcceptPolicy tracer, then add: ```yaml TraceOptionSeverity: - ns: '' - severity: InfoF + severity: Info - ns: Node.ChainDB - severity: DebugF + severity: Debug - ns: Node.AcceptPolicy severity: SilentF ``` @@ -635,7 +635,7 @@ __Trace filtering__ is affected by __annotation__ and __configuration__ componen For the purposes of trace dispatcher implementation, direct trace filtering can be done by `filterTraceBySeverity`, which only processes messages further with a severity equal or greater as the given one. E.g.: ```haskell -let filteredTracer = filterTraceBySeverity WarningF exampleTracer +let filteredTracer = filterTraceBySeverity Warning exampleTracer ``` A more general filter function is offered, which gives access to the object and a `LoggingContext`, which contains the namespace, the severity, the privacy and the detailLevel: diff --git a/trace-dispatcher/examples/Examples/Aggregation.hs b/trace-dispatcher/examples/Examples/Aggregation.hs index 281933a8e14..6672cffd563 100644 --- a/trace-dispatcher/examples/Examples/Aggregation.hs +++ b/trace-dispatcher/examples/Examples/Aggregation.hs @@ -51,7 +51,7 @@ calculate BaseStats{..} _ _ val = testAggregation :: IO () testAggregation = do - simpleTracer <- standardTracer + simpleTracer <- standardTracer formTracer <- humanFormatter True "cardano" simpleTracer tracer <- foldTraceM calculate emptyStats formTracer configureTracers emptyTraceConfig baseStatsDocumented [tracer] diff --git a/trace-dispatcher/examples/Examples/Configuration.hs b/trace-dispatcher/examples/Examples/Configuration.hs index f36d09ae26a..a5d9bd22b73 100644 --- a/trace-dispatcher/examples/Examples/Configuration.hs +++ b/trace-dispatcher/examples/Examples/Configuration.hs @@ -45,8 +45,15 @@ config1 = TraceConfig { , (["tracer2"], [ConfSeverity (SeverityF (Just Critical))]) , (["tracer2","bubble"], [ConfSeverity (SeverityF (Just Info))]) ] - , tcForwarder = LocalSocket "forwarder.log" - , tcForwarderQueueSize = 100 + , tcForwarder = TraceOptionForwarder { + tofAddress = LocalSocket "forwarder.log" + , tofMode = Responder + , tofConnQueueSize = 100 + , tofDisconnQueueSize = 1000 + } + , tcNodeName = Nothing + , tcPeerFreqency = Nothing + , tcResourceFreqency = Nothing } config2 :: TraceConfig @@ -56,11 +63,18 @@ config2 = TraceConfig { , (["tracer2"], [ConfSeverity (SeverityF (Just Warning))]) , (["tracer2","bubble"], [ConfSeverity (SeverityF (Just Debug))]) ] - , tcForwarder = LocalSocket "forwarder.log" - , tcForwarderQueueSize = 100 + , tcForwarder = TraceOptionForwarder { + tofAddress = LocalSocket "forwarder.log" + , tofMode = Responder + , tofConnQueueSize = 100 + , tofDisconnQueueSize = 1000 + } + , tcNodeName = Just "node-1" + , tcPeerFreqency = Nothing + , tcResourceFreqency = Nothing } -testConfig' :: MonadIO m => TraceConfig -> Trace m TestMessage -> Trace m TestMessage -> m () +testConfig' :: TraceConfig -> Trace IO TestMessage -> Trace IO TestMessage -> IO () testConfig' tc t1 t2 = do let bubbleTracer = appendName "bubble" t2 configureTracers tc testMessageDocumented [t1, t2] diff --git a/trace-dispatcher/examples/Examples/DataPoint.hs b/trace-dispatcher/examples/Examples/DataPoint.hs new file mode 100644 index 00000000000..8460c5ff076 --- /dev/null +++ b/trace-dispatcher/examples/Examples/DataPoint.hs @@ -0,0 +1,51 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE ScopedTypeVariables #-} + +{-# OPTIONS_GHC -Wno-orphans #-} + +module Examples.DataPoint ( + testDataPoint +) where + +import qualified Data.Aeson as A +import Data.ByteString.Lazy.UTF8 +import qualified Data.Map.Strict as M +import Trace.Forward.Utils.DataPoint (DataPoint (..)) +import GHC.Conc +import GHC.Generics (Generic) + +import Cardano.Logging + + + +data BaseStats = BaseStats { + bsMeasure :: Double, + bsMin :: Double, + bsMax :: Double, + bsCount :: Int, + bsSum :: Double + } deriving (Eq, Ord, Show, Generic) + +instance A.ToJSON BaseStats where + toEncoding = A.genericToEncoding A.defaultOptions + +instance Show DataPoint where + show (DataPoint a) = toString $ A.encode a + +namesForBaseStats :: BaseStats -> Namespace +namesForBaseStats _ = ["BaseStats"] + +emptyStats :: BaseStats +emptyStats = BaseStats 0.0 100000000.0 (-100000000.0) 0 0.0 + +testDataPoint :: IO () +testDataPoint = do + dpMap <- newTVarIO M.empty + let rawDataPointTracer = dataPointTracer dpMap + dpTracer <- mkDataPointTracer + rawDataPointTracer + namesForBaseStats + traceWith dpTracer emptyStats + dps <- readTVarIO dpMap + print dps diff --git a/trace-dispatcher/examples/Examples/Documentation.hs b/trace-dispatcher/examples/Examples/Documentation.hs index 730c30ccc95..e9dfc4d7526 100644 --- a/trace-dispatcher/examples/Examples/Documentation.hs +++ b/trace-dispatcher/examples/Examples/Documentation.hs @@ -19,4 +19,4 @@ docTracers = do (appendName "node" t2') bl <- documentMarkdown traceForgeEventDocu [t1, t2] res <- buildersToText bl emptyTraceConfig - T.writeFile "/home/yupanqui/IOHK/Testdocu.md" res + T.writeFile "/tmp/Testdocu.md" res diff --git a/trace-dispatcher/examples/Examples/TestObjects.hs b/trace-dispatcher/examples/Examples/TestObjects.hs index c858ee58a7a..8d28a072bcf 100644 --- a/trace-dispatcher/examples/Examples/TestObjects.hs +++ b/trace-dispatcher/examples/Examples/TestObjects.hs @@ -25,7 +25,7 @@ import Cardano.Logging import qualified Data.Aeson as AE import qualified Data.HashMap.Strict as HM import Data.Kind (Type) -import Data.Text (Text, pack) +import Data.Text (pack) import Data.Word (Word64) import GHC.Generics import Text.Printf (printf) @@ -94,9 +94,6 @@ newtype LogHash = LogHash { unLogHash :: Word64 } instance AE.ToJSON LogHash where toEncoding = AE.genericToEncoding AE.defaultOptions -showT :: Show a => a -> Text -showT = pack . show - -- The actual test trace messages data TraceForgeEvent blk = TraceStartLeadershipCheck SlotNo @@ -142,11 +139,11 @@ instance LogFormatting (TraceForgeEvent LogBlock) where ] asMetrics (TraceStartLeadershipCheck slotNo) = - [IntM "aboutToLeadSlotLast" (fromIntegral $ unSlotNo slotNo)] + [IntM "cardano.node.aboutToLeadSlotLast" (fromIntegral $ unSlotNo slotNo)] asMetrics (TraceSlotIsImmutable slot _tipPoint _tipBlkNo) = - [IntM "slotIsImmutable" (fromIntegral $ unSlotNo slot)] + [IntM "cardano.node.slotIsImmutable" (fromIntegral $ unSlotNo slot)] asMetrics (TraceBlockFromFuture slot _slotNo) = - [IntM "blockFromFuture" (fromIntegral $ unSlotNo slot)] + [IntM "cardano.node.blockFromFuture" (fromIntegral $ unSlotNo slot)] traceForgeEventDocu :: Documented (TraceForgeEvent LogBlock) traceForgeEventDocu = Documented diff --git a/trace-dispatcher/examples/Main.hs b/trace-dispatcher/examples/Main.hs index 48705ab53b1..9ca46988f81 100644 --- a/trace-dispatcher/examples/Main.hs +++ b/trace-dispatcher/examples/Main.hs @@ -9,14 +9,26 @@ import Examples.EKG import Examples.FrequencyLimiting import Examples.Routing import Examples.Trivial +import Examples.DataPoint + main :: IO () main = do + putStrLn "test1" test1 + putStrLn "test2" test2 + putStrLn "testAggregation" testAggregation + putStrLn "testRouting" testRouting + putStrLn "testConfig" testConfig + putStrLn "testLimiting" testLimiting + putStrLn "docTracers" docTracers + putStrLn "testEKG" testEKG + putStrLn "testDataPoint" + testDataPoint diff --git a/trace-dispatcher/examples/config.json b/trace-dispatcher/examples/config.json index efb7e3985d2..043f925d71c 100644 --- a/trace-dispatcher/examples/config.json +++ b/trace-dispatcher/examples/config.json @@ -2,15 +2,15 @@ "TraceOptionSeverity": [ { "ns": "", - "severity": "InfoF" + "severity": "Info" }, { "ns": "Cardano.Node.AcceptPolicy", - "severity": "SilenceF" + "severity": "Silence" }, { "ns": "Cardano.Node.ChainDB", - "severity": "DebugF" + "severity": "Debug" } ], "TraceOptionDetail": [ @@ -42,7 +42,7 @@ "TraceOptionForwarder": { "filePath": "/tmp/forwarder.sock" }, - "TraceOptionForwardQueueSize": 1000, + "TraceOptionForwardQueueSize": 1000, "TraceOptionLimiter": [ ] diff --git a/trace-dispatcher/examples/config.nix b/trace-dispatcher/examples/config.nix index 6e5d2f3b3e9..e2fb20a3b1e 100644 --- a/trace-dispatcher/examples/config.nix +++ b/trace-dispatcher/examples/config.nix @@ -1,9 +1,9 @@ To add in node-services.nix TraceOptionSeverity = [ - {ns = ""; severity = "InfoF";} - {ns = "Cardano.Node.AcceptPolicy"; severity = "SilenceF";} - {ns = "Cardano.Node.ChainDB"; severity = "DebugF";} + {ns = ""; severity = "Info";} + {ns = "Cardano.Node.AcceptPolicy"; severity = "Silence";} + {ns = "Cardano.Node.ChainDB"; severity = "Debug";} ]; TraceOptionDetail = [ diff --git a/trace-dispatcher/src/Cardano/Logging.hs b/trace-dispatcher/src/Cardano/Logging.hs index d6e0e5aca2f..3414c43bd65 100644 --- a/trace-dispatcher/src/Cardano/Logging.hs +++ b/trace-dispatcher/src/Cardano/Logging.hs @@ -9,7 +9,9 @@ import Cardano.Logging.FrequencyLimiter as X import Cardano.Logging.Trace as X import Cardano.Logging.Tracer.EKG as X import Cardano.Logging.Tracer.Standard as X +import Cardano.Logging.Forwarding as X import Cardano.Logging.Tracer.Forward as X +import Cardano.Logging.Tracer.DataPoint as X import Cardano.Logging.Types as X import Cardano.Logging.Tracer.Composed as X import Control.Tracer as X hiding (traceWith, nullTracer, Tracer) diff --git a/trace-dispatcher/src/Cardano/Logging/Configuration.hs b/trace-dispatcher/src/Cardano/Logging/Configuration.hs index e6a0f236359..2ab502664c4 100644 --- a/trace-dispatcher/src/Cardano/Logging/Configuration.hs +++ b/trace-dispatcher/src/Cardano/Logging/Configuration.hs @@ -20,7 +20,7 @@ module Cardano.Logging.Configuration , getBackends ) where -import Control.Exception (throwIO) +import Control.Exception (throwIO, SomeException, catch) import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.IO.Unlift (MonadUnliftIO) import qualified Control.Tracer as T @@ -53,17 +53,27 @@ defaultConfig = emptyTraceConfig { } -- | Call this function at initialisation, and later for reconfiguration -configureTracers :: Monad m => TraceConfig -> Documented a -> [Trace m a]-> m () -configureTracers config (Documented documented) tracers = do - mapM_ (configureTrace Reset) tracers - mapM_ (configureAllTrace (Config config)) tracers - mapM_ (configureTrace Optimize) tracers - where +configureTracers :: forall a. + TraceConfig + -> Documented a + -> [Trace IO a] + -> IO () +configureTracers config (Documented documented) tracers = + catch + (do + mapM_ (configureTrace Reset) tracers + mapM_ (configureAllTrace (Config config)) tracers + mapM_ (configureTrace Optimize) tracers) + (\ (ex :: SomeException) -> print (show ex ++ " " ++ show (head documented))) + where configureTrace control (Trace tr) = T.traceWith tr (emptyLoggingContext, Just control, dmPrototype (head documented)) configureAllTrace control (Trace tr) = mapM - ((\ m -> T.traceWith tr (emptyLoggingContext, Just control, m)) . dmPrototype) + (\d -> + catch + (((\ m -> T.traceWith tr (emptyLoggingContext, Just control, m)) . dmPrototype) d) + (\ (ex :: SomeException) -> print (show ex ++ " " ++ show d))) documented -- | Take a selector function called 'extract'. @@ -362,7 +372,7 @@ parseRepresentation bs = transform (decodeEither' bs) transform (Left e) = Left e transform (Right rl) = Right $ transform' emptyTraceConfig rl transform' :: TraceConfig -> ConfigRepresentation -> TraceConfig - transform' (TraceConfig tc _fc _fcc) cr = + transform' TraceConfig {tcOptions=tc} cr = let tc' = foldl' (\ tci (TraceOptionSeverity ns severity') -> let ns' = split (=='.') ns ns'' = if ns' == [""] then [] else ns' @@ -390,7 +400,9 @@ parseRepresentation bs = transform (decodeEither' bs) in TraceConfig tc'''' (traceOptionForwarder cr) - (traceOptionForwardQueueSize cr) + (traceOptionNodeName cr) + (traceOptionPeerFreqency cr) + (traceOptionResourceFreqency cr) data TraceOptionSeverity = TraceOptionSeverity { nsS :: Text @@ -456,13 +468,17 @@ instance AE.FromJSON TraceOptionLimiter where <*> obj .: "limiterName" <*> obj .: "limiterFrequency" + + data ConfigRepresentation = ConfigRepresentation { traceOptionSeverity :: [TraceOptionSeverity] , traceOptionDetail :: [TraceOptionDetail] , traceOptionBackend :: [TraceOptionBackend] , traceOptionLimiter :: [TraceOptionLimiter] - , traceOptionForwarder :: ForwarderAddr - , traceOptionForwardQueueSize :: Int + , traceOptionForwarder :: TraceOptionForwarder + , traceOptionNodeName :: Maybe Text + , traceOptionPeerFreqency :: Maybe Int + , traceOptionResourceFreqency :: Maybe Int } deriving (Eq, Ord, Show) @@ -473,4 +489,6 @@ instance AE.FromJSON ConfigRepresentation where <*> obj .: "TraceOptionBackend" <*> obj .: "TraceOptionLimiter" <*> obj .: "TraceOptionForwarder" - <*> obj .: "TraceOptionForwardQueueSize" + <*> obj .:? "TraceOptionNodeName" + <*> obj .:? "TraceOptionPeerFreqency" + <*> obj .:? "TraceOptionResourceFreqency" diff --git a/trace-dispatcher/src/Cardano/Logging/DocuGenerator.hs b/trace-dispatcher/src/Cardano/Logging/DocuGenerator.hs index be2844703fa..e1db0b55bad 100644 --- a/trace-dispatcher/src/Cardano/Logging/DocuGenerator.hs +++ b/trace-dispatcher/src/Cardano/Logging/DocuGenerator.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE LambdaCase #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -9,62 +8,121 @@ module Cardano.Logging.DocuGenerator ( , addFiltered , addLimiter , docTracer + , docTracerDatapoint + , anyProto + , showT + , DocuResult + , appDoc + , mapDoc ) where import Cardano.Logging.Types -import Control.Monad.IO.Class (MonadIO, liftIO) -import qualified Control.Tracer as T -import Data.Aeson.Text (encodeToLazyText) -import Data.IORef (modifyIORef, newIORef, readIORef) -import Data.List (intersperse, nub, sortBy) -import qualified Data.Map as Map -import Data.Text (Text) +import Control.Exception (SomeException, catch) +import Control.Monad.IO.Class (MonadIO, liftIO) +import qualified Control.Tracer as T +import Data.IORef (modifyIORef, newIORef, readIORef) +import Data.List (intersperse, nub, sortBy) +import qualified Data.Map as Map +import Data.Text (Text, pack, toLower) +import qualified Data.Text as T import Data.Text.Internal.Builder (toLazyText) -import Data.Text.Lazy (toStrict) -import Data.Text.Lazy.Builder (Builder, fromString, fromText, - singleton) -import Data.Time (getZonedTime) +import Data.Text.Lazy (toStrict) +import Data.Text.Lazy.Builder (Builder, fromString, fromText, + singleton) +import Data.Time (getZonedTime) +import Trace.Forward.Utils.DataPoint (DataPoint (..)) + +data DocuResult = + DocuTracer Builder + | DocuMetric Builder + | DocuDatapoint Builder + +isTracer :: DocuResult -> Bool +isTracer DocuTracer {} = True +isTracer _ = False + +isMetric :: DocuResult -> Bool +isMetric DocuMetric {} = True +isMetric _ = False + +isDatapoint :: DocuResult -> Bool +isDatapoint DocuDatapoint {} = True +isDatapoint _ = False + +unpackDocu :: DocuResult -> Builder +unpackDocu (DocuTracer b) = b +unpackDocu (DocuMetric b) = b +unpackDocu (DocuDatapoint b) = b + +anyProto :: a +anyProto = undefined + +showT :: Show a => a -> Text +showT = pack . show + +appDoc :: (a -> b) -> DocMsg a -> DocMsg b +appDoc f DocMsg {..} = DocMsg (f dmPrototype) dmMetricsMD dmMarkdown + +mapDoc :: (a -> b) -> [DocMsg a] -> [DocMsg b] +mapDoc f = map (appDoc f) docTracer :: MonadIO m => BackendConfig - -> m (Trace m FormattedMessage) -docTracer backendConfig = liftIO $ do - pure $ Trace $ T.arrow $ T.emit output + -> Trace m FormattedMessage +docTracer backendConfig = Trace $ T.arrow $ T.emit output where output p@(_, Just Document {}, FormattedMetrics m) = docIt backendConfig (FormattedMetrics m) p output (lk, Just c@Document {}, FormattedForwarder lo) = - docIt backendConfig (FormattedHuman False "") (lk, Just c, lo) + docIt backendConfig (FormattedForwarder lo) (lk, Just c, lo) output (lk, Just c@Document {}, FormattedHuman co msg) = docIt backendConfig (FormattedHuman co "") (lk, Just c, msg) output (lk, Just c@Document {}, FormattedMachine msg) = docIt backendConfig (FormattedMachine "") (lk, Just c, msg) output (_, _, _) = pure () -documentTracers :: MonadIO m => Documented a -> [Trace m a] -> m DocCollector +docTracerDatapoint :: MonadIO m + => BackendConfig + -> Trace m DataPoint +docTracerDatapoint backendConfig = Trace $ T.arrow $ T.emit output + where + output p@(_, Just Document {}, DataPoint m) = + docItDatapoint backendConfig (DataPoint m) p + output (_, _, _) = pure () + +documentTracers :: Documented a -> [Trace IO a] -> IO DocCollector documentTracers (Documented documented) tracers = do let docIdx = zip documented [0..] coll <- fmap DocCollector (liftIO $ newIORef Map.empty) mapM_ (docTrace docIdx coll) tracers pure coll where - docTrace docIdx docColl (Trace tr) = + docTrace docIdx dc@(DocCollector docColl) (Trace tr) = mapM_ - (\ (DocMsg {..}, idx) -> do - T.traceWith tr (emptyLoggingContext, - Just (Document idx dmMarkdown dmMetricsMD docColl), - dmPrototype)) + (\ (DocMsg {..}, idx) -> catch ( + T.traceWith tr (emptyLoggingContext, + Just (Document idx dmMarkdown dmMetricsMD dc), dmPrototype)) + (\ (ex :: SomeException) -> + modifyIORef docColl + (\ docMap -> + Map.insert + idx + (case Map.lookup idx docMap of + Just e -> e { ldDoc = ldDoc e <> "Error generating doc" <> (pack . show) ex} + Nothing -> emptyLogDoc ("Error generating doc" <> (pack . show) ex) []) + docMap))) docIdx + addFiltered :: MonadIO m => TraceControl -> Maybe SeverityF -> m () addFiltered (Document idx mdText mdMetrics (DocCollector docRef)) (Just sev) = do liftIO $ modifyIORef docRef (\ docMap -> Map.insert idx - ((\e -> e { ldFiltered = sev : ldFiltered e}) + ((\e -> e { ldFiltered = seq sev (sev : ldFiltered e)}) (case Map.lookup idx docMap of Just e -> e - Nothing -> emptyLogDoc mdText mdMetrics)) + Nothing -> seq mdText (seq mdMetrics (emptyLogDoc mdText mdMetrics)))) docMap) addFiltered _ _ = pure () @@ -73,10 +131,10 @@ addLimiter (Document idx mdText mdMetrics (DocCollector docRef)) (ln, lf) = do liftIO $ modifyIORef docRef (\ docMap -> Map.insert idx - ((\e -> e { ldLimiter = (ln, lf) : ldLimiter e}) + ((\e -> e { ldLimiter = seq ln (seq lf ((ln, lf) : ldLimiter e))}) (case Map.lookup idx docMap of Just e -> e - Nothing -> emptyLogDoc mdText mdMetrics)) + Nothing -> seq mdText (seq mdMetrics (emptyLogDoc mdText mdMetrics)))) docMap) addLimiter _ _ = pure () @@ -90,59 +148,161 @@ docIt backend formattedMessage (LoggingContext {..}, liftIO $ modifyIORef docRef (\ docMap -> Map.insert idx - ((\e -> e { ldBackends = (backend, formattedMessage) : ldBackends e - , ldNamespace = lcNamespace : ldNamespace e + ((\e -> e { ldBackends = seq backend (seq formattedMessage + ((backend, formattedMessage) : ldBackends e)) + , ldNamespace = seq lcNamespace + (lcNamespace : ldNamespace e) , ldSeverity = case lcSeverity of Nothing -> ldSeverity e - Just s -> s : ldSeverity e + Just s -> seq s (s : ldSeverity e) , ldPrivacy = case lcPrivacy of Nothing -> ldPrivacy e - Just s -> s : ldPrivacy e + Just p -> seq p (p : ldPrivacy e) , ldDetails = case lcDetails of Nothing -> ldDetails e - Just s -> s : ldDetails e + Just d -> seq d (d : ldDetails e) }) (case Map.lookup idx docMap of Just e -> e - Nothing -> emptyLogDoc mdText mdMetrics)) + Nothing -> seq mdText (seq mdMetrics (emptyLogDoc mdText mdMetrics)))) docMap) -buildersToText :: [(Namespace, Builder)] -> TraceConfig -> IO Text +docItDatapoint :: MonadIO m => + BackendConfig + -> DataPoint + -> (LoggingContext, Maybe TraceControl, a) + -> m () +docItDatapoint _backend _formattedMessage (LoggingContext {..}, + Just (Document idx mdText _mdMetrics (DocCollector docRef)), _msg) = do + liftIO $ modifyIORef docRef (\ docMap -> + Map.insert + idx + ((\e -> e { ldNamespace = seq lcNamespace + (lcNamespace : ldNamespace e) + , ldBackends = [(DatapointBackend, FormattedMachine "")] + }) + (case Map.lookup idx docMap of + Just e -> e + Nothing -> seq mdText (emptyLogDoc mdText []))) + docMap) + +generateTOC :: [Namespace] -> [Namespace] -> [Namespace] -> Builder +generateTOC traces metrics datapoints = + generateTOCTraces + <> generateTOCMetrics + <> generateTOCDatapoints + where + generateTOCTraces = + fromText "\n1.[Trace Messages] (#trace-messages)" + <> mconcat (zipWith (curry namespaceToToc) traces [(1 :: Int) .. ]) + generateTOCDatapoints = + fromText "\n3.[Datapoints] (#datapoints)" + <> mconcat (zipWith (curry namespaceToToc) datapoints [(1 :: Int) .. ]) + namespaceToToc (ns, i) = + fromText "\n1." + <> fromText ((pack.show) i) + <> fromText " [" + <> namespaceBuilder ns + <> fromText "] (#" + <> namespaceRefBuilder ns + <> fromText ")" + namespaceBuilder ns = mconcat (intersperse (singleton '.') (map fromText ns)) + namespaceRefBuilder ns = mconcat (map (fromText . toLower) ns) + generateTOCMetrics = + fromText "\n2.[Metrics] (#metrics)" + <> mconcat (zipWith (curry nameToToc) metrics [(1 :: Int) .. ]) + nameToToc ([name], i) = + fromText "\n2." + <> fromText ((pack.show) i) + <> fromText " [" + <> fromText name + <> fromText "] (#" + <> fromText (nameRefBuilder name) + <> fromText ")" + nameToToc (list, _i) = + fromText "unexpected" <> fromText ((pack . show) list) + nameRefBuilder name = toLower $ T.filter (/= '.') name + +buildersToText :: [(Namespace, DocuResult)] -> TraceConfig -> IO Text buildersToText builderList configuration = do time <- getZonedTime --- tz <- getTimeZone - let sortedBuilders = sortBy (\ (l,_) (r,_) -> compare l r) builderList - num = length builderList - content = mconcat $ intersperse (fromText "\n\n") (map snd sortedBuilders) + let traceBuilders = sortBy (\ (l,_) (r,_) -> compare l r) + (filter (isTracer . snd) builderList) + metricsBuilders = sortBy (\ (l,_) (r,_) -> compare l r) + (filter (isMetric .snd) builderList) + datapointBuilders = sortBy (\ (l,_) (r,_) -> compare l r) + (filter (isDatapoint . snd) builderList) + header = fromText "# Cardano Trace Documentation" + header1 = fromText "# Table Of Contents" + toc = generateTOC (map fst traceBuilders) (map fst metricsBuilders) (map fst datapointBuilders) + header2 = fromText "\n\n## Trace Messages\n" + contentT = mconcat $ intersperse (fromText "\n\n") + (map (unpackDocu . snd) traceBuilders) + header3 = fromText "\n\n## Metrics\n" + contentM = mconcat $ intersperse (fromText "\n\n") + (map (unpackDocu . snd) metricsBuilders) + header4 = fromText "\n\n## Datapoints\n" + contentD = mconcat $ intersperse (fromText "\n\n") + (map (unpackDocu . snd) datapointBuilders) config = fromString $ "\n\nConfiguration: " <> show configuration - numbers = fromString $ "\n\n" <> show num <> " log messages." + numbers = fromString $ "\n\n" <> show (length builderList) <> " log messages." ts = fromString $ "\nGenerated at " <> show time <> "." - pure $ toStrict $ toLazyText (content <> config <> numbers <> ts) + pure $ toStrict $ toLazyText ( + header + <> header1 + <> toc + <> header2 + <> contentT + <> header3 + <> contentM + <> header4 + <> contentD + <> config + <> numbers + <> ts) -documentMarkdown :: MonadIO m => +documentMarkdown :: Documented a - -> [Trace m a] - -> m [(Namespace, Builder)] + -> [Trace IO a] + -> IO [(Namespace, DocuResult)] documentMarkdown (Documented documented) tracers = do DocCollector docRef <- documentTracers (Documented documented) tracers items <- fmap Map.toList (liftIO (readIORef docRef)) let sortedItems = sortBy (\ (_,l) (_,r) -> compare (ldNamespace l) (ldNamespace r)) items - pure $ map (\(i, ld) -> case ldNamespace ld of + let messageDocs = map (\(i, ld) -> case ldNamespace ld of [] -> (["No Namespace"], documentItem (i, ld)) - (hn:_) -> (hn, documentItem (i, ld))) - sortedItems + (hn:_) -> (hn, documentItem (i, ld))) sortedItems + metricsItems = filter (not . Map.null . ldMetricsDoc . snd) sortedItems + metricsDocs = map documentMetrics metricsItems + pure $ messageDocs ++ concat metricsDocs where - documentItem :: (Int, LogDoc) -> Builder - documentItem (_idx, ld@LogDoc {..}) = mconcat $ intersperse (fromText "\n\n") - [ namespacesBuilder (nub ldNamespace) - , betweenLines (fromText ldDoc) --- , representationBuilder (documented `listIndex` idx) - , propertiesBuilder ld - , configBuilder ld - , metricsBuilder ldMetricsDoc (filter fMetrics (nub ldBackends)) - ] + documentItem :: (Int, LogDoc) -> DocuResult + documentItem (_idx, ld@LogDoc {..}) = + case ldBackends of + [(DatapointBackend, _)] -> DocuDatapoint $ + mconcat $ intersperse (fromText "\n\n") + [ namespacesBuilder (nub ldNamespace) + , betweenLines (fromText ldDoc) + ] + _ -> DocuTracer $ + mconcat $ intersperse (fromText "\n\n") + [ namespacesBuilder (nub ldNamespace) + , betweenLines (fromText ldDoc) + , propertiesBuilder ld + , configBuilder ld + ] + + documentMetrics :: (Int, LogDoc) -> [([Text], DocuResult)] + documentMetrics (_idx, ld@LogDoc {..}) = + map (\(name, builder) -> ([name] , DocuMetric $ + mconcat $ intersperse (fromText "\n\n") + [ builder + , namespacesMetricsBuilder (nub ldNamespace) + , configMetricsBuilder ld + ])) + $ metricsBuilder ldMetricsDoc namespacesBuilder :: [Namespace] -> Builder namespacesBuilder [ns] = namespaceBuilder ns @@ -154,55 +314,14 @@ documentMarkdown (Documented documented) tracers = do namespaceBuilder ns = fromText "### " <> mconcat (intersperse (singleton '.') (map fromText ns)) - _representationBuilder :: LogFormatting a => Maybe (DocMsg a) -> Builder - _representationBuilder Nothing = mempty - _representationBuilder (Just DocMsg {..}) = mconcat - $ intersperse (singleton '\n') - [case forHuman dmPrototype of - "" -> mempty - t -> fromText "For human:\n" <> asCode (fromText t) - , let r1 = forMachine DMinimal dmPrototype - r2 = forMachine DNormal dmPrototype - r3 = forMachine DDetailed dmPrototype - in if r1 == mempty && r2 == mempty && r3 == mempty - then mempty - else if r1 == r2 && r2 == r3 - then fromText "For machine:\n" - <> asCode (fromText (toStrict (encodeToLazyText r1))) - else if r1 == r2 - then fromText "For machine regular:\n" - <> asCode (fromText (toStrict (encodeToLazyText r2))) - <> fromText "\nFor machine detailed: " - <> asCode (fromText (toStrict (encodeToLazyText r3))) - else if r2 == r3 - then fromText "For machine brief:\n" - <> asCode (fromText (toStrict (encodeToLazyText r1))) - <> fromText "\nFor machine regular:\n" - <> asCode (fromText (toStrict (encodeToLazyText r2))) - else fromText "For machine brief:\n" - <> asCode (fromText (toStrict (encodeToLazyText r1))) - <> fromText "\nFor machine regular:\n" - <> asCode (fromText (toStrict (encodeToLazyText r2))) - <> fromText "\nFor machine detailed:\n" - <> asCode (fromText (toStrict (encodeToLazyText r3))) - , case asMetrics dmPrototype of - [] -> mempty - l -> mconcat - (intersperse (singleton '\n') - (map - (\case - (IntM name i) -> - fromText "Integer metrics:\n" - <> asCode (fromText name) - <> singleton ' ' - <> fromString (show i) - (DoubleM name i) -> - fromText "Double metrics:\n" - <> asCode (fromText name) - <> singleton ' ' - <> fromString (show i)) - l)) - ] + namespacesMetricsBuilder :: [Namespace] -> Builder + namespacesMetricsBuilder [ns] = fromText "Dispatched by: \n" <> namespaceMetricsBuilder ns + namespacesMetricsBuilder [] = mempty + namespacesMetricsBuilder nsl = fromText "Dispatched by: \n" <> + mconcat (intersperse (singleton '\n')(map namespaceMetricsBuilder nsl)) + + namespaceMetricsBuilder :: Namespace -> Builder + namespaceMetricsBuilder ns = mconcat (intersperse (singleton '.') (map fromText ns)) propertiesBuilder :: LogDoc -> Builder propertiesBuilder LogDoc {..} = @@ -235,6 +354,12 @@ documentMarkdown (Documented documented) tracers = do <> filteredBuilder (nub ldFiltered) (nub ldSeverity) <> limiterBuilder (nub ldLimiter) + configMetricsBuilder :: LogDoc -> Builder + configMetricsBuilder LogDoc {..} = + fromText "From current configuration:\n" + <> filteredBuilder (nub ldFiltered) (nub ldSeverity) + <> limiterBuilder (nub ldLimiter) + backendsBuilder :: [(BackendConfig, FormattedMessage)] -> Builder backendsBuilder [] = fromText "No backends found" backendsBuilder l = fromText "Backends:\n\t\t\t" @@ -246,6 +371,8 @@ documentMarkdown (Documented documented) tracers = do backendFormatToText (be, FormattedHuman _c _) = asCode (fromString (show be)) backendFormatToText (be, FormattedMachine _) = asCode (fromString (show be)) + backendFormatToText (be, FormattedForwarder _) = asCode (fromString (show be)) + filteredBuilder :: [SeverityF] -> [SeverityS] -> Builder filteredBuilder [] _ = mempty @@ -258,7 +385,7 @@ documentMarkdown (Documented documented) tracers = do else (asCode . fromString) "Invisible" ([SeverityF Nothing], [_rh]) -> "Invisible" _ -> mempty - <> fromText " ~ " + <> fromText " because the filter level is " <> mconcat (intersperse (fromText ", ") (map (asCode . fromString . show) l)) @@ -275,60 +402,20 @@ documentMarkdown (Documented documented) tracers = do <> (asCode . fromString. show) d) l)) - fMetrics :: (BackendConfig, FormattedMessage) -> Bool - fMetrics (EKGBackend, FormattedMetrics (_hd:_tl)) = True - fMetrics _ = False + metricsBuilder :: Map.Map Text Text -> [(Text, Builder)] + metricsBuilder metricsDoc = + let metricsList = Map.toList metricsDoc + in map (\t@(name, _) -> (name, metricFormatToText t)) metricsList - metricsBuilder :: - Map.Map Text Text - -> [(BackendConfig, FormattedMessage)] - -> Builder - metricsBuilder _ [] = mempty - metricsBuilder metricsDoc l = - mconcat $ map (metricsFormatToText metricsDoc) l - - metricsFormatToText :: - Map.Map Text Text - -> (BackendConfig, FormattedMessage) - -> Builder - metricsFormatToText metricsDoc (_be, FormattedMetrics l) = - mconcat (intersperse (fromText ",\n") - (map (metricFormatToText metricsDoc) l)) - - metricFormatToText :: Map.Map Text Text -> Metric -> Builder - metricFormatToText metricsDoc (IntM name _) = - fromText "#### _Int metric:_ " + metricFormatToText :: (Text, Text) -> Builder + metricFormatToText (name, text) = + fromText "### " <> fromText name <> fromText "\n" - <> case Map.lookup name metricsDoc of - Just "" -> mempty - Just text -> betweenLines (fromText text) - Nothing -> mempty - - metricFormatToText metricsDoc (DoubleM name _) = - fromText "#### _Double metric:_ " - <> fromText name - <> fromText "\n" - <> case Map.lookup name metricsDoc of - Just "" -> mempty - Just text -> betweenLines (fromText text) - Nothing -> mempty - metricFormatToText metricsDoc (CounterM name _) = - fromText "#### _Counter metric:_ " - <> fromText name - <> fromText "\n" - <> case Map.lookup name metricsDoc of - Just "" -> mempty - Just text -> betweenLines (fromText text) - Nothing -> mempty + <> betweenLines (fromText text) asCode :: Builder -> Builder asCode b = singleton '`' <> b <> singleton '`' betweenLines :: Builder -> Builder betweenLines b = fromText "\n***\n" <> b <> fromText "\n***\n" - -_listIndex :: [a] -> Int -> Maybe a -_listIndex l i = if i >= length l - then Nothing - else Just (l !! i) diff --git a/trace-dispatcher/src/Cardano/Logging/Formatter.hs b/trace-dispatcher/src/Cardano/Logging/Formatter.hs index 0b52b5f7400..9e88719d140 100644 --- a/trace-dispatcher/src/Cardano/Logging/Formatter.hs +++ b/trace-dispatcher/src/Cardano/Logging/Formatter.hs @@ -50,11 +50,10 @@ metricsFormatter application (Trace tr) = in T.traceWith tr (lc { lcNamespace = application : lcNamespace lc} , Nothing , FormattedMetrics metrics) - (lc, Just ctrl, v) -> - let metrics = asMetrics v - in T.traceWith tr (lc { lcNamespace = application : lcNamespace lc} + (lc, Just ctrl, _v) -> + T.traceWith tr (lc { lcNamespace = application : lcNamespace lc} , Just ctrl - , FormattedMetrics metrics) + , FormattedMetrics []) -- | Format this trace as TraceObject for the trace forwarder forwardFormatter @@ -211,11 +210,12 @@ formatContextMachine hostname application LoggingContext {..} obj = do let severity = (pack . show) (fromMaybe Info lcSeverity) tid = fromMaybe ((pack . show) thid) ((stripPrefix "ThreadId " . pack . show) thid) - ns = application : lcNamespace + ns = mconcat (intersperse (singleton '.') + (map fromText (application : lcNamespace))) ts = pack $ formatTime defaultTimeLocale "%F %H:%M:%S%4Q" time pure $ AE.pairs $ "at" .= ts - <> "ns" .= ns - <> "message" .= obj + <> "ns" .= toStrict (toLazyText ns) + <> "data" .= obj <> "sev" .= severity <> "thread" .= tid <> "host" .= hostname diff --git a/trace-dispatcher/src/Cardano/Logging/Forwarding.hs b/trace-dispatcher/src/Cardano/Logging/Forwarding.hs new file mode 100644 index 00000000000..04b36c9b18d --- /dev/null +++ b/trace-dispatcher/src/Cardano/Logging/Forwarding.hs @@ -0,0 +1,257 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PackageImports #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module Cardano.Logging.Forwarding + ( + initForwarding + ) where + +import Codec.CBOR.Term (Term) +import Control.Concurrent.Async (async, race_, wait) +import Control.Monad (void) +import Control.Monad.IO.Class + +import "contra-tracer" Control.Tracer (contramap, stdoutTracer) +import qualified Data.ByteString.Lazy as LBS +import Data.Void (Void) +import Data.Word (Word16) + +import Ouroboros.Network.Driver.Limits (ProtocolTimeLimits) +import Ouroboros.Network.ErrorPolicy (nullErrorPolicies) +import Ouroboros.Network.IOManager (IOManager) +import Ouroboros.Network.Magic (NetworkMagic) +import Ouroboros.Network.Mux (MiniProtocol (..), + MiniProtocolLimits (..), MiniProtocolNum (..), + MuxMode (..), OuroborosApplication (..), + RunMiniProtocol (..), miniProtocolLimits, miniProtocolNum, + miniProtocolRun) +import Ouroboros.Network.Protocol.Handshake.Codec + (cborTermVersionDataCodec, codecHandshake, noTimeLimitsHandshake) +import Ouroboros.Network.Protocol.Handshake.Type (Handshake) +import Ouroboros.Network.Protocol.Handshake.Version + (acceptableVersion, simpleSingletonVersions) +import Ouroboros.Network.Snocket (Snocket, localAddressFromPath, + localSnocket) +import Ouroboros.Network.Socket (AcceptedConnectionsLimit (..), + SomeResponderApplication (..), cleanNetworkMutableState, + connectToNode, newNetworkMutableState, nullNetworkConnectTracers, + nullNetworkServerTracers, withServerNode) + +import qualified System.Metrics as EKG +import qualified System.Metrics.Configuration as EKGF +import System.Metrics.Network.Forwarder +import qualified Trace.Forward.Configuration.DataPoint as DPF +import qualified Trace.Forward.Configuration.TraceObject as TF +import Trace.Forward.Run.DataPoint.Forwarder +import Trace.Forward.Run.TraceObject.Forwarder +import Trace.Forward.Utils.DataPoint +import Trace.Forward.Utils.TraceObject + +import Cardano.Logging.Types +import Cardano.Logging.Utils (runInLoop) +import Cardano.Logging.Version + +initForwarding :: forall m. (MonadIO m) + => IOManager + -> TraceConfig + -> NetworkMagic + -> EKG.Store + -> m (ForwardSink TraceObject, DataPointStore) +initForwarding iomgr config networkMagic ekgStore = liftIO $ do + forwardSink <- initForwardSink tfConfig + dpStore <- initDataPointStore + launchForwarders + iomgr + config + networkMagic + ekgConfig + tfConfig + dpfConfig + ekgStore + forwardSink + dpStore + pure (forwardSink, dpStore) + where + LocalSocket p = tofAddress $ tcForwarder config + connSize = tofConnQueueSize $ tcForwarder config + disconnSize = tofDisconnQueueSize $ tcForwarder config + + ekgConfig :: EKGF.ForwarderConfiguration + ekgConfig = + EKGF.ForwarderConfiguration + { EKGF.forwarderTracer = contramap show stdoutTracer + , EKGF.acceptorEndpoint = EKGF.LocalPipe p + , EKGF.reConnectFrequency = 1.0 + , EKGF.actionOnRequest = const $ pure () + } + + tfConfig :: TF.ForwarderConfiguration TraceObject + tfConfig = + TF.ForwarderConfiguration + { TF.forwarderTracer = contramap show stdoutTracer + , TF.acceptorEndpoint = p + , TF.disconnectedQueueSize = disconnSize + , TF.connectedQueueSize = connSize + } + + dpfConfig :: DPF.ForwarderConfiguration + dpfConfig = + DPF.ForwarderConfiguration + { DPF.forwarderTracer = contramap show stdoutTracer + , DPF.acceptorEndpoint = p + } + +launchForwarders + :: IOManager + -> TraceConfig + -> NetworkMagic + -> EKGF.ForwarderConfiguration + -> TF.ForwarderConfiguration TraceObject + -> DPF.ForwarderConfiguration + -> EKG.Store + -> ForwardSink TraceObject + -> DataPointStore + -> IO () +launchForwarders iomgr TraceConfig{tcForwarder} networkMagic + ekgConfig tfConfig dpfConfig ekgStore sink dpStore = + void . async $ + runInLoop + (launchForwardersViaLocalSocket + iomgr + networkMagic + tcForwarder + ekgConfig + tfConfig + dpfConfig + sink + ekgStore + dpStore) + p 1 + where + LocalSocket p = tofAddress tcForwarder + +launchForwardersViaLocalSocket + :: IOManager + -> NetworkMagic + -> TraceOptionForwarder + -> EKGF.ForwarderConfiguration + -> TF.ForwarderConfiguration TraceObject + -> DPF.ForwarderConfiguration + -> ForwardSink TraceObject + -> EKG.Store + -> DataPointStore + -> IO () +launchForwardersViaLocalSocket iomgr networkMagic + TraceOptionForwarder {tofAddress=(LocalSocket p), tofMode=Initiator} + ekgConfig tfConfig dpfConfig sink ekgStore dpStore = + doConnectToAcceptor networkMagic (localSnocket iomgr) (localAddressFromPath p) + noTimeLimitsHandshake ekgConfig tfConfig dpfConfig sink ekgStore dpStore +launchForwardersViaLocalSocket iomgr networkMagic + TraceOptionForwarder {tofAddress=(LocalSocket p), tofMode=Responder} + ekgConfig tfConfig dpfConfig sink ekgStore dpStore = + doListenToAcceptor networkMagic (localSnocket iomgr) (localAddressFromPath p) + noTimeLimitsHandshake ekgConfig tfConfig dpfConfig sink ekgStore dpStore + +doConnectToAcceptor + :: NetworkMagic + -> Snocket IO fd addr + -> addr + -> ProtocolTimeLimits (Handshake ForwardingVersion Term) + -> EKGF.ForwarderConfiguration + -> TF.ForwarderConfiguration TraceObject + -> DPF.ForwarderConfiguration + -> ForwardSink TraceObject + -> EKG.Store + -> DataPointStore + -> IO () +doConnectToAcceptor networkMagic snocket address timeLimits + ekgConfig tfConfig dpfConfig sink ekgStore dpStore = do + connectToNode + snocket + (codecHandshake forwardingVersionCodec) + timeLimits + (cborTermVersionDataCodec forwardingCodecCBORTerm) + nullNetworkConnectTracers + acceptableVersion + (simpleSingletonVersions + ForwardingV_1 + (ForwardingVersionData networkMagic) + (forwarderApp [ (forwardEKGMetrics ekgConfig ekgStore, 1) + , (forwardTraceObjectsInit tfConfig sink, 2) + , (forwardDataPointsInit dpfConfig dpStore, 3) + ] + ) + ) + Nothing + address + where + forwarderApp + :: [(RunMiniProtocol 'InitiatorMode LBS.ByteString IO () Void, Word16)] + -> OuroborosApplication 'InitiatorMode addr LBS.ByteString IO () Void + forwarderApp protocols = + OuroborosApplication $ \_connectionId _shouldStopSTM -> + [ MiniProtocol + { miniProtocolNum = MiniProtocolNum num + , miniProtocolLimits = MiniProtocolLimits { maximumIngressQueue = maxBound } + , miniProtocolRun = prot + } + | (prot, num) <- protocols + ] + +doListenToAcceptor + :: Ord addr + => NetworkMagic + -> Snocket IO fd addr + -> addr + -> ProtocolTimeLimits (Handshake ForwardingVersion Term) + -> EKGF.ForwarderConfiguration + -> TF.ForwarderConfiguration TraceObject + -> DPF.ForwarderConfiguration + -> ForwardSink TraceObject + -> EKG.Store + -> DataPointStore + -> IO () +doListenToAcceptor networkMagic snocket address timeLimits + ekgConfig tfConfig dpfConfig sink ekgStore dpStore = do + networkState <- newNetworkMutableState + race_ (cleanNetworkMutableState networkState) + $ withServerNode + snocket + nullNetworkServerTracers + networkState + (AcceptedConnectionsLimit maxBound maxBound 0) + address + (codecHandshake forwardingVersionCodec) + timeLimits + (cborTermVersionDataCodec forwardingCodecCBORTerm) + acceptableVersion + (simpleSingletonVersions + ForwardingV_1 + (ForwardingVersionData networkMagic) + (SomeResponderApplication $ + forwarderApp [ (forwardEKGMetricsResp ekgConfig ekgStore, 1) + , (forwardTraceObjectsResp tfConfig sink, 2) + , (forwardDataPointsResp dpfConfig dpStore, 3) + ] + ) + ) + nullErrorPolicies + $ \_ serverAsync -> + wait serverAsync -- Block until async exception. + where + forwarderApp + :: [(RunMiniProtocol 'ResponderMode LBS.ByteString IO Void (), Word16)] + -> OuroborosApplication 'ResponderMode addr LBS.ByteString IO Void () + forwarderApp protocols = + OuroborosApplication $ \_connectionId _shouldStopSTM -> + [ MiniProtocol + { miniProtocolNum = MiniProtocolNum num + , miniProtocolLimits = MiniProtocolLimits { maximumIngressQueue = maxBound } + , miniProtocolRun = prot + } + | (prot, num) <- protocols + ] diff --git a/trace-dispatcher/src/Cardano/Logging/Tracer/Composed.hs b/trace-dispatcher/src/Cardano/Logging/Tracer/Composed.hs index d94bfd9e303..ab25a1e5091 100644 --- a/trace-dispatcher/src/Cardano/Logging/Tracer/Composed.hs +++ b/trace-dispatcher/src/Cardano/Logging/Tracer/Composed.hs @@ -3,19 +3,26 @@ module Cardano.Logging.Tracer.Composed ( mkCardanoTracer , mkCardanoTracer' + , mkDataPointTracer , MessageOrLimit(..) + , documentTracer ) where -import Data.Maybe (fromMaybe) +import Control.Exception (catch, SomeException) +import Data.Aeson.Types (ToJSON) +import Data.Maybe (fromMaybe) import Data.Text +import Trace.Forward.Utils.DataPoint (DataPoint (..)) + import Cardano.Logging.Configuration +import Cardano.Logging.DocuGenerator import Cardano.Logging.Formatter import Cardano.Logging.FrequencyLimiter (LimitingMessage (..)) import Cardano.Logging.Trace import Cardano.Logging.Types -import qualified Control.Tracer as NT +import qualified Control.Tracer as NT data MessageOrLimit m = Message m | Limit LimitingMessage @@ -119,3 +126,33 @@ mkCardanoTracer' trStdout trForward mbTrEkg name namesFor severityFor privacyFor case mbEkgTrace <> mbForwardTrace <> mbStdoutTrace of Nothing -> pure $ Trace NT.nullTracer Just tr -> pure (preFormatted backends tr) + +-- A simple dataPointTracer which supports building a namespace and entering a hook +-- function. +mkDataPointTracer :: forall dp. ToJSON dp + => Trace IO DataPoint + -> (dp -> [Text]) + -> IO (Trace IO dp) +mkDataPointTracer trDataPoint namesFor = do + let tr = NT.contramap DataPoint trDataPoint + pure $ withNamesAppended namesFor tr + +documentTracer :: + TraceConfig + -> Trace IO a + -> Documented a + -> IO [(Namespace, DocuResult)] +documentTracer trConfig trace trDoc = do + res <- catch + (do + configureTracers trConfig trDoc [trace] + pure True) + (\(e :: SomeException) -> do + putStrLn $ "Configuration exception" <> show e <> show trDoc + pure False) + if res + then catch (documentMarkdown trDoc [trace]) + (\(e :: SomeException) -> do + putStrLn $ "Documentation exception" <> show e <> show trDoc + pure []) + else pure [] diff --git a/trace-dispatcher/src/Cardano/Logging/Tracer/DataPoint.hs b/trace-dispatcher/src/Cardano/Logging/Tracer/DataPoint.hs new file mode 100644 index 00000000000..e342aeb4c25 --- /dev/null +++ b/trace-dispatcher/src/Cardano/Logging/Tracer/DataPoint.hs @@ -0,0 +1,57 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module Cardano.Logging.Tracer.DataPoint + ( + dataPointTracer + ) where + +import Control.Concurrent.STM.TVar (modifyTVar) +import Control.Monad.IO.Class +import Control.Monad.STM (atomically) +import Data.Map.Strict (insert) +import Data.List (intersperse) +import Data.Text (Text) +import Data.Text.Lazy (toStrict) +import Data.Text.Lazy.Builder (fromText, singleton, toLazyText) + +import qualified Control.Tracer as T +import Trace.Forward.Utils.DataPoint (DataPoint (..), DataPointStore) + +-- import Cardano.Logging.DocuGenerator +import Cardano.Logging.Types +import Cardano.Logging.Utils (uncurry3) + +--------------------------------------------------------------------------- + +dataPointTracer :: forall m. MonadIO m + => DataPointStore -- TVar (HM.HashMap DataPointName DataPoint) + -> Trace m DataPoint +dataPointTracer dataPointStore = + Trace $ T.arrow $ T.emit $ uncurry3 output + where + output :: + LoggingContext + -> Maybe TraceControl + -> DataPoint + -> m () + output LoggingContext {..} Nothing val = + liftIO $ atomically $ do + modifyTVar + dataPointStore + (insert + (nameSpaceToText lcNamespace) + val) + output LoggingContext {} (Just Reset) _msg = liftIO $ do + pure () + output _lk (Just _c@Document {}) _val = do + pure () + -- TODO docIt DataPoint (lk, Just c, val) + output LoggingContext {} _ _a = pure () + + nameSpaceToText :: Namespace -> Text + nameSpaceToText namespace = toStrict $ toLazyText $ + mconcat (intersperse (singleton '.') + (map fromText namespace)) diff --git a/trace-dispatcher/src/Cardano/Logging/Tracer/Forward.hs b/trace-dispatcher/src/Cardano/Logging/Tracer/Forward.hs index 68abed59d55..e70556133a9 100644 --- a/trace-dispatcher/src/Cardano/Logging/Tracer/Forward.hs +++ b/trace-dispatcher/src/Cardano/Logging/Tracer/Forward.hs @@ -1,12 +1,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE PackageImports #-} {-# LANGUAGE ScopedTypeVariables #-} --- IMPORTANT: please note that the latest changes in this module are temporary ones. --- It will be replaced by new dispatcher's code, in "integration PR". - module Cardano.Logging.Tracer.Forward ( forwardTracer @@ -15,31 +10,19 @@ module Cardano.Logging.Tracer.Forward import Control.Monad.IO.Class import qualified Control.Tracer as T -import "contra-tracer" Control.Tracer (contramap, stdoutTracer) - -import Ouroboros.Network.IOManager (IOManager) - -import qualified System.Metrics as EKG -import qualified System.Metrics.Configuration as EKGF -import qualified Trace.Forward.Configuration.TraceObject as TF -import Trace.Forward.Utils.TraceObject +import Trace.Forward.Utils.TraceObject (ForwardSink, writeToSink) import Cardano.Logging.DocuGenerator import Cardano.Logging.Types -import Cardano.Logging.Utils(uncurry3) +import Cardano.Logging.Utils (uncurry3) --------------------------------------------------------------------------- forwardTracer :: forall m. (MonadIO m) - => IOManager - -> TraceConfig - -> m (Trace m FormattedMessage) -forwardTracer iomgr config = liftIO $ do - forwardSink <- initForwardSink tfConfig - store <- EKG.newStore - EKG.registerGcMetrics store - launchForwarders iomgr (tcForwarder config) store ekgConfig tfConfig forwardSink - pure $ Trace $ T.arrow $ T.emit $ uncurry3 (output forwardSink) + => ForwardSink TraceObject + -> Trace m FormattedMessage +forwardTracer forwardSink = + Trace $ T.arrow $ T.emit $ uncurry3 (output forwardSink) where output :: ForwardSink TraceObject @@ -52,37 +35,5 @@ forwardTracer iomgr config = liftIO $ do output _sink LoggingContext {} (Just Reset) _msg = liftIO $ do pure () output _sink lk (Just c@Document {}) (FormattedForwarder lo) = do - docIt Forwarder (FormattedHuman False "") (lk, Just c, lo) + docIt Forwarder (FormattedForwarder lo) (lk, Just c, lo) output _sink LoggingContext {} _ _a = pure () - - LocalSocket p = tcForwarder config - - ekgConfig :: EKGF.ForwarderConfiguration - ekgConfig = - EKGF.ForwarderConfiguration - { EKGF.forwarderTracer = contramap show stdoutTracer - , EKGF.acceptorEndpoint = EKGF.LocalPipe p - , EKGF.reConnectFrequency = 1.0 - , EKGF.actionOnRequest = const $ pure () - } - - tfConfig :: TF.ForwarderConfiguration TraceObject - tfConfig = - TF.ForwarderConfiguration - { TF.forwarderTracer = contramap show stdoutTracer - , TF.acceptorEndpoint = p - , TF.disconnectedQueueSize = 200000 - , TF.connectedQueueSize = 2000 - } - -launchForwarders - :: IOManager - -> ForwarderAddr - -> EKG.Store - -> EKGF.ForwarderConfiguration - -> TF.ForwarderConfiguration TraceObject - -> ForwardSink TraceObject - -> IO () -launchForwarders _iomgr _ep _store _ekgConfig _tfConfig _sink = - -- Temp code, will be replaced by new dispatcher's code. - return () diff --git a/trace-dispatcher/src/Cardano/Logging/Tracer/Standard.hs b/trace-dispatcher/src/Cardano/Logging/Tracer/Standard.hs index c99fadb9cb5..43ae9a62819 100644 --- a/trace-dispatcher/src/Cardano/Logging/Tracer/Standard.hs +++ b/trace-dispatcher/src/Cardano/Logging/Tracer/Standard.hs @@ -7,13 +7,13 @@ module Cardano.Logging.Tracer.Standard ( import Control.Concurrent.Async import Control.Concurrent.Chan.Unagi.Bounded +import Control.Exception (catch, BlockedIndefinitelyOnMVar) import Control.Monad (forever, when) import Control.Monad.IO.Class -import Data.IORef (IORef, modifyIORef, newIORef, readIORef) +import Data.IORef (IORef, modifyIORef', newIORef, readIORef) import Data.Maybe (isNothing) import Data.Text (Text) import qualified Data.Text.IO as TIO -import Data.Void (Void) import System.IO (hFlush, stdout) import Cardano.Logging.DocuGenerator @@ -24,7 +24,7 @@ import qualified Control.Tracer as T -- | The state of a standard tracer newtype StandardTracerState = StandardTracerState { - stRunning :: Maybe (InChan Text, OutChan Text, Async Void) + stRunning :: Maybe (InChan Text, OutChan Text, Async ()) } emptyStandardTracerState :: StandardTracerState @@ -71,14 +71,16 @@ standardTracer = do startStdoutThread :: IORef StandardTracerState -> IO () startStdoutThread stateRef = do (inChan, outChan) <- newChan 2048 - as <- async (stdoutThread outChan) + as <- async (catch + (stdoutThread outChan) + (\(_ :: BlockedIndefinitelyOnMVar) -> pure ())) link as - modifyIORef stateRef (\ st -> + modifyIORef' stateRef (\ st -> st {stRunning = Just (inChan, outChan, as)}) -- | The new thread, which does the actual write from the queue. -- runs forever, and never returns -stdoutThread :: OutChan Text -> IO Void +stdoutThread :: OutChan Text -> IO () stdoutThread outChan = forever $ do readChan outChan >>= TIO.putStrLn diff --git a/trace-dispatcher/src/Cardano/Logging/Types.hs b/trace-dispatcher/src/Cardano/Logging/Types.hs index 4be6900354f..e22a26766cb 100644 --- a/trace-dispatcher/src/Cardano/Logging/Types.hs +++ b/trace-dispatcher/src/Cardano/Logging/Types.hs @@ -23,6 +23,8 @@ module Cardano.Logging.Types ( , ConfigOption(..) , ForwarderAddr(..) , FormatLogging(..) + , ForwarderMode(..) + , TraceOptionForwarder(..) , TraceConfig(..) , emptyTraceConfig , FormattedMessage(..) @@ -47,7 +49,9 @@ import qualified Data.HashMap.Strict as HM import Data.IORef import Data.Map (Map) import qualified Data.Map as Map -import Data.Text (Text, pack) +import qualified Data.Map.Strict as SMap + +import Data.Text (Text, pack, unpack) import Data.Text.Lazy (toStrict) import Data.Time (UTCTime) import GHC.Generics @@ -128,7 +132,10 @@ data DocMsg a = DocMsg { dmPrototype :: a , dmMetricsMD :: [(Text, Text)] , dmMarkdown :: Text -} deriving (Show) +} + +instance Show (DocMsg a) where + show (DocMsg _ _ md) = unpack md -- | Context any log message carries data LoggingContext = LoggingContext { @@ -196,7 +203,9 @@ instance AE.FromJSON SeverityF where parseJSON (AE.String "Critical") = pure (SeverityF (Just Critical)) parseJSON (AE.String "Alert") = pure (SeverityF (Just Alert)) parseJSON (AE.String "Emergency") = pure (SeverityF (Just Emergency)) - parseJSON (AE.String "Scilence") = pure (SeverityF Nothing) + parseJSON (AE.String "Silence") = pure (SeverityF Nothing) + parseJSON invalid = fail $ "Parsing of filter Severity failed." + <> "Unknown severity: " <> show invalid instance Ord SeverityF where compare (SeverityF (Just s1)) (SeverityF (Just s2)) = compare s1 s2 @@ -237,22 +246,26 @@ data BackendConfig = Forwarder | Stdout FormatLogging | EKGBackend + | DatapointBackend deriving (Eq, Ord, Show, Generic) instance AE.ToJSON BackendConfig where toJSON Forwarder = AE.String "Forwarder" + toJSON DatapointBackend = AE.String "DatapointBackend" toJSON EKGBackend = AE.String "EKGBackend" toJSON (Stdout f) = AE.String $ "Stdout " <> (pack . show) f instance AE.FromJSON BackendConfig where parseJSON (AE.String "Forwarder") = pure Forwarder parseJSON (AE.String "EKGBackend") = pure EKGBackend + parseJSON (AE.String "DatapointBackend") = pure DatapointBackend parseJSON (AE.String "Stdout HumanFormatColoured") = pure $ Stdout HumanFormatColoured parseJSON (AE.String "Stdout HumanFormatUncoloured") = pure $ Stdout HumanFormatUncoloured parseJSON (AE.String "Stdout MachineFormat") = pure $ Stdout MachineFormat - parseJSON other = error (show other) + parseJSON other = fail $ "Parsing of backend config failed." + <> "Unknown config: " <> show other data FormatLogging = HumanFormatColoured @@ -262,7 +275,7 @@ data FormatLogging = -- Configuration options for individual namespace elements data ConfigOption = - -- | Severity level for a filter (default is WarningF) + -- | Severity level for a filter (default is Warning) ConfSeverity SeverityF -- | Detail level (default is DNormal) | ConfDetail DetailLevel @@ -281,19 +294,65 @@ newtype ForwarderAddr instance AE.FromJSON ForwarderAddr where parseJSON = AE.withObject "ForwarderAddr" $ \o -> LocalSocket <$> o AE..: "filePath" +data ForwarderMode = + -- | Forwarder works as a client: it initiates network connection with + -- 'cardano-tracer' and/or another Haskell acceptor application. + Initiator + -- | Forwarder works as a server: it accepts network connection from + -- 'cardano-tracer' and/or another Haskell acceptor application. + | Responder + deriving (Eq, Ord, Show, Generic) + +data TraceOptionForwarder = TraceOptionForwarder { + tofAddress :: ForwarderAddr + , tofMode :: ForwarderMode + , tofConnQueueSize :: Word + , tofDisconnQueueSize :: Word +} deriving (Eq, Ord, Show) + +instance AE.FromJSON TraceOptionForwarder where + parseJSON (AE.Object obj) = + TraceOptionForwarder + <$> obj AE..: "address" + <*> obj AE..: "mode" + <*> obj AE..:? "connQueueSize" AE..!= 2000 + <*> obj AE..:? "disconnQueueSize" AE..!= 200000 + +defaultForwarder :: TraceOptionForwarder +defaultForwarder = TraceOptionForwarder { + tofAddress = LocalSocket "forwarder.sock" + , tofMode = Responder + , tofConnQueueSize = 2000 + , tofDisconnQueueSize = 200000 +} + +instance AE.FromJSON ForwarderMode where + parseJSON (AE.String "Initiator") = pure Initiator + parseJSON (AE.String "Responder") = pure Responder + parseJSON other = fail $ "Parsing of ForwarderMode failed." + <> "Unknown ForwarderMode: " <> show other + data TraceConfig = TraceConfig { -- | Options specific to a certain namespace - tcOptions :: Map.Map Namespace [ConfigOption] - , tcForwarder :: ForwarderAddr - , tcForwarderQueueSize :: Int + tcOptions :: Map.Map Namespace [ConfigOption] + -- | Options for the forwarder + , tcForwarder :: TraceOptionForwarder + -- | Optional human-readable name of the node. + , tcNodeName :: Maybe Text + -- | Optional peer trace frequency in milliseconds. + , tcPeerFreqency :: Maybe Int + -- | Optional resource trace frequency in milliseconds. + , tcResourceFreqency :: Maybe Int } deriving (Eq, Ord, Show) emptyTraceConfig :: TraceConfig emptyTraceConfig = TraceConfig { tcOptions = Map.empty - , tcForwarder = LocalSocket "forwarder.log" - , tcForwarderQueueSize = 1500 + , tcForwarder = defaultForwarder + , tcNodeName = Nothing + , tcPeerFreqency = Just 2000 -- Every 2 seconds + , tcResourceFreqency = Just 1000 -- Every second } --------------------------------------------------------------------------- @@ -311,15 +370,15 @@ data TraceControl where newtype DocCollector = DocCollector (IORef (Map Int LogDoc)) data LogDoc = LogDoc { - ldDoc :: Text - , ldMetricsDoc :: Map Text Text - , ldNamespace :: [Namespace] - , ldSeverity :: [SeverityS] - , ldPrivacy :: [Privacy] - , ldDetails :: [DetailLevel] - , ldBackends :: [(BackendConfig, FormattedMessage)] - , ldFiltered :: [SeverityF] - , ldLimiter :: [(Text, Double)] + ldDoc :: ! Text + , ldMetricsDoc :: ! (SMap.Map Text Text) + , ldNamespace :: ! [Namespace] + , ldSeverity :: ! [SeverityS] + , ldPrivacy :: ! [Privacy] + , ldDetails :: ! [DetailLevel] + , ldBackends :: ! [(BackendConfig, FormattedMessage)] + , ldFiltered :: ! [SeverityF] + , ldLimiter :: ! [(Text, Double)] } deriving(Eq, Show) emptyLogDoc :: Text -> [(Text, Text)] -> LogDoc @@ -357,17 +416,17 @@ instance LogFormatting b => LogFormatting (Folding a b) where instance LogFormatting Double where forMachine _dtal d = mkObject [ "val" .= AE.String ((pack . show) d)] - forHuman d = (pack . show) d + forHuman = pack . show asMetrics d = [DoubleM "" d] instance LogFormatting Int where forMachine _dtal i = mkObject [ "val" .= AE.String ((pack . show) i)] - forHuman i = (pack . show) i + forHuman = pack . show asMetrics i = [IntM "" (fromIntegral i)] instance LogFormatting Integer where forMachine _dtal i = mkObject [ "val" .= AE.String ((pack . show) i)] - forHuman i = (pack . show) i + forHuman = pack . show asMetrics i = [IntM "" i] --------------------------------------------------------------------------- diff --git a/trace-dispatcher/src/Cardano/Logging/Utils.hs b/trace-dispatcher/src/Cardano/Logging/Utils.hs index 3e29ba58205..50331825042 100644 --- a/trace-dispatcher/src/Cardano/Logging/Utils.hs +++ b/trace-dispatcher/src/Cardano/Logging/Utils.hs @@ -1,7 +1,37 @@ +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE PackageImports #-} + module Cardano.Logging.Utils ( + runInLoop, uncurry3 ) where +import Control.Concurrent (threadDelay) +import Control.Exception (SomeAsyncException (..), fromException, tryJust) +import "contra-tracer" Control.Tracer (showTracing, stdoutTracer, traceWith) + +-- | Run monadic action in a loop. If there's an exception, it will re-run +-- the action again, after pause that grows. +runInLoop :: IO () -> FilePath -> Word -> IO () +runInLoop action localSocket prevDelayInSecs = + tryJust excludeAsyncExceptions action >>= \case + Left e -> do + logTrace $ "connection with " <> show localSocket <> " failed: " <> show e + threadDelay . fromIntegral $ currentDelayInSecs * 1000000 + runInLoop action localSocket currentDelayInSecs + Right _ -> return () + where + excludeAsyncExceptions e = + case fromException e of + Just SomeAsyncException {} -> Nothing + _ -> Just e + + logTrace = traceWith $ showTracing stdoutTracer + + currentDelayInSecs = + if prevDelayInSecs < 60 + then prevDelayInSecs * 2 + else 60 -- After we reached 60+ secs delay, repeat an attempt every minute. -- | Converts a curried function to a function on a triple. uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d diff --git a/trace-dispatcher/src/Cardano/Logging/Version.hs b/trace-dispatcher/src/Cardano/Logging/Version.hs new file mode 100644 index 00000000000..cb157935249 --- /dev/null +++ b/trace-dispatcher/src/Cardano/Logging/Version.hs @@ -0,0 +1,62 @@ +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} + +module Cardano.Logging.Version + ( ForwardingVersion (..) + , ForwardingVersionData (..) + , forwardingVersionCodec + , forwardingCodecCBORTerm + ) where + +import Data.Text (Text) +import qualified Data.Text as T +import Data.Typeable (Typeable) + +import qualified Codec.CBOR.Term as CBOR + +import Ouroboros.Network.CodecCBORTerm +import Ouroboros.Network.Magic +import Ouroboros.Network.Protocol.Handshake.Version (Accept (..), Acceptable (..)) + +data ForwardingVersion + = ForwardingV_1 + | ForwardingV_2 + deriving (Eq, Ord, Enum, Bounded, Show, Typeable) + +forwardingVersionCodec :: CodecCBORTerm (Text, Maybe Int) ForwardingVersion +forwardingVersionCodec = CodecCBORTerm { encodeTerm, decodeTerm } + where + encodeTerm ForwardingV_1 = CBOR.TInt 1 + encodeTerm ForwardingV_2 = CBOR.TInt 2 + + decodeTerm (CBOR.TInt 1) = Right ForwardingV_1 + decodeTerm (CBOR.TInt 2) = Right ForwardingV_2 + decodeTerm (CBOR.TInt n) = Left ( T.pack "decode ForwardingVersion: unknown tag: " <> T.pack (show n) + , Just n + ) + decodeTerm _ = Left ( T.pack "decode ForwardingVersion: unexpected term" + , Nothing + ) + +newtype ForwardingVersionData = ForwardingVersionData + { networkMagic :: NetworkMagic + } deriving (Eq, Show, Typeable) + +instance Acceptable ForwardingVersionData where + acceptableVersion local remote + | local == remote = Accept local + | otherwise = Refuse $ T.pack $ "ForwardingVersionData mismatch: " + ++ show local + ++ " /= " ++ show remote + +forwardingCodecCBORTerm :: ForwardingVersion -> CodecCBORTerm Text ForwardingVersionData +forwardingCodecCBORTerm _ = CodecCBORTerm { encodeTerm, decodeTerm } + where + encodeTerm :: ForwardingVersionData -> CBOR.Term + encodeTerm ForwardingVersionData { networkMagic } = + CBOR.TInt (fromIntegral $ unNetworkMagic networkMagic) + + decodeTerm :: CBOR.Term -> Either Text ForwardingVersionData + decodeTerm (CBOR.TInt x) | x >= 0 && x <= 0xffffffff = Right (ForwardingVersionData $ NetworkMagic $ fromIntegral x) + | otherwise = Left $ T.pack $ "networkMagic out of bound: " <> show x + decodeTerm t = Left $ T.pack $ "unknown encoding: " ++ show t diff --git a/trace-dispatcher/test/Cardano/Logging/Test/Config.hs b/trace-dispatcher/test/Cardano/Logging/Test/Config.hs index 5689bb5a5f5..a808dc0c54b 100644 --- a/trace-dispatcher/test/Cardano/Logging/Test/Config.hs +++ b/trace-dispatcher/test/Cardano/Logging/Test/Config.hs @@ -1,6 +1,10 @@ {-# OPTIONS_GHC -Wno-orphans #-} module Cardano.Logging.Test.Config ( + config1 + , config2 + , config3 + , config4 ) where import Data.Map (fromList) @@ -42,5 +46,40 @@ config2 = emptyTraceConfig { ] } + +config3 :: TraceConfig +config3 = emptyTraceConfig { + tcOptions = fromList + [ ([] :: Namespace, + [ ConfSeverity (SeverityF (Just Debug)) + , ConfDetail DNormal + , ConfBackend [Stdout HumanFormatColoured, Forwarder, EKGBackend] + ]) + , (["Node", "Test", "Message1"], + [ ConfSeverity (SeverityF (Just Debug)) + , ConfDetail DNormal + , ConfBackend [Stdout HumanFormatColoured, EKGBackend] + , ConfLimiter "message1 limiter 100" 100 + ]) + , (["Node", "Test", "Message2"], + [ ConfSeverity (SeverityF (Just Error)) + , ConfDetail DMinimal + , ConfBackend [Forwarder, EKGBackend] + ]) + ] + } + +-- | different configurations for testing +config4 :: TraceConfig +config4 = emptyTraceConfig { + tcOptions = fromList + [([] :: Namespace, + [ ConfSeverity (SeverityF (Just Debug)) + , ConfDetail DNormal + , ConfBackend [EKGBackend] + ]) + ] + } + instance Arbitrary TraceConfig where arbitrary = elements [config1, config2] diff --git a/trace-dispatcher/test/Cardano/Logging/Test/Oracles.hs b/trace-dispatcher/test/Cardano/Logging/Test/Oracles.hs index 689ba1de733..7b56814a468 100644 --- a/trace-dispatcher/test/Cardano/Logging/Test/Oracles.hs +++ b/trace-dispatcher/test/Cardano/Logging/Test/Oracles.hs @@ -83,9 +83,9 @@ occurences mid (fmsg : rest) = if isMessageWithId mid fmsg then 1 + occurences mid rest else occurences mid rest --- | Returns true if the given message has this id, otherwise fals +-- | Returns true if the given message has this id, otherwise false isMessageWithId :: MessageID -> FormattedMessage -> Bool -isMessageWithId mid (FormattedMetrics [IntM _ idm]) +isMessageWithId mid (FormattedMetrics (IntM _ idm : _)) = fromIntegral idm == mid isMessageWithId _ (FormattedMetrics []) = False isMessageWithId mid (FormattedHuman _ txt) = idInText mid txt diff --git a/trace-dispatcher/test/Cardano/Logging/Test/Tracer.hs b/trace-dispatcher/test/Cardano/Logging/Test/Tracer.hs index 38bf34b3013..9b82ef42c7e 100644 --- a/trace-dispatcher/test/Cardano/Logging/Test/Tracer.hs +++ b/trace-dispatcher/test/Cardano/Logging/Test/Tracer.hs @@ -1,11 +1,12 @@ +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE ScopedTypeVariables #-} module Cardano.Logging.Test.Tracer ( testTracer ) where -import Data.IORef import Control.Monad.IO.Class +import Data.IORef import Cardano.Logging @@ -15,6 +16,6 @@ testTracer :: MonadIO m testTracer ioRef = liftIO $ pure $ Trace $ arrow $ emit output where - output (LoggingContext{}, Nothing, msg) = liftIO $ do + output (LoggingContext{}, Nothing, !msg) = liftIO $ do modifyIORef ioRef (msg :) output (LoggingContext{}, _, _) = pure () diff --git a/trace-dispatcher/test/Cardano/Logging/Test/Types.hs b/trace-dispatcher/test/Cardano/Logging/Test/Types.hs index 4ed14bf2922..5174756721f 100644 --- a/trace-dispatcher/test/Cardano/Logging/Test/Types.hs +++ b/trace-dispatcher/test/Cardano/Logging/Test/Types.hs @@ -22,10 +22,6 @@ data Message = | Message3 MessageID Double deriving (Eq, Ord, Show) - -showT :: Show a => a -> Text -showT = pack . show - instance LogFormatting Message where forMachine _dtal (Message1 mid i) = mkObject [ "kind" .= String "Message1" @@ -53,7 +49,11 @@ instance LogFormatting Message where forHuman (Message3 mid d) = "Message3 <" <> showT mid <> "> " <> showT d asMetrics (Message1 mid _i) = - [IntM "Metrics1" (fromIntegral mid)] + [ IntM "Metrics1" (fromIntegral mid) + , IntM "Metrics2" (fromIntegral mid) + , IntM "Metrics3" (fromIntegral mid) + , IntM "Metrics4" (fromIntegral mid) + , IntM "Metrics5" (fromIntegral mid)] asMetrics _ = [] instance Arbitrary Message where diff --git a/trace-dispatcher/trace-dispatcher.cabal b/trace-dispatcher/trace-dispatcher.cabal index e3c230a1d81..a193a3a111f 100644 --- a/trace-dispatcher/trace-dispatcher.cabal +++ b/trace-dispatcher/trace-dispatcher.cabal @@ -19,12 +19,15 @@ library Cardano.Logging.Configuration Cardano.Logging.DocuGenerator Cardano.Logging.Formatter + Cardano.Logging.Forwarding Cardano.Logging.FrequencyLimiter + Cardano.Logging.Tracer.DataPoint Cardano.Logging.Tracer.EKG Cardano.Logging.Tracer.Standard Cardano.Logging.Tracer.Forward Cardano.Logging.Tracer.Composed Cardano.Logging.Utils + Cardano.Logging.Version Control.Tracer.Arrow Control.Tracer @@ -42,6 +45,7 @@ library , ekg-forward , hostname , network + , ouroboros-network , ouroboros-network-framework , serialise , stm @@ -78,6 +82,7 @@ executable trace-dispatcher-examples Examples.Routing Examples.EKG Examples.Configuration + Examples.DataPoint Examples.FrequencyLimiting Examples.Documentation hs-source-dirs: examples @@ -90,14 +95,16 @@ executable trace-dispatcher-examples , ekg , ekg-core , hostname + , stm , text , trace-dispatcher + , trace-forward , time , unagi-chan >= 0.4.1.4 , unliftio , unliftio-core - , stm , unordered-containers + , utf8-string , yaml ghc-options: -Wall -Wcompat @@ -129,17 +136,17 @@ test-suite trace-dispatcher-test , ekg-core , hostname , text - , trace-dispatcher + , stm + , tasty + , tasty-quickcheck , time + , trace-dispatcher , unagi-chan >= 0.4.1.4 , unliftio , unliftio-core - , stm , unordered-containers , yaml , QuickCheck - , tasty - , tasty-quickcheck ghc-options: -Wall -Wcompat @@ -150,3 +157,25 @@ test-suite trace-dispatcher-test -Wredundant-constraints -Wmissing-export-lists -Wno-incomplete-patterns + +benchmark trace-dispatcher-bench + type: exitcode-stdio-1.0 + hs-source-dirs: bench, test + main-is: trace-dispatcher-bench.hs + default-language: Haskell2010 + default-extensions: OverloadedStrings + other-modules: Cardano.Logging.Test.Types + Cardano.Logging.Test.Oracles + Cardano.Logging.Test.Config + Cardano.Logging.Test.Tracer + Cardano.Logging.Test.Messages + Cardano.Logging.Test.Script + build-depends: base >=4.12 && <5 + , aeson + , containers + , criterion + , ekg + , text + , time + , trace-dispatcher + , QuickCheck diff --git a/trace-forward/src/Trace/Forward/Utils/TraceObject.hs b/trace-forward/src/Trace/Forward/Utils/TraceObject.hs index bd02703e366..a4c453d41d9 100644 --- a/trace-forward/src/Trace/Forward/Utils/TraceObject.hs +++ b/trace-forward/src/Trace/Forward/Utils/TraceObject.hs @@ -71,8 +71,18 @@ writeToSink ForwardSink{forwardQueue, disconnectedSize, connectedSize, wasUsed} maybeFlushQueueToStdout q = do qLen <- atomically $ lengthTBQueue q if fromIntegral qLen == connectedSize - then atomically $ switchQueue disconnectedSize - else atomically (flushTBQueue q) >>= mapM_ print >> hFlush stdout + then atomically $ do + -- The small queue is full, so we have to switch to a big one and + -- then flush collected items from the small queue and store them in + -- a big one. + acceptedItems <- flushTBQueue q + switchQueue disconnectedSize + bigQ <- readTVar forwardQueue + mapM_ (writeTBQueue bigQ) acceptedItems + else do + -- The big queue is full, we have to flush it to stdout. + atomically (flushTBQueue q) >>= mapM_ print + hFlush stdout checkIfSinkWasUsed q = atomically $ whenM (readTVar wasUsed) $ switchToAnotherQueue q diff --git a/trace-resources/cbits/os-support-darwin.c b/trace-resources/cbits/os-support-darwin.c index 7806418577e..5a763ebbc07 100644 --- a/trace-resources/cbits/os-support-darwin.c +++ b/trace-resources/cbits/os-support-darwin.c @@ -32,7 +32,7 @@ /* c_get_process_memory_info */ -int c_get_process_memory_info(struct mach_task_basic_info *counters, int pid) +int c_get_process_memory_info2(struct mach_task_basic_info *counters, int pid) { task_t task = MACH_PORT_NULL; if (task_for_pid(current_task(), pid, &task) != KERN_SUCCESS) { @@ -49,7 +49,7 @@ int c_get_process_memory_info(struct mach_task_basic_info *counters, int pid) /* c_get_host_info */ /* currently this is not used -int c_get_host_info(struct host_basic_info *counters) +int c_get_host_info2(struct host_basic_info *counters) { mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; mach_port_t host_port = mach_host_self(); @@ -63,7 +63,7 @@ int c_get_host_info(struct host_basic_info *counters) /* c_get_boot_time */ -long c_get_boot_time() +long c_get_boot_time2() { // copied from psutil // fetch sysctl "kern.boottime" @@ -79,7 +79,7 @@ long c_get_boot_time() } /* c_get_sys_cpu_times */ -int c_get_sys_cpu_times(CPU_TIMES *counters) +int c_get_sys_cpu_times2(CPU_TIMES *counters) { mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; host_cpu_load_info_data_t r_load; @@ -103,7 +103,7 @@ int c_get_sys_cpu_times(CPU_TIMES *counters) /* c_get_sys_disk_io_counters */ /* adapted from psutil */ -int c_get_sys_disk_io_counters(DISK_COUNTERS *counters) { +int c_get_sys_disk_io_counters2(DISK_COUNTERS *counters) { counters->ndsks = 0; // uncomment the following to extract disk I/O metrics // requires to include the right headers (see top of this file) @@ -221,7 +221,7 @@ int c_get_sys_disk_io_counters(DISK_COUNTERS *counters) { /* c_get_sys_network_io_counters */ /* adapted from psutil */ -int c_get_sys_network_io_counters(NET_IO *counters) { +int c_get_sys_network_io_counters2(NET_IO *counters) { counters->nifs = 0; int noutput = 0; char *msghdrbuf = NULL, *end_of_list, *next; diff --git a/trace-resources/cbits/os-support-win.c b/trace-resources/cbits/os-support-win.c index afba1b13990..3635e34764f 100644 --- a/trace-resources/cbits/os-support-win.c +++ b/trace-resources/cbits/os-support-win.c @@ -7,7 +7,7 @@ /* c_get_process_memory_info */ -int c_get_process_memory_info (PROCESS_MEMORY_COUNTERS *counters, DWORD pid) { +int c_get_process_memory_info2 (PROCESS_MEMORY_COUNTERS *counters, DWORD pid) { HANDLE hProc; hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid ); @@ -23,7 +23,7 @@ int c_get_process_memory_info (PROCESS_MEMORY_COUNTERS *counters, DWORD pid) { /* c_get_io_counters */ -int c_get_io_counters (IO_COUNTERS *counters, DWORD pid) { +int c_get_io_counters2 (IO_COUNTERS *counters, DWORD pid) { HANDLE hProc; hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid ); @@ -39,7 +39,7 @@ int c_get_io_counters (IO_COUNTERS *counters, DWORD pid) { // #define HI_T 429.4967296 /* c_get_sys_cpu_times */ -int c_get_sys_cpu_times (CPU_TIMES *cputimes) { +int c_get_sys_cpu_times2 (CPU_TIMES *cputimes) { FILETIME usert={0,0}, kernelt={0,0}, idlet={0,0}; if (! GetSystemTimes(&idlet, &kernelt, &usert) ) { return -2; @@ -52,7 +52,7 @@ int c_get_sys_cpu_times (CPU_TIMES *cputimes) { } /* c_get_proc_cpu_times */ -int c_get_proc_cpu_times (CPU_TIMES *cputimes, DWORD pid) { +int c_get_proc_cpu_times2 (CPU_TIMES *cputimes, DWORD pid) { HANDLE hProc; hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid ); @@ -73,13 +73,13 @@ int c_get_proc_cpu_times (CPU_TIMES *cputimes, DWORD pid) { } /* c_get_system_info */ -int c_get_system_info (SYSTEM_INFO *sysinfo) { +int c_get_system_info2 (SYSTEM_INFO *sysinfo) { GetSystemInfo (sysinfo); return 1; } /* c_get_win_bits */ -int c_get_win_bits (DWORD pid) { +int c_get_win_bits2 (DWORD pid) { BOOL res; HANDLE hProc; hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, diff --git a/trace-resources/include/os-support-darwin.h b/trace-resources/include/os-support-darwin.h index 5898b535218..e69d8646f65 100644 --- a/trace-resources/include/os-support-darwin.h +++ b/trace-resources/include/os-support-darwin.h @@ -29,9 +29,9 @@ typedef struct _DISK_COUNTERS { DISK_INFO dsks[MAX_DISK_COUNTERS]; } DISK_COUNTERS; -int c_get_process_memory_info (struct mach_task_basic_info *counters, int pid); +int c_get_process_memory_info2 (struct mach_task_basic_info *counters, int pid); //int c_get_host_info (struct host_basic_info *counters); -long c_get_boot_time(); -int c_get_sys_cpu_times(CPU_TIMES *counters); -int c_get_sys_network_io_counters(NET_IO *counters); -int c_get_sys_disk_io_counters(DISK_COUNTERS *counters); \ No newline at end of file +long c_get_boot_time2(); +int c_get_sys_cpu_times2(CPU_TIMES *counters); +int c_get_sys_network_io_counters2(NET_IO *counters); +int c_get_sys_disk_io_counters2(DISK_COUNTERS *counters); diff --git a/trace-resources/include/os-support-win.h b/trace-resources/include/os-support-win.h index 70da9fdc217..333ef6a2f26 100644 --- a/trace-resources/include/os-support-win.h +++ b/trace-resources/include/os-support-win.h @@ -5,10 +5,10 @@ typedef struct _CPU_TIMES { ULONGLONG idletime; } CPU_TIMES; -int c_get_process_memory_info (PROCESS_MEMORY_COUNTERS *counters, DWORD pid); -int c_get_io_counters (IO_COUNTERS *counters, DWORD pid); -int c_get_sys_cpu_times (CPU_TIMES *cputimes); -int c_get_proc_cpu_times (CPU_TIMES *cputimes, DWORD pid); -int c_get_system_info (SYSTEM_INFO *sysinfo); -int c_get_win_bits (DWORD pid); +int c_get_process_memory_info2 (PROCESS_MEMORY_COUNTERS *counters, DWORD pid); +int c_get_io_counters2 (IO_COUNTERS *counters, DWORD pid); +int c_get_sys_cpu_times2 (CPU_TIMES *cputimes); +int c_get_proc_cpu_times2 (CPU_TIMES *cputimes, DWORD pid); +int c_get_system_info2 (SYSTEM_INFO *sysinfo); +int c_get_win_bits2 (DWORD pid); diff --git a/trace-resources/src/Cardano/Logging/Resources/Darwin.hsc b/trace-resources/src/Cardano/Logging/Resources/Darwin.hsc index 785218f69ff..38a0628fa59 100644 --- a/trace-resources/src/Cardano/Logging/Resources/Darwin.hsc +++ b/trace-resources/src/Cardano/Logging/Resources/Darwin.hsc @@ -72,14 +72,14 @@ instance Storable MachTaskBasicInfo where <*> (#peek struct mach_task_basic_info, suspend_count) ptr poke _ _ = pure () -foreign import ccall unsafe c_get_process_memory_info :: Ptr MachTaskBasicInfo -> CInt -> IO CInt +foreign import ccall unsafe c_get_process_memory_info2 :: Ptr MachTaskBasicInfo -> CInt -> IO CInt getMemoryInfo :: ProcessID -> IO MachTaskBasicInfo getMemoryInfo pid = allocaBytes 128 $ \ptr -> do - throwIfNeg_ (\res -> "c_get_process_memory_info: failure returned: " ++ show (pred res)) - (succ <$> c_get_process_memory_info ptr (fromIntegral pid)) + throwIfNeg_ (\res -> "c_get_process_memory_info2: failure returned: " ++ show (pred res)) + (succ <$> c_get_process_memory_info2 ptr (fromIntegral pid)) peek ptr readRessoureStatsInternal :: IO (Maybe ResourceStats) diff --git a/trace-resources/src/Cardano/Logging/Resources/Types.hs b/trace-resources/src/Cardano/Logging/Resources/Types.hs index 6399b0219ef..01a21befcdb 100644 --- a/trace-resources/src/Cardano/Logging/Resources/Types.hs +++ b/trace-resources/src/Cardano/Logging/Resources/Types.hs @@ -10,7 +10,7 @@ module Cardano.Logging.Resources.Types ) where -import Cardano.Logging.Types +import Cardano.Logging import Data.Aeson import Data.Text (pack) import Data.Word @@ -75,15 +75,15 @@ jsonEncodingOptions = defaultOptions docResourceStats :: Documented ResourceStats docResourceStats = Documented [ DocMsg - (pure 0) - [("Stat.Cputicks", "Reports the CPU ticks, sice the process was started") - ,("Mem.Resident", "TODO JNF") - ,("RTS.GcLiveBytes", "TODO JNF") - ,("RTS.GcMajorNum", "TODO JNF") - ,("RTS.GcMinorNum", "TODO JNF") - ,("RTS.Gcticks", "TODO JNF") - ,("RTS.Mutticks", "TODO JNF") - ,("RTS.Threads","TODO JNF") + anyProto + [("stat.cputicks", "Reports the CPU ticks, sice the process was started") + ,("mem.resident", "TODO JNF") + ,("rts.gcLiveBytes", "TODO JNF") + ,("rts.gcMajorNum", "TODO JNF") + ,("rts.gcMinorNum", "TODO JNF") + ,("rts.gcticks", "TODO JNF") + ,("rts.mutticks", "TODO JNF") + ,("rts.threads","TODO JNF") ] "TODO JNF" ] @@ -112,12 +112,12 @@ instance LogFormatting ResourceStats where ] asMetrics rs = - [ IntM "Stat.Cputicks" (fromIntegral $ rCentiCpu rs) - , IntM "Mem.Resident" (fromIntegral $ rRSS rs) - , IntM "RTS.GcLiveBytes" (fromIntegral $ rLive rs) - , IntM "RTS.GcMajorNum" (fromIntegral $ rGcsMajor rs) - , IntM "RTS.GcMinorNum" (fromIntegral $ rGcsMinor rs) - , IntM "RTS.Gcticks" (fromIntegral $ rCentiGC rs) - , IntM "RTS.Mutticks" (fromIntegral $ rCentiMut rs) - , IntM "Stat.Threads" (fromIntegral $ rThreads rs) + [ IntM "stat.cputicks" (fromIntegral $ rCentiCpu rs) + , IntM "mem.resident" (fromIntegral $ rRSS rs) + , IntM "rts.gcLiveBytes" (fromIntegral $ rLive rs) + , IntM "rts.gcMajorNum" (fromIntegral $ rGcsMajor rs) + , IntM "rts.gcMinorNum" (fromIntegral $ rGcsMinor rs) + , IntM "rts.gcticks" (fromIntegral $ rCentiGC rs) + , IntM "rts.mutticks" (fromIntegral $ rCentiMut rs) + , IntM "rts.stat.threads" (fromIntegral $ rThreads rs) ] diff --git a/trace-resources/src/Cardano/Logging/Resources/Windows.hsc b/trace-resources/src/Cardano/Logging/Resources/Windows.hsc index e5f043fa688..0176ba859da 100644 --- a/trace-resources/src/Cardano/Logging/Resources/Windows.hsc +++ b/trace-resources/src/Cardano/Logging/Resources/Windows.hsc @@ -78,7 +78,7 @@ instance Storable ProcessMemoryCounters where <*> (#peek PROCESS_MEMORY_COUNTERS, PeakPagefileUsage) ptr poke _ _ = pure () -foreign import ccall unsafe c_get_process_memory_info :: Ptr ProcessMemoryCounters -> CInt -> IO CInt +foreign import ccall unsafe c_get_process_memory_info2 :: Ptr ProcessMemoryCounters -> CInt -> IO CInt {- I/O counters -} {- https://docs.microsoft.com/de-de/windows/win32/api/winnt/ns-winnt-io_counters @@ -127,14 +127,14 @@ instance Storable CpuTimes where <*> (#peek CPU_TIMES, idletime) ptr poke _ _ = pure () -foreign import ccall unsafe c_get_proc_cpu_times :: Ptr CpuTimes -> CInt -> IO CInt +foreign import ccall unsafe c_get_proc_cpu_times2 :: Ptr CpuTimes -> CInt -> IO CInt getMemoryInfo :: ProcessId -> IO ProcessMemoryCounters getMemoryInfo pid = allocaBytes 128 $ \ptr -> do - throwIfNeg_ (\res -> "c_get_process_memory_info: failure returned: " ++ show res) - (c_get_process_memory_info ptr (fromIntegral pid)) + throwIfNeg_ (\res -> "c_get_process_memory_info2: failure returned: " ++ show res) + (c_get_process_memory_info2 ptr (fromIntegral pid)) peek ptr readRessoureStatsInternal :: IO (Maybe ResourceStats) @@ -166,10 +166,10 @@ readRessoureStatsInternal = getCurrentProcessId >>= \pid -> do getCpuTimes :: ProcessId -> IO CpuTimes getCpuTimes pid = allocaBytes 128 $ \ptr -> do - res <- c_get_proc_cpu_times ptr (fromIntegral pid) + res <- c_get_proc_cpu_times2 ptr (fromIntegral pid) if res <= 0 then do - putStrLn $ "c_get_proc_cpu_times: failure returned: " ++ (show res) + putStrLn $ "c_get_proc_cpu_times2: failure returned: " ++ (show res) return $ CpuTimes 0 0 0 else peek ptr