Debug mode for scripts
Discussed in https://github.com/nushell/nushell/discussions/4530
Originally posted by cypof February 18, 2022 What would be the best way to run nu scripts in debug mode? E.g. bash can run scripts with settings like this:
# stop and show the stack on any error
set -eE -o functrace
# error on unset variables
set -u
# print each command before executing it
set -x
# extend "set -x" above with source file, line number, function name etc
export PS4='+(${BASH_SOURCE:-""}:${LINENO}) ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
```</div>
Oh yeah, one thing I forgot to mention: You can set the log_level setting in the config. If you set it to trace, you'll get a lot of trace info. You can check here to see an example config and how to set it.
i think log_level is disabled atm. we need to re-enable it i think. i may have disabled it when testing --perf.
Powershell has $ErrorActionPreference = "Stop"
In regards to debugging and testing, I also really like the -wi "what if" flag that powershell commands have. Maybe that could also be an environment variable (could be indicated in the prompt as training wheels).
I was looking for an equivalent of: set -x when I found this issue.
I couldn't find mention of log_level in the latest configuration, and setting it doesn't seem to work out.
Is there a command one might use in place of set -x, or some known workaround to this? (aside from explicitly printing each command in a script before its execution)
not that i know of. i end up putting prints everywhere
I see! Did the team decide to keep it disabled because of design decisions, or...? Is there interest in making it work again, or should it be considered as "removed permanently"?
@aslynatilla I'm confused now. --log-level is a parameter to nushell and should still work but there never has been a way to print every statement before it executes in nushell script code.
@fdncred my bad. I had misunderstood what setting log-level to trace could do. Thanks for making it clearer for me!
Personally I'd very much like to be able to work with a script in an IDE, step through it, watch locals, etc. It's very time-consuming having to debug most scripting languages by, essentially, printf statements, just because they're for scripting, and if the idea is that nu offers the features of a real language but still convenient for shell use, then I think something like this could be really powerful. I presume some sort of language server would be in order here.
@stellarpower agreed. step debugging would be awesome. I believe vscode has the ability to use DAP now https://microsoft.github.io/debug-adapter-protocol/. If you look at our vscode extension, we're just starting to add basic IDE support, but debugging isn't currently included.
with the standard library, you can use the std log debug command to log thing in debug mode, i.e. by setting $env.NU_LOG_LEVEL to DEBUG or 0 :yum:
What about utilizing the existing OpenTelemetry Ecosystem?
- it could be configurable so that nushell does not record everything.
- things like
log <LEVEL> <MESSAGE>could be exported as events. - it could automatically set TRACEPARENT and TRACECONTEXT env vars for external commands, so if the external commands also use OTEL, their spans/events are recorded in the right place.
Those are just a few ideas, but I think fleshing out a nutshell <-> OTEL integration could also be useful for:
- Running Nushell as the shell in CI/Build environments, where it's typically hardest to gain insight as to what exactly happened.
- organising the output of long running scripts by annotating it with traces and allowing users to view them in the tool they desire.
Any thoughts?
We now have a Debugger trait which can be used to implement custom debuggers (an example is the debug profile command). At some point, we want to allow implementing custom debuggers without the need of modifying Nushell's source code, e.g., by extending the plugin protocol to allow implementing debuggers as plugins.
To elaborate a bit further: Using the info that this debugger trait is available, I think utilizing the tracing crate with tracing-opentelemetry could work out nicely.
Entering and leaving blocks or pipelines enters and leaves the associated spans. I'm just a bit unsure how to best include the stdout of commands in the spans. As far as I can tell, the various stdouts are not passed through the Debugger trait?
Adding a collector to just print executed commands to stdout should be trivial afterwards.
You should be able to capture stdout from an external process via leave_element() of the Debugger trait which takes the result parameter. It's not possible to capture Nushell's own stdout from within Nushell (IIRC), and we don't use stdout anyway for passing data, only for the final print to the REPL. You could just track the values directly via leave_element() and its result.
Workaround: https://github.com/nushell-prophet/dotnu#dotnu-set-x