There are two options:
- You can start entire
V E G A
andtendermint
and fire instructions at your node and debug the results. - You can attach the
dlv
debugger to the integration tests.
For both you'll need to
- Read and follow instructions in
GETTING_STARTED.md
first. - Install
dlv
if you've not already done so. InVSCode
you can do this by launching the "Command Palette" and runningGo: Install/Update Tools
, selectdlv
, press OK.
Once you have successfully installed V E G A
with tendermint
these are the steps to let you debug.
-
Build the debug version (with optimisations disabled) of all the binaries with:
DEBUGVEGA=yes make build
If you're on a Mac
make build
will fail. This is because Mac OS isn't updatingbash
beyond version 3.x (something to do with GPL). The easiest solution is to install a recentbash
e.g. withhttps://brew.sh/
and then either run the above in the newbash
instance or add your new bash to/etc/shells
and then dochsh
to change your default shell. -
Use "Command Palette" to run
Debug: Open launch.json
. If you didn't already have alaunch.json
file, this will create one with the below default configuration which can be used to debug the current package. Enter the following intolaunch.json
(which will be by default created insidevega/.vscode/
):{ "version": "0.2.0", "configurations": [ { "name": "Debug V E G A", "type": "go", "request": "attach", "mode": "remote", "remotePath": "/path/to/vega", // trading-core "port": 2345, "host": "127.0.0.1", "showLog":true, "trace":"log" } ] }
Edit the
"remotePath"
appropriately to reflect where your trading-core source code lives. -
Now open ideally two terminal windows. In the first one launch
tendermint
as you normally would. To hard-reset the chain and start from scratch usetendermint unsafe_reset_all && tendermint init && tendermint node 2>./tendermint.stderr.out 1>./tendermint.stdout.out
Now launch the
dlv
debugger withV E G A
by runningdlv exec /path/to/vega/cmd/vega/vega-dbg --headless --listen=:2345 --log --api-version=2 -- node
again replacing the path to match where your git copy of trading core lives. If all went well you'll see something like:
API server listening at: [::]:2345 2019-10-13T20:37:41+01:00 info layer=debugger launching process with args: [/path/to/vega/cmd/vega/vega-dbg node] debugserver-@(#)PROGRAM:LLDB PROJECT:lldb-1100.0.28..1 for x86_64. Got a connection, launched process /path/to/vega/cmd/vega/vega (pid = 35671).
-
Finally in
VSCode
open the Debug panel and run theDebug V E G A
configuration created in the 2nd step above. At this pointV E G A
should be running. -
Test that
V E G A
is running as expected by e.g. visitinghttp://localhost:3003/statistics
or trying something in the GraphQL playground athttp://localhost:3004/
. If all is well you should be able to create users, place orders etc. as normal. More to the point breakpoints, call stack and variables should be usable as normal inVSCode
.
-
Build a debug version of the
godog
test harness: from the root of theV E G A
core repositoryDEBUGVEGA=yes go test -c ./integration/...
-
Use "Command Palette" to run
Debug: Open launch.json
. If you didn't already have alaunch.json
file, this will create one with the below default configuration which can be used to debug the current package. Enter the following intolaunch.json
(which will be by default created insidevega/.vscode/
):{ "version": "0.2.0", "configurations": [ { "name": "Debug Test", "type": "go", "request": "attach", "mode": "remote", "port": 2345, "host": "127.0.0.1", "showLog":true, "trace":"log" } ] }
-
Stick a breakpoint somewhere in the code that you know will be triggered by your integration test (this clearly has to be in a
.go
file, not.feature
). -
Launch the feature test you care about (in the example below it's
2668-price-monitoring.feature
)dlv exec ./integration.test --headless --listen=:2345 --log --api-version=2 -- -godog.format=pretty -- $(pwd)/integration/features/2668-price-monitoring.feature
The
godog
test harness is now running insidedlv
and it has launched the integration test you chose. -
Finally in
VSCode
open the Debug panel and run theDebug Test
.
Prerequisites: Vim version >= 8.0 and the vim-go plug-in.
A debug binary can be built using the go test -c
command, which works in the same way go build
would. Some compiler optimisations, however, can mess up the output when trying to print certain variables (e.g. slices being passed appearing empty, or containing seemingly garbage values).
To disable any and all compiler optimisations we might encounter, simply add the gcflags="ALL=-N -l"
option.
To build the vega binary for debugging, then:
go test -c -gcflags="ALL=-N -l" ./cmd/vega
To build a binary to step through integration tests, simply run
go test -c -gcflags="ALL=-N -l" ./core/integration
The output will be a binary called either vega.test
or integration.test
.
As-is, you can use the compiled binary to step through the code in dlv. Setting breakpoints using things like b core/execution/market.go:2107
is quite tedious, though, and only shows you a few lines of code around the breakpoint. Having the ability to set breakpoints and check out variables in our editor is what we're after. To do that, we need to start dlv as a debug server, so we can connect to it from inside Vim:
dlv exec --headless --api-version=2 --listen 127.0.0.1:9876 ./integration.test -- ./core/integration/features
The address and port to listen to is arbitrary, but in this particular example, we'll use 9876. In this example we're starting a debug session on the integration test binary. To debug vega.test
, just replace integration.test
with vega.test
(obviously).
Passing in additional arguments/parameters is as easy as just appending --
to the command above and specifying the desired arguments and flags. To run integration tests with a specific tag, for example, the full command looks like this:
dlv exec --headless --api-version=2 --listen 127.0.0.1:9876 ./integration.test -- --godog.tags=LPWrong -- ./core/integration/features
Now that dlv is running, we can open the code we want to step through in Vim, and connect to our debugger:
vim core/execution/market.go
Once in our editor, just enter the command :GoDebugConnect 127.0.0.1:9876
Debugger buffers will load as you've configured (default is the call stack top left, call stack, arguments, and registers bottom left, runtime and routine info bottom buffer). Open any file, jump to any line where you want to set a breakpoint, and run the :GoDebugBreakpoint
(or :GoDebugBr
) command.
To start executing the code, run :GoDebugContinue
, and the test binary will run until a breakpoint is encountered. From that point on, you can use standard debugger commands (like :GoDebugStep
, :GoDebugStepOut
, and of course :GoDebugContinue
). A full list of commands, what they do can be found by running :h :GoDebug
.
The vim-go
plug-in documentation also contains a list of default bindings (e.g. F9 for toggling a breakpoint, F5 for :GoDebugContinue
), and detailed instructions on how to create your own bindings, how to customise your setup (:h go-debug-settings
).
To stop debugging, run :GoDebugStop
. This will close the debug buffers, and the dlv process will return.
Seeing what value a variable is set to is arguably the most common thing to do when debugging. Simply run :GoDebugPrint foo
to see a full print-out of what a variable actually holds. Seeing as we're dealing with maps and arrays of objects quite a lot. It's important to note that dlv (and by extension vim-go debugging) does not restrict access to unexported fields, so things like :GoDebugPrint order.Price.u[0]
work fine. :GoDebugPrint
evaluates its argument as an expression, so things like :GoDebugPrint foo == 10
is valid.
Setting a variable to a different value is equally possible, but just like delve itself, this is limited to types like bool
, float
, int
, and uint
variants, and pointers. This can be useful when debugging functions that have some boolean argument (e.g. force
is set to false
, change to true by running :GoDebugSet force true
).