Skip to main content

Debugging

Allows analyzing code execution in real time.

Introduction​

During coding, it often happens that you need to analyze code execution.

With Netuno we can use:

  • _out.print - To show some information in the data output (output).
  • _log.info - To show some information in the Netuno server terminal.

However, there are also more complex scenarios where we want to analyze more deeply, for example checking several values of objects and variables at the same time, testing the execution of some specific code in this context, all to better understand the behavior.

It is always possible to use in these more complex cases the methods shown above such as _out.print and _log.info, but we can fall into a very laborious and confusing process to reach a good understanding of what is happening.

Debugging serves precisely to provide a good understanding of what is happening, especially in more complex situations.

Debugging is the process used in development to find and reduce defects, failures, wrong behaviors, etc.

Debugging can be divided into 3 important mechanisms:

  • Breakpoint: Makes code execution stop, we can then start investigating where the code is stopped.
  • Watch: Allows observing the values of variables where the code is stopped.
  • Code Execution: We can execute any code temporarily, to perform some test at the point where execution is stopped for debugging.

Breakpoint​

The breakpoint is where in the code execution should be paused to start the debugging process.

To start debugging in any code and in any language supported by Netuno, such as JavaScript, Python, Ruby, Kotlin or Groovy, at the location where you want to start debugging, place the following code:

_exec.debug()

Since Netuno is polyglot, it works with any supported language, such as: JavaScript, Python, Kotlin, Ruby, or Groovy.

Now to start debugging, run the code and execution will be held, paused.

Then let's go to the development interface, in the backoffice under Build, and in the left side menu we have the option:

  • Debug

Where we can find the double green arrow that indicates that clicking on it will allow execution to continue:

Debug - Step Over

The double green arrow interrupts the debugging pause causing code execution to continue normally from the point where it stopped.

Watch​

To see the value of variables we use the yellow magnifying glass.

By clicking on the yellow magnifying glass we can enter the name of the variable whose value we want to observe.

Debug - Watch

The variable name and its current value appear in the list, we can observe the value of several variables, if any variable does not exist then there will be no value.

Execute Code​

We can inject code to be executed in the context of the breakpoint, that is, where debugging is happening.

We click on the blue code symbol and we can enter the code we intend to execute.

Debug - Execute Code

The executed code is presented in the list below with an indication that the code was executed successfully, if there is any error then the error message is presented together with the code.

Configuration for Remote Debugging​

When running Netuno locally, no configuration should be necessary.

Because in local development the host of the WebSocket address is configured automatically.

Local addresses normally use these values as host:

  • localhost
  • 127.0.0.1
  • 192.168.1.* - Example of any local network IP.
  • my-app.local.netu.no

Local addresses do not need any configuration, so this step can be skipped.

In production or remote development such as in a container or VPN, it may be necessary to define the external address (IP or domain) that is being used for the WebSocket connection.

In this case, navigate within the application being developed to the environment configuration file. In this example, we will use the development environment file, which is located at:

  • 📂 config/_development.json

Check if the configuration does not already exist, if it does not exist add at the end of the configuration file (in JSON format) the configuration parameters for the external address to be used in the WebSocket connection, such as for example:

{
...
"dev": {
"ws": {
"host": "dev.netuno.org"
}
},
...
}

The port information should not be added to the WebSocket host address.

Multiple host addresses can also be passed in an array:

{
...
"dev": {
"ws": {
"host": [ "my-container.dev.netuno.org", "my-project.com" ]
}
},
...
}

Proxy in Production (NGINX)​

In production it is common to use some web server that performs reverse proxy, such as NGINX.

For debugging to work through a proxy, it is then necessary to add a specific configuration to forward the traffic related to the WebSocket address:

server {
listen 443 ssl;
server_name my-project.com;

...

location /dev/ws/ {
proxy_pass http://127.0.0.1:9000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_http_version 1.1;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
add_header X-Frame-Options "";
}
}

Conclusion​

With the debugging interface and the _exec.debug() command we can perform a deep investigation of what is happening.

In most backend languages and technologies, especially scripting technologies, debugging is usually impossible or complex.

Netuno offers a simple way to debug polyglot code that works across the various supported languages such as JavaScript, Python, Ruby, Kotlin and Groovy.

Allows polyglot debugging in remote environments and in production.

Using debugging greatly speeds up development by offering greater precision to solve problems and becomes an essential tool, give it a try.