Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add labels to binary decoders for improved debugging #385

Merged
merged 2 commits into from
Jun 11, 2019

Conversation

Anviking
Copy link
Member

@Anviking Anviking commented Jun 7, 2019

Overview

  • I have added a few labels

Comments

Previously:

Right (Just *** Exception: Data.Binary.Get.runGet at position 84: isolate: the decoder consumed 82 bytes which is less than the expected 178 bytes
CallStack (from HasCallStack):
  error, called at libraries/binary/src/Data/Binary/Get.hs:351:5 in binary-0.8.6.0:Data.Binary.Get
λ> runExceptT $ getBlock j t

Now:

Right *** Exception: Data.Binary.Get.runGet at position 84: isolate: the decoder consumed 82 bytes which is less than the expected 178 bytes
getBlockHeader
getBlock
CallStack (from HasCallStack):
  error, called at libraries/binary/src/Data/Binary/Get.hs:351:5 in binary-0.8.6.0:Data.Binary.Get

@Anviking Anviking self-assigned this Jun 7, 2019
Copy link
Member

@jonathanknowles jonathanknowles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The individual code changes look fine to me!

However, I can't help wondering if there isn't an approach we could use that doesn't involve repeating the name of each function (which is a kind of boilerplate).

For example, would it be enough to add HasCallStack constraints to each of the functions we care about, instead of adding labels to them?

@@ -103,7 +104,8 @@ data SignedVote = SignedVote
{-# ANN module ("HLint: ignore Use <$>" :: String) #-}

getBlockHeader :: Get BlockHeader
getBlockHeader = (fromIntegral <$> getWord16be) >>= \s -> isolate s $ do
getBlockHeader = label "getBlockHeader"
$ (fromIntegral <$> getWord16be) >>= \s -> isolate s $ do
version <- getWord16be
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just nitpicking, but shouldn't this line (and the lines following it) be further indented by one block? Like this:

getBlockHeader = label "getBlockHeader" $
    (fromIntegral <$> getWord16be) >>= \s -> isolate s $ do
        version <- getWord16be
        contentSize <- getWord32be
        slotEpoch <- fromIntegral <$> getWord32be
        slotId <- fromIntegral <$> getWord32be
        ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it?

I view this as

function = auxiliarySetup $ do
   important
   things

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue that this function is slightly different from the others though, as the first line is wrapped, which introduces an extra level of indentation.

Clearly, both of the variants below are valid Haskell syntax:

Variant 1:

getBlockHeader = label "getBlockHeader" $
    (fromIntegral <$> getWord16be) >>= \s -> isolate s $ do
    version <- getWord16be
    contentSize <- getWord32be
    slotEpoch <- fromIntegral <$> getWord32be
    slotId <- fromIntegral <$> getWord32be

Variant 2:

getBlockHeader = label "getBlockHeader" $
    (fromIntegral <$> getWord16be) >>= \s -> isolate s $ do
        version <- getWord16be
        contentSize <- getWord32be
        slotEpoch <- fromIntegral <$> getWord32be
        slotId <- fromIntegral <$> getWord32be

In my opinion, the extra indentation of variant 2 makes the code more readable, as it gives a visual indication of exactly where the do block starts, i.e., that it is separate from the line starting (fromIntegral <$> getWord16be) >>= \s -> isolate s.

What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — I suppose 😄

I guess the extra indentation shattered my ability to ignore the (fromIntegral [...]) line, but that might have been 1) just because I was used to it, and 2) bad because it's obfuscating.

So I think this makes perfect sense. Thanks! 👍

lib/jormungandr/src/Cardano/Wallet/Jormungandr/Binary.hs Outdated Show resolved Hide resolved
@Anviking Anviking force-pushed the anviking/binary-labels branch from 352446a to cfef960 Compare June 10, 2019 11:48
@Anviking
Copy link
Member Author

Anviking commented Jun 10, 2019

HasCallStack

Thanks for the suggestion, @jonathanknowles!

SrcLoc for free seems neat. I wonder if won't require some trickery though, and I wonder if it's worth looking into now.

I guessed we would have

label' :: HasCallStack => Get a -> Get a
label' = Data.Binary.Get.label (someVariantOf prettyCallStack callStack)

getFoo :: HasCallStack => Get Foo
getFoo = label' $ do
    ...

or am I missing some obvious use of it?

And I kind of like the simplicity of label "getFoo" and that it signals clearly what it does.

Of course, it's possible to provide a misleading label…

const' <- Quantity <$> getWord64be
perByte <- Quantity <$> getWord64be
perCert <- Quantity <$> getWord64be
return $ LinearFee const' perByte perCert
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to do-notation for consistency with the rest of the module, to show variable names, and separate order of the binary format with the order of the LinearFee arguments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separate order of the binary format with the order of the LinearFee arguments.

Fair enough!

@Anviking Anviking force-pushed the anviking/binary-labels branch from cfef960 to 6cb662c Compare June 10, 2019 22:35
Copy link
Contributor

@akegalj akegalj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me.

As of discussion about making this more automatic with HasCallStack and similar I would propose to add it to wiki Blackboard.

This already improves debugging information and we can make it more elegant if needed later

@Anviking Anviking force-pushed the anviking/binary-labels branch from 2189175 to 1543d98 Compare June 11, 2019 13:20
@Anviking Anviking force-pushed the anviking/binary-labels branch from 1543d98 to 4fb7d9e Compare June 11, 2019 14:47
@KtorZ KtorZ merged commit aebc91f into master Jun 11, 2019
@KtorZ KtorZ deleted the anviking/binary-labels branch June 11, 2019 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants