You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The typical operating system has different processes running in the background, and each process is being managed by a single-core of our CPU and will run a series of calculations each time it is being ticked. To take full advantage of our CPU using a single process, we would need a number of processes that is at least equal to the number of cores in our CPU. In addition, each process might be responsible for running a series of calculations of different logic, which will give the end user a better control over the CPU’s behavior.
Copy file name to clipboardExpand all lines: diagnostics/index.md
+176-6Lines changed: 176 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -10,38 +10,208 @@ Goals of this lesson:
10
10
* Learn how to set up Node Debugger
11
11
* Step through breakpoints using Repl
12
12
* Inspecting in the Chrome debugger
13
+
* Explore more powerful debugging options
14
+
* Generate diagnostic deports to catch errors
15
+
* Finding memory leaks
13
16
14
17
Pre-requisites:
15
18
16
19
INTRO and expected outcomes
17
20
18
21
## Node.js Debugger
19
22
20
-
https://nodejs.org/api/debugger.html
23
+
Node pack a useful [built-in debugging](https://nodejs.org/api/debugger.html) tool. Let's try using it to debug a script and find out what is causing a thrown error using the command line approach first.
24
+
25
+
To begin we create a JavaScript file locally called `count.js` containing the following:
26
+
27
+
```
28
+
function count() {
29
+
for (let i = 1; i < 4; i++) {
30
+
debugger;
31
+
if (i > 2) {
32
+
throw 'Wait, I counted too far!'
33
+
}
34
+
console.log(i + ' hahaha');
35
+
}
36
+
}
37
+
38
+
function startACount() {
39
+
console.log('I will now begin to count...')
40
+
count();
41
+
}
42
+
43
+
startACount();
44
+
```
45
+
46
+
When we run this using `node count` (the `.js` is optional) in our command line tool it outputs an uncaught error:
47
+
48
+
```
49
+
I will now begin to count...
50
+
1 hahaha
51
+
2 hahaha
52
+
53
+
/count.js:5
54
+
throw 'Wait, I counted too far!'
55
+
^
56
+
Wait, I counted too far!
57
+
```
58
+
59
+
Something has gone wrong! Let's use the debugger tool to find out what.
60
+
61
+
### debugger;
62
+
63
+
In the above code you might have noticed the `debugger;` code on line 3. During normal operation this is ignored, but we can make use of this by running `inspect`:
64
+
65
+
```
66
+
node inspect count
67
+
```
68
+
69
+
This will enter `debug` mode where we can use command to inspect what is going on.
70
+
71
+
Firstly we can use `list()` to take a look at the place in the code we are currently exectuting. At first it'll be on line 16 `startACount()`. All good so far. We can then continue using `cont` to continue exectuting until we reach the break point.
72
+
73
+
By entering the `cont` command we should now see:
74
+
75
+
```
76
+
1 function count() {
77
+
2 for (let i = 1; i < 4; i++) {
78
+
> 3 debugger;
79
+
4 if (i > 2) {
80
+
5 throw 'Wait, I counted too far!'
81
+
```
82
+
83
+
We have paused execution at this point. Now we can delve deeper and inspect some of our code to see what is going on. To begin, we jump into the Node REPL by using the command `repl`.
84
+
85
+
This then lets us access the code directly. Type `i` to log the value for that variable:
86
+
87
+
```
88
+
debug> repl
89
+
Press Ctrl + C to leave debug repl
90
+
> i
91
+
1
92
+
```
93
+
94
+
This shows that we have the value "1" stored in `i`. This is fine, so we then leave the REPL with `Cmd+C` and continue with `cont`.
95
+
96
+
Repeating the above shows `i` is now "2". Continue one more time. The value of `i` should now be "3".
97
+
98
+
The error hasn't thrown yet but we can carefully approach it by using `next`. This command steps through the lines one at a time.
99
+
100
+
Using `next` we should see the `if` statement, then a second `next` takes us to the `throw` statement:
101
+
102
+
```
103
+
debug> next
104
+
break in count.js:5
105
+
3 debugger;
106
+
4 if (i > 2) {
107
+
> 5 throw 'Wait, I counted too far!'
108
+
6 }
109
+
7 console.log(i + ' hahaha');
110
+
```
111
+
112
+
So we've managed to get to the moment when the script fails. Enter the `repl` command one last time and type `i`. We now see that it contains the value "3". Checking the `if` statement above, we can see why this now hits the `throw` statement.
113
+
114
+
You can quit the debugger by typing `.exit` or by pressing `Cmd+C` twice.
115
+
116
+
### Watchers
117
+
118
+
119
+
120
+
### Homework
121
+
122
+
Feel free to try moving the `debugger;` statement around in the above. You can also try using the `help` command in the `debug` mode to see other options.
123
+
124
+
Try breaking the code and then using the `debug` mode to narrow down the issue. Inspecting variables using the REPL can be helpful to find logic errors or catch situations where variables contain unexpected values.
We don't just need the command line to debug our code. We can also make use of Chrome's debugging tools to help navigate our code.
130
+
131
+
```
132
+
node --inspect index.js
133
+
```
134
+
135
+
The above runs the inspector, but in our case it throws an error, so we can have it pause on exectution to give us time to step through the code by using:
136
+
137
+
```
138
+
node --inspect-brk count.js
139
+
```
140
+
141
+
This will run the Chrome inspector and tell it to pause on any break points (`debugger;`).
142
+
143
+
It now gives us a URL. We can ignore this and instead, open Chrome and put in the address: `about:inspect`.
144
+
145
+
On this page we should see a link to our `count.js` process as it is currently running. Clicking the `inspect` link opens the `DevTools` window. We can then begin running the script within our DevTools window by pressing the blue _Resume_ button on the top right.
146
+
147
+
This should cause the script to reach our `debugger;` line as follows:
148
+
149
+
TODO: IMAGE: A screenshot of the DevTools showing the debugger line highlighted.
150
+
151
+
Beside the blue _Resume_ button you'll find controls to step through the code, by stepping over the next function call, step into and out of functions and step forward line by line.
152
+
153
+
We can also select the line numbers to toggle temporary breakpoints, to help drill down on specific areas of the code. These are listed under `Breakpoints` on the right panel.
154
+
155
+
On the right panel you can also manage _Watchers_ and more.
156
+
157
+
You can select `Console` in the tabs to see the output of the logs as we step through the code.
158
+
159
+
### Debugging our error
160
+
161
+
One approach will be to highlight line `4` in our code (click on the line number to highlight it with a blue background), then press the blue _Resume_ button until the execution pauses on the `if` statement.
162
+
163
+
You can hover your mouse cursor over the `i` to see what value it contains (you can slso see this information on the right panel under `Scope`).
164
+
165
+
Repeat pressing the _Resume_ button until `i` contains "3". Pressing _Resume_ again causes the code to disappear as it has encounted the error. We can see the error in our command line.
166
+
167
+
### Worker threads
168
+
169
+
Chrome DevTools doesn't support debugging [worker threads]({{ "/child-processes/" | url }}) yet. We can handle these using [ndb](https://github.com/GoogleChromeLabs/ndb).
170
+
171
+
## Debugging with ndb
172
+
173
+
You can install `ndb` globally by running:
174
+
175
+
```
176
+
npm install ndb -g
177
+
```
178
+
179
+
If you are using MacOS and encounter an error (`gyp: No Xcode or CLT version detected!`) you may need to install XCode or run:
180
+
181
+
```
182
+
sudo xcode-select -r
183
+
```
184
+
185
+
Then you can run `ndb` against the code with:
186
+
187
+
```
188
+
ndb count
189
+
```
190
+
191
+
This will download Chromium and present a similar view to before, albeit wrapped in a slightly smoother package.
192
+
193
+
You can debug the code as above, adding breakpoints as needed, hovering over the variables to see their values, and much more.
25
194
26
-
Note: Chrome DevTools doesn't support debugging worker threads yet. ndb can be used to debug them.
195
+
Find more information on [debugging using ndb](https://github.com/GoogleChromeLabs/ndb).
27
196
28
-
### Diagnostic reports
197
+
##Generating diagnostic reports
29
198
30
-
Use Node's built-in `diagnostic report` feature:
199
+
Sometimes we need more information to work out what is going on. To help with this, we can make use of Node's built-in `diagnostic report` feature:
> With the report option enabled, diagnostic reports can be triggered on unhandled exceptions, fatal errors and user signals, in addition to triggering programmatically through API calls.
35
204
36
205
206
+
## Async hooks
37
207
38
208
- A lot of services track everything going on in Node by monkey patching anything that is asynchronous, to keep track of processes over time
39
209
- Introducing AsyncHooks from https://github.com/nodejs/diagnostics
40
210
41
211
* note: don't use console.log inside async_hooks methods as it is asynchronous and will cause infinite `init` calls, instead use `process._rawDebug(msg)`
0 commit comments